forked from firka/flutter
[web] Move styling from FlutterViewEmbedder to StyleManager (flutter/engine#47489)
- Move default style values from `FlutterViewEmbedder` to `StyleManager`. - Move DOM tag names from `FlutterViewEmbedder` to `DomManager`. - Deduplicate style sheet creation code and put it in `StyleManager`. Part of Part of https://github.com/flutter/flutter/issues/134443
This commit is contained in:
@@ -3838,7 +3838,6 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/font_fallback_data.dart + ../
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/font_fallbacks.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/fonts.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/frame_reference.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/global_styles.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/html/backdrop_filter.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/html/bitmap_canvas.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/html/canvas.dart + ../../../flutter/LICENSE
|
||||
@@ -4008,6 +4007,7 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/embedding_strat
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/embedding_strategy.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/full_page_embedding_strategy.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/style_manager.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/window.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/text.dart + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/lib/web_ui/lib/tile_mode.dart + ../../../flutter/LICENSE
|
||||
@@ -6600,7 +6600,6 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/font_fallback_data.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/font_fallbacks.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/fonts.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/frame_reference.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/global_styles.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/html/backdrop_filter.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/html/bitmap_canvas.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/html/canvas.dart
|
||||
@@ -6770,6 +6769,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/embedding_strateg
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/embedding_strategy.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/full_page_embedding_strategy.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/hot_restart_cache_handler.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/view_embedder/style_manager.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/window.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/text.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/tile_mode.dart
|
||||
|
||||
@@ -64,7 +64,6 @@ export 'engine/font_fallback_data.dart';
|
||||
export 'engine/font_fallbacks.dart';
|
||||
export 'engine/fonts.dart';
|
||||
export 'engine/frame_reference.dart';
|
||||
export 'engine/global_styles.dart';
|
||||
export 'engine/html/backdrop_filter.dart';
|
||||
export 'engine/html/bitmap_canvas.dart';
|
||||
export 'engine/html/canvas.dart';
|
||||
@@ -192,4 +191,5 @@ export 'engine/view_embedder/embedding_strategy/custom_element_embedding_strateg
|
||||
export 'engine/view_embedder/embedding_strategy/embedding_strategy.dart';
|
||||
export 'engine/view_embedder/embedding_strategy/full_page_embedding_strategy.dart';
|
||||
export 'engine/view_embedder/hot_restart_cache_handler.dart';
|
||||
export 'engine/view_embedder/style_manager.dart';
|
||||
export 'engine/window.dart';
|
||||
|
||||
@@ -9,14 +9,15 @@ import '../engine.dart' show buildMode, renderer, window;
|
||||
import 'browser_detection.dart';
|
||||
import 'configuration.dart';
|
||||
import 'dom.dart';
|
||||
import 'global_styles.dart';
|
||||
import 'keyboard_binding.dart';
|
||||
import 'platform_dispatcher.dart';
|
||||
import 'pointer_binding.dart';
|
||||
import 'semantics.dart';
|
||||
import 'text_editing/text_editing.dart';
|
||||
import 'view_embedder/dimensions_provider/dimensions_provider.dart';
|
||||
import 'view_embedder/dom_manager.dart';
|
||||
import 'view_embedder/embedding_strategy/embedding_strategy.dart';
|
||||
import 'view_embedder/style_manager.dart';
|
||||
|
||||
/// Controls the placement and lifecycle of a Flutter view on the web page.
|
||||
///
|
||||
@@ -62,12 +63,6 @@ class FlutterViewEmbedder {
|
||||
/// Abstracts all the DOM manipulations required to embed a Flutter app in an user-supplied `hostElement`.
|
||||
final EmbeddingStrategy _embeddingStrategy;
|
||||
|
||||
// The tag name for the Flutter View, which hosts the app.
|
||||
static const String flutterViewTagName = 'flutter-view';
|
||||
|
||||
// The tag name for the glass-pane.
|
||||
static const String glassPaneTagName = 'flt-glass-pane';
|
||||
|
||||
/// The element that contains the [sceneElement].
|
||||
///
|
||||
/// This element is created and inserted in the HTML DOM once. It is never
|
||||
@@ -136,13 +131,6 @@ class FlutterViewEmbedder {
|
||||
DomElement get announcementsHostDEPRECATED => _announcementsHost;
|
||||
late DomElement _announcementsHost;
|
||||
|
||||
static const String defaultFontStyle = 'normal';
|
||||
static const String defaultFontWeight = 'normal';
|
||||
static const double defaultFontSize = 14;
|
||||
static const String defaultFontFamily = 'sans-serif';
|
||||
static const String defaultCssFont =
|
||||
'$defaultFontStyle $defaultFontWeight ${defaultFontSize}px $defaultFontFamily';
|
||||
|
||||
void reset() {
|
||||
// How was the current renderer selected?
|
||||
const String rendererSelection = FlutterConfiguration.flutterWebAutoDetect
|
||||
@@ -161,8 +149,8 @@ class FlutterViewEmbedder {
|
||||
);
|
||||
|
||||
// Create and inject the [_glassPaneElement].
|
||||
_flutterViewElement = domDocument.createElement(flutterViewTagName);
|
||||
_glassPaneElement = domDocument.createElement(glassPaneTagName);
|
||||
_flutterViewElement = domDocument.createElement(DomManager.flutterViewTagName);
|
||||
_glassPaneElement = domDocument.createElement(DomManager.glassPaneTagName);
|
||||
|
||||
// This must be attached to the DOM now, so the engine can create a host
|
||||
// node (ShadowDOM or a fallback) next.
|
||||
@@ -186,35 +174,35 @@ class FlutterViewEmbedder {
|
||||
});
|
||||
_glassPaneShadow = shadowRoot;
|
||||
|
||||
final DomHTMLStyleElement shadowRootStyleElement = createDomHTMLStyleElement(configuration.nonce);
|
||||
shadowRootStyleElement.id = 'flt-internals-stylesheet';
|
||||
// The shadowRootStyleElement must be appended to the DOM, or its `sheet` will be null later.
|
||||
shadowRoot.appendChild(shadowRootStyleElement);
|
||||
applyGlobalCssRulesToSheet(
|
||||
shadowRootStyleElement,
|
||||
defaultCssFont: defaultCssFont,
|
||||
StyleManager.attachGlobalStyles(
|
||||
node: shadowRoot,
|
||||
styleId: 'flt-internals-stylesheet',
|
||||
styleNonce: configuration.nonce,
|
||||
cssSelectorPrefix: '',
|
||||
);
|
||||
|
||||
_textEditingHostNode =
|
||||
createTextEditingHostNode(_flutterViewElement, defaultCssFont, configuration.nonce);
|
||||
createTextEditingHostNode(_flutterViewElement, configuration.nonce);
|
||||
|
||||
// Don't allow the scene to receive pointer events.
|
||||
_sceneHostElement = domDocument.createElement('flt-scene-host')
|
||||
..style.pointerEvents = 'none';
|
||||
_sceneHostElement = domDocument.createElement(DomManager.sceneHostTagName);
|
||||
StyleManager.styleSceneHost(
|
||||
_sceneHostElement,
|
||||
debugShowSemanticsNodes: configuration.debugShowSemanticsNodes,
|
||||
);
|
||||
|
||||
renderer.reset(this);
|
||||
|
||||
_semanticsHostElement = domDocument.createElement('flt-semantics-host');
|
||||
_semanticsHostElement.style
|
||||
..position = 'absolute'
|
||||
..transformOrigin = '0 0 0';
|
||||
updateSemanticsScreenProperties();
|
||||
_semanticsHostElement = domDocument.createElement(DomManager.semanticsHostTagName);
|
||||
StyleManager.styleSemanticsHost(
|
||||
_semanticsHostElement,
|
||||
window.devicePixelRatio,
|
||||
);
|
||||
|
||||
final DomElement accessibilityPlaceholder = EngineSemanticsOwner
|
||||
.instance.semanticsHelper
|
||||
.prepareAccessibilityPlaceholder();
|
||||
|
||||
_announcementsHost = createDomElement('flt-announcement-host');
|
||||
_announcementsHost = createDomElement(DomManager.announcementsHostTagName);
|
||||
|
||||
shadowRoot.append(accessibilityPlaceholder);
|
||||
shadowRoot.append(_sceneHostElement);
|
||||
@@ -232,12 +220,6 @@ class FlutterViewEmbedder {
|
||||
// with the platform view, the platform view will be reachable.
|
||||
_flutterViewElement.appendChild(_semanticsHostElement);
|
||||
|
||||
// When debugging semantics, make the scene semi-transparent so that the
|
||||
// semantics tree is more prominent.
|
||||
if (configuration.debugShowSemanticsNodes) {
|
||||
_sceneHostElement.style.opacity = '0.3';
|
||||
}
|
||||
|
||||
KeyboardBinding.initInstance();
|
||||
PointerBinding.initInstance(
|
||||
_flutterViewElement,
|
||||
@@ -247,14 +229,6 @@ class FlutterViewEmbedder {
|
||||
window.onResize.listen(_metricsDidChange);
|
||||
}
|
||||
|
||||
/// The framework specifies semantics in physical pixels, but CSS uses
|
||||
/// logical pixels. To compensate, an inverse scale is injected at the root
|
||||
/// level.
|
||||
void updateSemanticsScreenProperties() {
|
||||
_semanticsHostElement.style
|
||||
.setProperty('transform', 'scale(${1 / window.devicePixelRatio})');
|
||||
}
|
||||
|
||||
/// Called immediately after browser window metrics change.
|
||||
///
|
||||
/// When there is a text editing going on in mobile devices, do not change
|
||||
@@ -265,7 +239,10 @@ class FlutterViewEmbedder {
|
||||
/// Note: always check for rotations for a mobile device. Update the physical
|
||||
/// size if the change is caused by a rotation.
|
||||
void _metricsDidChange(ui.Size? newSize) {
|
||||
updateSemanticsScreenProperties();
|
||||
StyleManager.scaleSemanticsHost(
|
||||
_semanticsHostElement,
|
||||
window.devicePixelRatio,
|
||||
);
|
||||
// TODO(dit): Do not computePhysicalSize twice, https://github.com/flutter/flutter/issues/117036
|
||||
if (isMobile && !window.isRotation() && textEditing.isEditing) {
|
||||
window.computeOnScreenKeyboardInsets(true);
|
||||
@@ -338,19 +315,16 @@ FlutterViewEmbedder ensureFlutterViewEmbedderInitialized() =>
|
||||
|
||||
/// Creates a node to host text editing elements and applies a stylesheet
|
||||
/// to Flutter nodes that exist outside of the shadowDOM.
|
||||
DomElement createTextEditingHostNode(DomElement root, String defaultFont, String? nonce) {
|
||||
final DomElement domElement =
|
||||
domDocument.createElement('flt-text-editing-host');
|
||||
final DomHTMLStyleElement styleElement = createDomHTMLStyleElement(nonce);
|
||||
|
||||
styleElement.id = 'flt-text-editing-stylesheet';
|
||||
root.appendChild(styleElement);
|
||||
applyGlobalCssRulesToSheet(
|
||||
styleElement,
|
||||
cssSelectorPrefix: FlutterViewEmbedder.flutterViewTagName,
|
||||
defaultCssFont: defaultFont,
|
||||
DomElement createTextEditingHostNode(DomElement root, String? nonce) {
|
||||
StyleManager.attachGlobalStyles(
|
||||
node: root,
|
||||
styleId: 'flt-text-editing-stylesheet',
|
||||
styleNonce: nonce,
|
||||
cssSelectorPrefix: DomManager.flutterViewTagName,
|
||||
);
|
||||
|
||||
final DomElement domElement =
|
||||
domDocument.createElement('flt-text-editing-host');
|
||||
root.appendChild(domElement);
|
||||
|
||||
return domElement;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
import 'package:ui/ui.dart' as ui;
|
||||
|
||||
import '../dom.dart';
|
||||
import '../embedder.dart';
|
||||
import '../html/bitmap_canvas.dart';
|
||||
import '../profiler.dart';
|
||||
import '../view_embedder/style_manager.dart';
|
||||
import 'layout_fragmenter.dart';
|
||||
import 'layout_service.dart';
|
||||
import 'paint_service.dart';
|
||||
@@ -539,7 +539,7 @@ class RootStyleNode extends StyleNode {
|
||||
ui.TextBaseline? get _textBaseline => null;
|
||||
|
||||
@override
|
||||
String get _fontFamily => paragraphStyle.fontFamily ?? FlutterViewEmbedder.defaultFontFamily;
|
||||
String get _fontFamily => paragraphStyle.fontFamily ?? StyleManager.defaultFontFamily;
|
||||
|
||||
@override
|
||||
List<String>? get _fontFamilyFallback => null;
|
||||
@@ -551,7 +551,7 @@ class RootStyleNode extends StyleNode {
|
||||
List<ui.FontVariation>? get _fontVariations => null;
|
||||
|
||||
@override
|
||||
double get _fontSize => paragraphStyle.fontSize ?? FlutterViewEmbedder.defaultFontSize;
|
||||
double get _fontSize => paragraphStyle.fontSize ?? StyleManager.defaultFontSize;
|
||||
|
||||
@override
|
||||
double? get _letterSpacing => null;
|
||||
|
||||
@@ -9,8 +9,8 @@ import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
|
||||
|
||||
import '../browser_detection.dart';
|
||||
import '../dom.dart';
|
||||
import '../embedder.dart';
|
||||
import '../util.dart';
|
||||
import '../view_embedder/style_manager.dart';
|
||||
import 'canvas_paragraph.dart';
|
||||
import 'layout_fragmenter.dart';
|
||||
import 'ruler.dart';
|
||||
@@ -469,7 +469,7 @@ class EngineTextStyle implements ui.TextStyle {
|
||||
|
||||
static final List<String> _testFonts = <String>['FlutterTest', 'Ahem'];
|
||||
String get effectiveFontFamily {
|
||||
final String fontFamily = this.fontFamily.isEmpty ? FlutterViewEmbedder.defaultFontFamily : this.fontFamily;
|
||||
final String fontFamily = this.fontFamily.isEmpty ? StyleManager.defaultFontFamily : this.fontFamily;
|
||||
// In the flutter tester environment, we use predictable-size test fonts.
|
||||
// This makes widget tests predictable and less flaky.
|
||||
String result = fontFamily;
|
||||
@@ -501,7 +501,7 @@ class EngineTextStyle implements ui.TextStyle {
|
||||
TextHeightStyle _createHeightStyle() {
|
||||
return TextHeightStyle(
|
||||
fontFamily: effectiveFontFamily,
|
||||
fontSize: fontSize ?? FlutterViewEmbedder.defaultFontSize,
|
||||
fontSize: fontSize ?? StyleManager.defaultFontSize,
|
||||
height: height,
|
||||
// TODO(mdebbar): Pass the actual value when font features become supported
|
||||
// https://github.com/flutter/flutter/issues/64595
|
||||
@@ -738,12 +738,18 @@ class ParagraphPlaceholder {
|
||||
final ui.TextBaseline baseline;
|
||||
}
|
||||
|
||||
/// Converts [fontWeight] to its CSS equivalent value.
|
||||
String? fontWeightToCss(ui.FontWeight? fontWeight) {
|
||||
if (fontWeight == null) {
|
||||
return null;
|
||||
extension FontStyleExtension on ui.FontStyle {
|
||||
/// Converts a [ui.FontStyle] value to its CSS equivalent.
|
||||
String toCssString() {
|
||||
return this == ui.FontStyle.normal ? 'normal' : 'italic';
|
||||
}
|
||||
}
|
||||
|
||||
extension FontWeightExtension on ui.FontWeight {
|
||||
/// Converts a [ui.FontWeight] value to its CSS equivalent.
|
||||
String toCssString() {
|
||||
return fontWeightIndexToCss(fontWeightIndex: index);
|
||||
}
|
||||
return fontWeightIndexToCss(fontWeightIndex: fontWeight.index);
|
||||
}
|
||||
|
||||
String fontWeightIndexToCss({int fontWeightIndex = 3}) {
|
||||
@@ -813,11 +819,10 @@ void applyTextStyleToElement({
|
||||
cssStyle.fontSize = '${fontSize.floor()}px';
|
||||
}
|
||||
if (style.fontWeight != null) {
|
||||
cssStyle.fontWeight = fontWeightToCss(style.fontWeight)!;
|
||||
cssStyle.fontWeight = style.fontWeight!.toCssString();
|
||||
}
|
||||
if (style.fontStyle != null) {
|
||||
cssStyle.fontStyle =
|
||||
style.fontStyle == ui.FontStyle.normal ? 'normal' : 'italic';
|
||||
cssStyle.fontStyle = style.fontStyle!.toCssString();
|
||||
}
|
||||
// For test environment use effectiveFontFamily since we need to
|
||||
// consistently use the correct test font.
|
||||
|
||||
@@ -7,8 +7,8 @@ import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
|
||||
|
||||
import '../browser_detection.dart';
|
||||
import '../dom.dart';
|
||||
import '../embedder.dart';
|
||||
import '../util.dart';
|
||||
import '../view_embedder/style_manager.dart';
|
||||
import 'measurement.dart';
|
||||
import 'paragraph.dart';
|
||||
|
||||
@@ -18,33 +18,12 @@ String buildCssFontString({
|
||||
required double? fontSize,
|
||||
required String fontFamily,
|
||||
}) {
|
||||
final StringBuffer result = StringBuffer();
|
||||
final String cssFontStyle = fontStyle?.toCssString() ?? StyleManager.defaultFontStyle;
|
||||
final String cssFontWeight = fontWeight?.toCssString() ?? StyleManager.defaultFontWeight;
|
||||
final int cssFontSize = (fontSize ?? StyleManager.defaultFontSize).floor();
|
||||
final String cssFontFamily = canonicalizeFontFamily(fontFamily)!;
|
||||
|
||||
// Font style
|
||||
if (fontStyle != null) {
|
||||
result.write(fontStyle == ui.FontStyle.normal ? 'normal' : 'italic');
|
||||
} else {
|
||||
result.write(FlutterViewEmbedder.defaultFontStyle);
|
||||
}
|
||||
result.write(' ');
|
||||
|
||||
// Font weight.
|
||||
if (fontWeight != null) {
|
||||
result.write(fontWeightToCss(fontWeight));
|
||||
} else {
|
||||
result.write(FlutterViewEmbedder.defaultFontWeight);
|
||||
}
|
||||
result.write(' ');
|
||||
|
||||
if (fontSize != null) {
|
||||
result.write(fontSize.floor());
|
||||
} else {
|
||||
result.write(FlutterViewEmbedder.defaultFontSize);
|
||||
}
|
||||
result.write('px ');
|
||||
result.write(canonicalizeFontFamily(fontFamily));
|
||||
|
||||
return result.toString();
|
||||
return '$cssFontStyle $cssFontWeight ${cssFontSize}px $cssFontFamily';
|
||||
}
|
||||
|
||||
/// Contains all styles that have an effect on the height of text.
|
||||
|
||||
@@ -38,6 +38,21 @@ import '../embedder.dart';
|
||||
class DomManager {
|
||||
DomManager.fromFlutterViewEmbedderDEPRECATED(this._embedder);
|
||||
|
||||
/// The tag name for the Flutter View root element.
|
||||
static const String flutterViewTagName = 'flutter-view';
|
||||
|
||||
/// The tag name for the glass-pane.
|
||||
static const String glassPaneTagName = 'flt-glass-pane';
|
||||
|
||||
/// The tag name for the scene host.
|
||||
static const String sceneHostTagName = 'flt-scene-host';
|
||||
|
||||
/// The tag name for the semantics host.
|
||||
static const String semanticsHostTagName = 'flt-semantics-host';
|
||||
|
||||
/// The tag name for the accessibility announcements host.
|
||||
static const String announcementsHostTagName = 'flt-announcement-host';
|
||||
|
||||
final FlutterViewEmbedder _embedder;
|
||||
|
||||
/// The root DOM element for the entire Flutter View.
|
||||
|
||||
@@ -2,11 +2,77 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'browser_detection.dart';
|
||||
import 'dom.dart';
|
||||
import 'text_editing/text_editing.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
// Applies the required global CSS to an incoming [DomCSSStyleSheet] `sheet`.
|
||||
import '../browser_detection.dart';
|
||||
import '../dom.dart';
|
||||
import '../text_editing/text_editing.dart';
|
||||
import 'dom_manager.dart';
|
||||
|
||||
/// Manages the CSS styles of the Flutter View.
|
||||
class StyleManager {
|
||||
static const String defaultFontStyle = 'normal';
|
||||
static const String defaultFontWeight = 'normal';
|
||||
static const double defaultFontSize = 14.0;
|
||||
static const String defaultFontFamily = 'sans-serif';
|
||||
static const String defaultCssFont = '$defaultFontStyle $defaultFontWeight ${defaultFontSize}px $defaultFontFamily';
|
||||
|
||||
static void attachGlobalStyles({
|
||||
required DomNode node,
|
||||
required String styleId,
|
||||
required String? styleNonce,
|
||||
required String cssSelectorPrefix,
|
||||
}) {
|
||||
final DomHTMLStyleElement styleElement = createDomHTMLStyleElement(styleNonce);
|
||||
styleElement.id = styleId;
|
||||
// The style element must be appended to the DOM, or its `sheet` will be null later.
|
||||
node.appendChild(styleElement);
|
||||
applyGlobalCssRulesToSheet(
|
||||
styleElement,
|
||||
defaultCssFont: StyleManager.defaultCssFont,
|
||||
cssSelectorPrefix: cssSelectorPrefix,
|
||||
);
|
||||
}
|
||||
|
||||
static void styleSceneHost(
|
||||
DomElement sceneHost, {
|
||||
bool debugShowSemanticsNodes = false,
|
||||
}) {
|
||||
assert(sceneHost.tagName.toLowerCase() == DomManager.sceneHostTagName.toLowerCase());
|
||||
// Don't allow the scene to receive pointer events.
|
||||
sceneHost.style.pointerEvents = 'none';
|
||||
// When debugging semantics, make the scene semi-transparent so that the
|
||||
// semantics tree is more prominent.
|
||||
if (debugShowSemanticsNodes) {
|
||||
sceneHost.style.opacity = '0.3';
|
||||
}
|
||||
}
|
||||
|
||||
static void styleSemanticsHost(
|
||||
DomElement semanticsHost,
|
||||
double devicePixelRatio,
|
||||
) {
|
||||
assert(semanticsHost.tagName.toLowerCase() == DomManager.semanticsHostTagName.toLowerCase());
|
||||
semanticsHost.style
|
||||
..position = 'absolute'
|
||||
..transformOrigin = '0 0 0';
|
||||
scaleSemanticsHost(semanticsHost, devicePixelRatio);
|
||||
}
|
||||
|
||||
/// The framework specifies semantics in physical pixels, but CSS uses
|
||||
/// logical pixels. To compensate, an inverse scale is injected at the root
|
||||
/// level.
|
||||
static void scaleSemanticsHost(
|
||||
DomElement semanticsHost,
|
||||
double devicePixelRatio,
|
||||
) {
|
||||
assert(semanticsHost.tagName.toLowerCase() == DomManager.semanticsHostTagName.toLowerCase());
|
||||
semanticsHost.style.transform = 'scale(${1 / devicePixelRatio})';
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the required global CSS to an incoming [DomCSSStyleSheet] `sheet`.
|
||||
@visibleForTesting
|
||||
void applyGlobalCssRulesToSheet(
|
||||
DomHTMLStyleElement styleElement, {
|
||||
String cssSelectorPrefix = '',
|
||||
@@ -20,7 +86,7 @@ void applyGlobalCssRulesToSheet(
|
||||
|
||||
// Fixes #115216 by ensuring that our parameters only affect the flt-scene-host children.
|
||||
sheet.insertRule('''
|
||||
$cssSelectorPrefix flt-scene-host {
|
||||
$cssSelectorPrefix ${DomManager.sceneHostTagName} {
|
||||
font: $defaultCssFont;
|
||||
}
|
||||
''', sheet.cssRules.length);
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:test/bootstrap/browser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:ui/src/engine.dart';
|
||||
|
||||
import '../../common/matchers.dart';
|
||||
|
||||
void main() {
|
||||
internalBootstrapBrowserTest(() => doTests);
|
||||
}
|
||||
|
||||
void doTests() {
|
||||
group('StyleManager', () {
|
||||
test('styleSceneHost', () {
|
||||
expect(
|
||||
() => StyleManager.styleSceneHost(createDomHTMLDivElement()),
|
||||
throwsAssertionError,
|
||||
);
|
||||
|
||||
final DomElement sceneHost = createDomElement('flt-scene-host');
|
||||
StyleManager.styleSceneHost(sceneHost);
|
||||
expect(sceneHost.style.pointerEvents, 'none');
|
||||
expect(sceneHost.style.opacity, isEmpty);
|
||||
|
||||
final DomElement sceneHost2 = createDomElement('flt-scene-host');
|
||||
StyleManager.styleSceneHost(sceneHost2, debugShowSemanticsNodes: true);
|
||||
expect(sceneHost2.style.pointerEvents, 'none');
|
||||
expect(sceneHost2.style.opacity, isNotEmpty);
|
||||
});
|
||||
|
||||
test('styleSemanticsHost', () {
|
||||
expect(
|
||||
() => StyleManager.styleSemanticsHost(createDomHTMLDivElement(), 1.0),
|
||||
throwsAssertionError,
|
||||
reason: 'Only accepts a <flt-semantics-host> element.'
|
||||
);
|
||||
|
||||
final DomElement semanticsHost = createDomElement('flt-semantics-host');
|
||||
StyleManager.styleSemanticsHost(semanticsHost, 4.0);
|
||||
expect(semanticsHost.style.transform, 'scale(0.25)');
|
||||
expect(semanticsHost.style.position, 'absolute');
|
||||
expect(semanticsHost.style.transformOrigin, anyOf('0px 0px 0px', '0px 0px'));
|
||||
});
|
||||
|
||||
test('scaleSemanticsHost', () {
|
||||
expect(
|
||||
() => StyleManager.scaleSemanticsHost(createDomHTMLDivElement(), 1.0),
|
||||
throwsAssertionError,
|
||||
reason: 'Only accepts a <flt-semantics-host> element.'
|
||||
);
|
||||
|
||||
final DomElement semanticsHost = createDomElement('flt-semantics-host');
|
||||
StyleManager.scaleSemanticsHost(semanticsHost, 5.0);
|
||||
expect(semanticsHost.style.transform, 'scale(0.2)');
|
||||
// Didn't set other styles.
|
||||
expect(semanticsHost.style.position, isEmpty);
|
||||
expect(semanticsHost.style.transformOrigin, isEmpty);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import 'paragraph/helper.dart';
|
||||
|
||||
DomElement get sceneHost =>
|
||||
EnginePlatformDispatcher.instance.implicitView!.dom.renderingHost
|
||||
.querySelector('flt-scene-host')!;
|
||||
.querySelector(DomManager.sceneHostTagName)!;
|
||||
|
||||
void main() {
|
||||
internalBootstrapBrowserTest(() => testMain);
|
||||
|
||||
@@ -19,7 +19,7 @@ const bool debugTest = false;
|
||||
|
||||
DomElement get sceneHost =>
|
||||
EnginePlatformDispatcher.instance.implicitView!.dom.renderingHost
|
||||
.querySelector('flt-scene-host')!;
|
||||
.querySelector(DomManager.sceneHostTagName)!;
|
||||
|
||||
Future<void> main() async {
|
||||
if (!debugTest) {
|
||||
|
||||
@@ -529,8 +529,8 @@ String spanStyle({
|
||||
}
|
||||
|
||||
TextStyle styleWithDefaults({
|
||||
String fontFamily = FlutterViewEmbedder.defaultFontFamily,
|
||||
double fontSize = FlutterViewEmbedder.defaultFontSize,
|
||||
String fontFamily = StyleManager.defaultFontFamily,
|
||||
double fontSize = StyleManager.defaultFontSize,
|
||||
FontWeight? fontWeight,
|
||||
FontStyle? fontStyle,
|
||||
double? height,
|
||||
|
||||
@@ -10,8 +10,8 @@ import 'package:ui/ui.dart';
|
||||
import '../paragraph/helper.dart';
|
||||
|
||||
final EngineTextStyle defaultStyle = EngineTextStyle.only(
|
||||
fontFamily: FlutterViewEmbedder.defaultFontFamily,
|
||||
fontSize: FlutterViewEmbedder.defaultFontSize,
|
||||
fontFamily: StyleManager.defaultFontFamily,
|
||||
fontSize: StyleManager.defaultFontSize,
|
||||
);
|
||||
final EngineTextStyle style1 = defaultStyle.copyWith(fontSize: 20);
|
||||
final EngineTextStyle style2 = defaultStyle.copyWith(color: blue);
|
||||
|
||||
Reference in New Issue
Block a user