Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/layout/reftests/border-image/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 15 kB image not shown  

Quelle  gen-refs.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 http://mozilla.org/MPL/2.0/.

# Generates tables of background images which correspond with border images for
# creating reftests. Input is the filename containing input defined below (a subset
# of the allowed CSS border properties). An html representation of a table is
# output to stdout.
#
# Usage: python gen-refs.py input_filename
#
# Input must take the form (order is not important, nothing is optional, distance in order top, right, bottom, left):
# width: p;
# height: p;
# border-width: p;
# border-image-source: ...;
# border-image-slice: p p p p;
# note that actually border-image-slice takes numbers without px, which represent pixels anyway (or at least coords)
# border-image-width: np np np np;
# border-image-repeat: stretch | repeat | round;
# border-image-outset: np np np np;
#
# where:
# p ::= n'px'
# np ::= n | p
#
# Assumes there is no intrinsic size for the border-image-source, so uses
# the size of the border image area.

import sys


class Point:
    def __init__(self, w=0, h=0):
        self.x = w
        self.y = h


class Size:
    def __init__(self, w=0, h=0):
        self.width = w
        self.height = h


class Rect:
    def __init__(self, x=0, y=0, x2=0, y2=0):
        self.x = x
        self.y = y
        self.x2 = x2
        self.y2 = y2

    def width(self):
        return self.x2 - self.x

    def height(self):
        return self.y2 - self.y


class Props:
    def __init__(self):
        self.size = Size()


class np:
    def __init__(self, n, p):
        self.n = n
        self.p = p

    def get_absolute(self, ref):
        if not self.p == 0:
            return self.p
        return self.n * ref


def parse_p(tok):
    if tok[-2:] == "px":
        return float(tok[:-2])
    print("Whoops, not a pixel value", tok)


def parse_np(tok):
    if tok[-2:] == "px":
        return np(0, float(tok[:-2]))
    return np(float(tok), 0)


def parse(filename):
    f = open(filename, "r")
    props = Props()
    for l in f:
        l = l.strip()
        if not l[-1] == ";":
            continue
        toks = l[:-1].split()
        if toks[0] == "border-width:":
            props.width = parse_p(toks[1])
        if toks[0] == "height:":
            props.size.height = parse_p(toks[1])
        if toks[0] == "width:":
            props.size.width = parse_p(toks[1])
        if toks[0] == "border-image-source:":
            props.source = l[l.find(":") + 1 : l.rfind(";")].strip()
        if toks[0] == "border-image-repeat:":
            props.repeat = toks[1]
        if toks[0] == "border-image-slice:":
            props.slice = map(parse_p, toks[1:5])
        if toks[0] == "border-image-width:":
            props.image_width = map(parse_np, toks[1:5])
        if toks[0] == "border-image-outset:":
            props.outset = map(parse_np, toks[1:5])
    f.close()
    return props


# the result of normalisation is that all sizes are in pixels and the size,
# widths, and outset have been normalised to a size and width - the former is
# the element's interior, the latter is the width of the drawn border.
def normalise(props):
    result = Props()
    result.source = props.source
    result.repeat = props.repeat
    result.width = map(lambda x: x.get_absolute(props.width), props.image_width)
    outsets = map(lambda x: x.get_absolute(props.width), props.outset)
    result.size.width = props.size.width + 2 * props.width + outsets[1] + outsets[3]
    result.size.height = props.size.height + 2 * props.width + outsets[0] + outsets[2]
    result.slice = props.slice
    for i in [0, 2]:
        if result.slice[i] > result.size.height:
            result.slice[i] = result.size.height
        if result.slice[i + 1] > result.size.width:
            result.slice[i + 1] = result.size.width

    return result


def check_parse(props):
    if not hasattr(props, "source"):
        print("missing border-image-source")
        return False
    if not hasattr(props.size, "width"):
        print("missing width")
        return False
    if not hasattr(props.size, "height"):
        print("missing height")
        return False
    if not hasattr(props, "width"):
        print("missing border-width")
        return False
    if not hasattr(props, "image_width"):
        print("missing border-image-width")
        return False
    if not hasattr(props, "slice"):
        print("missing border-image-slice")
        return False
    if not hasattr(props, "repeat"or (
        props.repeat not in ["stretch""repeat""round"]
    ):
        print("missing or incorrect border-image-repeat '" + props.repeat + "'")
        return False
    if not hasattr(props, "outset"):
        print("missing border-image-outset")
        return False

    return True


def check_normalise(props):
    if not hasattr(props, "source"):
        print("missing border-image-source")
        return False
    if not hasattr(props.size, "width"):
        print("missing width")
        return False
    if not hasattr(props.size, "height"):
        print("missing height")
        return False
    if not hasattr(props, "slice"):
        print("missing border-image-slice")
        return False
    if not hasattr(props, "repeat"or (
        props.repeat not in ["stretch""repeat""round"]
    ):
        print("missing or incorrect border-image-repeat '" + props.repeat + "'")
        return False

    return True


class Tile:
    def __init__(self):
        self.slice = Rect()
        self.border_width = Rect()


# throughout, we will use arrays for nine-patches, the indices correspond thusly:
# 0 1 2
# 3 4 5
# 6 7 8


# Compute the source tiles' slice and border-width sizes
def make_src_tiles():
    tiles = [Tile() for i in range(9)]

    rows = [range(3 * i, 3 * (i + 1)) for i in range(3)]
    cols = [[i, i + 3, i + 6] for i in range(3)]

    row_limits_slice = [
        0,
        props.slice[3],
        props.size.width - props.slice[1],
        props.size.width,
    ]
    row_limits_width = [
        0,
        props.width[3],
        props.size.width - props.width[1],
        props.size.width,
    ]
    for r in range(3):
        for t in [tiles[i] for i in cols[r]]:
            t.slice.x = row_limits_slice[r]
            t.slice.x2 = row_limits_slice[r + 1]
            t.border_width.x = row_limits_width[r]
            t.border_width.x2 = row_limits_width[r + 1]

    col_limits_slice = [
        0,
        props.slice[0],
        props.size.height - props.slice[2],
        props.size.height,
    ]
    col_limits_width = [
        0,
        props.width[0],
        props.size.height - props.width[2],
        props.size.height,
    ]
    for c in range(3):
        for t in [tiles[i] for i in rows[c]]:
            t.slice.y = col_limits_slice[c]
            t.slice.y2 = col_limits_slice[c + 1]
            t.border_width.y = col_limits_width[c]
            t.border_width.y2 = col_limits_width[c + 1]

    return tiles


def compute(props):
    tiles = make_src_tiles()

    # corners scale easy
    for t in [tiles[i] for i in [0, 2, 6, 8]]:
        t.scale = Point(
            t.border_width.width() / t.slice.width(),
            t.border_width.height() / t.slice.height(),
        )
    # edges are by their secondary dimension
    for t in [tiles[i] for i in [1, 7]]:
        t.scale = Point(
            t.border_width.height() / t.slice.height(),
            t.border_width.height() / t.slice.height(),
        )
    for t in [tiles[i] for i in [3, 5]]:
        t.scale = Point(
            t.border_width.width() / t.slice.width(),
            t.border_width.width() / t.slice.width(),
        )
    # the middle is scaled by the factors for the top and left edges
    tiles[4].scale = Point(tiles[1].scale.x, tiles[3].scale.y)

    # the size of a source tile for the middle section
    src_tile_size = Size(
        tiles[4].slice.width() * tiles[4].scale.x,
        tiles[4].slice.height() * tiles[4].scale.y,
    )

    # the size of a single destination tile in the central part
    dest_tile_size = Size()
    if props.repeat == "stretch":
        dest_tile_size.width = tiles[4].border_width.width()
        dest_tile_size.height = tiles[4].border_width.height()
        for t in [tiles[i] for i in [1, 7]]:
            t.scale.x = t.border_width.width() / t.slice.width()
        for t in [tiles[i] for i in [3, 5]]:
            t.scale.y = t.border_width.height() / t.slice.height()
    elif props.repeat == "repeat":
        dest_tile_size = src_tile_size
    elif props.repeat == "round":
        dest_tile_size.width = tiles[4].border_width.width() / math.ceil(
            tiles[4].border_width.width() / src_tile_size.width
        )
        dest_tile_size.height = tiles[4].border_width.height() / math.ceil(
            tiles[4].border_width.height() / src_tile_size.height
        )
        for t in [tiles[i] for i in [1, 4, 7]]:
            t.scale.x = dest_tile_size.width / t.slice.width()
        for t in [tiles[i] for i in [3, 4, 5]]:
            t.scale.y = dest_tile_size.height / t.slice.height()
    else:
        print("Whoops, invalid border-image-repeat value")

    # catch overlapping slices. Its easier to deal with it here than to catch
    # earlier and have to avoid all the divide by zeroes above
    for t in tiles:
        if t.slice.width() < 0:
            t.scale.x = 0
        if t.slice.height() < 0:
            t.scale.y = 0

    tiles_h = int(math.ceil(tiles[4].border_width.width() / dest_tile_size.width) + 2)
    tiles_v = int(math.ceil(tiles[4].border_width.height() / dest_tile_size.height) + 2)

    # if border-image-repeat: repeat, then we will later center the tiles, that
    # means we need an extra tile for the two 'half' tiles at either end
    if props.repeat == "repeat":
        if tiles_h % 2 == 0:
            tiles_h += 1
        if tiles_v % 2 == 0:
            tiles_v += 1
    dest_tiles = [Tile() for i in range(tiles_h * tiles_v)]

    # corners
    corners = [
        (0, 0),
        (tiles_h - 1, 2),
        (tiles_v * (tiles_h - 1), 6),
        (tiles_v * tiles_h - 1, 8),
    ]
    for d, s in corners:
        dest_tiles[d].size = Size(
            tiles[s].scale.x * props.size.width, tiles[s].scale.y * props.size.height
        )
        dest_tiles[d].dest_size = Size(
            tiles[s].border_width.width(), tiles[s].border_width.height()
        )
    dest_tiles[0].offset = Point(0, 0)
    dest_tiles[tiles_h - 1].offset = Point(
        tiles[2].border_width.width() - dest_tiles[tiles_h - 1].size.width, 0
    )
    dest_tiles[tiles_v * (tiles_h - 1)].offset = Point(
        0,
        tiles[6].border_width.height()
        - dest_tiles[tiles_v * (tiles_h - 1)].size.height,
    )
    dest_tiles[tiles_v * tiles_h - 1].offset = Point(
        tiles[8].border_width.width() - dest_tiles[tiles_h * tiles_v - 1].size.width,
        tiles[8].border_width.height() - dest_tiles[tiles_h * tiles_v - 1].size.height,
    )

    # horizontal edges
    for i in range(1, tiles_h - 1):
        dest_tiles[i].size = Size(
            tiles[1].scale.x * props.size.width, tiles[1].scale.y * props.size.height
        )
        dest_tiles[(tiles_v - 1) * tiles_h + i].size = Size(
            tiles[7].scale.x * props.size.width, tiles[7].scale.y * props.size.height
        )
        dest_tiles[i].dest_size = Size(
            dest_tile_size.width, tiles[1].border_width.height()
        )
        dest_tiles[(tiles_v - 1) * tiles_h + i].dest_size = Size(
            dest_tile_size.width, tiles[7].border_width.height()
        )
        dest_tiles[i].offset = Point(
            -tiles[1].scale.x * tiles[1].slice.x, -tiles[1].scale.y * tiles[1].slice.y
        )
        dest_tiles[(tiles_v - 1) * tiles_h + i].offset = Point(
            -tiles[7].scale.x * tiles[7].slice.x, -tiles[7].scale.y * tiles[7].slice.y
        )

    # vertical edges
    for i in range(1, tiles_v - 1):
        dest_tiles[i * tiles_h].size = Size(
            tiles[3].scale.x * props.size.width, tiles[3].scale.y * props.size.height
        )
        dest_tiles[(i + 1) * tiles_h - 1].size = Size(
            tiles[5].scale.x * props.size.width, tiles[5].scale.y * props.size.height
        )
        dest_tiles[i * tiles_h].dest_size = Size(
            tiles[3].border_width.width(), dest_tile_size.height
        )
        dest_tiles[(i + 1) * tiles_h - 1].dest_size = Size(
            tiles[5].border_width.width(), dest_tile_size.height
        )
        dest_tiles[i * tiles_h].offset = Point(
            -tiles[3].scale.x * tiles[3].slice.x, -tiles[3].scale.y * tiles[3].slice.y
        )
        dest_tiles[(i + 1) * tiles_h - 1].offset = Point(
            -tiles[5].scale.x * tiles[5].slice.x, -tiles[5].scale.y * tiles[5].slice.y
        )

    # middle
    for i in range(1, tiles_v - 1):
        for j in range(1, tiles_h - 1):
            dest_tiles[i * tiles_h + j].size = Size(
                tiles[4].scale.x * props.size.width,
                tiles[4].scale.y * props.size.height,
            )
            dest_tiles[i * tiles_h + j].offset = Point(
                -tiles[4].scale.x * tiles[4].slice.x,
                -tiles[4].scale.y * tiles[4].slice.y,
            )
            dest_tiles[i * tiles_h + j].dest_size = dest_tile_size

    # edge and middle tiles are centered with border-image-repeat: repeat
    # we need to change the offset to take account of this and change the dest_size
    # of the tiles at the sides of the edges if they are clipped
    if props.repeat == "repeat":
        diff_h = (
            (tiles_h - 2) * dest_tile_size.width - tiles[4].border_width.width()
        ) / 2
        diff_v = (
            (tiles_v - 2) * dest_tile_size.height - tiles[4].border_width.height()
        ) / 2
        for i in range(0, tiles_h):
            dest_tiles[tiles_h + i].dest_size.height -= diff_v
            dest_tiles[tiles_h + i].offset.y -= diff_v  # * tiles[4].scale.y
            dest_tiles[(tiles_v - 2) * tiles_h + i].dest_size.height -= diff_v
        for i in range(0, tiles_v):
            dest_tiles[i * tiles_h + 1].dest_size.width -= diff_h
            dest_tiles[i * tiles_h + 1].offset.x -= diff_h  # * tiles[4].scale.x
            dest_tiles[(i + 1) * tiles_h - 2].dest_size.width -= diff_h

    # output the table to simulate the border
    print("")
    for i in range(tiles_h):
        print('')
    for i in range(tiles_v):
        print(
            ''
        )
        for j in range(tiles_h):
            width = dest_tiles[i * tiles_h + j].size.width
            height = dest_tiles[i * tiles_h + j].size.height
            # catch any tiles with negative widths/heights
            # this happends when the total of the border-image-slices > borde drawing area
            if width <= 0 or height <= 0:
                print(' ')
            else:
                print(
                    ' '
                )
        print("")
    print("

                    + str(width)
                    + "px "
                    + str(height)
                    + "px; background-position: "
                    + str(dest_tiles[i * tiles_h + j].offset.x)
                    + "px "
                    + str(dest_tiles[i * tiles_h + j].offset.y)
                    + 'px;">
"
)


# start here
args = sys.argv[1:]
if len(args) == 0:
    print("whoops: no source file")
    exit(1)


props = parse(args[0])
if not check_parse(props):
    print(dir(props))
    exit(1)
props = normalise(props)
if not check_normalise(props):
    exit(1)
compute(props)

Messung V0.5
C=94 H=97 G=95

¤ Dauer der Verarbeitung: 0.13 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.