mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
vendor/hayro-interpret/src/pattern.rs: ShadingPattern::new takes the default colour spaces (#3018) and no opacity (this PR); without_opacity (#2977) and set_alpha both kept
This commit is contained in:
@@ -7316,6 +7316,38 @@ trailer << /Root 1 0 R >>
|
||||
assert_eq!(px(75, 50), vec![255, 255, 255, 255], "outside the mask");
|
||||
}
|
||||
|
||||
/// Issue #3176: `CA` / `ca` belong to the graphics state at paint time, so a `gs` after
|
||||
/// `SCN` / `scn` still fades a shading pattern, and a stroke takes the stroke alpha. The
|
||||
/// pattern took the fill alpha current at `scn`/`SCN`, so both shapes came out opaque.
|
||||
#[test]
|
||||
fn shading_pattern_uses_the_alpha_current_at_paint_time() {
|
||||
let content = "/Pattern CS /P0 SCN /S1 gs 10 w 0 75 m 100 75 l S /Pattern cs /P0 scn /F1 gs 0 0 100 50 re f";
|
||||
let pdf = format!(
|
||||
"%PDF-1.7
|
||||
1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
|
||||
2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj
|
||||
3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 100 100] /Contents 4 0 R
|
||||
/Resources << /ExtGState << /S1 << /CA 0.25 >> /F1 << /ca 0.25 >> >> /Pattern << /P0 5 0 R >> >> >> endobj
|
||||
4 0 obj << /Length {} >> stream
|
||||
{content}
|
||||
endstream endobj
|
||||
5 0 obj << /PatternType 2 /Shading << /ShadingType 2 /ColorSpace /DeviceRGB /Coords [0 0 100 0] /Extend [true true]
|
||||
/Function << /FunctionType 2 /Domain [0 1] /C0 [1 0 0] /C1 [1 0 0] /N 1 >> >> >> endobj
|
||||
trailer << /Root 1 0 R >>
|
||||
%%EOF",
|
||||
content.len()
|
||||
);
|
||||
let mut r = PageRenderer::new(Arc::new(pdf.into_bytes()), RenderConfig::default());
|
||||
let p = r.render(RenderRequest { page: 0, kind: RequestKind::Pixels, tile: None, scale: 1.0, tag: 0, ..Default::default() });
|
||||
assert!(p.error.is_none(), "{:?}", p.error);
|
||||
let px = |x: u32, y: u32| p.rgba[((y * p.width + x) * 4) as usize..][..4].to_vec();
|
||||
// Red at 25% over white is about (255, 191, 191); opaque red would be (255, 0, 0).
|
||||
for (what, x, y) in [("the stroke under /CA 0.25", 50, 25), ("the fill under /ca 0.25", 50, 75)] {
|
||||
let c = px(x, y);
|
||||
assert!(c[0] >= 250 && (185..=197).contains(&c[1]) && (185..=197).contains(&c[2]), "{what}: {c:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// ISO 32000-2 §8.5.4: `W` / `W*` clip with the current path once whichever path-painting
|
||||
/// operator ends it has painted it, `S`, `f` or `B` as much as `n`. The vendored interpreter
|
||||
/// applied the clip only on `n`: after `re W* S` everything later painted outside the clip,
|
||||
|
||||
@@ -159,6 +159,8 @@ pub(crate) fn get_paint<'a>(context: &Context<'a>, is_stroke: bool) -> Paint<'a>
|
||||
pattern.set_transfer_function(tf.clone());
|
||||
}
|
||||
|
||||
// PdfCraft patch: `CA`/`ca` can be set by a `gs` after the pattern colour operator, so use the alpha current at paint time.
|
||||
pattern.set_alpha(data.alpha);
|
||||
pattern.pre_concat_transform(context.root_transform());
|
||||
|
||||
Paint::Pattern(Box::new(pattern))
|
||||
|
||||
+9
-3
@@ -46,7 +46,6 @@ impl<'a> Pattern<'a> {
|
||||
Object::Dict(dict) => Some(Self::Shading(ShadingPattern::new(
|
||||
&dict,
|
||||
&ctx.interpreter_cache.object_cache,
|
||||
ctx.get().graphics_state.non_stroke_alpha,
|
||||
defaults,
|
||||
)?)),
|
||||
Object::Stream(stream) => Some(Self::Tiling(Box::new(TilingPattern::new(
|
||||
@@ -81,6 +80,14 @@ impl<'a> Pattern<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// PdfCraft patch: set the alpha of the graphics state in effect when the pattern is painted. The `gs` operator
|
||||
/// can come after `scn`/`SCN`, so the alpha must not be captured when the pattern is selected.
|
||||
pub(crate) fn set_alpha(&mut self, alpha: f32) {
|
||||
if let Self::Shading(p) = self {
|
||||
p.opacity = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_transfer_function(&mut self, tf: ActiveTransferFunction) {
|
||||
if let Self::Shading(p) = self {
|
||||
p.transfer_function = Some(tf);
|
||||
@@ -114,7 +121,6 @@ impl ShadingPattern {
|
||||
pub(crate) fn new(
|
||||
dict: &Dict<'_>,
|
||||
cache: &Cache,
|
||||
opacity: f32,
|
||||
defaults: &DefaultColorSpaces<'_, '_>,
|
||||
) -> Option<Self> {
|
||||
let shading = dict.get::<Object<'_>>(SHADING).and_then(|o| {
|
||||
@@ -133,7 +139,7 @@ impl ShadingPattern {
|
||||
|
||||
Some(Self {
|
||||
shading: Arc::new(shading),
|
||||
opacity,
|
||||
opacity: 1.0,
|
||||
matrix,
|
||||
transfer_function: None,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user