Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/servo/components/style/properties/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 36 kB image not shown  

Quelle  data.py   Sprache: Python

 
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

import re
from counted_unknown_properties import COUNTED_UNKNOWN_PROPERTIES

# It is important that the order of these physical / logical variants matches
# the order of the enum variants in logical_geometry.rs
PHYSICAL_SIDES = ["top""right""bottom""left"]
PHYSICAL_CORNERS = ["top-left""top-right""bottom-right""bottom-left"]
PHYSICAL_AXES = ["y""x"]
PHYSICAL_SIZES = ["height""width"]
LOGICAL_SIDES = ["block-start""block-end""inline-start""inline-end"]
LOGICAL_CORNERS = ["start-start""start-end""end-start""end-end"]
LOGICAL_SIZES = ["block-size""inline-size"]
LOGICAL_AXES = ["block""inline"]

# bool is True when logical
ALL_SIDES = [(side, Falsefor side in PHYSICAL_SIDES] + [
    (side, Truefor side in LOGICAL_SIDES
]
ALL_SIZES = [(size, Falsefor size in PHYSICAL_SIZES] + [
    (size, Truefor size in LOGICAL_SIZES
]
ALL_CORNERS = [(corner, Falsefor corner in PHYSICAL_CORNERS] + [
    (corner, Truefor corner in LOGICAL_CORNERS
]
ALL_AXES = [(axis, Falsefor axis in PHYSICAL_AXES] + [
    (axis, Truefor axis in LOGICAL_AXES
]

SYSTEM_FONT_LONGHANDS = """font_family font_size font_style
                           font_stretch font_weight""".split()

PRIORITARY_PROPERTIES = set(
    [
        # The writing-mode group has the most priority of all property groups, as
        # sizes like font-size can depend on it.
        "writing-mode",
        "direction",
        "text-orientation",
        # The fonts and colors group has the second priority, as all other lengths
        # and colors depend on them.
        #
        # There are some interdependencies between these, but we fix them up in
        # Cascade::fixup_font_stuff.
        # Needed to properly compute the zoomed font-size.
        "-x-text-scale",
        # Needed to do font-size computation in a language-dependent way.
        "-x-lang",
        # Needed for ruby to respect language-dependent min-font-size
        # preferences properly, see bug 1165538.
        "-moz-min-font-size-ratio",
        # font-size depends on math-depth's computed value.
        "math-depth",
        # Needed to compute the first available font and its used size,
        # in order to compute font-relative units correctly.
        "font-size",
        "font-size-adjust",
        "font-weight",
        "font-stretch",
        "font-style",
        "font-family",
        # color-scheme affects how system colors and light-dark() resolve.
        "color-scheme",
        # forced-color-adjust affects whether colors are adjusted.
        "forced-color-adjust",
        # Zoom affects all absolute lengths.
        "zoom",
        # Line height lengths depend on this.
        "line-height",
    ]
)

VISITED_DEPENDENT_PROPERTIES = set(
    [
        "column-rule-color",
        "text-emphasis-color",
        "-webkit-text-fill-color",
        "-webkit-text-stroke-color",
        "text-decoration-color",
        "fill",
        "stroke",
        "caret-color",
        "background-color",
        "border-top-color",
        "border-right-color",
        "border-bottom-color",
        "border-left-color",
        "border-block-start-color",
        "border-inline-end-color",
        "border-block-end-color",
        "border-inline-start-color",
        "outline-color",
        "color",
    ]
)

# Bitfield values for all rule types which can have property declarations.
STYLE_RULE = 1 << 0
PAGE_RULE = 1 << 1
KEYFRAME_RULE = 1 << 2
POSITION_TRY_RULE = 1 << 3

ALL_RULES = STYLE_RULE | PAGE_RULE | KEYFRAME_RULE
DEFAULT_RULES = STYLE_RULE | KEYFRAME_RULE
DEFAULT_RULES_AND_PAGE = DEFAULT_RULES | PAGE_RULE
DEFAULT_RULES_EXCEPT_KEYFRAME = STYLE_RULE
DEFAULT_RULES_AND_POSITION_TRY = DEFAULT_RULES | POSITION_TRY_RULE

# Rule name to value dict
RULE_VALUES = {
    "Style": STYLE_RULE,
    "Page": PAGE_RULE,
    "Keyframe": KEYFRAME_RULE,
    "PositionTry": POSITION_TRY_RULE,
}


def rule_values_from_arg(that):
    if isinstance(that, int):
        return that
    mask = 0
    for rule in that.split():
        mask |= RULE_VALUES[rule]
    return mask


def maybe_moz_logical_alias(engine, side, prop):
    if engine == "gecko" and side[1]:
        axis, dir = side[0].split("-")
        if axis == "inline":
            return prop % dir
    return None


def to_rust_ident(name):
    name = name.replace("-""_")
    if name in ["static""super""box""move"]:  # Rust keywords
        name += "_"
    return name


def to_snake_case(ident):
    return re.sub("([A-Z]+)"lambda m: "_" + m.group(1).lower(), ident).strip("_")


def to_camel_case(ident):
    return re.sub(
        "(^|_|-)([a-z0-9])"lambda m: m.group(2).upper(), ident.strip("_").strip("-")
    )


def to_camel_case_lower(ident):
    camel = to_camel_case(ident)
    return camel[0].lower() + camel[1:]


https://drafts.csswg.org/cssom/#css-property-to-idl-attribute
def to_idl_name(ident):
    return re.sub("-([a-z])"lambda m: m.group(1).upper(), ident)


def parse_aliases(value):
    aliases = {}
    for pair in value.split():
        [a, v] = pair.split("=")
        aliases[a] = v
    return aliases


class Keyword(object):
    def __init__(
        self,
        name,
        values,
        gecko_constant_prefix=None,
        gecko_enum_prefix=None,
        custom_consts=None,
        extra_gecko_values=None,
        extra_servo_values=None,
        gecko_aliases=None,
        servo_aliases=None,
        gecko_strip_moz_prefix=None,
        gecko_inexhaustive=None,
    ):
        self.name = name
        self.values = values.split()
        if gecko_constant_prefix and gecko_enum_prefix:
            raise TypeError(
                "Only one of gecko_constant_prefix and gecko_enum_prefix "
                "can be specified"
            )
        self.gecko_constant_prefix = (
            gecko_constant_prefix or "NS_STYLE_" + self.name.upper().replace("-""_")
        )
        self.gecko_enum_prefix = gecko_enum_prefix
        self.extra_gecko_values = (extra_gecko_values or "").split()
        self.extra_servo_values = (extra_servo_values or "").split()
        self.gecko_aliases = parse_aliases(gecko_aliases or "")
        self.servo_aliases = parse_aliases(servo_aliases or "")
        self.consts_map = {} if custom_consts is None else custom_consts
        self.gecko_strip_moz_prefix = (
            True if gecko_strip_moz_prefix is None else gecko_strip_moz_prefix
        )
        self.gecko_inexhaustive = gecko_inexhaustive or (gecko_enum_prefix is None)

    def values_for(self, engine):
        if engine == "gecko":
            return self.values + self.extra_gecko_values
        elif engine == "servo":
            return self.values + self.extra_servo_values
        else:
            raise Exception("Bad engine: " + engine)

    def aliases_for(self, engine):
        if engine == "gecko":
            return self.gecko_aliases
        elif engine == "servo":
            return self.servo_aliases
        else:
            raise Exception("Bad engine: " + engine)

    def gecko_constant(self, value):
        moz_stripped = (
            value.replace("-moz-""")
            if self.gecko_strip_moz_prefix
            else value.replace("-moz-""moz-")
        )
        mapped = self.consts_map.get(value)
        if self.gecko_enum_prefix:
            parts = moz_stripped.replace("-""_").split("_")
            parts = mapped if mapped else [p.title() for p in parts]
            return self.gecko_enum_prefix + "::" + "".join(parts)
        else:
            suffix = mapped if mapped else moz_stripped.replace("-""_")
            return self.gecko_constant_prefix + "_" + suffix.upper()

    def needs_cast(self):
        return self.gecko_enum_prefix is None

    def maybe_cast(self, type_str):
        return "as " + type_str if self.needs_cast() else ""

    def casted_constant_name(self, value, cast_type):
        if cast_type is None:
            raise TypeError("We should specify the cast_type.")

        if self.gecko_enum_prefix is None:
            return cast_type.upper() + "_" + self.gecko_constant(value)
        else:
            return (
                cast_type.upper()
                + "_"
                + self.gecko_constant(value).upper().replace("::""_")
            )


def arg_to_bool(arg):
    if isinstance(arg, bool):
        return arg
    assert arg in ["True""False"], "Unexpected value for boolean arguement: " + repr(
        arg
    )
    return arg == "True"


def parse_property_aliases(alias_list):
    result = []
    if alias_list:
        for alias in alias_list.split():
            (name, _, pref) = alias.partition(":")
            result.append((name, pref))
    return result


def to_phys(name, logical, physical):
    return name.replace(logical, physical).replace("inset-""")


class Property(object):
    def __init__(
        self,
        name,
        spec,
        servo_pref,
        gecko_pref,
        enabled_in,
        rule_types_allowed,
        aliases,
        extra_prefixes,
        flags,
    ):
        self.name = name
        if not spec:
            raise TypeError("Spec should be specified for " + name)
        self.spec = spec
        self.ident = to_rust_ident(name)
        self.camel_case = to_camel_case(self.ident)
        self.servo_pref = servo_pref
        self.gecko_pref = gecko_pref
        self.rule_types_allowed = rule_values_from_arg(rule_types_allowed)
        # For enabled_in, the setup is as follows:
        # It needs to be one of the four values: ["", "ua", "chrome", "content"]
        #  * "chrome" implies "ua", and implies that they're explicitly
        #    enabled.
        #  * "" implies the property will never be parsed.
        #  * "content" implies the property is accessible unconditionally,
        #    modulo a pref, set via servo_pref / gecko_pref.
        assert enabled_in in ("""ua""chrome""content")
        self.enabled_in = enabled_in
        self.aliases = parse_property_aliases(aliases)
        self.extra_prefixes = parse_property_aliases(extra_prefixes)
        self.flags = flags.split() if flags else []

    def rule_types_allowed_names(self):
        for name in RULE_VALUES:
            if self.rule_types_allowed & RULE_VALUES[name] != 0:
                yield name

    def experimental(self, engine):
        if engine == "gecko":
            return bool(self.gecko_pref)
        elif engine == "servo":
            return bool(self.servo_pref)
        else:
            raise Exception("Bad engine: " + engine)

    def explicitly_enabled_in_ua_sheets(self):
        return self.enabled_in in ("ua""chrome")

    def explicitly_enabled_in_chrome(self):
        return self.enabled_in == "chrome"

    def enabled_in_content(self):
        return self.enabled_in == "content"

    def is_visited_dependent(self):
        return self.name in VISITED_DEPENDENT_PROPERTIES

    def is_prioritary(self):
        return self.name in PRIORITARY_PROPERTIES

    def nscsspropertyid(self):
        return "nsCSSPropertyID::eCSSProperty_" + self.ident


class Longhand(Property):
    def __init__(
        self,
        style_struct,
        name,
        spec=None,
        animation_type=None,
        keyword=None,
        predefined_type=None,
        servo_pref=None,
        gecko_pref=None,
        enabled_in="content",
        need_index=False,
        gecko_ffi_name=None,
        has_effect_on_gecko_scrollbars=None,
        rule_types_allowed=DEFAULT_RULES,
        cast_type="u8",
        logical=False,
        logical_group=None,
        aliases=None,
        extra_prefixes=None,
        boxed=False,
        flags=None,
        allow_quirks="No",
        ignored_when_colors_disabled=False,
        simple_vector_bindings=False,
        vector=False,
        servo_restyle_damage="repaint",
        affects=None,
    ):
        Property.__init__(
            self,
            name=name,
            spec=spec,
            servo_pref=servo_pref,
            gecko_pref=gecko_pref,
            enabled_in=enabled_in,
            rule_types_allowed=rule_types_allowed,
            aliases=aliases,
            extra_prefixes=extra_prefixes,
            flags=flags,
        )

        self.affects = affects
        self.flags += self.affects_flags()

        self.keyword = keyword
        self.predefined_type = predefined_type
        self.style_struct = style_struct
        self.has_effect_on_gecko_scrollbars = has_effect_on_gecko_scrollbars
        assert (
            has_effect_on_gecko_scrollbars in [NoneFalseTrue]
            and not style_struct.inherited
            or (gecko_pref is None and enabled_in != "")
            == (has_effect_on_gecko_scrollbars is None)
        ), (
            "Property "
            + name
            + ": has_effect_on_gecko_scrollbars must be "
            + "specified, and must have a value of True or False, iff a "
            + "property is inherited and is behind a Gecko pref or internal"
        )
        self.need_index = need_index
        self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
        self.cast_type = cast_type
        self.logical = arg_to_bool(logical)
        self.logical_group = logical_group
        if self.logical:
            assert logical_group, "Property " + name + " must have a logical group"

        self.boxed = arg_to_bool(boxed)
        self.allow_quirks = allow_quirks
        self.ignored_when_colors_disabled = ignored_when_colors_disabled
        self.is_vector = vector
        self.simple_vector_bindings = simple_vector_bindings

        # This is done like this since just a plain bool argument seemed like
        # really random.
        if animation_type is None:
            animation_type = "normal"
        assert animation_type in ["none""normal""discrete"]
        self.animation_type = animation_type
        self.animatable = animation_type != "none"

        # See compute_damage for the various values this can take
        self.servo_restyle_damage = servo_restyle_damage

    def affects_flags(self):
        # Layout is the stronger hint. This property animation affects layout
        # or frame construction. `display` or `width` are examples that should
        # use this.
        if self.affects == "layout":
            return ["AFFECTS_LAYOUT"]
        # This property doesn't affect layout, but affects overflow.
        # `transform` and co. are examples of this.
        if self.affects == "overflow":
            return ["AFFECTS_OVERFLOW"]
        # This property affects the rendered output but doesn't affect layout.
        # `opacity`, `color`, or `z-index` are examples of this.
        if self.affects == "paint":
            return ["AFFECTS_PAINT"]
        # This property doesn't affect rendering in any way.
        # `user-select` is an example of this.
        assert self.affects == "", (
            "Property "
            + self.name
            + ': affects must be specified and be one of ["layout", "overflow", "paint", ""], see Longhand.affects_flags for documentation'
        )
        return []

    @staticmethod
    def type():
        return "longhand"

    # For a given logical property, return the kind of mapping we need to
    # perform, and which logical value we represent, in a tuple.
    def logical_mapping_data(self, data):
        if not self.logical:
            return []
        # Sizes and axes are basically the same for mapping, we just need
        # slightly different replacements (block-size -> height, etc rather
        # than -x/-y) below.
        for [ty, logical_items, physical_items] in [
            ["Side", LOGICAL_SIDES, PHYSICAL_SIDES],
            ["Corner", LOGICAL_CORNERS, PHYSICAL_CORNERS],
            ["Axis", LOGICAL_SIZES, PHYSICAL_SIZES],
            ["Axis", LOGICAL_AXES, PHYSICAL_AXES],
        ]:
            candidate = [s for s in logical_items if s in self.name]
            if candidate:
                assert len(candidate) == 1
                return [ty, candidate[0], logical_items, physical_items]
        assert False"Don't know how to deal with " + self.name

    def logical_mapping_kind(self, data):
        assert self.logical
        [kind, item, _, _] = self.logical_mapping_data(data)
        return "LogicalMappingKind::{}(Logical{}::{})".format(
            kind, kind, to_camel_case(item.replace("-size"""))
        )

    # For a given logical property return all the physical property names
    # corresponding to it.
    def all_physical_mapped_properties(self, data):
        if not self.logical:
            return []
        [_, logical_side, _, physical_items] = self.logical_mapping_data(data)
        return [
            data.longhands_by_name[to_phys(self.name, logical_side, physical_side)]
            for physical_side in physical_items
        ]

    def may_be_disabled_in(self, shorthand, engine):
        if engine == "gecko":
            return self.gecko_pref and self.gecko_pref != shorthand.gecko_pref
        elif engine == "servo":
            return self.servo_pref and self.servo_pref != shorthand.servo_pref
        else:
            raise Exception("Bad engine: " + engine)

    def base_type(self):
        if self.predefined_type and not self.is_vector:
            return "crate::values::specified::{}".format(self.predefined_type)
        return "longhands::{}::SpecifiedValue".format(self.ident)

    def specified_type(self):
        if self.predefined_type and not self.is_vector:
            ty = "crate::values::specified::{}".format(self.predefined_type)
        else:
            ty = "longhands::{}::SpecifiedValue".format(self.ident)
        if self.boxed:
            ty = "Box<{}>".format(ty)
        return ty

    def specified_is_copy(self):
        if self.is_vector or self.boxed:
            return False
        if self.predefined_type:
            return self.predefined_type in {
                "AlignContent",
                "AlignItems",
                "AlignSelf",
                "Appearance",
                "AnimationComposition",
                "AnimationDirection",
                "AnimationFillMode",
                "AnimationPlayState",
                "AspectRatio",
                "BaselineSource",
                "BreakBetween",
                "BreakWithin",
                "BackgroundRepeat",
                "BorderImageRepeat",
                "BorderStyle",
                "table::CaptionSide",
                "Clear",
                "ColumnCount",
                "Contain",
                "ContentVisibility",
                "ContainerType",
                "Display",
                "FillRule",
                "Float",
                "FontLanguageOverride",
                "FontSizeAdjust",
                "FontStretch",
                "FontStyle",
                "FontSynthesis",
                "FontVariantEastAsian",
                "FontVariantLigatures",
                "FontVariantNumeric",
                "FontWeight",
                "GreaterThanOrEqualToOneNumber",
                "GridAutoFlow",
                "ImageRendering",
                "Inert",
                "InitialLetter",
                "Integer",
                "PositionArea",
                "PositionAreaKeyword",
                "PositionProperty",
                "JustifyContent",
                "JustifyItems",
                "JustifySelf",
                "LineBreak",
                "LineClamp",
                "MasonryAutoFlow",
                "MozTheme",
                "BoolInteger",
                "text::MozControlCharacterVisibility",
                "MathDepth",
                "MozScriptMinSize",
                "MozScriptSizeMultiplier",
                "TransformBox",
                "TextDecorationSkipInk",
                "NonNegativeNumber",
                "OffsetRotate",
                "Opacity",
                "OutlineStyle",
                "Overflow",
                "OverflowAnchor",
                "OverflowClipBox",
                "OverflowWrap",
                "OverscrollBehavior",
                "PageOrientation",
                "Percentage",
                "PointerEvents",
                "PositionTryOrder",
                "PositionVisibility",
                "PrintColorAdjust",
                "ForcedColorAdjust",
                "Resize",
                "RubyPosition",
                "SVGOpacity",
                "SVGPaintOrder",
                "ScrollbarGutter",
                "ScrollSnapAlign",
                "ScrollSnapAxis",
                "ScrollSnapStop",
                "ScrollSnapStrictness",
                "ScrollSnapType",
                "TextAlign",
                "TextAlignLast",
                "TextDecorationLine",
                "TextEmphasisPosition",
                "TextJustify",
                "TextTransform",
                "TextUnderlinePosition",
                "TouchAction",
                "TransformStyle",
                "UserFocus",
                "UserInput",
                "UserSelect",
                "VectorEffect",
                "WordBreak",
                "XSpan",
                "XTextScale",
                "ZIndex",
                "Zoom",
            }
        if self.name == "overflow-y":
            return True
        return bool(self.keyword)

    def animated_type(self):
        assert self.animatable
        computed = "<{} as ToComputedValue>::ComputedValue".format(self.base_type())
        if self.animation_type == "discrete":
            return computed
        return "<{} as ToAnimatedValue>::AnimatedValue".format(computed)


class Shorthand(Property):
    def __init__(
        self,
        name,
        sub_properties,
        spec=None,
        servo_pref=None,
        gecko_pref=None,
        enabled_in="content",
        rule_types_allowed=DEFAULT_RULES,
        aliases=None,
        extra_prefixes=None,
        flags=None,
    ):
        Property.__init__(
            self,
            name=name,
            spec=spec,
            servo_pref=servo_pref,
            gecko_pref=gecko_pref,
            enabled_in=enabled_in,
            rule_types_allowed=rule_types_allowed,
            aliases=aliases,
            extra_prefixes=extra_prefixes,
            flags=flags,
        )
        self.sub_properties = sub_properties

    def get_animatable(self):
        for sub in self.sub_properties:
            if sub.animatable:
                return True
        return False

    animatable = property(get_animatable)

    @staticmethod
    def type():
        return "shorthand"


class Alias(object):
    def __init__(self, name, original, gecko_pref):
        self.name = name
        self.ident = to_rust_ident(name)
        self.camel_case = to_camel_case(self.ident)
        self.original = original
        self.enabled_in = original.enabled_in
        self.animatable = original.animatable
        self.servo_pref = original.servo_pref
        self.gecko_pref = gecko_pref
        self.rule_types_allowed = original.rule_types_allowed
        self.flags = original.flags

    @staticmethod
    def type():
        return "alias"

    def rule_types_allowed_names(self):
        for name in RULE_VALUES:
            if self.rule_types_allowed & RULE_VALUES[name] != 0:
                yield name

    def experimental(self, engine):
        if engine == "gecko":
            return bool(self.gecko_pref)
        elif engine == "servo":
            return bool(self.servo_pref)
        else:
            raise Exception("Bad engine: " + engine)

    def explicitly_enabled_in_ua_sheets(self):
        return self.enabled_in in ["ua""chrome"]

    def explicitly_enabled_in_chrome(self):
        return self.enabled_in == "chrome"

    def enabled_in_content(self):
        return self.enabled_in == "content"

    def nscsspropertyid(self):
        return "nsCSSPropertyID::eCSSPropertyAlias_%s" % self.ident


class Method(object):
    def __init__(self, name, return_type=None, arg_types=None, is_mut=False):
        self.name = name
        self.return_type = return_type
        self.arg_types = arg_types or []
        self.is_mut = is_mut

    def arg_list(self):
        args = ["_: " + x for x in self.arg_types]
        args = ["&mut self" if self.is_mut else "&self"] + args
        return ", ".join(args)

    def signature(self):
        sig = "fn %s(%s)" % (self.name, self.arg_list())
        if self.return_type:
            sig = sig + " -> " + self.return_type
        return sig

    def declare(self):
        return self.signature() + ";"

    def stub(self):
        return self.signature() + "{ unimplemented!() }"


class StyleStruct(object):
    def __init__(self, name, inherited, gecko_name=None):
        self.gecko_struct_name = "Gecko" + name
        self.name = name
        self.name_lower = to_snake_case(name)
        self.ident = to_rust_ident(self.name_lower)
        self.longhands = []
        self.inherited = inherited
        self.gecko_name = gecko_name or name
        self.gecko_ffi_name = "nsStyle" + self.gecko_name
        self.document_dependent = self.gecko_name in ["Font""Visibility""Text"]


class PropertiesData(object):
    def __init__(self, engine):
        self.engine = engine
        self.longhands = []
        self.longhands_by_name = {}
        self.longhands_by_logical_group = {}
        self.longhand_aliases = []
        self.shorthands = []
        self.shorthands_by_name = {}
        self.shorthand_aliases = []
        self.counted_unknown_properties = [
            CountedUnknownProperty(p) for p in COUNTED_UNKNOWN_PROPERTIES
        ]

        self.style_structs = [
            StyleStruct("Background", inherited=False),
            StyleStruct("Border", inherited=False),
            StyleStruct("Box", inherited=False, gecko_name="Display"),
            StyleStruct("Column", inherited=False),
            StyleStruct("Counters", inherited=False, gecko_name="Content"),
            StyleStruct("Effects", inherited=False),
            StyleStruct("Font", inherited=True),
            StyleStruct("InheritedBox", inherited=True, gecko_name="Visibility"),
            StyleStruct("InheritedSVG", inherited=True, gecko_name="SVG"),
            StyleStruct("InheritedTable", inherited=True, gecko_name="TableBorder"),
            StyleStruct("InheritedText", inherited=True, gecko_name="Text"),
            StyleStruct("InheritedUI", inherited=True, gecko_name="UI"),
            StyleStruct("List", inherited=True),
            StyleStruct("Margin", inherited=False),
            StyleStruct("Outline", inherited=False),
            StyleStruct("Padding", inherited=False),
            StyleStruct("Page", inherited=False),
            StyleStruct("Position", inherited=False),
            StyleStruct("SVG", inherited=False, gecko_name="SVGReset"),
            StyleStruct("Table", inherited=False),
            StyleStruct("Text", inherited=False, gecko_name="TextReset"),
            StyleStruct("UI", inherited=False, gecko_name="UIReset"),
            StyleStruct("XUL", inherited=False),
        ]
        self.current_style_struct = None

    def active_style_structs(self):
        return [s for s in self.style_structs if s.longhands]

    def add_prefixed_aliases(self, property):
        # FIXME Servo's DOM architecture doesn't support vendor-prefixed properties.
        #       See servo/servo#14941.
        if self.engine == "gecko":
            for prefix, pref in property.extra_prefixes:
                property.aliases.append(("-%s-%s" % (prefix, property.name), pref))

    def declare_longhand(self, name, engines=None, **kwargs):
        engines = engines.split()
        if self.engine not in engines:
            return

        longhand = Longhand(self.current_style_struct, name, **kwargs)
        self.add_prefixed_aliases(longhand)
        longhand.aliases = [Alias(xp[0], longhand, xp[1]) for xp in longhand.aliases]
        self.longhand_aliases += longhand.aliases
        self.current_style_struct.longhands.append(longhand)
        self.longhands.append(longhand)
        self.longhands_by_name[name] = longhand
        if longhand.logical_group:
            self.longhands_by_logical_group.setdefault(
                longhand.logical_group, []
            ).append(longhand)

        return longhand

    def declare_shorthand(self, name, sub_properties, engines, *args, **kwargs):
        engines = engines.split()
        if self.engine not in engines:
            return

        sub_properties = [self.longhands_by_name[s] for s in sub_properties]
        shorthand = Shorthand(name, sub_properties, *args, **kwargs)
        self.add_prefixed_aliases(shorthand)
        shorthand.aliases = [Alias(xp[0], shorthand, xp[1]) for xp in shorthand.aliases]
        self.shorthand_aliases += shorthand.aliases
        self.shorthands.append(shorthand)
        self.shorthands_by_name[name] = shorthand
        return shorthand

    def shorthands_except_all(self):
        return [s for s in self.shorthands if s.name != "all"]

    def all_aliases(self):
        return self.longhand_aliases + self.shorthand_aliases


def _add_logical_props(data, props):
    groups = set()
    for prop in props:
        if prop not in data.longhands_by_name:
            assert data.engine == "servo"
            continue
        prop = data.longhands_by_name[prop]
        if prop.logical_group:
            groups.add(prop.logical_group)
    for group in groups:
        for prop in data.longhands_by_logical_group[group]:
            props.add(prop.name)


# These are probably Gecko bugs and should be supported per spec.
def _remove_common_first_line_and_first_letter_properties(props, engine):
    if engine == "gecko":
        props.remove("tab-size")
        props.remove("hyphens")
        props.remove("line-break")
        props.remove("text-align-last")
        props.remove("text-emphasis-position")
        props.remove("text-emphasis-style")
        props.remove("text-emphasis-color")
        props.remove("text-wrap-style")

    props.remove("overflow-wrap")
    props.remove("text-align")
    props.remove("text-justify")
    props.remove("white-space-collapse")
    props.remove("text-wrap-mode")
    props.remove("word-break")
    props.remove("text-indent")


class PropertyRestrictions:
    @staticmethod
    def logical_group(data, group):
        return [p.name for p in data.longhands_by_logical_group[group]]

    @staticmethod
    def shorthand(data, shorthand):
        if shorthand not in data.shorthands_by_name:
            return []
        return [p.name for p in data.shorthands_by_name[shorthand].sub_properties]

    @staticmethod
    def spec(data, spec_path):
        return [p.name for p in data.longhands if spec_path in p.spec]

    https://svgwg.org/svg2-draft/propidx.html
    @staticmethod
    def svg_text_properties():
        props = set(
            [
                "fill",
                "fill-opacity",
                "fill-rule",
                "paint-order",
                "stroke",
                "stroke-dasharray",
                "stroke-dashoffset",
                "stroke-linecap",
                "stroke-linejoin",
                "stroke-miterlimit",
                "stroke-opacity",
                "stroke-width",
                "text-rendering",
                "vector-effect",
            ]
        )
        return props

    @staticmethod
    def webkit_text_properties():
        props = set(
            [
                # Kinda like css-text?
                "-webkit-text-stroke-width",
                "-webkit-text-fill-color",
                "-webkit-text-stroke-color",
            ]
        )
        return props

    https://drafts.csswg.org/css-pseudo/#first-letter-styling
    @staticmethod
    def first_letter(data):
        props = set(
            [
                "color",
                "opacity",
                "float",
                "initial-letter",
                # Kinda like css-fonts?
                "-moz-osx-font-smoothing",
                "vertical-align",
                # Will become shorthand of vertical-align (Bug 1830771)
                "baseline-source",
                "line-height",
                # Kinda like css-backgrounds?
                "background-blend-mode",
            ]
            + PropertyRestrictions.shorthand(data, "padding")
            + PropertyRestrictions.shorthand(data, "margin")
            + PropertyRestrictions.spec(data, "css-fonts")
            + PropertyRestrictions.spec(data, "css-backgrounds")
            + PropertyRestrictions.spec(data, "css-text")
            + PropertyRestrictions.spec(data, "css-shapes")
            + PropertyRestrictions.spec(data, "css-text-decor")
        )
        props = props.union(PropertyRestrictions.svg_text_properties())
        props = props.union(PropertyRestrictions.webkit_text_properties())

        _add_logical_props(data, props)

        _remove_common_first_line_and_first_letter_properties(props, data.engine)
        return props

    https://drafts.csswg.org/css-pseudo/#first-line-styling
    @staticmethod
    def first_line(data):
        props = set(
            [
                # Per spec.
                "color",
                "opacity",
                # Kinda like css-fonts?
                "-moz-osx-font-smoothing",
                "vertical-align",
                # Will become shorthand of vertical-align (Bug 1830771)
                "baseline-source",
                "line-height",
                # Kinda like css-backgrounds?
                "background-blend-mode",
            ]
            + PropertyRestrictions.spec(data, "css-fonts")
            + PropertyRestrictions.spec(data, "css-backgrounds")
            + PropertyRestrictions.spec(data, "css-text")
            + PropertyRestrictions.spec(data, "css-text-decor")
        )
        props = props.union(PropertyRestrictions.svg_text_properties())
        props = props.union(PropertyRestrictions.webkit_text_properties())

        # These are probably Gecko bugs and should be supported per spec.
        for prop in PropertyRestrictions.shorthand(data, "border"):
            props.remove(prop)
        for prop in PropertyRestrictions.shorthand(data, "border-radius"):
            props.remove(prop)
        props.remove("box-shadow")

        _remove_common_first_line_and_first_letter_properties(props, data.engine)
        return props

    https://drafts.csswg.org/css-pseudo/#placeholder
    #
    # The spec says that placeholder and first-line have the same restrictions,
    # but that's not true in Gecko and we also allow a handful other properties
    # for ::placeholder.
    @staticmethod
    def placeholder(data):
        props = PropertyRestrictions.first_line(data)
        props.add("opacity")
        props.add("text-overflow")
        props.add("text-align")
        props.add("text-justify")
        for p in PropertyRestrictions.shorthand(data, "text-wrap"):
            props.add(p)
        for p in PropertyRestrictions.shorthand(data, "white-space"):
            props.add(p)
        # ::placeholder can't be SVG text
        props -= PropertyRestrictions.svg_text_properties()

        return props

    https://drafts.csswg.org/css-pseudo/#marker-pseudo
    @staticmethod
    def marker(data):
        return set(
            [
                "color",
                "text-combine-upright",
                "text-transform",
                "unicode-bidi",
                "direction",
                "content",
                "line-height",
                "-moz-osx-font-smoothing",
            ]
            + PropertyRestrictions.shorthand(data, "text-wrap")
            + PropertyRestrictions.shorthand(data, "white-space")
            + PropertyRestrictions.spec(data, "css-fonts")
            + PropertyRestrictions.spec(data, "css-animations")
            + PropertyRestrictions.spec(data, "css-transitions")
        )

    https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element
    @staticmethod
    def cue(data):
        return set(
            [
                "color",
                "opacity",
                "visibility",
                "text-shadow",
                "text-combine-upright",
                "ruby-position",
                # XXX Should these really apply to cue?
                "-moz-osx-font-smoothing",
                # FIXME(emilio): background-blend-mode should be part of the
                # background shorthand, and get reset, per
                https://drafts.fxtf.org/compositing/#background-blend-mode
                "background-blend-mode",
            ]
            + PropertyRestrictions.shorthand(data, "text-decoration")
            + PropertyRestrictions.shorthand(data, "text-wrap")
            + PropertyRestrictions.shorthand(data, "white-space")
            + PropertyRestrictions.shorthand(data, "background")
            + PropertyRestrictions.shorthand(data, "outline")
            + PropertyRestrictions.shorthand(data, "font")
            + PropertyRestrictions.shorthand(data, "font-synthesis")
        )


class CountedUnknownProperty:
    def __init__(self, name):
        self.name = name
        self.ident = to_rust_ident(name)
        self.camel_case = to_camel_case(self.ident)

Messung V0.5
C=93 H=86 G=89

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.