mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:57:44 +00:00
LibWeb: Record painting commands in coordinates of stacking context
By storing painting command coordinates relative to the nearest stacking context we can get rid of the Translate command. Additionally, this allows us to easily check if the bounding rectangles of the commands cover or intersect within a stacking context. This should be useful if we decide to optimize by avoiding the execution of commands that will be overpainted by the results of subsequent commands.
This commit is contained in:
parent
311cc7d9b9
commit
4318bcf447
6 changed files with 76 additions and 68 deletions
|
@ -113,7 +113,7 @@ ScopedCornerRadiusClip::ScopedCornerRadiusClip(PaintContext& context, DevicePixe
|
|||
.bottom_right = border_radii.bottom_right.as_corner(context),
|
||||
.bottom_left = border_radii.bottom_left.as_corner(context)
|
||||
};
|
||||
auto clipper = BorderRadiusCornerClipper::create(corner_radii, border_rect, border_radii, corner_clip);
|
||||
auto clipper = BorderRadiusCornerClipper::create(corner_radii, context.painter().state().translation.map(border_rect.to_type<int>()).to_type<DevicePixels>(), border_radii, corner_clip);
|
||||
if (!clipper.is_error()) {
|
||||
m_corner_clipper = clipper.release_value();
|
||||
m_context.painter().sample_under_corners(*m_corner_clipper);
|
||||
|
|
|
@ -484,7 +484,7 @@ void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase ph
|
|||
.bottom_left = border_radii_data.bottom_left.as_corner(context)
|
||||
};
|
||||
if (border_radii_data.has_any_radius()) {
|
||||
auto corner_clipper = BorderRadiusCornerClipper::create(corner_radii, context.rounded_device_rect(*clip_rect), border_radii_data, CornerClip::Outside);
|
||||
auto corner_clipper = BorderRadiusCornerClipper::create(corner_radii, context.painter().state().translation.map(context.rounded_device_rect(*clip_rect).to_type<int>()).to_type<DevicePixels>(), border_radii_data, CornerClip::Outside);
|
||||
if (corner_clipper.is_error()) {
|
||||
dbgln("Failed to create overflow border-radius corner clipper: {}", corner_clipper.error());
|
||||
return;
|
||||
|
@ -689,7 +689,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
|||
.bottom_left = border_radii.bottom_left.as_corner(context)
|
||||
};
|
||||
if (border_radii.has_any_radius()) {
|
||||
auto clipper = BorderRadiusCornerClipper::create(corner_radii, clip_box, border_radii);
|
||||
auto clipper = BorderRadiusCornerClipper::create(corner_radii, context.painter().state().translation.map(clip_box.to_type<int>()).to_type<DevicePixels>(), border_radii);
|
||||
if (!clipper.is_error()) {
|
||||
corner_clipper = clipper.release_value();
|
||||
context.painter().sample_under_corners(*corner_clipper);
|
||||
|
|
|
@ -123,13 +123,6 @@ CommandResult DrawScaledBitmap::execute(CommandExecutionState& state) const
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult Translate::execute(CommandExecutionState& state) const
|
||||
{
|
||||
auto& painter = state.painter();
|
||||
painter.translate(translation_delta);
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult SaveState::execute(CommandExecutionState& state) const
|
||||
{
|
||||
auto& painter = state.painter();
|
||||
|
@ -168,9 +161,6 @@ CommandResult SetFont::execute(CommandExecutionState& state) const
|
|||
CommandResult PushStackingContext::execute(CommandExecutionState& state) const
|
||||
{
|
||||
auto& painter = state.painter();
|
||||
if (has_fixed_position) {
|
||||
painter.translate(-painter.translation());
|
||||
}
|
||||
if (semitransparent_or_has_non_identity_transform) {
|
||||
auto destination_rect = transformed_destination_rect.to_rounded<int>();
|
||||
|
||||
|
@ -485,57 +475,61 @@ void RecordingPainter::fill_rect(Gfx::IntRect const& rect, Color color)
|
|||
|
||||
void RecordingPainter::fill_path(FillPathUsingColorParams params)
|
||||
{
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(params.translation.value_or({})).to_type<int>();
|
||||
auto aa_translation = state().translation.map(params.translation.value_or(Gfx::FloatPoint {}));
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(aa_translation).to_type<int>();
|
||||
push_command(FillPathUsingColor {
|
||||
.path_bounding_rect = path_bounding_rect,
|
||||
.path = params.path,
|
||||
.color = params.color,
|
||||
.winding_rule = params.winding_rule,
|
||||
.aa_translation = params.translation,
|
||||
.aa_translation = aa_translation,
|
||||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::fill_path(FillPathUsingPaintStyleParams params)
|
||||
{
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(params.translation.value_or({})).to_type<int>();
|
||||
auto aa_translation = state().translation.map(params.translation.value_or(Gfx::FloatPoint {}));
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(aa_translation).to_type<int>();
|
||||
push_command(FillPathUsingPaintStyle {
|
||||
.path_bounding_rect = path_bounding_rect,
|
||||
.path = params.path,
|
||||
.paint_style = params.paint_style,
|
||||
.winding_rule = params.winding_rule,
|
||||
.opacity = params.opacity,
|
||||
.aa_translation = params.translation,
|
||||
.aa_translation = aa_translation,
|
||||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::stroke_path(StrokePathUsingColorParams params)
|
||||
{
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(params.translation.value_or({})).to_type<int>();
|
||||
auto aa_translation = state().translation.map(params.translation.value_or(Gfx::FloatPoint {}));
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(aa_translation).to_type<int>();
|
||||
push_command(StrokePathUsingColor {
|
||||
.path_bounding_rect = path_bounding_rect,
|
||||
.path = params.path,
|
||||
.color = params.color,
|
||||
.thickness = params.thickness,
|
||||
.aa_translation = params.translation,
|
||||
.aa_translation = aa_translation,
|
||||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::stroke_path(StrokePathUsingPaintStyleParams params)
|
||||
{
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(params.translation.value_or({})).to_type<int>();
|
||||
auto aa_translation = state().translation.map(params.translation.value_or(Gfx::FloatPoint {}));
|
||||
auto path_bounding_rect = params.path.bounding_box().translated(aa_translation).to_type<int>();
|
||||
push_command(StrokePathUsingPaintStyle {
|
||||
.path_bounding_rect = path_bounding_rect,
|
||||
.path = params.path,
|
||||
.paint_style = params.paint_style,
|
||||
.thickness = params.thickness,
|
||||
.aa_translation = params.translation,
|
||||
.aa_translation = aa_translation,
|
||||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::draw_ellipse(Gfx::IntRect const& a_rect, Color color, int thickness)
|
||||
{
|
||||
push_command(DrawEllipse {
|
||||
.rect = a_rect,
|
||||
.rect = state().translation.map(a_rect),
|
||||
.color = color,
|
||||
.thickness = thickness,
|
||||
});
|
||||
|
@ -544,7 +538,7 @@ void RecordingPainter::draw_ellipse(Gfx::IntRect const& a_rect, Color color, int
|
|||
void RecordingPainter::fill_ellipse(Gfx::IntRect const& a_rect, Color color, Gfx::AntiAliasingPainter::BlendMode blend_mode)
|
||||
{
|
||||
push_command(FillElipse {
|
||||
.rect = a_rect,
|
||||
.rect = state().translation.map(a_rect),
|
||||
.color = color,
|
||||
.blend_mode = blend_mode,
|
||||
});
|
||||
|
@ -553,7 +547,7 @@ void RecordingPainter::fill_ellipse(Gfx::IntRect const& a_rect, Color color, Gfx
|
|||
void RecordingPainter::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data)
|
||||
{
|
||||
push_command(PaintLinearGradient {
|
||||
.gradient_rect = gradient_rect,
|
||||
.gradient_rect = state().translation.map(gradient_rect),
|
||||
.linear_gradient_data = data,
|
||||
});
|
||||
}
|
||||
|
@ -561,7 +555,7 @@ void RecordingPainter::fill_rect_with_linear_gradient(Gfx::IntRect const& gradie
|
|||
void RecordingPainter::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position)
|
||||
{
|
||||
push_command(PaintConicGradient {
|
||||
.rect = rect,
|
||||
.rect = state().translation.map(rect),
|
||||
.conic_gradient_data = data,
|
||||
.position = position });
|
||||
}
|
||||
|
@ -569,7 +563,7 @@ void RecordingPainter::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, C
|
|||
void RecordingPainter::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size)
|
||||
{
|
||||
push_command(PaintRadialGradient {
|
||||
.rect = rect,
|
||||
.rect = state().translation.map(rect),
|
||||
.radial_gradient_data = data,
|
||||
.center = center,
|
||||
.size = size });
|
||||
|
@ -578,7 +572,7 @@ void RecordingPainter::fill_rect_with_radial_gradient(Gfx::IntRect const& rect,
|
|||
void RecordingPainter::draw_rect(Gfx::IntRect const& rect, Color color, bool rough)
|
||||
{
|
||||
push_command(DrawRect {
|
||||
.rect = rect,
|
||||
.rect = state().translation.map(rect),
|
||||
.color = color,
|
||||
.rough = rough });
|
||||
}
|
||||
|
@ -586,7 +580,7 @@ void RecordingPainter::draw_rect(Gfx::IntRect const& rect, Color color, bool rou
|
|||
void RecordingPainter::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, float opacity, Gfx::Painter::ScalingMode scaling_mode)
|
||||
{
|
||||
push_command(DrawScaledBitmap {
|
||||
.dst_rect = dst_rect,
|
||||
.dst_rect = state().translation.map(dst_rect),
|
||||
.bitmap = bitmap,
|
||||
.src_rect = src_rect,
|
||||
.opacity = opacity,
|
||||
|
@ -598,8 +592,8 @@ void RecordingPainter::draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color col
|
|||
{
|
||||
push_command(DrawLine {
|
||||
.color = color,
|
||||
.from = from,
|
||||
.to = to,
|
||||
.from = state().translation.map(from),
|
||||
.to = state().translation.map(to),
|
||||
.thickness = thickness,
|
||||
.style = style,
|
||||
.alternate_color = alternate_color,
|
||||
|
@ -609,7 +603,7 @@ void RecordingPainter::draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color col
|
|||
void RecordingPainter::draw_text(Gfx::IntRect const& rect, StringView raw_text, Gfx::TextAlignment alignment, Color color, Gfx::TextElision elision, Gfx::TextWrapping wrapping)
|
||||
{
|
||||
push_command(DrawText {
|
||||
.rect = rect,
|
||||
.rect = state().translation.map(rect),
|
||||
.raw_text = String::from_utf8(raw_text).release_value_but_fixme_should_propagate_errors(),
|
||||
.alignment = alignment,
|
||||
.color = color,
|
||||
|
@ -621,7 +615,7 @@ void RecordingPainter::draw_text(Gfx::IntRect const& rect, StringView raw_text,
|
|||
void RecordingPainter::draw_text(Gfx::IntRect const& rect, StringView raw_text, Gfx::Font const& font, Gfx::TextAlignment alignment, Color color, Gfx::TextElision elision, Gfx::TextWrapping wrapping)
|
||||
{
|
||||
push_command(DrawText {
|
||||
.rect = rect,
|
||||
.rect = state().translation.map(rect),
|
||||
.raw_text = String::from_utf8(raw_text).release_value_but_fixme_should_propagate_errors(),
|
||||
.alignment = alignment,
|
||||
.color = color,
|
||||
|
@ -634,7 +628,7 @@ void RecordingPainter::draw_text(Gfx::IntRect const& rect, StringView raw_text,
|
|||
void RecordingPainter::draw_signed_distance_field(Gfx::IntRect const& dst_rect, Color color, Gfx::GrayscaleBitmap const& sdf, float smoothing)
|
||||
{
|
||||
push_command(DrawSignedDistanceField {
|
||||
.rect = dst_rect,
|
||||
.rect = state().translation.map(dst_rect),
|
||||
.color = color,
|
||||
.sdf = sdf,
|
||||
.smoothing = smoothing,
|
||||
|
@ -645,18 +639,16 @@ void RecordingPainter::draw_text_run(Gfx::IntPoint baseline_start, Utf8View stri
|
|||
{
|
||||
push_command(DrawTextRun {
|
||||
.color = color,
|
||||
.baseline_start = baseline_start,
|
||||
.baseline_start = state().translation.map(baseline_start),
|
||||
.string = String::from_utf8(string.as_string()).release_value_but_fixme_should_propagate_errors(),
|
||||
.font = font,
|
||||
.rect = rect,
|
||||
.rect = state().translation.map(rect),
|
||||
});
|
||||
}
|
||||
|
||||
void RecordingPainter::add_clip_rect(Gfx::IntRect const& rect)
|
||||
{
|
||||
push_command(AddClipRect {
|
||||
.rect = rect,
|
||||
});
|
||||
push_command(AddClipRect { .rect = state().translation.map(rect) });
|
||||
}
|
||||
|
||||
void RecordingPainter::clear_clip_rect()
|
||||
|
@ -666,16 +658,12 @@ void RecordingPainter::clear_clip_rect()
|
|||
|
||||
void RecordingPainter::translate(int dx, int dy)
|
||||
{
|
||||
push_command(Translate {
|
||||
.translation_delta = Gfx::IntPoint { dx, dy },
|
||||
});
|
||||
m_state_stack.last().translation.translate(dx, dy);
|
||||
}
|
||||
|
||||
void RecordingPainter::translate(Gfx::IntPoint delta)
|
||||
{
|
||||
push_command(Translate {
|
||||
.translation_delta = delta,
|
||||
});
|
||||
m_state_stack.last().translation.translate(delta.to_type<float>());
|
||||
}
|
||||
|
||||
void RecordingPainter::set_font(Gfx::Font const& font)
|
||||
|
@ -685,11 +673,14 @@ void RecordingPainter::set_font(Gfx::Font const& font)
|
|||
|
||||
void RecordingPainter::save()
|
||||
{
|
||||
m_state_stack.append(m_state_stack.last());
|
||||
push_command(SaveState {});
|
||||
}
|
||||
|
||||
void RecordingPainter::restore()
|
||||
{
|
||||
VERIFY(m_state_stack.size() > 1);
|
||||
m_state_stack.take_last();
|
||||
push_command(RestoreState {});
|
||||
}
|
||||
|
||||
|
@ -699,10 +690,18 @@ void RecordingPainter::push_stacking_context(PushStackingContextParams params)
|
|||
.semitransparent_or_has_non_identity_transform = params.semitransparent_or_has_non_identity_transform,
|
||||
.has_fixed_position = params.has_fixed_position,
|
||||
.opacity = params.opacity,
|
||||
.source_rect = params.source_rect,
|
||||
.transformed_destination_rect = params.transformed_destination_rect,
|
||||
.painter_location = params.painter_location,
|
||||
.source_rect = state().translation.map(params.source_rect),
|
||||
.transformed_destination_rect = state().translation.map(params.transformed_destination_rect),
|
||||
.painter_location = state().translation.map(params.painter_location),
|
||||
});
|
||||
|
||||
if (params.has_fixed_position) {
|
||||
state().translation.set_translation(0, 0);
|
||||
}
|
||||
|
||||
if (params.semitransparent_or_has_non_identity_transform) {
|
||||
m_state_stack.append(State());
|
||||
}
|
||||
}
|
||||
|
||||
void RecordingPainter::pop_stacking_context(PopStackingContextParams params)
|
||||
|
@ -711,13 +710,17 @@ void RecordingPainter::pop_stacking_context(PopStackingContextParams params)
|
|||
.semitransparent_or_has_non_identity_transform = params.semitransparent_or_has_non_identity_transform,
|
||||
.scaling_mode = params.scaling_mode,
|
||||
});
|
||||
|
||||
if (params.semitransparent_or_has_non_identity_transform) {
|
||||
m_state_stack.take_last();
|
||||
}
|
||||
}
|
||||
|
||||
void RecordingPainter::paint_progressbar(Gfx::IntRect frame_rect, Gfx::IntRect progress_rect, Palette palette, int min, int max, int value, StringView text)
|
||||
{
|
||||
push_command(PaintProgressbar {
|
||||
.frame_rect = frame_rect,
|
||||
.progress_rect = progress_rect,
|
||||
.frame_rect = state().translation.map(frame_rect),
|
||||
.progress_rect = state().translation.map(progress_rect),
|
||||
.palette = palette,
|
||||
.min = min,
|
||||
.max = max,
|
||||
|
@ -728,13 +731,13 @@ void RecordingPainter::paint_progressbar(Gfx::IntRect frame_rect, Gfx::IntRect p
|
|||
|
||||
void RecordingPainter::paint_frame(Gfx::IntRect rect, Palette palette, Gfx::FrameStyle style)
|
||||
{
|
||||
push_command(PaintFrame { rect, palette, style });
|
||||
push_command(PaintFrame { state().translation.map(rect), palette, style });
|
||||
}
|
||||
|
||||
void RecordingPainter::apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, CSS::ResolvedBackdropFilter const& backdrop_filter)
|
||||
{
|
||||
push_command(ApplyBackdropFilter {
|
||||
.backdrop_region = backdrop_region,
|
||||
.backdrop_region = state().translation.map(backdrop_region),
|
||||
.border_radii_data = border_radii_data,
|
||||
.backdrop_filter = backdrop_filter,
|
||||
});
|
||||
|
@ -758,19 +761,19 @@ void RecordingPainter::paint_text_shadow(int blur_radius, Gfx::IntRect bounding_
|
|||
{
|
||||
push_command(PaintTextShadow {
|
||||
.blur_radius = blur_radius,
|
||||
.shadow_bounding_rect = bounding_rect,
|
||||
.text_rect = text_rect,
|
||||
.shadow_bounding_rect = state().translation.map(bounding_rect),
|
||||
.text_rect = state().translation.map(text_rect),
|
||||
.text = String::from_utf8(text.as_string()).release_value_but_fixme_should_propagate_errors(),
|
||||
.font = font,
|
||||
.color = color,
|
||||
.fragment_baseline = fragment_baseline,
|
||||
.draw_location = draw_location });
|
||||
.draw_location = state().translation.map(draw_location) });
|
||||
}
|
||||
|
||||
void RecordingPainter::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius)
|
||||
{
|
||||
push_command(FillRectWithRoundedCorners {
|
||||
.rect = rect,
|
||||
.rect = state().translation.map(rect),
|
||||
.color = color,
|
||||
.top_left_radius = top_left_radius,
|
||||
.top_right_radius = top_right_radius,
|
||||
|
@ -795,13 +798,13 @@ void RecordingPainter::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect
|
|||
|
||||
void RecordingPainter::push_stacking_context_with_mask(Gfx::IntRect paint_rect)
|
||||
{
|
||||
push_command(PushStackingContextWithMask { .paint_rect = paint_rect });
|
||||
push_command(PushStackingContextWithMask { .paint_rect = state().translation.map(paint_rect) });
|
||||
}
|
||||
|
||||
void RecordingPainter::pop_stacking_context_with_mask(RefPtr<Gfx::Bitmap> mask_bitmap, Gfx::Bitmap::MaskKind mask_kind, Gfx::IntRect paint_rect, float opacity)
|
||||
{
|
||||
push_command(PopStackingContextWithMask {
|
||||
.paint_rect = paint_rect,
|
||||
.paint_rect = state().translation.map(paint_rect),
|
||||
.mask_bitmap = mask_bitmap,
|
||||
.mask_kind = mask_kind,
|
||||
.opacity = opacity });
|
||||
|
@ -810,8 +813,8 @@ void RecordingPainter::pop_stacking_context_with_mask(RefPtr<Gfx::Bitmap> mask_b
|
|||
void RecordingPainter::draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness = 1)
|
||||
{
|
||||
push_command(DrawTriangleWave {
|
||||
.p1 = a_p1,
|
||||
.p2 = a_p2,
|
||||
.p1 = state().translation.map(a_p1),
|
||||
.p2 = state().translation.map(a_p2),
|
||||
.color = color,
|
||||
.amplitude = amplitude,
|
||||
.thickness = thickness });
|
||||
|
|
|
@ -83,12 +83,6 @@ struct DrawScaledBitmap {
|
|||
[[nodiscard]] CommandResult execute(CommandExecutionState&) const;
|
||||
};
|
||||
|
||||
struct Translate {
|
||||
Gfx::IntPoint translation_delta;
|
||||
|
||||
[[nodiscard]] CommandResult execute(CommandExecutionState&) const;
|
||||
};
|
||||
|
||||
struct SaveState {
|
||||
[[nodiscard]] CommandResult execute(CommandExecutionState&) const;
|
||||
};
|
||||
|
@ -367,7 +361,6 @@ using PaintingCommand = Variant<
|
|||
DrawText,
|
||||
FillRect,
|
||||
DrawScaledBitmap,
|
||||
Translate,
|
||||
SaveState,
|
||||
RestoreState,
|
||||
AddClipRect,
|
||||
|
@ -510,6 +503,17 @@ public:
|
|||
|
||||
void execute(Gfx::Bitmap&);
|
||||
|
||||
RecordingPainter()
|
||||
{
|
||||
m_state_stack.append(State());
|
||||
}
|
||||
|
||||
struct State {
|
||||
Gfx::AffineTransform translation;
|
||||
};
|
||||
State& state() { return m_state_stack.last(); }
|
||||
State const& state() const { return m_state_stack.last(); }
|
||||
|
||||
private:
|
||||
void push_command(PaintingCommand command)
|
||||
{
|
||||
|
@ -517,6 +521,7 @@ private:
|
|||
}
|
||||
|
||||
Vector<PaintingCommand> m_painting_commands;
|
||||
Vector<State> m_state_stack;
|
||||
};
|
||||
|
||||
class RecordingPainterStateSaver {
|
||||
|
|
|
@ -564,7 +564,7 @@ void paint_box_shadow(PaintContext& context,
|
|||
.offset_y = offset_y,
|
||||
.blur_radius = blur_radius,
|
||||
.spread_distance = spread_distance,
|
||||
.device_content_rect = device_content_rect,
|
||||
.device_content_rect = context.painter().state().translation.map(device_content_rect.to_type<int>()).to_type<DevicePixels>(),
|
||||
};
|
||||
|
||||
if (box_shadow_data.placement == ShadowPlacement::Inner) {
|
||||
|
|
|
@ -343,8 +343,8 @@ void StackingContext::paint(PaintContext& context) const
|
|||
paint_internal(context);
|
||||
context.painter().pop_stacking_context(pop_stacking_context_params);
|
||||
} else {
|
||||
context.painter().push_stacking_context(push_stacking_context_params);
|
||||
context.painter().translate(affine_transform.translation().to_rounded<int>());
|
||||
context.painter().push_stacking_context(push_stacking_context_params);
|
||||
paint_internal(context);
|
||||
context.painter().pop_stacking_context(pop_stacking_context_params);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue