Skip to content

Commit 99b4662

Browse files
committed
Fix #54
1 parent f166d4b commit 99b4662

2 files changed

Lines changed: 117 additions & 25 deletions

File tree

src/attributes.rs

Lines changed: 116 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
198292
pub 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
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ pub mod types {
159159
pub use attributes::{
160160
AttributeOwner, BlockAlign, FieldRole, FieldState, InlineAlign,
161161
LayoutBorderStyle, LayoutTextPosition, LineHeight, ListNumbering, NoteType,
162-
Placement, RubyAlign, RubyPosition, TableHeaderScope, TextAlign,
162+
Placement, RubyAlign, RubyPosition, Sides, TableHeaderScope, TextAlign,
163163
TextDecorationType, WritingMode,
164164
};
165165
pub use color::{

0 commit comments

Comments
 (0)