Skip to content

[QMS-902] Improve HiDPI Support#1134

Open
jmlzr wants to merge 8 commits into
Maproom:devfrom
jmlzr:QMS-902
Open

[QMS-902] Improve HiDPI Support#1134
jmlzr wants to merge 8 commits into
Maproom:devfrom
jmlzr:QMS-902

Conversation

@jmlzr

@jmlzr jmlzr commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What is the linked issue for this pull request:

QMS-#902

What you have done:

  • Fixed a fundamental issue where drawTile used physical instead of logical pixels.
  • Rewrote TMS drawing to make it work properly.
  • Fixed VRT maps and DEMs loading data at wrong resolution on scaled screens
  • Handle non-compliant WMTS servers correcty

Steps to perform a simple smoke test:

Open TMS and WMTS maps with various tile sizes.
Try a DEM and a VRT map.

Does the code comply to the coding rules and naming conventions Coding Guidelines:

  • yes

Is every user facing string in a tr() macro?

  • yes

Did you add the ticket number and title into the changelog? Keep the numeric order in each release block.

  • yes, I didn't forget to change changelog.txt

@kiozen

kiozen commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

At least on old fashioned, normal screens everything is the same 😄

jmlzr added 2 commits June 26, 2026 10:59
Rewrite CMapTMS::draw from scratch to be maintainable again and
correctly handle tiles of different sizes other then 256px (like HiDPI
tiles).
@jmlzr

jmlzr commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

I now made VRT maps and DEMs load data at physical resolution, till now they used logical which would reduce quality for HiDPI screens.
Reverted my previous changes to the exotic formats that no one ever seem to have tested.

At least on old fashioned, normal screens everything is the same 😄

Rendering of TMS tiles with size != 256px should look different for you as well! Confirmed with setting my screen to 1.0 scale.
You can try e.g. any Thunderforest map with @2x appended to the url.

jmlzr added 4 commits June 26, 2026 12:14
Take HiDPI scaling into account to read at the physical pixel
resolution. Previously logical pixels were used resulting in a quality
loss of DEM shadings on HiDPI screens.
Those changes have not been tested and were properly wrong.
The same information is available in IDrawContext::buffer_t::image using
the devicePixelRatio method.
Same change as to CDemVRT which should behave identical in that regard.
@jmlzr

jmlzr commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Side note: Just noticed that some window sizes result in the VRT code choosing a buffer size 1 pixel smaller than the buffer from the drawing context which will possibly cause a scale at the end:
dem gdal buf: 1228 2064 context buf: 1226 2063 (keep in mind that the dem buffer has a 1px border so should be 2px larger per axis)
I think that's probably a rounding error resulting from having logical pixels :/ Not much we can do here.

jmlzr added 2 commits June 26, 2026 14:42
Some HiDPI servers reuse a standard TileMatrixSet (e.g. TileWidth=256) while
serving larger (e.g. 512px) tiles. Add layer_t::tileScale, learned from the
first tile, and divide the candidate pixel span by it during selection so
tiles land 1:1 on physical pixels.
@jmlzr

jmlzr commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

WMTS should now be working as expected even with problematic servers.

With that this PR is ready for review.

@jmlzr jmlzr marked this pull request as ready for review June 26, 2026 12:53
@kkarsten62

Copy link
Copy Markdown
Contributor

Just to note.

I notice some compiler warnings in my dev environment. Some already exists quite a while but some are new and seems related to this PR:

/home/karl/GPS/qmapshack_jmlzr/3rdparty/alglib/src/ap.cpp:4613: Warnung: ‘++’ expression of ‘volatile’-qualified type is deprecated [-Wvolatile]
/home/karl/GPS/qmapshack_jmlzr/3rdparty/alglib/src/ap.cpp: In function ‘void alglib_impl::ae_spin_wait(ae_int_t)’:
/home/karl/GPS/qmapshack_jmlzr/3rdparty/alglib/src/ap.cpp:4613:21: warning: ‘++’ expression of ‘volatile’-qualified type is deprecated [-Wvolatile]
 4613 |     for(i=0; i<cnt; i++)
      |                     ^
/home/karl/GPS/qmapshack_jmlzr/3rdparty/alglib/src/ap.cpp:4615: Warnung: ‘--’ expression of ‘volatile’-qualified type is deprecated [-Wvolatile]
/home/karl/GPS/qmapshack_jmlzr/3rdparty/alglib/src/ap.cpp:4615:13: warning: ‘--’ expression of ‘volatile’-qualified type is deprecated [-Wvolatile]
 4615 |             ae_never_change_it--;
      |             ^~~~~~~~~~~~~~~~~~
