Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/test/browser/test_glfw3_css_scaling.c
4150 views
1
/*
2
* Copyright 2024 The Emscripten Authors. All rights reserved.
3
* Emscripten is available under two separate licenses, the MIT license and the
4
* University of Illinois/NCSA Open Source License. Both these licenses can be
5
* found in the LICENSE file.
6
*/
7
8
#include <GLFW/glfw3.h>
9
#include <assert.h>
10
#include <emscripten/html5.h>
11
#include <stdio.h>
12
13
/*
14
* History:
15
* - This test was added after the issue #22847 was reported (November 2024).
16
* - For historical reasons, the JavaScript GLFW implementation includes a feature: the ability to scale the canvas via CSS.
17
* - Note that this feature is not part of GLFW as GLFW does not offer any API to scale the window.
18
* - Being undocumented/untested, this feature was accidentally removed when HiDPI support was added (in 3.1.51 / December 2023).
19
* - This test was added to document this feature and ensure proper behavior.
20
*
21
* What does this feature do?
22
* - if there is a CSS rule that specifies the size of the canvas (ex: `#canvas { width: 100%;}`), then the canvas
23
* will be scaled to match this value. Note that from a GLFW point of view, the size of the window remains what
24
* gets specified in `glfwCreateWindow` and/or `glfwSetWindowSize`
25
* - only global CSS rules apply, as setting a CSS rule on the canvas itself is removed (ex: `<canvas style="width:100%;">` is ignored)
26
*
27
* In HiDPI mode, (`glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE)`), this feature cannot work and as a result is disabled (because the canvas
28
* is sized using `devicePixelRatio` as the factor and CSS is used to scale it at the desired size).
29
*/
30
31
/**
32
* As explained above, this function adds a global CSS rule instead of setting the CSS style directly on the canvas
33
* because it gets ignored otherwise. */
34
EM_JS(void, addCSSScalingRule, (), {
35
const style = document.createElement('style');
36
style.appendChild(document.createTextNode("#canvas { width: 700px; height: 500px; }"));
37
document.head.appendChild(style);
38
})
39
40
/**
41
* Since it is unclear in which browser/resolution this test will run we compute the actual ratio used by the test.
42
* This has the neat effect that the test can be run manually on a HiDPI screen.
43
*/
44
EM_JS(double, getDevicePixelRatio, (), {return (typeof devicePixelRatio == 'number' && devicePixelRatio) || 1.0;})
45
46
/**
47
* Checks window size and framebuffer size according to ratio */
48
static void checkWindowSize(GLFWwindow *window, int expectedWidth, int expectedHeight, float ratio) {
49
// first check the window size
50
int w, h;
51
glfwGetWindowSize(window, &w, &h);
52
printf("windowSize => %d == %d && %d == %d\n", w, expectedWidth, h, expectedHeight);
53
assert(w == expectedWidth && h == expectedHeight);
54
55
// second check the frame buffer size
56
int fbw, fbh;
57
glfwGetFramebufferSize(window, &fbw, &fbh);
58
printf("framebufferSize => %d == %d && %d == %d\n", fbw, (int) (expectedWidth * ratio), fbh, (int) (expectedHeight * ratio));
59
assert(fbw == (int) (expectedWidth * ratio) && fbh == (int) (expectedHeight * ratio));
60
}
61
62
// Create a window without HiDPI support and without CSS rule => expected sizes to match
63
void use_case_1() {
64
printf("Use case #1\n");
65
GLFWwindow* window = glfwCreateWindow(640, 480, "test_glfw3_css_scaling.c", NULL, NULL);
66
assert(window);
67
checkWindowSize(window, 640, 480, 1.0);
68
double w, h;
69
emscripten_get_element_css_size("#canvas", &w, &h);
70
printf("CSS Size=%.0fx%.0f\n", w, h);
71
assert(w == 640 && h == 480);
72
glfwDestroyWindow(window);
73
}
74
75
// Create a window without HiDPI support, and with CSS rule =>
76
// the window size should match the creation size, but the CSS size should match the rule.
77
void use_case_2() {
78
printf("Use case #2\n");
79
GLFWwindow* window = glfwCreateWindow(640, 480, "test_glfw3_css_scaling.c", NULL, NULL);
80
assert(window);
81
checkWindowSize(window, 640, 480, 1.0);
82
double w, h;
83
emscripten_get_element_css_size("#canvas", &w, &h);
84
printf("CSS Size=%.0fx%.0f\n", w, h);
85
assert(w == 700 && h == 500); // Rule is "#canvas { width: 700px; height: 500px; }"
86
glfwDestroyWindow(window);
87
}
88
89
// Create a window with HiDPI support, and with CSS rule =>
90
// the window size and framebuffer size should match the creation size (CSS rule is ignored)
91
void use_case_3() {
92
printf("Use case #3\n");
93
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
94
GLFWwindow* window = glfwCreateWindow(640, 480, "test_glfw3_css_scaling.c", NULL, NULL);
95
assert(window);
96
double dpr = getDevicePixelRatio();
97
printf("devicePixelRatio=%.0f\n", dpr);
98
checkWindowSize(window, 640, 480, dpr);
99
double w, h;
100
emscripten_get_element_css_size("#canvas", &w, &h);
101
printf("CSS Size=%.0fx%.0f\n", w, h);
102
assert(w == 640 && h == 480);
103
glfwDestroyWindow(window);
104
}
105
106
int main() {
107
assert(glfwInit() == GLFW_TRUE);
108
109
use_case_1();
110
111
// Add CSS rule for the following use cases
112
addCSSScalingRule();
113
114
use_case_2();
115
use_case_3();
116
117
printf("All tests complete\n");
118
glfwTerminate();
119
return 0;
120
}
121
122