mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-30 13:16:56 -06:00
Merge PR #570
This commit is contained in:
@@ -181,6 +181,7 @@ Newest first.
|
||||
- **2026-10-11** · Properties gains InDesign's Pathfinder section (Add, Subtract, Intersect, Exclude Overlap, Minus Back) with several objects selected; section titles and icon buttons have accessible names. No readiness percentage change.
|
||||
- **2026-10-12** · The Eyedropper samples a placed image: clicking the photo with text (or objects) selected fills them with the image's colour under the pointer, as an unnamed colour (`color.sample`), as in InDesign. Images on locked layers can be sampled. No readiness percentage change.
|
||||
- **2026-10-12** · The section marker character shows its section's marker text on document pages (nothing when the section has none) instead of the word "Section", which stays on parent pages; editing the marker recomposes (#556). No readiness percentage change.
|
||||
- **2026-10-12** · On screen, blend modes blend with the objects below and not with the paper, as in InDesign and in PDF export: a Color Dodge or Screen object over blank paper shows as it is. No readiness percentage change.
|
||||
- **2026-10-12** · Words in capitals hyphenate like capitalized words (FERRUM COM-MODI), as in InDesign; Hyphenate Capitalized Words off keeps them whole. No readiness percentage change.
|
||||
- **2026-10-12** · Load Swatches refuses an `.ase` file with more than 100,000 colors, and `swatch.load` merges a file of 100,000 colors in under 0.1 s (it took 9.6 s of CPU in a test build). No readiness percentage change.
|
||||
- **2026-10-11** · `transform.move {copy}`, Edit › Duplicate and Step and Repeat return the copies' ids, so a script can go on with them. No readiness percentage change.
|
||||
|
||||
@@ -394,6 +394,13 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Blend modes blend with the objects below, not with the paper (as in InDesign and in PDF,
|
||||
// where the page's group starts transparent): a Color Dodge or Screen object over blank paper
|
||||
// shows as it is. So the items are drawn in their own group, laid over the paper once.
|
||||
let isolate = f.opts.paper && spread_blends(doc, sp);
|
||||
if isolate {
|
||||
ctx.push_layer(None, None, None, None, None);
|
||||
}
|
||||
// Layers back to front; within each layer parent items first (document spreads only).
|
||||
for layer in doc.layers.iter().rev() {
|
||||
if !layer.visible || f.opts.printing_only && !layer.printable {
|
||||
@@ -428,6 +435,9 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
if isolate {
|
||||
ctx.pop_layer();
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_item(&mut self, ctx: &mut RenderContext, f: &Frame, it: &Item, parent: Affine, page: Option<usize>) {
|
||||
@@ -922,6 +932,17 @@ pub(crate) fn overprints(f: &Frame, swatch: &str, tint: f32, flag: bool) -> bool
|
||||
f.opts.overprint_preview && (flag || (f.doc.settings.overprint_black && swatch == designcraft_color::swatch::BLACK && tint >= 0.999))
|
||||
}
|
||||
|
||||
/// Does any item on the spread, or on the parent pages it shows, use a blend mode other than
|
||||
/// Normal (groups and pasted-in items included)?
|
||||
fn spread_blends(doc: &Document, sp: &designcraft_doc::Spread) -> bool {
|
||||
let blends = |it: &Item| {
|
||||
let mut any = false;
|
||||
it.walk(&mut |i| any |= i.blend != Default::default());
|
||||
any
|
||||
};
|
||||
sp.items.iter().any(|i| blends(i)) || doc.parents.iter().any(|p| p.items.iter().any(|i| blends(i)))
|
||||
}
|
||||
|
||||
pub fn blend_mode(b: DcBlend) -> BlendMode {
|
||||
use DcBlend as B;
|
||||
let mix = match b {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
//! Blend modes blend with the objects below, never with the paper: over blank paper an object in
|
||||
//! Color Dodge (or any other mode) shows as it is, as in InDesign and in the exported PDF.
|
||||
|
||||
use designcraft_color::{BlendMode, Color, Swatch};
|
||||
use designcraft_compose::Cache;
|
||||
use designcraft_doc::{Document, Fill, Item, ItemId, Shape, SpreadRef, build::NewDocument};
|
||||
use designcraft_geom::{Affine, Rect, shapes};
|
||||
use designcraft_render::{Placed, RenderOptions, Renderer};
|
||||
|
||||
/// A 200 x 100 page: a mid-blue rectangle on the right half, and over both halves a black
|
||||
/// rectangle in `blend`.
|
||||
fn document(blend: BlendMode) -> Document {
|
||||
let mut d = Document::new(&NewDocument { width: 200.0, height: 100.0, facing_pages: false, ..Default::default() });
|
||||
d.swatches.push(Swatch::color("Mid blue", Color::rgb(0.2, 0.4, 0.6)));
|
||||
let mut rect = |r: Rect, swatch: &str, blend: BlendMode| {
|
||||
let id = ItemId(d.alloc());
|
||||
let mut it = Item::new(id, d.default_layer(), Shape::Rectangle, shapes::rectangle(r));
|
||||
it.fill = Fill::swatch(swatch);
|
||||
it.blend = blend;
|
||||
d.insert_item(SpreadRef::Doc(0), it, None).unwrap();
|
||||
};
|
||||
rect(Rect::new(100.0, 0.0, 200.0, 100.0), "Mid blue", BlendMode::Normal);
|
||||
rect(Rect::new(20.0, 20.0, 180.0, 80.0), "[Black]", blend);
|
||||
d
|
||||
}
|
||||
|
||||
fn pixel(d: &Document, x: u32, y: u32) -> [u8; 4] {
|
||||
let mut r = Renderer::new();
|
||||
r.threads = 0;
|
||||
let placed = [Placed { spread: SpreadRef::Doc(0), xf: Affine::IDENTITY }];
|
||||
let img = r.render(d, &Cache::new(), &placed, 200, 100, Affine::IDENTITY, &RenderOptions::default());
|
||||
let i = ((y * 200 + x) * 4) as usize;
|
||||
[img.pixels[i], img.pixels[i + 1], img.pixels[i + 2], img.pixels[i + 3]]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_blend_mode_over_blank_paper_shows_the_object_as_it_is() {
|
||||
let d = document(BlendMode::ColorDodge);
|
||||
// Over the paper: black ([Black] shows as about 52 grey), as in Normal (it used to dodge the white paper to white, vanishing).
|
||||
let over_paper = pixel(&d, 50, 50);
|
||||
assert!(over_paper[0] < 80 && over_paper[1] < 80 && over_paper[2] < 80, "{over_paper:?}");
|
||||
// Over the blue rectangle it still blends: black in Color Dodge leaves the blue as it is.
|
||||
let over_blue = pixel(&d, 150, 50);
|
||||
assert!(over_blue[2] > 120 && over_blue[2] > over_blue[0], "{over_blue:?}");
|
||||
// Normal is unchanged.
|
||||
let normal = pixel(&document(BlendMode::Normal), 150, 50);
|
||||
assert!(normal[0] < 80 && normal[2] < 80, "{normal:?}");
|
||||
}
|
||||
Reference in New Issue
Block a user