@@ -155,34 +155,30 @@ impl<'a> LayoutAttributes<'a> {
155155 }
156156
157157 /// Write the `/BorderColor` attribute.
158- pub fn border_color ( & mut self , color : [ f32 ; 3 ] ) -> & mut Self {
159- self . dict . insert ( Name ( b"BorderColor" ) ) . array ( ) . typed ( ) . items ( color) ;
158+ pub fn border_color ( & mut self , color : Sides < [ f32 ; 3 ] > ) -> & mut Self {
159+ let obj = self . dict . insert ( Name ( b"BorderColor" ) ) ;
160+ color. write_iter ( obj) ;
160161 self
161162 }
162163
163164 /// Write the `/BorderStyle` attribute.
164- pub fn border_style ( & mut self , style : [ LayoutBorderStyle ; 4 ] ) -> & mut Self {
165- self . dict
166- . insert ( Name ( b"BorderStyle" ) )
167- . array ( )
168- . typed ( )
169- . items ( style. into_iter ( ) . map ( LayoutBorderStyle :: to_name) ) ;
165+ pub fn border_style ( & mut self , style : Sides < LayoutBorderStyle > ) -> & mut Self {
166+ let obj = self . dict . insert ( Name ( b"BorderStyle" ) ) ;
167+ style. write_map_primitive ( obj, LayoutBorderStyle :: to_name) ;
170168 self
171169 }
172170
173171 /// Write the `/BorderThickness` attribute.
174- pub fn border_thickness ( & mut self , thickness : [ f32 ; 4 ] ) -> & mut Self {
175- self . dict
176- . insert ( Name ( b"BorderThickness" ) )
177- . array ( )
178- . typed ( )
179- . items ( thickness) ;
172+ pub fn border_thickness ( & mut self , thickness : Sides < f32 > ) -> & mut Self {
173+ let obj = self . dict . insert ( Name ( b"BorderThickness" ) ) ;
174+ thickness. write_primitive ( obj) ;
180175 self
181176 }
182177
183178 /// Write the `/Padding` attribute.
184- pub fn padding ( & mut self , padding : [ f32 ; 4 ] ) -> & mut Self {
185- self . dict . insert ( Name ( b"Padding" ) ) . array ( ) . typed ( ) . items ( padding) ;
179+ pub fn padding ( & mut self , padding : Sides < f32 > ) -> & mut Self {
180+ let obj = self . dict . insert ( Name ( b"Padding" ) ) ;
181+ padding. write_primitive ( obj) ;
186182 self
187183 }
188184
@@ -193,6 +189,104 @@ impl<'a> LayoutAttributes<'a> {
193189 }
194190}
195191
192+ /// A value that applies to the four sides of a rectangular container.
193+ #[ derive( Debug , Copy , Clone , Default , Eq , PartialEq , Hash ) ]
194+ pub struct Sides < T > {
195+ /// The value before the rectangle, in the block progression direction. In
196+ /// the LTR writing mode, this is the top side.
197+ pub before : T ,
198+ /// The value after the rectangle, in the block progression direction. In
199+ /// the LTR writing mode, this is the bottom side.
200+ pub after : T ,
201+ /// The value at the inline start edge of the rectangle. In the LTR writing
202+ /// mode, this is the left side.
203+ pub start : T ,
204+ /// The value at the inline end edge of the rectangle. In the LTR writing
205+ /// mode, this is the right side.
206+ pub end : T ,
207+ }
208+
209+ impl < T > Sides < T > {
210+ /// Create a new `Sides` struct with the given values for each side.
211+ pub fn new ( before : T , after : T , start : T , end : T ) -> Self {
212+ Self { before, after, start, end }
213+ }
214+
215+ /// Create a new `Sides` struct with an array ordered as `[before, after,
216+ /// start, end]`, just like in the PDF specification.
217+ pub fn from_array ( array : [ T ; 4 ] ) -> Self {
218+ let [ before, after, start, end] = array;
219+ Self { before, after, start, end }
220+ }
221+
222+ /// Create a new `Sides` with the same value for all sides.
223+ pub fn uniform ( value : T ) -> Self
224+ where
225+ T : Clone ,
226+ {
227+ Self {
228+ before : value. clone ( ) ,
229+ after : value. clone ( ) ,
230+ start : value. clone ( ) ,
231+ end : value,
232+ }
233+ }
234+
235+ /// Check if all sides have the same value.
236+ fn is_uniform ( & self ) -> bool
237+ where
238+ T : PartialEq ,
239+ {
240+ self . before == self . after && self . before == self . start && self . before == self . end
241+ }
242+
243+ /// Get the sides as an array ordered as `[before, after, start, end]`.
244+ fn into_array ( self ) -> [ T ; 4 ] {
245+ [ self . before , self . after , self . start , self . end ]
246+ }
247+
248+ /// Write the sides of a primitive type.
249+ fn write_primitive ( self , obj : Obj < ' _ > )
250+ where
251+ T : Primitive + PartialEq ,
252+ {
253+ self . write_map_primitive ( obj, |side| side) ;
254+ }
255+
256+ /// Write the sides of a value that can be mapped to a primitive type with a
257+ /// closure.
258+ fn write_map_primitive < P > ( self , obj : Obj < ' _ > , mut to_primitive : impl FnMut ( T ) -> P )
259+ where
260+ T : PartialEq ,
261+ P : Primitive ,
262+ {
263+ if self . is_uniform ( ) {
264+ obj. primitive ( to_primitive ( self . before ) ) ;
265+ } else {
266+ let mut array = obj. array ( ) ;
267+ for side in self . into_array ( ) {
268+ array. push ( ) . primitive ( to_primitive ( side) ) ;
269+ }
270+ }
271+ }
272+
273+ /// Write the sides of an iterable type containing primitive values.
274+ fn write_iter < P > ( self , obj : Obj < ' _ > )
275+ where
276+ T : IntoIterator < Item = P > + PartialEq ,
277+ P : Primitive ,
278+ {
279+ if self . is_uniform ( ) {
280+ obj. array ( ) . typed ( ) . items ( self . before ) ;
281+ } else {
282+ let mut array = obj. array ( ) ;
283+ for side in self . into_array ( ) {
284+ array. push ( ) . array ( ) . typed ( ) . items ( side) ;
285+ }
286+ }
287+ }
288+ }
289+
196290/// Placement of an element.
197291#[ derive( Debug , Copy , Clone , Eq , PartialEq , Hash ) ]
198292pub enum Placement {
@@ -390,18 +484,16 @@ impl LayoutAttributes<'_> {
390484 }
391485
392486 /// Write the `/TBorderStyle` attribute. PDF 1.5+.
393- pub fn table_border_style ( & mut self , style : [ LayoutBorderStyle ; 4 ] ) -> & mut Self {
394- self . dict
395- . insert ( Name ( b"TBorderStyle" ) )
396- . array ( )
397- . typed ( )
398- . items ( style. into_iter ( ) . map ( LayoutBorderStyle :: to_name) ) ;
487+ pub fn table_border_style ( & mut self , style : Sides < LayoutBorderStyle > ) -> & mut Self {
488+ let obj = self . dict . insert ( Name ( b"TBorderStyle" ) ) ;
489+ style. write_map_primitive ( obj, LayoutBorderStyle :: to_name) ;
399490 self
400491 }
401492
402493 /// Write the `/TPadding` attribute. PDF 1.5+.
403- pub fn table_padding ( & mut self , padding : f32 ) -> & mut Self {
404- self . dict . pair ( Name ( b"TPadding" ) , padding) ;
494+ pub fn table_padding ( & mut self , padding : Sides < f32 > ) -> & mut Self {
495+ let obj = self . dict . insert ( Name ( b"TPadding" ) ) ;
496+ padding. write_primitive ( obj) ;
405497 self
406498 }
407499}
0 commit comments