use crate::model::dimension::{Dimension, Emu, SixtieThousandthDeg, ThousandthPercent};
use crate::model::geometry::{EdgeInsets, Offset, Size};
use super::content::Block;
use super::identifiers::RelId;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ImageFormat {
Png,
Jpeg,
Gif,
Bmp,
Tiff,
Emf,
Wmf,
Svg,
WebP,
Unknown,
}
impl ImageFormat {
pub fn detect(target_path: &str, data: &[u8]) -> Self {
let ext = target_path
.rsplit('.')
.next()
.map(|e| e.to_ascii_lowercase());
match ext.as_deref() {
Some("png") => Self::Png,
Some("jpg" | "jpeg") => Self::Jpeg,
Some("gif") => Self::Gif,
Some("bmp") => Self::Bmp,
Some("tif" | "tiff") => Self::Tiff,
Some("emf") => Self::Emf,
Some("wmf") => Self::Wmf,
Some("svg" | "svgz") => Self::Svg,
Some("webp") => Self::WebP,
_ => Self::detect_by_magic(data),
}
}
fn detect_by_magic(data: &[u8]) -> Self {
match data {
[0x89, b'P', b'N', b'G', ..] => Self::Png,
[0xFF, 0xD8, 0xFF, ..] => Self::Jpeg,
[b'G', b'I', b'F', b'8', ..] => Self::Gif,
[b'B', b'M', ..] => Self::Bmp,
[0x01, 0x00, 0x00, 0x00, _, _, _, _, 0x20, 0x45, 0x4D, 0x46, ..] => Self::Emf,
[b'R', b'I', b'F', b'F', _, _, _, _, b'W', b'E', b'B', b'P', ..] => Self::WebP,
[b'<', ..] => Self::Svg,
_ => Self::Unknown,
}
}
}
#[derive(Clone, Debug)]
pub struct Image {
pub extent: Size<Emu>,
pub effect_extent: Option<EdgeInsets<Emu>>,
pub doc_properties: DocProperties,
pub graphic_frame_locks: Option<GraphicFrameLocks>,
pub graphic: Option<GraphicContent>,
pub placement: ImagePlacement,
}
#[derive(Clone, Debug)]
pub enum ImagePlacement {
Inline {
distance: EdgeInsets<Emu>,
},
Anchor(AnchorProperties),
}
#[derive(Clone, Debug)]
pub struct DocProperties {
pub id: u32,
pub name: String,
pub description: Option<String>,
pub hidden: Option<bool>,
pub title: Option<String>,
}
#[derive(Clone, Copy, Debug)]
pub struct GraphicFrameLocks {
pub no_change_aspect: Option<bool>,
pub no_drilldown: Option<bool>,
pub no_grp: Option<bool>,
pub no_move: Option<bool>,
pub no_resize: Option<bool>,
pub no_select: Option<bool>,
}
#[derive(Clone, Debug)]
pub enum GraphicContent {
Picture(Picture),
WordProcessingShape(WordProcessingShape),
}
#[derive(Clone, Debug)]
pub struct WordProcessingShape {
pub cnv_pr: Option<DocProperties>,
pub shape_properties: Option<ShapeProperties>,
pub body_pr: Option<BodyProperties>,
pub txbx_content: Vec<Block>,
}
#[derive(Clone, Debug)]
pub struct BodyProperties {
pub rotation: Option<Dimension<SixtieThousandthDeg>>,
pub vert: Option<TextVerticalType>,
pub wrap: Option<TextWrappingType>,
pub left_inset: Option<Dimension<Emu>>,
pub top_inset: Option<Dimension<Emu>>,
pub right_inset: Option<Dimension<Emu>>,
pub bottom_inset: Option<Dimension<Emu>>,
pub anchor: Option<TextAnchoringType>,
pub auto_fit: Option<TextAutoFit>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextVerticalType {
Horz,
Vert,
Vert270,
WordArtVert,
EaVert,
MongolianVert,
WordArtVertRtl,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextWrappingType {
None,
Square,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextAnchoringType {
Top,
Center,
Bottom,
Justified,
Distributed,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TextAutoFit {
NoAutoFit,
NormalAutoFit,
SpAutoFit,
}
#[derive(Clone, Debug)]
pub struct Picture {
pub nv_pic_pr: NvPicProperties,
pub blip_fill: BlipFill,
pub shape_properties: Option<ShapeProperties>,
}
#[derive(Clone, Debug)]
pub struct NvPicProperties {
pub cnv_pr: DocProperties,
pub cnv_pic_pr: Option<CnvPicProperties>,
}
#[derive(Clone, Debug)]
pub struct CnvPicProperties {
pub prefer_relative_resize: Option<bool>,
pub pic_locks: Option<PicLocks>,
}
#[derive(Clone, Copy, Debug)]
pub struct PicLocks {
pub no_change_aspect: Option<bool>,
pub no_crop: Option<bool>,
pub no_resize: Option<bool>,
pub no_move: Option<bool>,
pub no_rot: Option<bool>,
pub no_select: Option<bool>,
pub no_edit_points: Option<bool>,
pub no_adjust_handles: Option<bool>,
pub no_change_arrowheads: Option<bool>,
pub no_change_shape_type: Option<bool>,
pub no_grp: Option<bool>,
}
#[derive(Clone, Debug)]
pub struct BlipFill {
pub rotate_with_shape: Option<bool>,
pub dpi: Option<u32>,
pub blip: Option<Blip>,
pub src_rect: Option<RelativeRect>,
pub stretch: Option<StretchFill>,
}
#[derive(Clone, Debug)]
pub struct Blip {
pub embed: Option<RelId>,
pub link: Option<RelId>,
pub compression: Option<BlipCompression>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BlipCompression {
Email,
Hqprint,
None,
Print,
Screen,
}
#[derive(Clone, Copy, Debug)]
pub struct RelativeRect {
pub left: Option<Dimension<ThousandthPercent>>,
pub top: Option<Dimension<ThousandthPercent>>,
pub right: Option<Dimension<ThousandthPercent>>,
pub bottom: Option<Dimension<ThousandthPercent>>,
}
#[derive(Clone, Copy, Debug)]
pub struct StretchFill {
pub fill_rect: Option<RelativeRect>,
}
#[derive(Clone, Debug)]
pub struct ShapeProperties {
pub bw_mode: Option<BlackWhiteMode>,
pub transform: Option<Transform2D>,
pub preset_geometry: Option<PresetGeometryDef>,
pub fill: Option<DrawingFill>,
pub outline: Option<Outline>,
}
#[derive(Clone, Copy, Debug)]
pub struct Transform2D {
pub rotation: Option<Dimension<SixtieThousandthDeg>>,
pub flip_h: Option<bool>,
pub flip_v: Option<bool>,
pub offset: Option<Offset<Emu>>,
pub extent: Option<Size<Emu>>,
}
#[derive(Clone, Debug)]
pub struct PresetGeometryDef {
pub preset: PresetShapeType,
pub adjust_values: Vec<GeomGuide>,
}
#[derive(Clone, Debug)]
pub struct GeomGuide {
pub name: String,
pub formula: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PresetShapeType {
Rect,
RoundRect,
Ellipse,
Triangle,
RtTriangle,
Diamond,
Parallelogram,
Trapezoid,
Pentagon,
Hexagon,
Octagon,
Star4,
Star5,
Star6,
Star8,
Star10,
Star12,
Star16,
Star24,
Star32,
Line,
Plus,
Can,
Cube,
Donut,
NoSmoking,
BlockArc,
Heart,
Sun,
Moon,
SmileyFace,
LightningBolt,
Cloud,
Arc,
Plaque,
Frame,
Bevel,
FoldedCorner,
Chevron,
HomePlate,
Ribbon,
Ribbon2,
Pie,
PieWedge,
Chord,
Teardrop,
Arrow,
LeftArrow,
RightArrow,
UpArrow,
DownArrow,
LeftRightArrow,
UpDownArrow,
QuadArrow,
BentArrow,
UturnArrow,
CircularArrow,
CurvedRightArrow,
CurvedLeftArrow,
CurvedUpArrow,
CurvedDownArrow,
StripedRightArrow,
NotchedRightArrow,
BentUpArrow,
LeftUpArrow,
LeftRightUpArrow,
LeftArrowCallout,
RightArrowCallout,
UpArrowCallout,
DownArrowCallout,
LeftRightArrowCallout,
UpDownArrowCallout,
QuadArrowCallout,
SwooshArrow,
LeftCircularArrow,
LeftRightCircularArrow,
Callout1,
Callout2,
Callout3,
AccentCallout1,
AccentCallout2,
AccentCallout3,
BorderCallout1,
BorderCallout2,
BorderCallout3,
AccentBorderCallout1,
AccentBorderCallout2,
AccentBorderCallout3,
WedgeRectCallout,
WedgeRoundRectCallout,
WedgeEllipseCallout,
CloudCallout,
LeftBracket,
RightBracket,
LeftBrace,
RightBrace,
BracketPair,
BracePair,
StraightConnector1,
BentConnector2,
BentConnector3,
BentConnector4,
BentConnector5,
CurvedConnector2,
CurvedConnector3,
CurvedConnector4,
CurvedConnector5,
FlowChartProcess,
FlowChartDecision,
FlowChartInputOutput,
FlowChartPredefinedProcess,
FlowChartInternalStorage,
FlowChartDocument,
FlowChartMultidocument,
FlowChartTerminator,
FlowChartPreparation,
FlowChartManualInput,
FlowChartManualOperation,
FlowChartConnector,
FlowChartPunchedCard,
FlowChartPunchedTape,
FlowChartSummingJunction,
FlowChartOr,
FlowChartCollate,
FlowChartSort,
FlowChartExtract,
FlowChartMerge,
FlowChartOfflineStorage,
FlowChartOnlineStorage,
FlowChartMagneticTape,
FlowChartMagneticDisk,
FlowChartMagneticDrum,
FlowChartDisplay,
FlowChartDelay,
FlowChartAlternateProcess,
FlowChartOffpageConnector,
ActionButtonBlank,
ActionButtonHome,
ActionButtonHelp,
ActionButtonInformation,
ActionButtonForwardNext,
ActionButtonBackPrevious,
ActionButtonEnd,
ActionButtonBeginning,
ActionButtonReturn,
ActionButtonDocument,
ActionButtonSound,
ActionButtonMovie,
IrregularSeal1,
IrregularSeal2,
Wave,
DoubleWave,
EllipseRibbon,
EllipseRibbon2,
VerticalScroll,
HorizontalScroll,
LeftRightRibbon,
Gear6,
Gear9,
Funnel,
MathPlus,
MathMinus,
MathMultiply,
MathDivide,
MathEqual,
MathNotEqual,
CornerTabs,
SquareTabs,
PlaqueTabs,
ChartX,
ChartStar,
ChartPlus,
HalfFrame,
Corner,
DiagStripe,
NonIsoscelesTrapezoid,
Heptagon,
Decagon,
Dodecagon,
Round1Rect,
Round2SameRect,
Round2DiagRect,
SnipRoundRect,
Snip1Rect,
Snip2SameRect,
Snip2DiagRect,
Other(String),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BlackWhiteMode {
Auto,
Black,
BlackGray,
BlackWhite,
Clr,
Gray,
GrayWhite,
Hidden,
InvGray,
LtGray,
White,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DrawingFill {
NoFill,
}
#[derive(Clone, Debug)]
pub struct Outline {
pub width: Option<Dimension<Emu>>,
pub cap: Option<LineCap>,
pub compound: Option<CompoundLine>,
pub alignment: Option<PenAlignment>,
pub fill: Option<DrawingFill>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LineCap {
Flat,
Round,
Square,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CompoundLine {
Single,
Double,
ThickThin,
ThinThick,
Triple,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PenAlignment {
Center,
Inset,
}
#[derive(Clone, Copy, Debug)]
pub struct AnchorProperties {
pub distance: EdgeInsets<Emu>,
pub simple_pos: Option<Offset<Emu>>,
pub use_simple_pos: Option<bool>,
pub horizontal_position: AnchorPosition,
pub vertical_position: AnchorPosition,
pub wrap: TextWrap,
pub behind_text: bool,
pub lock_anchor: bool,
pub allow_overlap: bool,
pub relative_height: u32,
pub layout_in_cell: Option<bool>,
pub hidden: Option<bool>,
}
#[derive(Clone, Copy, Debug)]
pub enum AnchorPosition {
Offset {
relative_from: AnchorRelativeFrom,
offset: Dimension<Emu>,
},
Align {
relative_from: AnchorRelativeFrom,
alignment: AnchorAlignment,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AnchorRelativeFrom {
Page,
Margin,
Column,
Character,
Paragraph,
Line,
InsideMargin,
OutsideMargin,
TopMargin,
BottomMargin,
LeftMargin,
RightMargin,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AnchorAlignment {
Left,
Center,
Right,
Inside,
Outside,
Top,
Bottom,
}
#[derive(Clone, Copy, Debug)]
pub enum TextWrap {
None,
Square {
distance: EdgeInsets<Emu>,
wrap_text: WrapText,
},
Tight {
distance: EdgeInsets<Emu>,
wrap_text: WrapText,
},
TopAndBottom {
distance_top: Dimension<Emu>,
distance_bottom: Dimension<Emu>,
},
Through {
distance: EdgeInsets<Emu>,
wrap_text: WrapText,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum WrapText {
BothSides,
Left,
Right,
Largest,
}