From 2adc167f268bbdee5c81de27346be3f1d958137b Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 Apr 2024 11:22:15 +0200 Subject: [PATCH 1/4] windisplay: Fix regression related to fullscreen switching Fixes #1594 --- panda/src/windisplay/winGraphicsWindow.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index eea2a3a7e4..0a216be367 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -304,7 +304,9 @@ set_properties_now(WindowProperties &properties) { } if (do_fullscreen_switch(x_size, y_size)) { _properties.set_fullscreen(true); + _properties.set_size(x_size, y_size); properties.clear_size(); + properties.clear_origin(); } else { windisplay_cat.warning() << "Switching to fullscreen mode failed!\n"; @@ -950,7 +952,7 @@ do_fullscreen_switch(int x_size, int y_size) { SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, x_size, y_size, SWP_FRAMECHANGED | SWP_SHOWWINDOW); - handle_reshape(); + set_size_and_recalc(x_size, y_size); return true; } From 5da013e2e9a991c993532cc6886c53e4c38bccc0 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 Apr 2024 12:12:00 +0200 Subject: [PATCH 2/4] text: Properly handle surrogate pairs in text on Windows Fixes #1629 --- panda/src/text/textAssembler.I | 16 +++++- panda/src/text/textAssembler.cxx | 91 +++++++++++++++++++++++++------- panda/src/text/textAssembler.h | 8 +-- 3 files changed, 90 insertions(+), 25 deletions(-) diff --git a/panda/src/text/textAssembler.I b/panda/src/text/textAssembler.I index d72d3d99bf..3d547e1482 100644 --- a/panda/src/text/textAssembler.I +++ b/panda/src/text/textAssembler.I @@ -168,7 +168,7 @@ get_num_characters() const { * string. If the object at this position is a graphic object instead of a * character, returns 0. */ -INLINE wchar_t TextAssembler:: +INLINE char32_t TextAssembler:: get_character(int n) const { nassertr(n >= 0 && n < (int)_text_string.size(), 0); return _text_string[n]._character; @@ -232,7 +232,7 @@ get_num_cols(int r) const { * the object at this position is a graphic object instead of a character, * returns 0. */ -INLINE wchar_t TextAssembler:: +INLINE char32_t TextAssembler:: get_character(int r, int c) const { nassertr(r >= 0 && r < (int)_text_block.size(), 0); nassertr(c >= 0 && c < (int)_text_block[r]._string.size(), 0); @@ -315,6 +315,18 @@ TextCharacter(wchar_t character, { } +/** + * + */ +INLINE TextAssembler::TextCharacter:: +TextCharacter(char32_t character, + TextAssembler::ComputedProperties *cprops) : + _character(character), + _graphic(nullptr), + _cprops(cprops) +{ +} + /** * */ diff --git a/panda/src/text/textAssembler.cxx b/panda/src/text/textAssembler.cxx index 081f86f8ca..2bfb3a13a8 100644 --- a/panda/src/text/textAssembler.cxx +++ b/panda/src/text/textAssembler.cxx @@ -235,11 +235,16 @@ wstring TextAssembler:: get_plain_wtext() const { wstring wtext; - TextString::const_iterator si; - for (si = _text_string.begin(); si != _text_string.end(); ++si) { - const TextCharacter &tch = (*si); + for (const TextCharacter &tch : _text_string) { if (tch._graphic == nullptr) { - wtext += tch._character; + if (sizeof(wchar_t) >= 4 || (tch._character & ~0xffff) == 0) { + wtext += (wchar_t)tch._character; + } else { + // Use a surrogate pair. + char32_t v = (char32_t)tch._character - 0x10000u; + wtext += (wchar_t)((v >> 10u) | 0xd800u); + wtext += (wchar_t)((v & 0x3ffu) | 0xdc00u); + } } else { wtext.push_back(0); } @@ -269,11 +274,16 @@ get_wordwrapped_plain_wtext() const { wtext += '\n'; } - TextString::const_iterator si; - for (si = row._string.begin(); si != row._string.end(); ++si) { - const TextCharacter &tch = (*si); + for (const TextCharacter &tch : row._string) { if (tch._graphic == nullptr) { - wtext += tch._character; + if (sizeof(wchar_t) >= 4 || (tch._character & ~0xffff) == 0) { + wtext += (wchar_t)tch._character; + } else { + // Use a surrogate pair. + char32_t v = (char32_t)tch._character - 0x10000u; + wtext += (wchar_t)((v >> 10u) | 0xd800u); + wtext += (wchar_t)((v & 0x3ffu) | 0xdc00u); + } } else { wtext.push_back(0); } @@ -295,12 +305,17 @@ get_wtext() const { wstring wtext; PT(ComputedProperties) current_cprops = _initial_cprops; - TextString::const_iterator si; - for (si = _text_string.begin(); si != _text_string.end(); ++si) { - const TextCharacter &tch = (*si); + for (const TextCharacter &tch : _text_string) { current_cprops->append_delta(wtext, tch._cprops); if (tch._graphic == nullptr) { - wtext += tch._character; + if (sizeof(wchar_t) >= 4 || (tch._character & ~0xffff) == 0) { + wtext += (wchar_t)tch._character; + } else { + // Use a surrogate pair. + char32_t v = (char32_t)tch._character - 0x10000u; + wtext += (wchar_t)((v >> 10u) | 0xd800u); + wtext += (wchar_t)((v & 0x3ffu) | 0xdc00u); + } } else { wtext.push_back(text_embed_graphic_key); wtext += tch._graphic_wname; @@ -341,12 +356,17 @@ get_wordwrapped_wtext() const { wtext += '\n'; } - TextString::const_iterator si; - for (si = row._string.begin(); si != row._string.end(); ++si) { - const TextCharacter &tch = (*si); + for (const TextCharacter &tch : row._string) { current_cprops->append_delta(wtext, tch._cprops); if (tch._graphic == nullptr) { - wtext += tch._character; + if (sizeof(wchar_t) >= 4 || (tch._character & ~0xffff) == 0) { + wtext += (wchar_t)tch._character; + } else { + // Use a surrogate pair. + char32_t v = (char32_t)tch._character - 0x10000u; + wtext += (wchar_t)((v >> 10u) | 0xd800u); + wtext += (wchar_t)((v & 0x3ffu) | 0xdc00u); + } } else { wtext.push_back(text_embed_graphic_key); wtext += tch._graphic_wname; @@ -623,6 +643,18 @@ assemble_text() { */ PN_stdfloat TextAssembler:: calc_width(wchar_t character, const TextProperties &properties) { + return calc_width((char32_t)character, properties); +} + +/** + * Returns the width of a single character, according to its associated font. + * This also correctly calculates the width of cheesy ligatures and accented + * characters, which may not exist in the font as such. + * + * This does not take kerning into account, however. + */ +PN_stdfloat TextAssembler:: +calc_width(char32_t character, const TextProperties &properties) { if (character == ' ') { // A space is a special case. TextFont *font = properties.get_font(); @@ -846,6 +878,27 @@ scan_wtext(TextAssembler::TextString &output_string, << "Unknown TextGraphic: " << graphic_name << "\n"; } +#if WCHAR_MAX < 0x10FFFF + } else if (*si >= 0xd800 && *si < 0xdc00) { + // This is a high surrogate. Look for a subsequent low surrogate. + wchar_t ch = *si; + ++si; + if (si == send) { + text_cat.warning() + << "High surrogate at end of text.\n"; + return; + } + wchar_t ch2 = *si; + if (ch2 >= 0xdc00 && ch2 < 0xe000) { + char32_t code_point = 0x10000 + ((ch - 0xd800) << 10) + (ch2 - 0xdc00); + output_string.push_back(TextCharacter(code_point, current_cprops)); + ++si; + } else { + text_cat.warning() + << "High surrogate was not followed by low surrogate in text.\n"; + } +#endif + } else { // A normal character. Apply it. output_string.push_back(TextCharacter(*si, current_cprops)); @@ -1422,10 +1475,8 @@ assemble_row(TextAssembler::TextRow &row, hb_buffer_t *harfbuff = nullptr; #endif - TextString::const_iterator si; - for (si = row._string.begin(); si != row._string.end(); ++si) { - const TextCharacter &tch = (*si); - wchar_t character = tch._character; + for (const TextCharacter &tch : row._string) { + char32_t character = tch._character; const TextGraphic *graphic = tch._graphic; const TextProperties *properties = &(tch._cprops->_properties); diff --git a/panda/src/text/textAssembler.h b/panda/src/text/textAssembler.h index 20f9b2c1e5..a4c7182ce4 100644 --- a/panda/src/text/textAssembler.h +++ b/panda/src/text/textAssembler.h @@ -78,14 +78,14 @@ PUBLISHED: int calc_index(int r, int c) const; INLINE int get_num_characters() const; - INLINE wchar_t get_character(int n) const; + INLINE char32_t get_character(int n) const; INLINE const TextGraphic *get_graphic(int n) const; INLINE const TextProperties &get_properties(int n) const; INLINE PN_stdfloat get_width(int n) const; INLINE int get_num_rows() const; INLINE int get_num_cols(int r) const; - INLINE wchar_t get_character(int r, int c) const; + INLINE char32_t get_character(int r, int c) const; INLINE const TextGraphic *get_graphic(int r, int c) const; INLINE const TextProperties &get_properties(int r, int c) const; INLINE PN_stdfloat get_width(int r, int c) const; @@ -98,6 +98,7 @@ PUBLISHED: INLINE const LVector2 &get_lr() const; static PN_stdfloat calc_width(wchar_t character, const TextProperties &properties); + static PN_stdfloat calc_width(char32_t character, const TextProperties &properties); static PN_stdfloat calc_width(const TextGraphic *graphic, const TextProperties &properties); static bool has_exact_character(wchar_t character, const TextProperties &properties); @@ -132,13 +133,14 @@ private: class TextCharacter { public: INLINE TextCharacter(wchar_t character, ComputedProperties *cprops); + INLINE TextCharacter(char32_t character, ComputedProperties *cprops); INLINE TextCharacter(const TextGraphic *graphic, const std::wstring &graphic_wname, ComputedProperties *cprops); INLINE TextCharacter(const TextCharacter ©); INLINE void operator = (const TextCharacter ©); - wchar_t _character; + char32_t _character; const TextGraphic *_graphic; std::wstring _graphic_wname; PT(ComputedProperties) _cprops; From a9206041d96a41c19d870cfd085751222fa3258a Mon Sep 17 00:00:00 2001 From: Disyer Date: Sun, 31 Mar 2024 12:05:05 +0300 Subject: [PATCH 3/4] ffmpeg: Use ch_layout in favor of removed channel_layout and channels Closes #1641 --- panda/src/ffmpeg/ffmpegAudioCursor.cxx | 22 ++++++++++++++++++++-- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index aab7d14f6e..bde539fe64 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -99,7 +99,15 @@ FfmpegAudioCursor(FfmpegAudio *src) : _audio_timebase = av_q2d(stream->time_base); _audio_rate = codecpar->sample_rate; + + // As of libavformat version 60.25.100, the deprecated + // AVCodecParameters.channels has been removed. + // AVCodecParameters.ch_layout is available since version 59.18.101. +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(59, 18, 101) + _audio_channels = codecpar->ch_layout.nb_channels; +#else _audio_channels = codecpar->channels; +#endif /* LIBAVFORMAT_VERSION_INT */ const AVCodec *pAudioCodec = avcodec_find_decoder(codecpar->codec_id); if (pAudioCodec == nullptr) { @@ -138,10 +146,20 @@ FfmpegAudioCursor(FfmpegAudio *src) : } _resample_ctx = swr_alloc(); + + // As of libavformat version 60.25.100, the deprecated + // AVCodecContext.channel_layout has been removed. + // AVCodecContext.ch_layout is available since version 59.18.101. +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(59, 18, 101) + av_opt_set_chlayout(_resample_ctx, "in_chlayout", &_audio_ctx->ch_layout, 0); + av_opt_set_chlayout(_resample_ctx, "out_chlayout", &_audio_ctx->ch_layout, 0); +#else av_opt_set_int(_resample_ctx, "in_channel_count", _audio_channels, 0); av_opt_set_int(_resample_ctx, "out_channel_count", _audio_channels, 0); av_opt_set_int(_resample_ctx, "in_channel_layout", _audio_ctx->channel_layout, 0); av_opt_set_int(_resample_ctx, "out_channel_layout", _audio_ctx->channel_layout, 0); +#endif /* LIBAVFORMAT_VERSION_INT */ + av_opt_set_int(_resample_ctx, "in_sample_rate", _audio_ctx->sample_rate, 0); av_opt_set_int(_resample_ctx, "out_sample_rate", _audio_ctx->sample_rate, 0); av_opt_set_sample_fmt(_resample_ctx, "in_sample_fmt", _audio_ctx->sample_fmt, 0); @@ -155,7 +173,7 @@ FfmpegAudioCursor(FfmpegAudio *src) : #else ffmpeg_cat.error() << "Codec does not use signed 16-bit sample format, but support for libswresample has not been enabled.\n"; -#endif +#endif /* HAVE_SWRESAMPLE */ } _length = (_format_ctx->duration * 1.0) / AV_TIME_BASE; @@ -220,10 +238,10 @@ cleanup() { avcodec_flush_buffers(_audio_ctx); #endif - avcodec_close(_audio_ctx); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) avcodec_free_context(&_audio_ctx); #else + avcodec_close(_audio_ctx); av_free(_audio_ctx); #endif } diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index 2f63757e61..3b09678139 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -603,10 +603,10 @@ close_stream() { avcodec_flush_buffers(_video_ctx); #endif - avcodec_close(_video_ctx); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) avcodec_free_context(&_video_ctx); #else + avcodec_close(_video_ctx); av_free(_video_ctx); #endif } From 2436a065272bd708e31c589164750d4a4ff39f02 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 14 May 2024 22:22:16 +0200 Subject: [PATCH 4/4] glgsg: Better error when invalid ShaderPtrSpec type is encountered --- panda/src/glstuff/glShaderContext_src.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index f3c9a106c7..129c617b13 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -2255,7 +2255,12 @@ issue_parameters(int altered) { break; default: - nassertd(false) continue; +#ifndef NDEBUG + GLCAT.error() + << "Invalid ShaderPtrSpec type " << (int)ptr_data->_type + << " for shader input '" << spec._id._name << "'\n"; +#endif + continue; } switch (spec._dim[1]) {