@@ -59,6 +59,73 @@ void Document::save(const Path & /*path*/, const char * /*password*/) const {
5959
6060namespace {
6161
62+ void resolve_text_style_ (const pugi::xml_node node, TextStyle &result) {
63+ const pugi::xml_node run_properties = node.child (" a:rPr" );
64+
65+ if (const pugi::xml_attribute font_name =
66+ run_properties.child (" rFonts" ).attribute (" ascii" )) {
67+ result.font_name = font_name.value ();
68+ }
69+ if (const std::optional<Measure> font_size =
70+ read_hundredth_point_attribute (run_properties.attribute (" sz" ))) {
71+ result.font_size = font_size;
72+ }
73+ if (const std::optional<FontWeight> font_weight =
74+ read_font_weight_attribute (run_properties.attribute (" b" ))) {
75+ result.font_weight = font_weight;
76+ }
77+ if (const std::optional<FontStyle> font_style =
78+ read_font_style_attribute (run_properties.attribute (" i" ))) {
79+ result.font_style = font_style;
80+ }
81+ if (const bool font_underline =
82+ read_line_attribute (run_properties.attribute (" u" ))) {
83+ result.font_underline = font_underline;
84+ }
85+ if (const bool font_line_through =
86+ read_line_attribute (run_properties.attribute (" strike" ))) {
87+ result.font_line_through = font_line_through;
88+ }
89+ if (const std::optional<std::string> font_shadow =
90+ read_shadow_attribute (run_properties.attribute (" shadow" ))) {
91+ result.font_shadow = font_shadow;
92+ }
93+ if (const std::optional<Color> font_color =
94+ read_color_attribute (run_properties.attribute (" color" ))) {
95+ result.font_color = font_color;
96+ }
97+ if (const std::optional<Color> background_color =
98+ read_color_attribute (run_properties.attribute (" highlight" ))) {
99+ result.background_color = background_color;
100+ }
101+ }
102+
103+ void resolve_paragraph_style_ (const pugi::xml_node node,
104+ ParagraphStyle &result) {
105+ const pugi::xml_node paragraph_properties = node.child (" a:pPr" );
106+
107+ if (const std::optional<TextAlign> text_align =
108+ read_text_align_attribute (paragraph_properties.attribute (" jc" ))) {
109+ result.text_align = text_align;
110+ }
111+ if (const std::optional<Measure> margin_left = read_twips_attribute (
112+ paragraph_properties.child (" ind" ).attribute (" left" ))) {
113+ result.margin .left = margin_left;
114+ }
115+ if (const std::optional<Measure> margin_left = read_twips_attribute (
116+ paragraph_properties.child (" ind" ).attribute (" start" ))) {
117+ result.margin .left = margin_left;
118+ }
119+ if (const std::optional<Measure> margin_right = read_twips_attribute (
120+ paragraph_properties.child (" ind" ).attribute (" right" ))) {
121+ result.margin .right = margin_right;
122+ }
123+ if (const std::optional<Measure> margin_right = read_twips_attribute (
124+ paragraph_properties.child (" ind" ).attribute (" end" ))) {
125+ result.margin .right = margin_right;
126+ }
127+ }
128+
62129class ElementAdapter final : public abstract::ElementAdapter,
63130 public abstract::SlideAdapter,
64131 public abstract::LineBreakAdapter,
@@ -310,7 +377,13 @@ class ElementAdapter final : public abstract::ElementAdapter,
310377 [[nodiscard]] PageLayout
311378 slide_page_layout (const ElementIdentifier element_id) const override {
312379 (void )element_id;
313- return {}; // TODO
380+ // TODO
381+ return {
382+ .width = Measure (" 11.02 in" ),
383+ .height = Measure (" 8.27 in" ),
384+ .print_orientation = {},
385+ .margin = {},
386+ };
314387 }
315388 [[nodiscard]] ElementIdentifier
316389 slide_master_page (const ElementIdentifier element_id) const override {
@@ -489,79 +562,80 @@ class ElementAdapter final : public abstract::ElementAdapter,
489562
490563 [[nodiscard]] TableColumnStyle
491564 table_column_style (const ElementIdentifier element_id) const override {
492- const pugi::xml_node node = get_node (element_id);
493- TableColumnStyle result;
494- if (const std::optional<Measure> width =
495- read_twips_attribute (node.attribute (" a:w" ))) {
496- result.width = width;
497- }
498- return result;
565+ return get_partial_style (element_id).table_column_style ;
499566 }
500567
501568 [[nodiscard]] TableRowStyle
502- table_row_style (const ElementIdentifier) const override {
503- return {}; // TODO
569+ table_row_style (const ElementIdentifier element_id ) const override {
570+ return get_partial_style (element_id). table_row_style ;
504571 }
505572
506573 [[nodiscard]] bool
507574 table_cell_is_covered (const ElementIdentifier element_id) const override {
508- const pugi::xml_node node = get_node (element_id);
509- return std::strcmp (node.name (), " table:covered-table-cell" ) == 0 ;
575+ return false ;
510576 }
511577 [[nodiscard]] TableDimensions
512578 table_cell_span (const ElementIdentifier element_id) const override {
513- const pugi::xml_node node = get_node (element_id);
514- return {node.attribute (" table:number-rows-spanned" ).as_uint (1 ),
515- node.attribute (" table:number-columns-spanned" ).as_uint (1 )};
579+ return {1 , 1 }; // TODO
516580 }
517581 [[nodiscard]] ValueType
518582 table_cell_value_type (const ElementIdentifier element_id) const override {
519- const pugi::xml_node node = get_node (element_id);
520- if (const char *value_type = node.attribute (" office:value-type" ).value ();
521- std::strcmp (" float" , value_type) == 0 ) {
522- return ValueType::float_number;
523- }
524583 return ValueType::string;
525584 }
526585 [[nodiscard]] TableCellStyle
527- table_cell_style (const ElementIdentifier) const override {
528- return {}; // TODO
586+ table_cell_style (const ElementIdentifier element_id ) const override {
587+ return get_partial_style (element_id). table_cell_style ;
529588 }
530589
531590 [[nodiscard]] AnchorType
532591 frame_anchor_type (const ElementIdentifier element_id) const override {
533- const pugi::xml_node node = get_node (element_id);
534-
535- if (node.child (" wp:inline" )) {
536- return AnchorType::as_char;
537- }
538- return AnchorType::as_char; // TODO default?
592+ return AnchorType::at_page;
539593 }
540594 [[nodiscard]] std::optional<std::string>
541595 frame_x (const ElementIdentifier element_id) const override {
542- (void )element_id;
543- return std::nullopt ;
596+ if (const std::optional<Measure> x =
597+ read_emus_attribute (get_node (element_id)
598+ .child (" p:spPr" )
599+ .child (" a:xfrm" )
600+ .child (" a:off" )
601+ .attribute (" x" ))) {
602+ return x->to_string ();
603+ }
604+ return {};
544605 }
545606 [[nodiscard]] std::optional<std::string>
546607 frame_y (const ElementIdentifier element_id) const override {
547- (void )element_id;
548- return std::nullopt ;
608+ if (const std::optional<Measure> y =
609+ read_emus_attribute (get_node (element_id)
610+ .child (" p:spPr" )
611+ .child (" a:xfrm" )
612+ .child (" a:off" )
613+ .attribute (" y" ))) {
614+ return y->to_string ();
615+ }
616+ return {};
549617 }
550618 [[nodiscard]] std::optional<std::string>
551619 frame_width (const ElementIdentifier element_id) const override {
552- const pugi::xml_node inner_node = get_frame_inner_node (element_id);
553- if (const std::optional<Measure> width = read_emus_attribute (
554- inner_node.child (" wp:extent" ).attribute (" cx" ))) {
555- return width->to_string ();
620+ if (const std::optional<Measure> cx =
621+ read_emus_attribute (get_node (element_id)
622+ .child (" p:spPr" )
623+ .child (" a:xfrm" )
624+ .child (" a:ext" )
625+ .attribute (" cx" ))) {
626+ return cx->to_string ();
556627 }
557628 return {};
558629 }
559630 [[nodiscard]] std::optional<std::string>
560631 frame_height (const ElementIdentifier element_id) const override {
561- const pugi::xml_node inner_node = get_frame_inner_node (element_id);
562- if (const std::optional<Measure> height = read_emus_attribute (
563- inner_node.child (" wp:extent" ).attribute (" cy" ))) {
564- return height->to_string ();
632+ if (const std::optional<Measure> cy =
633+ read_emus_attribute (get_node (element_id)
634+ .child (" p:spPr" )
635+ .child (" a:xfrm" )
636+ .child (" a:ext" )
637+ .attribute (" cy" ))) {
638+ return cy->to_string ();
565639 }
566640 return {};
567641 }
@@ -614,18 +688,6 @@ class ElementAdapter final : public abstract::ElementAdapter,
614688 return {};
615689 }
616690
617- [[nodiscard]] pugi::xml_node
618- get_frame_inner_node (const ElementIdentifier element_id) const {
619- const pugi::xml_node node = get_node (element_id);
620- if (const pugi::xml_node anchor = node.child (" wp:anchor" )) {
621- return anchor;
622- }
623- if (const pugi::xml_node inline_node = node.child (" wp:inline" )) {
624- return inline_node;
625- }
626- return {};
627- }
628-
629691 [[nodiscard]] static std::string get_text (const pugi::xml_node node) {
630692 const std::string name = node.name ();
631693
@@ -639,22 +701,35 @@ class ElementAdapter final : public abstract::ElementAdapter,
639701 return " " ;
640702 }
641703
642- [[nodiscard]] const char *
643- get_style_name (const ElementIdentifier element_id) const {
644- (void )element_id;
645- return {}; // TODO
646- }
647-
648704 [[nodiscard]] ResolvedStyle
649705 get_partial_style (const ElementIdentifier element_id) const {
650- (void )element_id;
651- return {}; // TODO
706+ if (const ElementRegistry::Element *element =
707+ m_registry->element (element_id);
708+ element != nullptr ) {
709+ if (element->type == ElementType::paragraph) {
710+ ResolvedStyle result;
711+ resolve_text_style_ (element->node , result.text_style );
712+ resolve_paragraph_style_ (element->node , result.paragraph_style );
713+ return result;
714+ }
715+ if (element->type == ElementType::span) {
716+ ResolvedStyle result;
717+ resolve_text_style_ (element->node , result.text_style );
718+ return result;
719+ }
720+ }
721+ return {};
652722 }
653723
654724 [[nodiscard]] ResolvedStyle
655725 get_intermediate_style (const ElementIdentifier element_id) const {
656- (void )element_id;
657- return {}; // TODO
726+ const ElementIdentifier parent_id = element_parent (element_id);
727+ if (parent_id == null_element_id) {
728+ return get_partial_style (element_id);
729+ }
730+ ResolvedStyle base = get_intermediate_style (parent_id);
731+ base.override (get_partial_style (element_id));
732+ return base;
658733 }
659734};
660735
0 commit comments