Commits:
-
09a1810a
by Emilio Cobos Álvarez at 2024-12-09T16:52:44+00:00
Bug 1909625 - Ignore CSS zoom and text zoom for canvas. r=gfx-reviewers,lsalzman
The spec doesn't mention anything about applying them, and other
browsers don't, so let's just be consistent...
Differential Revision: https://phabricator.services.mozilla.com/D221709
-
314fdd34
by Emilio Cobos Álvarez at 2024-12-09T16:52:45+00:00
Bug 1918454 - Prevent divide by zero when inverting effective zoom. r=firefox-style-system-reviewers,layout-reviewers,boris
See comment.
Differential Revision: https://phabricator.services.mozilla.com/D222090
9 changed files:
Changes:
dom/canvas/CanvasRenderingContext2D.cpp
| ... |
... |
@@ -6,6 +6,7 @@ |
|
6
|
6
|
#include "CanvasRenderingContext2D.h"
|
|
7
|
7
|
|
|
8
|
8
|
#include "mozilla/gfx/Helpers.h"
|
|
|
9
|
+#include "nsCSSValue.h"
|
|
9
|
10
|
#include "nsXULElement.h"
|
|
10
|
11
|
|
|
11
|
12
|
#include "nsMathUtils.h"
|
| ... |
... |
@@ -2585,14 +2586,8 @@ static already_AddRefed<StyleLockedDeclarationBlock> CreateDeclarationForServo( |
|
2585
|
2586
|
return nullptr;
|
|
2586
|
2587
|
}
|
|
2587
|
2588
|
|
|
2588
|
|
- // From canvas spec, force to set line-height property to 'normal' font
|
|
2589
|
|
- // property.
|
|
2590
|
2589
|
if (aProperty == eCSSProperty_font) {
|
|
2591
|
|
- const nsCString normalString = "normal"_ns;
|
|
2592
|
|
- Servo_DeclarationBlock_SetPropertyById(
|
|
2593
|
|
- servoDeclarations, eCSSProperty_line_height, &normalString, false,
|
|
2594
|
|
- env.mUrlExtraData, StyleParsingMode::DEFAULT, env.mCompatMode,
|
|
2595
|
|
- env.mLoader, env.mRuleType, {});
|
|
|
2590
|
+ Servo_DeclarationBlock_SanitizeForCanvas(servoDeclarations);
|
|
2596
|
2591
|
}
|
|
2597
|
2592
|
|
|
2598
|
2593
|
return servoDeclarations.forget();
|
| ... |
... |
@@ -2657,12 +2652,9 @@ static already_AddRefed<const ComputedStyle> GetFontStyleForServo( |
|
2657
|
2652
|
// The font-size component must be converted to CSS px for reserialization,
|
|
2658
|
2653
|
// so we update the declarations with the value from the computed style.
|
|
2659
|
2654
|
if (!sc->StyleFont()->mFont.family.is_system_font) {
|
|
2660
|
|
- nsAutoCString computedFontSize;
|
|
2661
|
|
- sc->GetComputedPropertyValue(eCSSProperty_font_size, computedFontSize);
|
|
2662
|
|
- Servo_DeclarationBlock_SetPropertyById(
|
|
2663
|
|
- declarations, eCSSProperty_font_size, &computedFontSize, false, nullptr,
|
|
2664
|
|
- StyleParsingMode::DEFAULT, eCompatibility_FullStandards, nullptr,
|
|
2665
|
|
- StyleCssRuleType::Style, {});
|
|
|
2655
|
+ float px = sc->StyleFont()->mFont.size.ToCSSPixels();
|
|
|
2656
|
+ Servo_DeclarationBlock_SetLengthValue(declarations, eCSSProperty_font_size,
|
|
|
2657
|
+ px, eCSSUnit_Pixel);
|
|
2666
|
2658
|
}
|
|
2667
|
2659
|
|
|
2668
|
2660
|
// The font getter is required to be reserialized based on what we
|
servo/components/style/properties/cascade.rs
| ... |
... |
@@ -1247,7 +1247,7 @@ impl<'b> Cascade<'b> { |
|
1247
|
1247
|
);
|
|
1248
|
1248
|
debug_assert!(
|
|
1249
|
1249
|
!text_scale.text_zoom_enabled(),
|
|
1250
|
|
- "We only ever disable text zoom (in svg:text), never enable it"
|
|
|
1250
|
+ "We only ever disable text zoom never enable it"
|
|
1251
|
1251
|
);
|
|
1252
|
1252
|
let device = builder.device;
|
|
1253
|
1253
|
builder.mutate_font().unzoom_fonts(device);
|
| ... |
... |
@@ -1257,9 +1257,8 @@ impl<'b> Cascade<'b> { |
|
1257
|
1257
|
debug_assert!(self.seen.contains(LonghandId::Zoom));
|
|
1258
|
1258
|
// NOTE(emilio): Intentionally not using the effective zoom here, since all the inherited
|
|
1259
|
1259
|
// zooms are already applied.
|
|
1260
|
|
- let zoom = builder.get_box().clone_zoom();
|
|
1261
|
1260
|
let old_size = builder.get_font().clone_font_size();
|
|
1262
|
|
- let new_size = old_size.zoom(zoom);
|
|
|
1261
|
+ let new_size = old_size.zoom(builder.resolved_specified_zoom());
|
|
1263
|
1262
|
if old_size == new_size {
|
|
1264
|
1263
|
return;
|
|
1265
|
1264
|
}
|
servo/components/style/properties/properties.mako.rs
| ... |
... |
@@ -2711,6 +2711,19 @@ impl<'a> StyleBuilder<'a> { |
|
2711
|
2711
|
self.get_box().clone_zoom()
|
|
2712
|
2712
|
}
|
|
2713
|
2713
|
|
|
|
2714
|
+ /// The zoom we need to apply for this element, without including ancestor effective zooms.
|
|
|
2715
|
+ pub fn resolved_specified_zoom(&self) -> computed::Zoom {
|
|
|
2716
|
+ let zoom = self.specified_zoom();
|
|
|
2717
|
+ if zoom.is_document() {
|
|
|
2718
|
+ // If our inherited effective zoom has derived to zero, there's not much we can do.
|
|
|
2719
|
+ // This value is not exposed to content anyways (it's used for scrollbars and to avoid
|
|
|
2720
|
+ // zoom affecting canvas).
|
|
|
2721
|
+ self.inherited_effective_zoom().inverted().unwrap_or(computed::Zoom::ONE)
|
|
|
2722
|
+ } else {
|
|
|
2723
|
+ zoom
|
|
|
2724
|
+ }
|
|
|
2725
|
+ }
|
|
|
2726
|
+
|
|
2714
|
2727
|
/// Inherited zoom.
|
|
2715
|
2728
|
pub fn inherited_effective_zoom(&self) -> computed::Zoom {
|
|
2716
|
2729
|
self.inherited_style.effective_zoom
|
| ... |
... |
@@ -2747,7 +2760,7 @@ impl<'a> StyleBuilder<'a> { |
|
2747
|
2760
|
let lh = device.calc_line_height(&font, writing_mode, None);
|
|
2748
|
2761
|
if line_height_base == LineHeightBase::InheritedStyle {
|
|
2749
|
2762
|
// Apply our own zoom if our style source is the parent style.
|
|
2750
|
|
- computed::NonNegativeLength::new(self.get_box().clone_zoom().zoom(lh.px()))
|
|
|
2763
|
+ computed::NonNegativeLength::new(self.resolved_specified_zoom().zoom(lh.px()))
|
|
2751
|
2764
|
} else {
|
|
2752
|
2765
|
lh
|
|
2753
|
2766
|
}
|
servo/components/style/values/computed/box.rs
| ... |
... |
@@ -357,6 +357,21 @@ impl Zoom { |
|
357
|
357
|
self == Self::ONE
|
|
358
|
358
|
}
|
|
359
|
359
|
|
|
|
360
|
+ /// Returns whether we're the `document` keyword.
|
|
|
361
|
+ #[inline]
|
|
|
362
|
+ pub fn is_document(self) -> bool {
|
|
|
363
|
+ self == Self::DOCUMENT
|
|
|
364
|
+ }
|
|
|
365
|
+
|
|
|
366
|
+ /// Returns the inverse of our value.
|
|
|
367
|
+ #[inline]
|
|
|
368
|
+ pub fn inverted(&self) -> Option<Self> {
|
|
|
369
|
+ if self.0.value == 0 {
|
|
|
370
|
+ return None;
|
|
|
371
|
+ }
|
|
|
372
|
+ Some(Self(Self::ONE.0 / self.0))
|
|
|
373
|
+ }
|
|
|
374
|
+
|
|
360
|
375
|
/// Returns the value as a float.
|
|
361
|
376
|
#[inline]
|
|
362
|
377
|
pub fn value(&self) -> f32 {
|
servo/components/style/values/specified/length.rs
| ... |
... |
@@ -103,7 +103,7 @@ impl FontBaseSize { |
|
103
|
103
|
Self::InheritedStyle => {
|
|
104
|
104
|
// If we're using the size from our inherited style, we still need to apply our
|
|
105
|
105
|
// own zoom.
|
|
106
|
|
- let zoom = style.get_box().clone_zoom();
|
|
|
106
|
+ let zoom = style.resolved_specified_zoom();
|
|
107
|
107
|
style.get_parent_font().clone_font_size().zoom(zoom)
|
|
108
|
108
|
},
|
|
109
|
109
|
}
|
servo/ports/geckolib/glue.rs
| ... |
... |
@@ -4972,6 +4972,21 @@ fn set_property( |
|
4972
|
4972
|
)
|
|
4973
|
4973
|
}
|
|
4974
|
4974
|
|
|
|
4975
|
+#[no_mangle]
|
|
|
4976
|
+pub unsafe extern "C" fn Servo_DeclarationBlock_SanitizeForCanvas(
|
|
|
4977
|
+ declarations: &LockedDeclarationBlock,
|
|
|
4978
|
+) {
|
|
|
4979
|
+ use style::properties::PropertyDeclaration;
|
|
|
4980
|
+ use style::values::specified::{LineHeight, XTextScale, Zoom};
|
|
|
4981
|
+ // From canvas spec, force to set line-height property to 'normal' font property.
|
|
|
4982
|
+ // Also, for compat, disable text scaling and CSS zoom.
|
|
|
4983
|
+ write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
|
|
4984
|
+ decls.push(PropertyDeclaration::LineHeight(LineHeight::Normal), Importance::Normal);
|
|
|
4985
|
+ decls.push(PropertyDeclaration::Zoom(Zoom::Document), Importance::Normal);
|
|
|
4986
|
+ decls.push(PropertyDeclaration::XTextScale(XTextScale::None), Importance::Normal);
|
|
|
4987
|
+ });
|
|
|
4988
|
+}
|
|
|
4989
|
+
|
|
4975
|
4990
|
#[no_mangle]
|
|
4976
|
4991
|
pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty(
|
|
4977
|
4992
|
declarations: &LockedDeclarationBlock,
|
testing/web-platform/tests/css/css-viewport/zoom/canvas-ref.html
|
|
1
|
+<!DOCTYPE html>
|
|
|
2
|
+<style>
|
|
|
3
|
+canvas {
|
|
|
4
|
+ width: 600px;
|
|
|
5
|
+ height: 200px;
|
|
|
6
|
+}
|
|
|
7
|
+</style>
|
|
|
8
|
+<script>
|
|
|
9
|
+document.addEventListener("DOMContentLoaded", () => {
|
|
|
10
|
+ const ctx = document.getElementById("canvas").getContext("2d");
|
|
|
11
|
+ ctx.font = "48px serif";
|
|
|
12
|
+ ctx.fillText(ctx.font, 10, 50);
|
|
|
13
|
+});
|
|
|
14
|
+</script>
|
|
|
15
|
+<canvas id="canvas" width="300" height="100"></canvas> |
testing/web-platform/tests/css/css-viewport/zoom/canvas.html
|
|
1
|
+<!DOCTYPE html>
|
|
|
2
|
+<link rel="help" href="">"https://bugzilla.mozilla.org/show_bug.cgi?id=1909625">
|
|
|
3
|
+<link rel="help" href="">"https://html.spec.whatwg.org/#dom-context-2d-font">
|
|
|
4
|
+<link rel="author" href="">"mailto:emilio@xxxxxxxxx" title="Emilio Cobos Álvarez">
|
|
|
5
|
+<link rel="author" href="">"https://mozilla.org" title="Mozilla">
|
|
|
6
|
+<link rel="match" href="">"canvas-ref.html">
|
|
|
7
|
+<title>zoom is ignored for canvas</title>
|
|
|
8
|
+<style>
|
|
|
9
|
+canvas {
|
|
|
10
|
+ zoom: 2;
|
|
|
11
|
+}
|
|
|
12
|
+</style>
|
|
|
13
|
+<script>
|
|
|
14
|
+document.addEventListener("DOMContentLoaded", () => {
|
|
|
15
|
+ const ctx = document.getElementById("canvas").getContext("2d");
|
|
|
16
|
+ ctx.font = "48px serif";
|
|
|
17
|
+ ctx.fillText(ctx.font, 10, 50);
|
|
|
18
|
+});
|
|
|
19
|
+</script>
|
|
|
20
|
+<canvas id="canvas" width="300" height="100"></canvas> |
testing/web-platform/tests/css/css-viewport/zoom/textarea-very-small-zoom-crash.html
|
|
1
|
+<style>
|
|
|
2
|
+*:nth-of-type(1) {
|
|
|
3
|
+ zoom: 5%;
|
|
|
4
|
+}
|
|
|
5
|
+</style>
|
|
|
6
|
+<textarea> |
|