mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-09-11 20:47:56 +03:00
Slightly simplify border masks
This commit is contained in:
parent
a846e0062f
commit
03b8f1acc3
@ -1,44 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="5"
|
||||
width="5"
|
||||
viewBox="0 0 5 5"
|
||||
version="1.1"
|
||||
id="svg16"
|
||||
sodipodi:docname="mask.svg"
|
||||
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="100.40082"
|
||||
inkscape:cx="1.7679139"
|
||||
inkscape:cy="2.5597401"
|
||||
inkscape:window-width="1504"
|
||||
inkscape:window-height="955"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="44"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg16" />
|
||||
<defs
|
||||
id="defs16" />
|
||||
<path
|
||||
id="rect2"
|
||||
d="M 1 0 L 1 1 L 0 1 L 0 2 L 1 2 L 1 3 L 0 3 L 0 4 L 1 4 L 1 5 L 2 5 L 3 5 L 4 5 L 5 5 L 5 4 L 5 3 L 5 2 L 5 1 L 5 0 L 4 0 L 3 0 L 3 1 L 2 1 L 2 0 L 1 0 z M 2 2 L 3 2 L 3 3 L 2 3 L 2 2 z " />
|
||||
<rect
|
||||
style="opacity:0.5;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.04315;stroke-miterlimit:3"
|
||||
id="rect1"
|
||||
width="1"
|
||||
height="1"
|
||||
x="0"
|
||||
y="2" />
|
||||
<svg height="5" width="5" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M 1 0 L 1 1 L 0 1 L 0 2 L 1 2 L 1 3 L 0 3 L 0 4 L 1 4 L 1 5 L 2 5 L 3 5 L 4 5 L 5 5 L 5 4 L 5 3 L 5 2 L 5 1 L 5 0 L 4 0 L 3 0 L 3 1 L 2 1 L 2 0 L 1 0 z M 2 2 L 3 2 L 3 3 L 2 3 L 2 2 z " />
|
||||
<rect fill="black" opacity="0.5" width="1" height="1" x="0" y="2" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 340 B |
@ -62,6 +62,7 @@ def draw_page(page, stream):
|
||||
draw_background(
|
||||
stream, stacking_context.box.background, clip_box=False,
|
||||
bleed=page.bleed, marks=marks)
|
||||
set_mask_border(stream, page)
|
||||
draw_background(stream, page.canvas_background, clip_box=False)
|
||||
draw_border(stream, page)
|
||||
draw_stacking_context(stream, stacking_context)
|
||||
@ -116,7 +117,7 @@ def draw_stacking_context(stream, stacking_context):
|
||||
if isinstance(box, (boxes.BlockBox, boxes.MarginBox,
|
||||
boxes.InlineBlockBox, boxes.TableCellBox,
|
||||
boxes.FlexContainerBox, boxes.ReplacedBox)):
|
||||
maybe_set_mask_border(box, stream)
|
||||
set_mask_border(stream, box)
|
||||
# The canvas background was removed by layout_backgrounds
|
||||
draw_background(stream, box.background)
|
||||
draw_border(stream, box)
|
||||
@ -138,7 +139,7 @@ def draw_stacking_context(stream, stacking_context):
|
||||
|
||||
# Point 4
|
||||
for block in stacking_context.block_level_boxes:
|
||||
maybe_set_mask_border(block, stream)
|
||||
set_mask_border(stream, block)
|
||||
|
||||
if isinstance(block, boxes.TableBox):
|
||||
draw_table(stream, block)
|
||||
@ -444,7 +445,10 @@ def draw_border(stream, box):
|
||||
|
||||
# If there's a border image, that takes precedence.
|
||||
if box.style['border_image_source'][0] != 'none' and box.border_image is not None:
|
||||
draw_border_image(box, stream)
|
||||
draw_border_image(
|
||||
box, stream, box.border_image, box.style['border_image_slice'],
|
||||
box.style['border_image_repeat'], box.style['border_image_outset'],
|
||||
box.style['border_image_width'])
|
||||
return
|
||||
|
||||
widths = [getattr(box, f'border_{side}_width') for side in SIDES]
|
||||
@ -482,8 +486,8 @@ def draw_border(stream, box):
|
||||
stream, box, style, styled_color(style, color, side))
|
||||
|
||||
|
||||
def draw_border_image_impl(box, stream, image, slice_property,
|
||||
repeats, outsets, width_property):
|
||||
def draw_border_image(box, stream, image, border_slice, border_repeat, border_outset,
|
||||
border_width):
|
||||
"""Draw ``image`` as a border image for ``box`` on ``stream`` as specified."""
|
||||
# Shared by border-image-* and mask-border-*
|
||||
width, height, ratio = image.get_intrinsic_size(
|
||||
@ -492,8 +496,8 @@ def draw_border_image_impl(box, stream, image, slice_property,
|
||||
width, height, ratio, specified_width=None, specified_height=None,
|
||||
default_width=box.border_width(), default_height=box.border_height())
|
||||
|
||||
image_slice = slice_property[:4]
|
||||
should_fill = slice_property[4]
|
||||
image_slice = border_slice[:4]
|
||||
should_fill = border_slice[4]
|
||||
|
||||
def compute_slice_dimension(dimension, intrinsic):
|
||||
if isinstance(dimension, (int, float)):
|
||||
@ -507,7 +511,7 @@ def draw_border_image_impl(box, stream, image, slice_property,
|
||||
slice_bottom = compute_slice_dimension(image_slice[2], intrinsic_height)
|
||||
slice_left = compute_slice_dimension(image_slice[3], intrinsic_width)
|
||||
|
||||
style_repeat_x, style_repeat_y = repeats
|
||||
repeat_x, repeat_y = border_repeat
|
||||
|
||||
x, y, w, h, tl, tr, br, bl = box.rounded_border_box()
|
||||
px, py, pw, ph, ptl, ptr, pbr, pbl = box.rounded_padding_box()
|
||||
@ -523,10 +527,10 @@ def draw_border_image_impl(box, stream, image, slice_property,
|
||||
assert dimension.unit == 'px'
|
||||
return dimension.value
|
||||
|
||||
outset_top = compute_outset_dimension(outsets[0], border_top)
|
||||
outset_right = compute_outset_dimension(outsets[1], border_right)
|
||||
outset_bottom = compute_outset_dimension(outsets[2], border_bottom)
|
||||
outset_left = compute_outset_dimension(outsets[3], border_left)
|
||||
outset_top = compute_outset_dimension(border_outset[0], border_top)
|
||||
outset_right = compute_outset_dimension(border_outset[1], border_right)
|
||||
outset_bottom = compute_outset_dimension(border_outset[2], border_bottom)
|
||||
outset_left = compute_outset_dimension(border_outset[3], border_left)
|
||||
|
||||
x -= outset_left
|
||||
y -= outset_top
|
||||
@ -551,17 +555,16 @@ def draw_border_image_impl(box, stream, image, slice_property,
|
||||
# for percentage-based border-image-width values includes any expanded
|
||||
# area due to border-image-outset.
|
||||
border_top = compute_width_adjustment(
|
||||
width_property[0], border_top, slice_top, h)
|
||||
border_width[0], border_top, slice_top, h)
|
||||
border_right = compute_width_adjustment(
|
||||
width_property[1], border_right, slice_right, w)
|
||||
border_width[1], border_right, slice_right, w)
|
||||
border_bottom = compute_width_adjustment(
|
||||
width_property[2], border_bottom, slice_bottom, h)
|
||||
border_width[2], border_bottom, slice_bottom, h)
|
||||
border_left = compute_width_adjustment(
|
||||
width_property[3], border_left, slice_left, w)
|
||||
border_width[3], border_left, slice_left, w)
|
||||
|
||||
def draw_border_image_region(x, y, width, height, slice_x, slice_y,
|
||||
slice_width, slice_height,
|
||||
repeat_x='stretch', repeat_y='stretch',
|
||||
def draw_border_image_region(x, y, width, height, slice_x, slice_y, slice_width,
|
||||
slice_height, repeat_x='stretch', repeat_y='stretch',
|
||||
scale_x=None, scale_y=None):
|
||||
if 0 in (intrinsic_width, width, slice_width):
|
||||
scale_x = 0
|
||||
@ -652,73 +655,56 @@ def draw_border_image_impl(box, stream, image, slice_property,
|
||||
draw_border_image_region(
|
||||
x, y + h - border_bottom, border_left, border_bottom,
|
||||
0, intrinsic_height - slice_bottom, slice_left, slice_bottom)
|
||||
if slice_left + slice_right < intrinsic_width:
|
||||
if x_middle := slice_left + slice_right < intrinsic_width:
|
||||
# Top middle.
|
||||
draw_border_image_region(
|
||||
x + border_left, y, w - border_left - border_right, border_top,
|
||||
slice_left, 0, intrinsic_width - slice_left - slice_right,
|
||||
slice_top, repeat_x=style_repeat_x)
|
||||
slice_top, repeat_x=repeat_x)
|
||||
# Bottom middle.
|
||||
draw_border_image_region(
|
||||
x + border_left, y + h - border_bottom,
|
||||
w - border_left - border_right, border_bottom,
|
||||
slice_left, intrinsic_height - slice_bottom,
|
||||
intrinsic_width - slice_left - slice_right, slice_bottom,
|
||||
repeat_x=style_repeat_x)
|
||||
if slice_top + slice_bottom < intrinsic_height:
|
||||
repeat_x=repeat_x)
|
||||
if y_middle := slice_top + slice_bottom < intrinsic_height:
|
||||
# Right middle.
|
||||
draw_border_image_region(
|
||||
x + w - border_right, y + border_top,
|
||||
border_right, h - border_top - border_bottom,
|
||||
intrinsic_width - slice_right, slice_top,
|
||||
slice_right, intrinsic_height - slice_top - slice_bottom,
|
||||
repeat_y=style_repeat_y)
|
||||
repeat_y=repeat_y)
|
||||
# Left middle.
|
||||
draw_border_image_region(
|
||||
x, y + border_top, border_left, h - border_top - border_bottom,
|
||||
0, slice_top, slice_left,
|
||||
intrinsic_height - slice_top - slice_bottom,
|
||||
repeat_y=style_repeat_y)
|
||||
if (should_fill and slice_left + slice_right < intrinsic_width
|
||||
and slice_top + slice_bottom < intrinsic_height):
|
||||
repeat_y=repeat_y)
|
||||
if should_fill and x_middle and y_middle:
|
||||
# Fill middle.
|
||||
draw_border_image_region(
|
||||
x + border_left, y + border_top, w - border_left - border_right,
|
||||
h - border_top - border_bottom, slice_left, slice_top,
|
||||
intrinsic_width - slice_left - slice_right,
|
||||
intrinsic_height - slice_top - slice_bottom,
|
||||
repeat_x=style_repeat_x, repeat_y=style_repeat_y,
|
||||
repeat_x=repeat_x, repeat_y=repeat_y,
|
||||
scale_x=scale_left or scale_right, scale_y=scale_top or scale_bottom)
|
||||
|
||||
|
||||
def draw_border_image(box, stream):
|
||||
"""Draw ``box`` border image on ``stream``."""
|
||||
# See https://drafts.csswg.org/css-backgrounds-3/#border-images
|
||||
image = box.border_image
|
||||
|
||||
draw_border_image_impl(
|
||||
box, stream, image, box.style['border_image_slice'],
|
||||
box.style['border_image_repeat'], box.style['border_image_outset'],
|
||||
box.style['border_image_width'])
|
||||
|
||||
|
||||
def maybe_set_mask_border(box, stream):
|
||||
def set_mask_border(stream, box):
|
||||
"""Set ``box`` mask border as alpha state on ``stream``."""
|
||||
# See https://drafts.fxtf.org/css-masking/#the-mask-border
|
||||
if (box.style['mask_border_source'][0] != 'none'
|
||||
and box.mask_border_image is not None):
|
||||
x, y, w, h, tl, tr, br, bl = box.rounded_border_box()
|
||||
matrix = Matrix(e=x, f=y)
|
||||
matrix @= stream.ctm
|
||||
mask_stream = stream.set_alpha_state(
|
||||
x, y, w, h, box.style['mask_border_mode'] != 'luminosity')
|
||||
|
||||
image = box.mask_border_image
|
||||
|
||||
draw_border_image_impl(
|
||||
box, mask_stream, image, box.style['mask_border_slice'],
|
||||
box.style['mask_border_repeat'], box.style['mask_border_outset'],
|
||||
box.style['mask_border_width'])
|
||||
if box.style['mask_border_source'][0] == 'none' or box.mask_border_image is None:
|
||||
return
|
||||
x, y, w, h, tl, tr, br, bl = box.rounded_border_box()
|
||||
matrix = Matrix(e=x, f=y)
|
||||
matrix @= stream.ctm
|
||||
mask_stream = stream.set_alpha_state(x, y, w, h, box.style['mask_border_mode'])
|
||||
draw_border_image(
|
||||
box, mask_stream, box.mask_border_image, box.style['mask_border_slice'],
|
||||
box.style['mask_border_repeat'], box.style['mask_border_outset'],
|
||||
box.style['mask_border_width'])
|
||||
|
||||
|
||||
def clip_border_segment(stream, style, width, side, border_box,
|
||||
@ -1236,7 +1222,7 @@ def draw_inline_level(stream, page, box, offset_x=0, text_overflow='clip',
|
||||
boxes.InlineBlockBox, boxes.InlineFlexBox, boxes.InlineGridBox))
|
||||
draw_stacking_context(stream, stacking_context)
|
||||
else:
|
||||
maybe_set_mask_border(box, stream)
|
||||
set_mask_border(stream, box)
|
||||
draw_background(stream, box.background)
|
||||
draw_border(stream, box)
|
||||
if isinstance(box, (boxes.InlineBox, boxes.LineBox)):
|
||||
|
@ -112,13 +112,13 @@ class Stream(pydyf.Stream):
|
||||
self._states[key] = pydyf.Dictionary({'ca': alpha})
|
||||
super().set_state(key)
|
||||
|
||||
def set_alpha_state(self, x, y, width, height, is_alpha_based=False):
|
||||
def set_alpha_state(self, x, y, width, height, mode='luminosity'):
|
||||
alpha_stream = self.add_group(x, y, width, height)
|
||||
alpha_state = pydyf.Dictionary({
|
||||
'Type': '/ExtGState',
|
||||
'SMask': pydyf.Dictionary({
|
||||
'Type': '/Mask',
|
||||
'S': '/Alpha' if is_alpha_based else '/Luminosity',
|
||||
'S': f'/{mode.capitalize()}',
|
||||
'G': alpha_stream,
|
||||
}),
|
||||
'ca': 1,
|
||||
|
Loading…
Reference in New Issue
Block a user