summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2019-07-09 22:54:57 +0200
committerBartosz Kosiorek <gang65@poczta.onet.pl>2019-07-09 22:54:57 +0200
commit9bf6a30786fb75cb725fe038d77ef03e1ebc4bc0 (patch)
tree9ae002ca832df01bb4a269023956739017b72aee
parent187e3c83fe021267b913068432d1387ea140944a (diff)
tdf#126292 Fix unit conversion
Change-Id: I88711a1bf1bfd6078dc6948194449bcc91f34cce
-rw-r--r--src/lib/VSD5Parser.cpp2
-rw-r--r--src/lib/VSD6Parser.cpp6
-rw-r--r--src/lib/VSDCollector.h2
-rw-r--r--src/lib/VSDContentCollector.cpp5
-rw-r--r--src/lib/VSDContentCollector.h2
-rw-r--r--src/lib/VSDDocumentStructure.h51
-rw-r--r--src/lib/VSDFieldList.cpp104
-rw-r--r--src/lib/VSDFieldList.h9
-rw-r--r--src/lib/VSDParser.cpp6
-rw-r--r--src/lib/VSDStylesCollector.cpp2
-rw-r--r--src/lib/VSDStylesCollector.h2
-rw-r--r--src/test/data/Visio11TextFieldsWithUnits.vsdbin0 -> 36352 bytes
-rw-r--r--src/test/data/Visio6TextFieldsWithUnits.vsdbin0 -> 31744 bytes
-rw-r--r--src/test/importtest.cpp11
14 files changed, 176 insertions, 26 deletions
diff --git a/src/lib/VSD5Parser.cpp b/src/lib/VSD5Parser.cpp
index f16160e..c918510 100644
--- a/src/lib/VSD5Parser.cpp
+++ b/src/lib/VSD5Parser.cpp
@@ -464,7 +464,7 @@ void libvisio::VSD5Parser::readTextField(librevenge::RVNGInputStream *input)
else
{
double numericValue = readDouble(input);
- m_shape.m_fields.addNumericField(m_header.id, m_header.level, VSD_FIELD_FORMAT_Unknown, numericValue, 0xffff);
+ m_shape.m_fields.addNumericField(m_header.id, m_header.level, VSD_FIELD_FORMAT_Unknown, UNIT_NoCast, numericValue, 0xffff);
}
}
diff --git a/src/lib/VSD6Parser.cpp b/src/lib/VSD6Parser.cpp
index d2dd941..012528e 100644
--- a/src/lib/VSD6Parser.cpp
+++ b/src/lib/VSD6Parser.cpp
@@ -337,7 +337,7 @@ void libvisio::VSD6Parser::readTextField(librevenge::RVNGInputStream *input)
unsigned long initialPosition = input->tell();
input->seek(7, librevenge::RVNG_SEEK_CUR);
unsigned char unit = readU8(input);
- if (unit == 0xe8)
+ if (unit == UNIT_StringWithoutUnit)
{
int nameId = readS32(input);
input->seek(6, librevenge::RVNG_SEEK_CUR);
@@ -391,13 +391,13 @@ void libvisio::VSD6Parser::readTextField(librevenge::RVNGInputStream *input)
if (blockIdx != 2)
{
- if (unit == 0x28)
+ if (unit == UNIT_Date)
formatNumber = VSD_FIELD_FORMAT_MsoDateShort;
else
formatNumber = VSD_FIELD_FORMAT_Unknown;
}
- m_shape.m_fields.addNumericField(m_header.id, m_header.level, formatNumber, numericValue, formatStringId);
+ m_shape.m_fields.addNumericField(m_header.id, m_header.level, formatNumber, unit, numericValue, formatStringId);
}
}
diff --git a/src/lib/VSDCollector.h b/src/lib/VSDCollector.h
index 7286d1c..11fd25e 100644
--- a/src/lib/VSDCollector.h
+++ b/src/lib/VSDCollector.h
@@ -150,7 +150,7 @@ public:
// Field list
virtual void collectFieldList(unsigned id, unsigned level) = 0;
virtual void collectTextField(unsigned id, unsigned level, int nameId, int formatStringId) = 0;
- virtual void collectNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId) = 0;
+ virtual void collectNumericField(unsigned id, unsigned level, unsigned short format, unsigned short unit, double number, int formatStringId) = 0;
// Metadata
virtual void collectMetaData(const librevenge::RVNGPropertyList &metaData) = 0;
diff --git a/src/lib/VSDContentCollector.cpp b/src/lib/VSDContentCollector.cpp
index e15b4d9..e808b21 100644
--- a/src/lib/VSDContentCollector.cpp
+++ b/src/lib/VSDContentCollector.cpp
@@ -3436,7 +3436,7 @@ void libvisio::VSDContentCollector::collectTextField(unsigned id, unsigned level
}
}
-void libvisio::VSDContentCollector::collectNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId)
+void libvisio::VSDContentCollector::collectNumericField(unsigned id, unsigned level, unsigned short format, unsigned short unit, double number, int formatStringId)
{
_handleLevelChange(level);
VSDFieldListElement *pElement = m_stencilFields.getElement(m_fields.size());
@@ -3446,6 +3446,7 @@ void libvisio::VSDContentCollector::collectNumericField(unsigned id, unsigned le
if (element)
{
element->setValue(number);
+ element->setUnit(unit);
if (format == VSD_FIELD_FORMAT_Unknown)
{
std::map<unsigned, librevenge::RVNGString>::const_iterator iter = m_names.find(formatStringId);
@@ -3460,7 +3461,7 @@ void libvisio::VSDContentCollector::collectNumericField(unsigned id, unsigned le
}
else
{
- VSDNumericField tmpField(id, level, format, number, formatStringId);
+ VSDNumericField tmpField(id, level, format, unit, number, formatStringId);
m_fields.push_back(tmpField.getString(m_names));
}
}
diff --git a/src/lib/VSDContentCollector.h b/src/lib/VSDContentCollector.h
index 1252afe..58993d2 100644
--- a/src/lib/VSDContentCollector.h
+++ b/src/lib/VSDContentCollector.h
@@ -170,7 +170,7 @@ public:
// Field list
void collectFieldList(unsigned id, unsigned level) override;
void collectTextField(unsigned id, unsigned level, int nameId, int formatStringId) override;
- void collectNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId) override;
+ void collectNumericField(unsigned id, unsigned level, unsigned short format, unsigned short unit, double number, int formatStringId) override;
void startPage(unsigned pageId) override;
void endPage() override;
diff --git a/src/lib/VSDDocumentStructure.h b/src/lib/VSDDocumentStructure.h
index 4fd8b61..0d10b91 100644
--- a/src/lib/VSDDocumentStructure.h
+++ b/src/lib/VSDDocumentStructure.h
@@ -126,6 +126,57 @@
#define VSD_FONTFACE 0xd7
#define VSD_FONTFACES 0xd8
+// Unit conversions:
+#define UNIT_Number 32
+#define UNIT_Percent 33
+#define UNIT_Acre 36
+#define UNIT_Hectare 37
+#define UNIT_Date 40
+#define UNIT_DurationUnits 42
+#define UNIT_ElapsedWeek 43
+#define UNIT_ElapsedDay 44
+#define UNIT_ElapsedHour 45
+#define UNIT_ElapsedMin 46
+#define UNIT_ElapsedSec 47
+#define UNIT_TypeUnits 48
+#define UNIT_PicasAndPoints 49
+#define UNIT_Points 50
+#define UNIT_Picas 51
+#define UNIT_CicerosAndDidots 52
+#define UNIT_Didots 53
+#define UNIT_Ciceros 54
+#define UNIT_PageUnits 63
+#define UNIT_DrawingUnits 64
+#define UNIT_Inches 65
+#define UNIT_Feet 66
+#define UNIT_FeetAndInches 67
+#define UNIT_Centimeters 69
+#define UNIT_Miles 68
+#define UNIT_Millimeters 70
+#define UNIT_Meters 71
+#define UNIT_Kilometers 72
+#define UNIT_InchFractions 73
+#define UNIT_MileFractions 74
+#define UNIT_Yards 75
+#define UNIT_NauticalMiles 76
+#define UNIT_AngleUnits 80
+#define UNIT_Degrees 81
+#define UNIT_DegreeMinuteSecond 82
+#define UNIT_Radians 83
+#define UNIT_Minutes 84
+#define UNIT_Sec 85
+#define UNIT_GUID 95
+#define UNIT_Currency 111
+#define UNIT_NURBS 138
+#define UNIT_Polyline 139
+#define UNIT_Point 225
+#define UNIT_String 231
+#define UNIT_StringWithoutUnit 232
+#define UNIT_Multidimensional 233 // like Acre, square meters, sq. inches, hectare, sq. yards
+#define UNIT_Color 251
+#define UNIT_NoCast 252 // No unit conversion
+#define UNIT_Invalid 255
+
// Field formats
#define VSD_FIELD_FORMAT_NumGenNoUnits 0
diff --git a/src/lib/VSDFieldList.cpp b/src/lib/VSDFieldList.cpp
index f6fc62d..7b6d058 100644
--- a/src/lib/VSDFieldList.cpp
+++ b/src/lib/VSDFieldList.cpp
@@ -44,12 +44,12 @@ void libvisio::VSDTextField::setNameId(int nameId)
void libvisio::VSDNumericField::handle(VSDCollector *collector) const
{
- collector->collectNumericField(m_id, m_level, m_format, m_number, m_formatStringId);
+ collector->collectNumericField(m_id, m_level, m_format, m_unit, m_number, m_formatStringId);
}
libvisio::VSDFieldListElement *libvisio::VSDNumericField::clone()
{
- return new VSDNumericField(m_id, m_level, m_format, m_number, m_formatStringId);
+ return new VSDNumericField(m_id, m_level, m_format, m_unit, m_number, m_formatStringId);
}
#define MAX_BUFFER 1024
@@ -95,6 +95,85 @@ static librevenge::RVNGString doubleToString(const double value, const char* for
return librevenge::RVNGString(stringValue.c_str());
}
+double convertNumber(const unsigned short unit, const double number)
+{
+ switch (unit)
+ {
+ case UNIT_Percent:
+ return number*100.0;
+
+ case UNIT_Points:
+ return number*72.0;
+ case UNIT_Picas:
+ return number*6.0;
+ case UNIT_Didots:
+ return number*67.37400530504;
+ case UNIT_Ciceros:
+ return number*5.62984854;
+ case UNIT_Inches:
+ return number;
+ case UNIT_Feet:
+ return number*0.0833333333;
+ case UNIT_Centimeters:
+ return number*2.54;
+ case UNIT_Miles:
+ return number*63360;
+ case UNIT_Millimeters:
+ return number*25.4;
+ case UNIT_Meters:
+ return number*0.0254;
+ case UNIT_Kilometers:
+ return number*0.0000254;
+ default:
+ return number;
+ }
+}
+
+librevenge::RVNGString getUnitString(const unsigned short unit)
+{
+ switch (unit)
+ {
+ case UNIT_Number:
+ case UNIT_Date: // TODO
+ case UNIT_String:
+ case UNIT_StringWithoutUnit:
+ case UNIT_NoCast:
+ case UNIT_Invalid:
+ return "";
+ case UNIT_Percent:
+ return "%";
+ case UNIT_Acre:
+ return "acres";
+ case UNIT_Hectare:
+ return "ha";
+
+ case UNIT_Points:
+ return "pt";
+ case UNIT_Picas:
+ return "p";
+ case UNIT_Didots:
+ return "d";
+ case UNIT_Ciceros:
+ return "c";
+ case UNIT_Inches:
+ return "in";
+ case UNIT_Feet:
+ return "ft";
+ case UNIT_Centimeters:
+ return "cm";
+ case UNIT_Miles:
+ return "mi";
+ case UNIT_Millimeters:
+ return "mm";
+ case UNIT_Meters:
+ return "m";
+ case UNIT_Kilometers:
+ return "km";
+ default:
+ return "";
+ }
+}
+
librevenge::RVNGString libvisio::VSDNumericField::getString(const std::map<unsigned, librevenge::RVNGString> &)
{
if (m_format == VSD_FIELD_FORMAT_Unknown)
@@ -106,15 +185,14 @@ librevenge::RVNGString libvisio::VSDNumericField::getString(const std::map<unsig
{
// 0 Format string: 0.#### Example: 30060.9167
// 1 Format string: 0.#### u Example: 30060.9167 cm
- return doubleToString(m_number, "%.4g");
+ return doubleToString(convertNumber(m_unit, m_number), "%.4g");
}
case VSD_FIELD_FORMAT_0PlNoUnits:
case VSD_FIELD_FORMAT_0PlDefUnits:
{
// 2 Format string: 0 Example: 30061
// 3 Format string: 0 u Example: 30061 cm
- std::unique_ptr<librevenge::RVNGProperty> pProp{librevenge::RVNGPropertyFactory::newIntProp(m_number)};
- return pProp ? pProp->getStr() : librevenge::RVNGString();
+ return doubleToString(convertNumber(m_unit, m_number), "%.0f");
}
case VSD_FIELD_FORMAT_1PlNoUnits:
@@ -122,7 +200,7 @@ librevenge::RVNGString libvisio::VSDNumericField::getString(const std::map<unsig
{
// 4 Format string: 0.0 Example: 30060.9
// 5 Format string: 0.0 u Example: 30060.9 cm
- return doubleToString(m_number, "%.1f");
+ return doubleToString(convertNumber(m_unit, m_number), "%.1f");
}
case VSD_FIELD_FORMAT_2PlNoUnits:
@@ -130,7 +208,7 @@ librevenge::RVNGString libvisio::VSDNumericField::getString(const std::map<unsig
{
// 6 Format string: 0.00 Example: 30061.92
// 7 Format string: 0.00 u Example: 30061.92 cm
- return doubleToString(m_number, "%.2f");
+ return doubleToString(convertNumber(m_unit, m_number), "%.2f");
}
case VSD_FIELD_FORMAT_3PlNoUnits:
@@ -138,7 +216,7 @@ librevenge::RVNGString libvisio::VSDNumericField::getString(const std::map<unsig
{
// 8 Format string: 0.000 Example: 30061.916
// 9 Format string: 0.000 u Example: 30061.916 cm
- return doubleToString(m_number, "%.3f");
+ return doubleToString(convertNumber(m_unit, m_number), "%.3f");
}
//TODO VSD_FIELD_FORMAT_FeetAndInches 10 Format string: <,FEET/INCH>0.000 u
//TODO VSD_FIELD_FORMAT_Radians 11 Format string: <,rad>0.#### u
@@ -301,6 +379,12 @@ void libvisio::VSDNumericField::setFormat(unsigned short format)
{
m_format = format;
}
+
+void libvisio::VSDNumericField::setUnit(unsigned short unit)
+{
+ m_unit = unit;
+}
+
void libvisio::VSDNumericField::setValue(double number)
{
m_number = number;
@@ -362,10 +446,10 @@ void libvisio::VSDFieldList::addTextField(unsigned id, unsigned level, int nameI
m_elements[id] = make_unique<VSDTextField>(id, level, nameId, formatStringId);
}
-void libvisio::VSDFieldList::addNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId)
+void libvisio::VSDFieldList::addNumericField(unsigned id, unsigned level, unsigned short format, unsigned short unit, double number, int formatStringId)
{
if (m_elements.find(id) == m_elements.end())
- m_elements[id] = make_unique<VSDNumericField>(id, level, format, number, formatStringId);
+ m_elements[id] = make_unique<VSDNumericField>(id, level, format, unit, number, formatStringId);
}
void libvisio::VSDFieldList::handle(VSDCollector *collector) const
diff --git a/src/lib/VSDFieldList.h b/src/lib/VSDFieldList.h
index 9d47bb3..9fe2951 100644
--- a/src/lib/VSDFieldList.h
+++ b/src/lib/VSDFieldList.h
@@ -32,6 +32,7 @@ public:
virtual librevenge::RVNGString getString(const std::map<unsigned, librevenge::RVNGString> &) = 0;
virtual void setNameId(int) = 0;
virtual void setFormat(unsigned short) = 0;
+ virtual void setUnit(unsigned short) = 0;
virtual void setValue(double) = 0;
};
@@ -49,6 +50,7 @@ public:
librevenge::RVNGString getString(const std::map<unsigned, librevenge::RVNGString> &strVec) override;
void setNameId(int nameId) override;
void setFormat(unsigned short) override {}
+ void setUnit(unsigned short) override {}
void setValue(double) override {}
private:
unsigned m_id, m_level;
@@ -58,10 +60,11 @@ private:
class VSDNumericField : public VSDFieldListElement
{
public:
- VSDNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId)
+ VSDNumericField(unsigned id, unsigned level, unsigned short format, unsigned short unit, double number, int formatStringId)
: m_id(id),
m_level(level),
m_format(format),
+ m_unit(unit),
m_number(number),
m_formatStringId(formatStringId) {}
~VSDNumericField() override {}
@@ -70,11 +73,13 @@ public:
librevenge::RVNGString getString(const std::map<unsigned, librevenge::RVNGString> &) override;
void setNameId(int) override {}
void setFormat(unsigned short format) override;
+ void setUnit(unsigned short unit) override;
void setValue(double number) override;
private:
librevenge::RVNGString datetimeToString(const char *format, double datetime);
unsigned m_id, m_level;
unsigned short m_format;
+ unsigned short m_unit;
double m_number;
int m_formatStringId;
};
@@ -89,7 +94,7 @@ public:
void setElementsOrder(const std::vector<unsigned> &m_elementsOrder);
void addFieldList(unsigned id, unsigned level);
void addTextField(unsigned id, unsigned level, int nameId, int formatStringId);
- void addNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId);
+ void addNumericField(unsigned id, unsigned level, unsigned short format, unsigned short unit, double number, int formatStringId);
void addClonedField(unsigned id);
void handle(VSDCollector *collector) const;
void clear();
diff --git a/src/lib/VSDParser.cpp b/src/lib/VSDParser.cpp
index cc0bb96..980a4ca 100644
--- a/src/lib/VSDParser.cpp
+++ b/src/lib/VSDParser.cpp
@@ -2173,7 +2173,7 @@ void libvisio::VSDParser::readTextField(librevenge::RVNGInputStream *input)
unsigned long initialPosition = input->tell();
input->seek(7, librevenge::RVNG_SEEK_CUR);
unsigned char unit = readU8(input);
- if (unit == 0xe8)
+ if (unit == UNIT_StringWithoutUnit)
{
int nameId = readS32(input);
input->seek(6, librevenge::RVNG_SEEK_CUR);
@@ -2227,13 +2227,13 @@ void libvisio::VSDParser::readTextField(librevenge::RVNGInputStream *input)
if (blockIdx != 2)
{
- if (unit == 0x28)
+ if (unit == UNIT_Date)
formatNumber = VSD_FIELD_FORMAT_MsoDateShort;
else
formatNumber = VSD_FIELD_FORMAT_Unknown;
}
- m_shape.m_fields.addNumericField(m_header.id, m_header.level, formatNumber, numericValue, formatStringId);
+ m_shape.m_fields.addNumericField(m_header.id, m_header.level, formatNumber, unit, numericValue, formatStringId);
}
}
diff --git a/src/lib/VSDStylesCollector.cpp b/src/lib/VSDStylesCollector.cpp
index cc8021f..5503ede 100644
--- a/src/lib/VSDStylesCollector.cpp
+++ b/src/lib/VSDStylesCollector.cpp
@@ -408,7 +408,7 @@ void libvisio::VSDStylesCollector::collectTextField(unsigned /* id */, unsigned
_handleLevelChange(level);
}
-void libvisio::VSDStylesCollector::collectNumericField(unsigned /* id */, unsigned level, unsigned short /* format */, double /* number */, int /* formatStringId */)
+void libvisio::VSDStylesCollector::collectNumericField(unsigned /* id */, unsigned level, unsigned short /* format */, unsigned short /* unit */, double /* number */, int /* formatStringId */)
{
_handleLevelChange(level);
}
diff --git a/src/lib/VSDStylesCollector.h b/src/lib/VSDStylesCollector.h
index b18fdd6..6da8f2c 100644
--- a/src/lib/VSDStylesCollector.h
+++ b/src/lib/VSDStylesCollector.h
@@ -163,7 +163,7 @@ public:
// Field list
void collectFieldList(unsigned id, unsigned level) override;
void collectTextField(unsigned id, unsigned level, int nameId, int formatStringId) override;
- void collectNumericField(unsigned id, unsigned level, unsigned short format, double number, int formatStringId) override;
+ void collectNumericField(unsigned id, unsigned level, unsigned short format, unsigned short unit, double number, int formatStringId) override;
void collectMetaData(const librevenge::RVNGPropertyList &) override { }
diff --git a/src/test/data/Visio11TextFieldsWithUnits.vsd b/src/test/data/Visio11TextFieldsWithUnits.vsd
new file mode 100644
index 0000000..be927c5
--- /dev/null
+++ b/src/test/data/Visio11TextFieldsWithUnits.vsd
Binary files differ
diff --git a/src/test/data/Visio6TextFieldsWithUnits.vsd b/src/test/data/Visio6TextFieldsWithUnits.vsd
new file mode 100644
index 0000000..dbbf103
--- /dev/null
+++ b/src/test/data/Visio6TextFieldsWithUnits.vsd
Binary files differ
diff --git a/src/test/importtest.cpp b/src/test/importtest.cpp
index 100338d..6ced876 100644
--- a/src/test/importtest.cpp
+++ b/src/test/importtest.cpp
@@ -153,7 +153,7 @@ xmlDocPtr parse(const char *filename, xmlBufferPtr buffer)
xmlTextWriterEndDocument(writer);
xmlFreeTextWriter(writer);
- //std::cerr << "XML is '" << (const char *)xmlBufferContent(buffer) << "'" << std::endl;
+ std::cerr << "XML is '" << (const char *)xmlBufferContent(buffer) << "'" << std::endl;
return xmlParseMemory((const char *)xmlBufferContent(buffer), xmlBufferLength(buffer));
}
@@ -178,6 +178,7 @@ class ImportTest : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST(testVsdTextBlockWithoutBgColor);
CPPUNIT_TEST(testVsdNumericFormat);
CPPUNIT_TEST(testVsdDateTimeFormatting);
+ CPPUNIT_TEST(testVsd11TextfieldsWithUnits);
CPPUNIT_TEST(testBmpFileHeader);
CPPUNIT_TEST(testBmpFileHeader2);
CPPUNIT_TEST_SUITE_END();
@@ -192,6 +193,7 @@ class ImportTest : public CPPUNIT_NS::TestFixture
void testVsdTextBlockWithoutBgColor();
void testVsdNumericFormat();
void testVsdDateTimeFormatting();
+ void testVsd11TextfieldsWithUnits();
void testBmpFileHeader();
void testBmpFileHeader2();
@@ -333,6 +335,13 @@ void ImportTest::testVsdDateTimeFormatting()
assertXPathContent(m_doc, "/document/page/textObject/paragraph/span/insertText", "11/30/2005");
}
+// tdf#126292
+void ImportTest::testVsd11TextfieldsWithUnits()
+{
+ m_doc = parse("Visio11TextFieldsWithUnits.vsd", m_buffer);
+ assertXPathContent(m_doc, "/document/page/textObject/paragraph/span/insertText", "11/30/2005");
+}
+
void ImportTest::testBmpFileHeader()
{
m_doc = parse("bitmaps.vsd", m_buffer);