mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-02 14:16:56 -06:00
Envelopes: Anti-Alias and Preserve Shape Using change how distorted images draw
Envelope Options stored Anti-Alias and Preserve Shape Using, but nothing that draws an image read them: a distorted image was always smoothed and always cut into clip groups. - With Anti-Alias off, each piece of a distorted image is marked pixelated (saved as `pixelated`). The renderer draws it with nearest-neighbor sampling and without mips, SVG export writes `image-rendering: pixelated`, and PDF export writes it without /Interpolate. - With Preserve Shape Using Transparency, each piece is the image with a white opacity mask in the piece's shape instead of a clip group. The renderer paints an image whose mask is one plain white path straight into that path, as it does for an image in a clip group, when the path lies inside the image's frame. Docs: docs/mcp.md, docs/target-app-parity.md.
This commit is contained in:
@@ -6,25 +6,28 @@ use crate::images;
|
||||
|
||||
impl Renderer {
|
||||
pub(crate) fn draw_image(&mut self, ctx: &mut RenderContext, f: &Frame, im: &vectorcraft_doc::ImageObject) {
|
||||
self.draw_image_in(ctx, f, im, None);
|
||||
self.draw_image_in(ctx, f, im, None, false);
|
||||
}
|
||||
|
||||
/// Draw an image, or with `area` (a region in the document inside the image's frame, see
|
||||
/// [`plain_image`]) the image painted into that region.
|
||||
/// [`plain_image`]) the image painted into that region; with `pixelated`
|
||||
/// ([`vectorcraft_doc::NodeExtras::pixelated`]) without smoothing.
|
||||
pub(super) fn draw_image_in(
|
||||
&mut self,
|
||||
ctx: &mut RenderContext,
|
||||
f: &Frame,
|
||||
im: &vectorcraft_doc::ImageObject,
|
||||
area: Option<&(BezPath, FillRule)>,
|
||||
pixelated: bool,
|
||||
) {
|
||||
let rect = Rect::new(0.0, 0.0, im.width as f64, im.height as f64);
|
||||
// Outline mode draws the image's frame, and with Document Setup → Show Images in Outline
|
||||
// Mode its pixels in greyscale under the frame.
|
||||
let outline = f.opts.outline;
|
||||
// With mips the full pixels are only looked at (not marked used) until they're drawn, and
|
||||
// a mip the store holds is drawn without them: they may have been dropped (#2820).
|
||||
let mips = f.opts.image_mips;
|
||||
// a mip the store holds is drawn without them: they may have been dropped (#2820). A
|
||||
// pixelated image is drawn from its full pixels: a mip averages them.
|
||||
let mips = f.opts.image_mips && !pixelated;
|
||||
let unit = f.view * im.xf * Affine::scale_non_uniform(im.width as f64, im.height as f64);
|
||||
let shown = if outline && !f.doc.setup.outline_images {
|
||||
None
|
||||
@@ -39,7 +42,7 @@ impl Renderer {
|
||||
if let Some(pm) = shown {
|
||||
let sx = im.width as f64 / pm.width().max(1) as f64;
|
||||
let sy = im.height as f64 / pm.height().max(1) as f64;
|
||||
let quality = if f.opts.smooth_images { peniko::ImageQuality::Medium } else { peniko::ImageQuality::Low };
|
||||
let quality = if f.opts.smooth_images && !pixelated { peniko::ImageQuality::Medium } else { peniko::ImageQuality::Low };
|
||||
let sampler = peniko::ImageSampler { quality, ..Default::default() };
|
||||
ctx.set_paint(vello_cpu::Image { image: vello_cpu::ImageSource::Pixmap(pm), sampler });
|
||||
match area {
|
||||
|
||||
@@ -142,6 +142,21 @@ impl Renderer {
|
||||
if self.skipped(f, a) {
|
||||
return;
|
||||
}
|
||||
// An image masked by one white shape painted straight into the shape, as an image in a
|
||||
// clip group is (envelopes with Preserve Shape Using Transparency cut distorted images into
|
||||
// many such pieces).
|
||||
if let Some(m) = a.extras().mask.as_deref()
|
||||
&& !f.opts.outline
|
||||
&& !self.is_shape(a)
|
||||
&& let NodeKind::Image(im) = &a.kind
|
||||
&& white_shape_mask(m)
|
||||
&& let Some(region) = self.clip_of(&m.art)
|
||||
&& shape_masked_image(a, im, ®ion.0)
|
||||
{
|
||||
self.draw_image_in(ctx, f, im, Some(®ion), a.extras().pixelated);
|
||||
self.stats.drawn += 1;
|
||||
return;
|
||||
}
|
||||
if let Some(m) = a.extras().mask.as_deref()
|
||||
&& !m.disabled
|
||||
&& !f.opts.outline
|
||||
@@ -373,7 +388,7 @@ impl Renderer {
|
||||
&& let NodeKind::Image(im) = &image.kind
|
||||
&& plain_image(image, im, ®ion.0)
|
||||
{
|
||||
self.draw_image_in(ctx, f, im, Some(®ion));
|
||||
self.draw_image_in(ctx, f, im, Some(®ion), image.extras().pixelated);
|
||||
self.stats.drawn += 1;
|
||||
return;
|
||||
}
|
||||
@@ -427,7 +442,7 @@ impl Renderer {
|
||||
self.draw_shape(ctx, f, n, &bp, *rule);
|
||||
}
|
||||
NodeKind::Text(t) => self.draw_text(ctx, f, n, t),
|
||||
NodeKind::Image(im) => self.draw_image(ctx, f, im),
|
||||
NodeKind::Image(im) => self.draw_image_in(ctx, f, im, None, n.extras().pixelated),
|
||||
NodeKind::SymbolInstance { symbol, xf } => {
|
||||
if let Some(sym) = f.doc.symbols.iter().find(|s| &s.name == symbol)
|
||||
&& self.charge_symbol(&sym.art)
|
||||
|
||||
Reference in New Issue
Block a user