Skip to content

Commit 3571761

Browse files
authored
Use ICC profiles for colors (#48)
1 parent a405a57 commit 3571761

955 files changed

Lines changed: 209 additions & 14 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

NOTICE

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,126 @@
1+
================================================================================
2+
The Creative Commons Zero v1.0 Universal License applies to:
3+
* The ICC profiles found in `crates/svg2pdf/src/icc/*`
4+
5+
================================================================================
6+
7+
CC0 1.0 Universal
8+
9+
Statement of Purpose
10+
11+
The laws of most jurisdictions throughout the world automatically confer
12+
exclusive Copyright and Related Rights (defined below) upon the creator and
13+
subsequent owner(s) (each and all, an "owner") of an original work of
14+
authorship and/or a database (each, a "Work").
15+
16+
Certain owners wish to permanently relinquish those rights to a Work for the
17+
purpose of contributing to a commons of creative, cultural and scientific
18+
works ("Commons") that the public can reliably and without fear of later
19+
claims of infringement build upon, modify, incorporate in other works, reuse
20+
and redistribute as freely as possible in any form whatsoever and for any
21+
purposes, including without limitation commercial purposes. These owners may
22+
contribute to the Commons to promote the ideal of a free culture and the
23+
further production of creative, cultural and scientific works, or to gain
24+
reputation or greater distribution for their Work in part through the use and
25+
efforts of others.
26+
27+
For these and/or other purposes and motivations, and without any expectation
28+
of additional consideration or compensation, the person associating CC0 with a
29+
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
30+
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
31+
and publicly distribute the Work under its terms, with knowledge of his or her
32+
Copyright and Related Rights in the Work and the meaning and intended legal
33+
effect of CC0 on those rights.
34+
35+
1. Copyright and Related Rights. A Work made available under CC0 may be
36+
protected by copyright and related or neighboring rights ("Copyright and
37+
Related Rights"). Copyright and Related Rights include, but are not limited
38+
to, the following:
39+
40+
i. the right to reproduce, adapt, distribute, perform, display, communicate,
41+
and translate a Work;
42+
43+
ii. moral rights retained by the original author(s) and/or performer(s);
44+
45+
iii. publicity and privacy rights pertaining to a person's image or likeness
46+
depicted in a Work;
47+
48+
iv. rights protecting against unfair competition in regards to a Work,
49+
subject to the limitations in paragraph 4(a), below;
50+
51+
v. rights protecting the extraction, dissemination, use and reuse of data in
52+
a Work;
53+
54+
vi. database rights (such as those arising under Directive 96/9/EC of the
55+
European Parliament and of the Council of 11 March 1996 on the legal
56+
protection of databases, and under any national implementation thereof,
57+
including any amended or successor version of such directive); and
58+
59+
vii. other similar, equivalent or corresponding rights throughout the world
60+
based on applicable law or treaty, and any national implementations thereof.
61+
62+
2. Waiver. To the greatest extent permitted by, but not in contravention of,
63+
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
64+
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
65+
and Related Rights and associated claims and causes of action, whether now
66+
known or unknown (including existing as well as future claims and causes of
67+
action), in the Work (i) in all territories worldwide, (ii) for the maximum
68+
duration provided by applicable law or treaty (including future time
69+
extensions), (iii) in any current or future medium and for any number of
70+
copies, and (iv) for any purpose whatsoever, including without limitation
71+
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
72+
the Waiver for the benefit of each member of the public at large and to the
73+
detriment of Affirmer's heirs and successors, fully intending that such Waiver
74+
shall not be subject to revocation, rescission, cancellation, termination, or
75+
any other legal or equitable action to disrupt the quiet enjoyment of the Work
76+
by the public as contemplated by Affirmer's express Statement of Purpose.
77+
78+
3. Public License Fallback. Should any part of the Waiver for any reason be
79+
judged legally invalid or ineffective under applicable law, then the Waiver
80+
shall be preserved to the maximum extent permitted taking into account
81+
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
82+
is so judged Affirmer hereby grants to each affected person a royalty-free,
83+
non transferable, non sublicensable, non exclusive, irrevocable and
84+
unconditional license to exercise Affirmer's Copyright and Related Rights in
85+
the Work (i) in all territories worldwide, (ii) for the maximum duration
86+
provided by applicable law or treaty (including future time extensions), (iii)
87+
in any current or future medium and for any number of copies, and (iv) for any
88+
purpose whatsoever, including without limitation commercial, advertising or
89+
promotional purposes (the "License"). The License shall be deemed effective as
90+
of the date CC0 was applied by Affirmer to the Work. Should any part of the
91+
License for any reason be judged legally invalid or ineffective under
92+
applicable law, such partial invalidity or ineffectiveness shall not
93+
invalidate the remainder of the License, and in such case Affirmer hereby
94+
affirms that he or she will not (i) exercise any of his or her remaining
95+
Copyright and Related Rights in the Work or (ii) assert any associated claims
96+
and causes of action with respect to the Work, in either case contrary to
97+
Affirmer's express Statement of Purpose.
98+
99+
4. Limitations and Disclaimers.
100+
101+
a. No trademark or patent rights held by Affirmer are waived, abandoned,
102+
surrendered, licensed or otherwise affected by this document.
103+
104+
b. Affirmer offers the Work as-is and makes no representations or warranties
105+
of any kind concerning the Work, express, implied, statutory or otherwise,
106+
including without limitation warranties of title, merchantability, fitness
107+
for a particular purpose, non infringement, or the absence of latent or
108+
other defects, accuracy, or the present or absence of errors, whether or not
109+
discoverable, all to the greatest extent permissible under applicable law.
110+
111+
c. Affirmer disclaims responsibility for clearing rights of other persons
112+
that may apply to the Work or any use thereof, including without limitation
113+
any person's Copyright and Related Rights in the Work. Further, Affirmer
114+
disclaims responsibility for obtaining any necessary consents, permissions
115+
or other rights required for any use of the Work.
116+
117+
d. Affirmer understands and acknowledges that Creative Commons is not a
118+
party to this document and has no duty or obligation with respect to this
119+
CC0 or use of the Work.
120+
121+
For more information, please see
122+
http://creativecommons.org/publicdomain/zero/1.0/
123+
1124
================================================================================
2125
The CC BY-SA 4.0 License applies to:
3126

crates/svg2pdf/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ miniz_oxide = "0.7"
2222
pdf-writer = "0.9"
2323
usvg = { version = "0.36", default-features = false }
2424
image = { version = "0.24", default-features = false, features = ["jpeg", "png", "gif"], optional = true }
25+
once_cell = "1.18.0"
2526

2627
[dev-dependencies]
2728
usvg = { version = "0.36.0" }
360 Bytes
Binary file not shown.

crates/svg2pdf/src/icc/sRGB-v4.icc

480 Bytes
Binary file not shown.

crates/svg2pdf/src/lib.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,20 @@ Among the unsupported features are currently:
4646
mod render;
4747
mod util;
4848

49+
use once_cell::sync::Lazy;
4950
use pdf_writer::{Chunk, Content, Filter, Finish, Pdf, Rect, Ref, TextStr};
5051
use usvg::utils::view_box_to_transform;
5152
use usvg::{Align, AspectRatio, NonZeroRect, Size, Transform, Tree, TreeParsing};
5253

5354
use crate::render::tree_to_stream;
5455
use crate::util::context::Context;
55-
use crate::util::helper::dpi_ratio;
56+
use crate::util::helper::{deflate, dpi_ratio};
57+
58+
// The ICC profiles.
59+
static SRGB_ICC_DEFLATED: Lazy<Vec<u8>> =
60+
Lazy::new(|| deflate(include_bytes!("icc/sRGB-v4.icc")));
61+
static GRAY_ICC_DEFLATED: Lazy<Vec<u8>> =
62+
Lazy::new(|| deflate(include_bytes!("icc/sGrey-v4.icc")));
5663

5764
/// Set size and scaling preferences for the conversion.
5865
#[derive(Copy, Clone)]
@@ -201,10 +208,12 @@ pub fn convert_tree(tree: &Tree, options: Options) -> Vec<u8> {
201208
.isolated(true)
202209
.knockout(false)
203210
.color_space()
204-
.srgb();
211+
.icc_based(ctx.deferrer.srgb_ref());
205212
page.contents(content_ref);
206213
page.finish();
207214

215+
write_color_spaces(&mut ctx, &mut pdf);
216+
208217
let document_info_id = ctx.alloc_ref();
209218
pdf.document_info(document_info_id).producer(TextStr("svg2pdf"));
210219

@@ -341,9 +350,32 @@ pub fn convert_tree_into(
341350
let mut resources = x_object.resources();
342351
ctx.deferrer.pop(&mut resources);
343352

353+
resources.finish();
354+
x_object.finish();
355+
356+
write_color_spaces(&mut ctx, chunk);
357+
344358
ctx.alloc_ref()
345359
}
346360

361+
fn write_color_spaces(ctx: &mut Context, chunk: &mut Chunk) {
362+
if ctx.deferrer.used_srgb() {
363+
chunk
364+
.icc_profile(ctx.deferrer.srgb_ref(), &SRGB_ICC_DEFLATED)
365+
.n(3)
366+
.range([0.0, 1.0, 0.0, 1.0, 0.0, 1.0])
367+
.filter(Filter::FlateDecode);
368+
}
369+
370+
if ctx.deferrer.used_sgray() {
371+
chunk
372+
.icc_profile(ctx.deferrer.sgray_ref(), &GRAY_ICC_DEFLATED)
373+
.n(1)
374+
.range([0.0, 1.0])
375+
.filter(Filter::FlateDecode);
376+
}
377+
}
378+
347379
/// Return the dimensions of the PDF page
348380
fn pdf_size(tree: &Tree, options: Options) -> Size {
349381
// If no custom viewport is defined, we use the size of the tree.

crates/svg2pdf/src/render/clip_path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ fn create_complex_clip_path(
192192
.isolated(false)
193193
.knockout(false)
194194
.color_space()
195-
.srgb();
195+
.icc_based(ctx.deferrer.srgb_ref());
196196

197197
x_object.bbox(pdf_bbox);
198198
x_object.finish();

crates/svg2pdf/src/render/gradient.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ fn shading_soft_mask(
135135
.isolated(false)
136136
.knockout(false)
137137
.color_space()
138-
.d65_gray();
138+
.icc_based(ctx.deferrer.sgray_ref());
139139

140140
if ctx.options.compress {
141141
x_object.filter(Filter::FlateDecode);
@@ -166,9 +166,9 @@ fn shading_function(
166166
let mut shading = chunk.function_shading(shading_ref);
167167
shading.shading_type(properties.shading_type);
168168
if use_opacities {
169-
shading.color_space().d65_gray();
169+
shading.color_space().icc_based(ctx.deferrer.sgray_ref());
170170
} else {
171-
shading.color_space().srgb();
171+
shading.color_space().icc_based(ctx.deferrer.srgb_ref());
172172
}
173173

174174
shading.function(function_ref);

crates/svg2pdf/src/render/group.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn create_x_object(
7878
.isolated(group.is_isolated())
7979
.knockout(false)
8080
.color_space()
81-
.srgb();
81+
.icc_based(ctx.deferrer.srgb_ref());
8282

8383
x_object.bbox(pdf_bbox);
8484
x_object.finish();

crates/svg2pdf/src/render/mask.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub fn create(
8787
.isolated(false)
8888
.knockout(false)
8989
.color_space()
90-
.srgb();
90+
.icc_based(ctx.deferrer.srgb_ref());
9191

9292
x_object.bbox(actual_rect.to_pdf_rect());
9393
x_object.finish();

0 commit comments

Comments
 (0)