Skip to content

Commit b3cf924

Browse files
authored
Fix docx table width (#370)
1 parent 4af950e commit b3cf924

6 files changed

Lines changed: 76 additions & 25 deletions

File tree

src/odr/internal/html/document_element.cpp

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -367,26 +367,28 @@ void html::translate_table(Element element, HtmlWriter &out,
367367
for (Element cell : table_row.children()) {
368368
TableCell table_cell = cell.table_cell();
369369

370-
if (!table_cell.is_covered()) {
371-
TableDimensions cell_span = table_cell.span();
372-
373-
out.write_element_begin(
374-
"td",
375-
HtmlElementOptions()
376-
.set_attributes([&](const HtmlAttributeWriterCallback &clb) {
377-
if (cell_span.columns > 1) {
378-
clb("colspan", std::to_string(cell_span.columns));
379-
}
380-
if (cell_span.rows > 1) {
381-
clb("rowspan", std::to_string(cell_span.rows));
382-
}
383-
})
384-
.set_style(translate_table_cell_style(table_cell.style())));
385-
386-
translate_children(cell.children(), out, config);
387-
388-
out.write_element_end("td");
370+
if (table_cell.is_covered()) {
371+
continue;
389372
}
373+
374+
TableDimensions cell_span = table_cell.span();
375+
376+
out.write_element_begin(
377+
"td",
378+
HtmlElementOptions()
379+
.set_attributes([&](const HtmlAttributeWriterCallback &clb) {
380+
if (cell_span.columns > 1) {
381+
clb("colspan", std::to_string(cell_span.columns));
382+
}
383+
if (cell_span.rows > 1) {
384+
clb("rowspan", std::to_string(cell_span.rows));
385+
}
386+
})
387+
.set_style(translate_table_cell_style(table_cell.style())));
388+
389+
translate_children(cell.children(), out, config);
390+
391+
out.write_element_end("td");
390392
}
391393

392394
out.write_element_end("tr");

src/odr/internal/ooxml/ooxml_util.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <odr/internal/abstract/filesystem.hpp>
44
#include <odr/internal/common/path.hpp>
55
#include <odr/internal/html/common.hpp>
6+
#include <odr/internal/util/string_util.hpp>
67
#include <odr/internal/util/xml_util.hpp>
78

89
#include <cstring>
@@ -50,31 +51,52 @@ ooxml::read_half_point_attribute(pugi::xml_attribute attribute) {
5051
if (!attribute) {
5152
return {};
5253
}
53-
return Measure(attribute.as_float() * 0.5f, DynamicUnit("pt"));
54+
return Measure(attribute.as_double() * 0.5, DynamicUnit("pt"));
5455
}
5556

5657
std::optional<Measure>
5758
ooxml::read_hundredth_point_attribute(pugi::xml_attribute attribute) {
5859
if (!attribute) {
5960
return {};
6061
}
61-
return Measure(attribute.as_float() * 0.01f, DynamicUnit("pt"));
62+
return Measure(attribute.as_double() * 0.01, DynamicUnit("pt"));
6263
}
6364

6465
std::optional<Measure>
6566
ooxml::read_emus_attribute(pugi::xml_attribute attribute) {
6667
if (!attribute) {
6768
return {};
6869
}
69-
return Measure(attribute.as_float() / 914400.0f, DynamicUnit("in"));
70+
return Measure(attribute.as_double() / 914400.0, DynamicUnit("in"));
7071
}
7172

7273
std::optional<Measure>
7374
ooxml::read_twips_attribute(pugi::xml_attribute attribute) {
7475
if (!attribute) {
7576
return {};
7677
}
77-
return Measure(attribute.as_float() / 1440.0f, DynamicUnit("in"));
78+
return Measure(attribute.as_double() / 1440.0, DynamicUnit("in"));
79+
}
80+
81+
std::optional<Measure>
82+
ooxml::read_pct_attribute(pugi::xml_attribute attribute) {
83+
if (!attribute) {
84+
return {};
85+
}
86+
87+
// handle percentage which is not always a percentage for tables
88+
// http://officeopenxml.com/WPtableWidth.php
89+
// potentially this should be moved to a table parser
90+
91+
std::string val = attribute.value();
92+
util::string::trim(val);
93+
94+
if (val.find('%') != std::string::npos) {
95+
util::string::replace_all(val, "%", "");
96+
return Measure(std::stod(val), DynamicUnit("%"));
97+
}
98+
99+
return Measure(attribute.as_double() / 50.0, DynamicUnit("%"));
78100
}
79101

80102
std::optional<Measure> ooxml::read_width_attribute(pugi::xml_node node) {
@@ -92,7 +114,7 @@ std::optional<Measure> ooxml::read_width_attribute(pugi::xml_node node) {
92114
return Measure(0, DynamicUnit(""));
93115
}
94116
if (std::strcmp("pct", type) == 0) {
95-
return Measure(node.attribute("w:w").as_float(), DynamicUnit("%"));
117+
return read_pct_attribute(node.attribute("w:w"));
96118
}
97119
return {};
98120
}

src/odr/internal/ooxml/ooxml_util.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ std::optional<Measure> read_half_point_attribute(pugi::xml_attribute);
3333
std::optional<Measure> read_hundredth_point_attribute(pugi::xml_attribute);
3434
std::optional<Measure> read_emus_attribute(pugi::xml_attribute);
3535
std::optional<Measure> read_twips_attribute(pugi::xml_attribute);
36+
std::optional<Measure> read_pct_attribute(pugi::xml_attribute);
3637
std::optional<Measure> read_width_attribute(pugi::xml_node);
3738
bool read_line_attribute(pugi::xml_attribute);
3839
bool read_line_attribute(pugi::xml_node);

src/odr/internal/util/string_util.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <odr/internal/util/string_util.hpp>
22

3+
#include <algorithm>
4+
#include <cctype>
35
#include <codecvt>
46
#include <iomanip>
57
#include <locale>
@@ -17,6 +19,24 @@ bool string::ends_with(const std::string &string, const std::string &with) {
1719
with) == 0);
1820
}
1921

22+
void string::ltrim(std::string &s) {
23+
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
24+
return !std::isspace(ch);
25+
}));
26+
}
27+
28+
void string::rtrim(std::string &s) {
29+
s.erase(std::find_if(s.rbegin(), s.rend(),
30+
[](unsigned char ch) { return !std::isspace(ch); })
31+
.base(),
32+
s.end());
33+
}
34+
35+
void string::trim(std::string &s) {
36+
rtrim(s);
37+
ltrim(s);
38+
}
39+
2040
void string::replace_all(std::string &string, const std::string &search,
2141
const std::string &replace) {
2242
std::size_t pos = string.find(search);

src/odr/internal/util/string_util.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@
99
namespace odr::internal::util::string {
1010
bool starts_with(const std::string &string, const std::string &with);
1111
bool ends_with(const std::string &string, const std::string &with);
12+
13+
void ltrim(std::string &s);
14+
void rtrim(std::string &s);
15+
void trim(std::string &s);
16+
1217
void replace_all(std::string &string, const std::string &search,
1318
const std::string &replace);
19+
1420
void split(const std::string &string, const std::string &delimiter,
1521
std::function<void(const std::string &)> callback);
1622
std::vector<std::string> split(const std::string &string,

0 commit comments

Comments
 (0)