Skip to content

Commit ceec496

Browse files
committed
Add remaining shading types
1 parent f7364b4 commit ceec496

2 files changed

Lines changed: 174 additions & 18 deletions

File tree

src/color.rs

Lines changed: 160 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -893,11 +893,17 @@ writer!(ShadingPattern: |obj| {
893893
});
894894

895895
impl<'a> ShadingPattern<'a> {
896-
/// Start writing the `/Shading` dictionary.
897-
pub fn shading(&mut self) -> Shading<'_> {
896+
/// Start writing the `/Shading` dictionary for a type 1, 2, or 3 shading.
897+
pub fn function_shading(&mut self) -> FunctionShading<'_> {
898898
self.dict.insert(Name(b"Shading")).start()
899899
}
900900

901+
/// Add an indirect reference to a `/Shading` dictionary or a shading stream.
902+
pub fn shading_ref(&mut self, id: Ref) -> &mut Self {
903+
self.dict.pair(Name(b"Shading"), id);
904+
self
905+
}
906+
901907
/// Write the `/Matrix` attribute.
902908
///
903909
/// Sets the matrix to use for the pattern. Defaults to the identity matrix.
@@ -918,18 +924,18 @@ deref!('a, ShadingPattern<'a> => Dict< 'a>, dict);
918924
///
919925
/// This struct is created by [`PdfWriter::shading`] and
920926
/// [`ShadingPattern::shading`].
921-
pub struct Shading<'a> {
927+
pub struct FunctionShading<'a> {
922928
dict: Dict<'a>,
923929
}
924930

925-
writer!(Shading: |obj| Self { dict: obj.dict() });
931+
writer!(FunctionShading: |obj| Self { dict: obj.dict() });
926932