/home/karl/GPS/qmapshack_jmlzr/src/qmapshack/dem/CDemVRT.h:55: Warnung: defining ‘CDemVRT’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
In file included from /home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/G2GOEHWAFX/moc_CDemVRT.cpp:9,
                 from /home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/mocs_compilation.cpp:17:
/home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/G2GOEHWAFX/../../../../../../src/qmapshack/dem/CDemVRT.h:55:7: warning: defining ‘CDemVRT’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   55 | class CDemVRT : public IDem {
      |       ^~~~~~~
/usr/include/qt6/QtCore/qobject.h:19: In file included from /usr/include/qt6/QtCore/qobject.h:19,
In file included from /usr/include/qt6/QtCore/qobject.h:19,
                 from /usr/include/qt6/QtWidgets/qwidget.h:10,
                 from /usr/include/qt6/QtWidgets/qdockwidget.h:9,
                 from /usr/include/qt6/QtWidgets/QDockWidget:1,
                 from /home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/AL3DETLKD3/../../../../../../src/common/help/CHelp.h:22,
                 from /home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/AL3DETLKD3/moc_CHelp.cpp:9,
                 from /home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/mocs_compilation.cpp:2:
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
/home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/CMapVRT.h:48: Warnung: defining ‘CMapVRT’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
In file included from /home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/VQTIZUGSAA/moc_CMapVRT.cpp:9,
                 from /home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/mocs_compilation.cpp:153:
/home/karl/GPS/qmapshack_jmlzr/build/Desktop_RelWithDebInfo/src/qmapshack/qmapshack_autogen/VQTIZUGSAA/../../../../../../src/qmapshack/map/CMapVRT.h:48:7: warning: defining ‘CMapVRT’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   48 | class CMapVRT : public IMap {
      |       ^~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
/home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/garmin/CGarminTyp.cpp:842: Warnung: ‘QImage QImage::mirrored(bool, bool) const &’ is deprecated: Use flipped(Qt::Orientations) instead [-Wdeprecated-declarations]
/home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/garmin/CGarminTyp.cpp: In member function ‘virtual bool CGarminTyp::parsePolyline(QDataStream&, QMap<unsigned int, polyline_property>&)’:
/home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/garmin/CGarminTyp.cpp:842:49: warning: ‘QImage QImage::mirrored(bool, bool) const &’ is deprecated: Use flipped(Qt::Orientations) instead [-Wdeprecated-declarations]
  842 |       property.imgDay = property.imgDay.mirrored(false, true);
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
/usr/include/qt6/QtGui/qpixmap.h:13: In file included from /usr/include/qt6/QtGui/qpixmap.h:13,
In file included from /usr/include/qt6/QtGui/qpixmap.h:13,
                 from /usr/include/qt6/QtGui/qicon.h:10,
                 from /usr/include/qt6/QtGui/qabstractfileiconprovider.h:10,
                 from /usr/include/qt6/QtGui/QtGui:5,
                 from /home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/garmin/CGarminTyp.h:22,
                 from /home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/garmin/CGarminTyp.cpp:22:
/usr/include/qt6/QtGui/qimage.h:220:26: note: declared here
  220 |     [[nodiscard]] QImage mirrored(bool horizontally = false, bool vertically = true) const &
      |                          ^~~~~~~~
/home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/garmin/CGarminTyp.cpp:843: Warnung: ‘QImage QImage::mirrored(bool, bool) const &’ is deprecated: Use flipped(Qt::Orientations) instead [-Wdeprecated-declarations]
/home/karl/GPS/qmapshack_jmlzr/src/qmapshack/map/garmin/CGarminTyp.cpp:843:53: warning: ‘QImage QImage::mirrored(bool, bool) const &’ is deprecated: Use flipped(Qt::Orientations) instead [-Wdeprecated-declarations]
  843 |       property.imgNight = property.imgNight.mirrored(false, true);
      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
/usr/include/qt6/QtGui/qimage.h:220:26: note: declared here
  220 |     [[nodiscard]] QImage mirrored(bool horizontally = false, bool vertically = true) const &
      |                          ^~~~~~~~

@jmlzr

jmlzr commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@kkarsten62 all preexisting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants