Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 1e56ae3

Browse files
Merge pull request #7387 from livecodeian/bugfix-21615
[[ Bug 21615 ]] Implement HiDPI scaling in emscripten engine
2 parents a714e96 + a63f956 commit 1e56ae3

File tree

6 files changed

+112
-20
lines changed

6 files changed

+112
-20
lines changed

docs/notes/bugfix-21615.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Add HiDPI scaling support to HTML5 engine

engine/src/em-dc.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
3333
#include "globals.h"
3434
#include "graphics_util.h"
3535

36+
#include <emscripten.h>
37+
3638
/* ================================================================
3739
* Helper Functions
3840
* ================================================================ */
@@ -258,6 +260,7 @@ bool MCScreenDC::platform_getdisplays(bool p_effective, MCDisplay *&r_displays,
258260
return false;
259261

260262
t_display->viewport = t_display->workarea = MCEmscriptenGetDisplayRect();
263+
t_display->pixel_scale = emscripten_get_device_pixel_ratio();
261264

262265
r_displays = t_display;
263266
r_count = 1;

engine/src/em-event.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ mergeInto(LibraryManager.library, {
130130
tInput.addEventListener(type, handler);
131131
});
132132

133+
// Add listener for changes to device pixel ratio
134+
var matchQuery = `(resolution: ${window.devicePixelRatio}dppx)`;
135+
window.matchMedia(matchQuery).addListener(LiveCodeEvents._handleDevicePixelRatioChanged);
136+
133137
LiveCodeEvents._initialised = true;
134138
},
135139

@@ -892,6 +896,16 @@ mergeInto(LibraryManager.library, {
892896
// UI events
893897
// ----------------------------------------------------------------
894898

899+
_handleDevicePixelRatioChanged: function() {
900+
LiveCodeAsync.delay(function() {
901+
Module.ccall('MCEmscriptenHandleDevicePixelRatioChanged',
902+
'number', /* bool */
903+
[],
904+
[])
905+
});
906+
LiveCodeAsync.resume();
907+
},
908+
895909
// prevent context menu popup on right-click
896910
_handleContextMenu: function(e) {
897911
e.preventDefault()

engine/src/em-resolution.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,41 @@ for more details.
1616
You should have received a copy of the GNU General Public License
1717
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
1818

19+
#include "globdefs.h"
20+
#include "filedefs.h"
21+
#include "osspec.h"
22+
#include "typedefs.h"
23+
#include "parsedef.h"
24+
#include "objdefs.h"
25+
26+
#include "globals.h"
27+
1928
#include "em-util.h"
2029

2130
#include "sysdefs.h"
2231

2332
#include "graphics.h"
2433
#include "resolution.h"
34+
#include "stacklst.h"
2535

2636
#include <emscripten.h>
2737

2838
/* ================================================================
2939
* Resolution independence
3040
* ================================================================ */
3141

32-
/* FIXME use emscripten_get_device_pixel_ratio() */
42+
static MCGFloat s_emscripten_device_scale = 1.0;
3343

3444
void
3545
MCResPlatformInitPixelScaling()
3646
{
47+
s_emscripten_device_scale = emscripten_get_device_pixel_ratio();
3748
}
3849

3950
bool
4051
MCResPlatformSupportsPixelScaling()
4152
{
42-
return false;
53+
return true;
4354
}
4455

4556
bool
@@ -57,19 +68,31 @@ MCResPlatformCanSetPixelScale()
5768
MCGFloat
5869
MCResPlatformGetDefaultPixelScale()
5970
{
60-
MCEmscriptenNotImplemented();
61-
return NAN;
71+
return s_emscripten_device_scale;
6272
}
6373

6474
MCGFloat
6575
MCResPlatformGetUIDeviceScale()
6676
{
67-
MCEmscriptenNotImplemented();
68-
return NAN;
77+
return s_emscripten_device_scale;
6978
}
7079

7180
void
7281
MCResPlatformHandleScaleChange()
7382
{
74-
MCEmscriptenNotImplemented();
83+
// Global use-pixel-scaling value has been updated, so now we just need to reopen any open stack windows
84+
MCstacks->reopenallstackwindows();
85+
}
86+
87+
extern "C" MC_DLLEXPORT_DEF bool
88+
MCEmscriptenHandleDevicePixelRatioChanged()
89+
{
90+
MCGFloat t_scale = emscripten_get_device_pixel_ratio();
91+
if (t_scale != s_emscripten_device_scale)
92+
{
93+
s_emscripten_device_scale = t_scale;
94+
MCResPlatformHandleScaleChange();
95+
}
96+
97+
return true;
7598
}

engine/src/em-stack.cpp

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
3232
#include "graphics_util.h"
3333
#include "globals.h"
3434

35+
#include "region.h"
36+
3537
/* ================================================================
3638
* Stack initialisation
3739
* ================================================================ */
@@ -109,34 +111,83 @@ MCStack::release_window_buffer()
109111
* View management
110112
* ================================================================ */
111113

114+
static MCStackUpdateCallback s_updatewindow_callback = nullptr;
115+
static void *s_updatewindow_context = nullptr;
116+
112117
bool MCStack::view_platform_dirtyviewonresize() const
113118
{
114119
return true;
115120
}
116121

117-
void
118-
MCStack::view_platform_updatewindow(MCRegionRef p_dirty_region)
122+
void MCStack::view_platform_updatewindowwithcallback(MCRegionRef p_region, MCStackUpdateCallback p_callback, void *p_context)
123+
{
124+
s_updatewindow_callback = p_callback;
125+
s_updatewindow_context = p_context;
126+
127+
view_platform_updatewindow(p_region);
128+
129+
s_updatewindow_callback = nil;
130+
s_updatewindow_context = nil;
131+
}
132+
133+
void MCStack::view_platform_updatewindow(MCRegionRef p_dirty_region)
119134
{
120-
/* FIXME implement HiDPI support */
135+
MCRegionRef t_scaled_region;
136+
t_scaled_region = nil;
137+
138+
MCRegionRef t_screen_region;
139+
t_screen_region = nil;
140+
141+
MCGFloat t_scale;
142+
t_scale = MCResGetPixelScale();
143+
144+
if (t_scale != 1.0)
145+
{
146+
/* UNCHECKED */ MCRegionTransform(p_dirty_region, MCGAffineTransformMakeScale(t_scale, t_scale), t_scaled_region);
147+
t_screen_region = t_scaled_region;
148+
}
149+
else
150+
t_screen_region = p_dirty_region;
151+
152+
view_device_updatewindow(t_screen_region);
153+
154+
if (t_scaled_region != nil)
155+
MCRegionDestroy(t_scaled_region);
156+
}
121157

158+
void MCStack::view_device_updatewindow(MCRegionRef p_region)
159+
{
122160
/* dirtyrect() calls that occur prior to configure() being called
123161
* for the first time will result in an update region being too
124162
* big. Restrict to a valid region. */
125163

126164
uint32_t t_window = reinterpret_cast<uint32_t>(window);
127165

128-
MCGRegionRef t_region = MCGRegionRef(p_dirty_region);
129-
MCRectangle t_valid = MCEmscriptenGetWindowRect(t_window);
130-
t_valid.x = t_valid.y = 0;
166+
MCRectangle t_window_rect = MCEmscriptenGetWindowRect(t_window);
167+
MCRectangle t_canvas_rect = MCRectangleGetScaledCeilingRect(t_window_rect, MCResGetPixelScale());
168+
t_canvas_rect.x = t_canvas_rect.y = 0;
131169

132-
MCGRegionIntersectRect(t_region, MCRectangleToMCGIntegerRectangle(t_valid));
170+
MCGRegionRef t_region = MCGRegionRef(p_region);
133171

134-
MCGIntegerRectangle t_rect = MCGRegionGetBounds(t_region);
172+
MCGRegionIntersectRect(t_region, MCRectangleToMCGIntegerRectangle(t_canvas_rect));
135173

136-
MCEmscriptenSyncCanvasSize(t_window, t_valid.width, t_valid.height);
137-
138-
MCHtmlCanvasStackSurface t_surface(t_window, t_rect);
139-
view_surface_redrawwindow(&t_surface, t_region);
174+
MCGIntegerRectangle t_rect = MCGRegionGetBounds(t_region);
175+
MCEmscriptenSyncCanvasSize(t_window, t_canvas_rect.width, t_canvas_rect.height);
176+
177+
// IM-2014-01-30: [[ HiDPI ]] Ensure stack backing scale is set
178+
view_setbackingscale(MCResGetPixelScale());
179+
180+
MCHtmlCanvasStackSurface t_surface(t_window, MCGRegionGetBounds(t_region));
181+
if (t_surface.Lock())
182+
{
183+
// IM-2014-01-31: [[ HiDPI ]] If a callback is given then use it to render to the surface
184+
if (s_updatewindow_callback != nil)
185+
s_updatewindow_callback(&t_surface, (MCRegionRef)t_region, s_updatewindow_context);
186+
else
187+
view_surface_redrawwindow(&t_surface, t_region);
188+
189+
t_surface.Unlock();
190+
}
140191
}
141192

142193
MCRectangle

engine/src/stack.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ class MCStack : public MCObject, public MCMixinObjectHandle<MCStack>
10291029
uint32_t p_minwidth, uint32_t p_minheight,
10301030
uint32_t p_maxwidth, uint32_t p_maxheight);
10311031
void view_device_updatewindow(MCRegionRef p_region);
1032-
#elif defined(_MOBILE)
1032+
#elif defined(_MOBILE) || defined(__EMSCRIPTEN__)
10331033

10341034
// IM-2014-01-30: [[ HiDPI ]] platform-specific view device methods
10351035

0 commit comments

Comments
 (0)