927-
impl<'a> Shading<'a> {
933+
impl<'a> FunctionShading<'a> {
928934
/// Write the `/ShadingType` attribute.
929935
///
930936
/// Sets the type of shading. The available and required attributes change
931937
/// depending on this. Required.
932-
pub fn shading_type(&mut self, kind: ShadingType) -> &mut Self {
938+
pub fn shading_type(&mut self, kind: FunctionShadingType) -> &mut Self {
933939
self.dict.pair(Name(b"ShadingType"), kind.to_int());
934940
self
935941
}
@@ -990,7 +996,8 @@ impl<'a> Shading<'a> {
990996

991997
/// Write the `/Function` attribute.
992998
///
993-
/// Sets the 2-in function to use for shading. Required.
999+
/// Sets the function to use for shading. Number of in- and outputs depends
1000+
/// on shading type. Required for type 1, 2, and 3, optional otherwise.
9941001
pub fn function(&mut self, function: Ref) -> &mut Self {
9951002
self.dict.pair(Name(b"Function"), function);
9961003
self
@@ -1016,21 +1023,133 @@ impl<'a> Shading<'a> {
10161023
}
10171024
}
10181025

1019-
deref!('a, Shading<'a> => Dict<'a>, dict);
1026+
deref!('a, FunctionShading<'a> => Dict<'a>, dict);
10201027

1021-
/// What kind of shading to use.
1028+
/// Writer for a _embedded file stream_.
1029+
///
1030+
/// This struct is created by [`PdfWriter::stream_shading`].
1031+
pub struct StreamShading<'a> {
1032+
stream: Stream<'a>,
1033+
}
1034+
1035+
impl<'a> StreamShading<'a> {
1036+
/// Create a new character map writer.
1037+
pub(crate) fn start(stream: Stream<'a>) -> Self {
1038+
Self { stream }
1039+
}
1040+
1041+
/// Write the `/ShadingType` attribute.
1042+
///
1043+
/// Sets the type of shading. The available and required attributes change
1044+
/// depending on this. Required.
1045+
pub fn shading_type(&mut self, kind: StreamShadingType) -> &mut Self {
1046+
self.stream.pair(Name(b"ShadingType"), kind.to_int());
1047+
self
1048+
}
1049+
1050+
/// Start writing the `/ColorSpace` attribute.
1051+
///
1052+
/// Sets the color space of the shading function. May not be a `Pattern`
1053+
/// space. Required.
1054+
pub fn color_space(&mut self) -> ColorSpace<'_> {
1055+
self.stream.insert(Name(b"ColorSpace")).start()
1056+
}
1057+
1058+
/// Write the `/Background` attribute.
1059+
///
1060+
/// Sets the background color of the area to be shaded. The `background`
1061+
/// iterator must contain exactly as many elements as the current
1062+
/// color space has dimensions.
1063+
pub fn background(&mut self, background: impl IntoIterator<Item = f32>) -> &mut Self {
1064+
self.stream.insert(Name(b"Background")).array().items(background);
1065+
self
1066+
}
1067+
1068+
/// Write the `/BBox` attribute.
1069+
///
1070+
/// Sets the bounding box of the shading in the target coordinate system.
1071+
pub fn bbox(&mut self, bbox: Rect) -> &mut Self {
1072+
self.stream.pair(Name(b"BBox"), bbox);
1073+
self
1074+
}
1075+
1076+
/// Write the `/AntiAlias` attribute.
1077+
///
1078+
/// Sets whether to anti-alias the shading.
1079+
pub fn anti_alias(&mut self, anti_alias: bool) -> &mut Self {
1080+
self.stream.pair(Name(b"AntiAlias"), anti_alias);
1081+
self
1082+
}
1083+
1084+
/// Write the `/Function` attribute.
1085+
///
1086+
/// Sets the function to use for shading. Number of in- and outputs depends
1087+
/// on shading type. Optional.
1088+
pub fn function(&mut self, function: Ref) -> &mut Self {
1089+
self.stream.pair(Name(b"Function"), function);
1090+
self
1091+
}
1092+
1093+
/// Write the `/BitsPerCoordinate` attribute.
1094+
///
1095+
/// Sets how many bits are used to represent each vertex coordinate. Can be
1096+
/// any power of 2 between 1 and 32. Required.
1097+
pub fn bits_per_coordinate(&mut self, bits: i32) -> &mut Self {
1098+
self.stream.pair(Name(b"BitsPerCoordinate"), bits);
1099+
self
1100+
}
1101+
1102+
/// Write the `/BitsPerComponent` attribute.
1103+
///
1104+
/// Sets how many bits are used to represent each color component. Can be
1105+
/// any power of 2 between 1 and 16. Required.
1106+
pub fn bits_per_component(&mut self, bits: i32) -> &mut Self {
1107+
self.stream.pair(Name(b"BitsPerComponent"), bits);
1108+
self
1109+
}
1110+
1111+
/// Write the `/BitsPerFlag` attribute.
1112+
///
1113+
/// Sets how many bits are used to represent the vertices' edge flags. Can
1114+
/// be 0, 1, or 2. Required for type 4, 6, and 7.
1115+
pub fn bits_per_flag(&mut self, bits: i32) -> &mut Self {
1116+
self.stream.pair(Name(b"BitsPerFlag"), bits);
1117+
self
1118+
}
1119+
1120+
/// Write the `/Decode` attribute.
1121+
///
1122+
/// Sets the ranges of the vertices' coordinates. Required.
1123+
pub fn decode(&mut self, decode: impl IntoIterator<Item = f32>) -> &mut Self {
1124+
self.stream.insert(Name(b"Decode")).array().items(decode);
1125+
self
1126+
}
1127+
1128+
/// Write the `/VerticesPerRow` attribute.
1129+
///
1130+
/// Sets how many vertices are in each row of the lattice. Must be greater
1131+
/// than 2. Required for type 5.
1132+
pub fn vertices_per_row(&mut self, vertices: i32) -> &mut Self {
1133+
self.stream.pair(Name(b"VerticesPerRow"), vertices);
1134+
self
1135+
}
1136+
}
1137+
1138+
deref!('a, StreamShading<'a> => Stream<'a>, stream);
1139+
1140+
/// What kind of shading to use for a function-based shading.
10221141
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1023-
#[non_exhaustive]
1024-
pub enum ShadingType {
1142+
pub enum FunctionShadingType {
10251143
/// The function specifies the color for each point in the domain.
10261144
Function,
10271145
/// The function specifies the color for each point on a line.
10281146
Axial,
1029-
/// The function specifies the color for each circle between two nested circles.
1147+
/// The function specifies the color for each circle between two nested
1148+
/// circles.
10301149
Radial,
10311150
}
10321151

1033-
impl ShadingType {
1152+
impl FunctionShadingType {
10341153
pub(crate) fn to_int(self) -> i32 {
10351154
match self {
10361155
Self::Function => 1,
@@ -1040,6 +1159,34 @@ impl ShadingType {
10401159
}
10411160
}
10421161

1162+
/// What kind of shading to use.
1163+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1164+
pub enum StreamShadingType {
1165+
/// The function specifies which vertex has which color. The function is
1166+
/// optional.
1167+
FreeformGouraud,
1168+
/// The function specifies which vertex has which color. The function is
1169+
/// optional.
1170+
LatticeGouraud,
1171+
/// The function specifies which corner of the cell has which color. The
1172+
/// function is optional.
1173+
CoonsPatch,
1174+
/// The function specifies which corner of the cell has which color. The
1175+
/// function is optional.
1176+
TensorProductPatch,
1177+
}
1178+
1179+
impl StreamShadingType {
1180+
pub(crate) fn to_int(self) -> i32 {
1181+
match self {
1182+
Self::FreeformGouraud => 4,
1183+
Self::LatticeGouraud => 5,
1184+
Self::CoonsPatch => 6,
1185+
Self::TensorProductPatch => 7,
1186+
}
1187+
}
1188+
}
1189+
10431190
/// Writer for the _separation information dictionary_. PDF 1.3+.
10441191
///
10451192
/// This struct is created by [`Catalog::separation_info`].

src/lib.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ pub mod writers {
107107
};
108108
pub use color::{
109109
ColorSpace, DeviceN, DeviceNAttrs, DeviceNMixingHints, DeviceNProcess,
110-
IccProfile, OutputIntent, Separation, SeparationInfo, Shading, ShadingPattern,
111-
TilingPattern,
110+
FunctionShading, IccProfile, OutputIntent, Separation, SeparationInfo,
111+
ShadingPattern, StreamShading, StreamShadingType, TilingPattern,
112112
};
113113
pub use content::{
114114
Artifact, ExtGraphicsState, MarkContent, Operation, PositionedItems,
@@ -145,7 +145,7 @@ pub mod types {
145145
TableHeaderScope, TextAlign, TextDecorationType, WritingMode,
146146
};
147147
pub use color::{
148-
DeviceNSubtype, OutputIntentSubtype, PaintType, ShadingType, TilingType,
148+
DeviceNSubtype, FunctionShadingType, OutputIntentSubtype, PaintType, TilingType,
149149
};
150150
pub use content::{
151151
ArtifactAttachment, ArtifactSubtype, ArtifactType, BlendMode, ColorSpaceOperand,
@@ -502,11 +502,20 @@ impl PdfWriter {
502502
self.indirect(id).start()
503503
}
504504

505-
/// Start writing a shading.
506-
pub fn shading(&mut self, id: Ref) -> Shading<'_> {
505+
/// Start writing a function-based shading (type 1-3).
506+
pub fn function_shading(&mut self, id: Ref) -> FunctionShading<'_> {
507507
self.indirect(id).start()
508508
}
509509

510+
/// Start writing a stream-based shading (type 4-7).
511+
pub fn stream_shading<'a>(
512+
&'a mut self,
513+
id: Ref,
514+
content: &'a [u8],
515+
) -> StreamShading<'a> {
516+
StreamShading::start(self.stream(id, content))
517+
}
518+
510519
/// Start writing a tiling pattern stream.
511520
///
512521
/// You can create the content bytes using a [`Content`] builder.

0 commit comments

Comments
 (0)