summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorosnola <alonso@loria.fr>2017-07-13 16:29:57 +0200
committerDavid Tardon <dtardon@redhat.com>2017-07-13 16:29:57 +0200
commitfd69377a60eba6865e751ffbfaddc0666a1cb602 (patch)
treeb5e6c26df30b6e36d4a3116ca661a2202408b849
parent1e1bbbae0a929b0b421ce1f7793faf31d4f5eca8 (diff)
try to improve the parsing of v3 files
Change-Id: I59011935ce87d14309ff0265218b3f383f857ebd
-rw-r--r--src/lib/FHCollector.cpp183
-rw-r--r--src/lib/FHCollector.h13
-rw-r--r--src/lib/FHParser.cpp159
-rw-r--r--src/lib/FHParser.h2
-rw-r--r--src/lib/FHPath.cpp46
-rw-r--r--src/lib/FHPath.h6
-rw-r--r--src/lib/FHTypes.h26
-rw-r--r--src/lib/tokens.txt2
8 files changed, 393 insertions, 44 deletions
diff --git a/src/lib/FHCollector.cpp b/src/lib/FHCollector.cpp
index 146a33c..408e40a 100644
--- a/src/lib/FHCollector.cpp
+++ b/src/lib/FHCollector.cpp
@@ -238,11 +238,12 @@ private:
libfreehand::FHCollector::FHCollector() :
m_pageInfo(), m_fhTail(), m_block(), m_transforms(), m_paths(), m_strings(), m_names(), m_lists(),
m_layers(), m_groups(), m_clipGroups(), m_currentTransforms(), m_fakeTransforms(), m_compositePaths(),
- m_tStrings(), m_fonts(), m_paragraphs(), m_textBloks(), m_textObjects(), m_charProperties(),
+ m_pathTexts(), m_tStrings(), m_fonts(), m_paragraphs(), m_textBloks(), m_textObjects(), m_charProperties(),
m_rgbColors(), m_basicFills(), m_propertyLists(), m_basicLines(), m_displayTexts(), m_graphicStyles(),
m_attributeHolders(), m_data(), m_dataLists(), m_images(), m_multiColorLists(), m_linearFills(),
m_tints(), m_lensFills(), m_radialFills(), m_newBlends(), m_filterAttributeHolders(), m_opacityFilters(),
m_shadowFilters(), m_glowFilters(), m_tileFills(), m_symbolClasses(), m_symbolInstances(), m_patternFills(),
+ m_linePatterns(), m_arrowPaths(),
m_strokeId(0), m_fillId(0), m_contentId(0), m_visitedObjects()
{
}
@@ -322,6 +323,11 @@ void libfreehand::FHCollector::collectCompositePath(unsigned recordId, const lib
m_compositePaths[recordId] = compositePath;
}
+void libfreehand::FHCollector::collectPathText(unsigned recordId, const libfreehand::FHPathText &pathText)
+{
+ m_pathTexts[recordId] = pathText;
+}
+
void libfreehand::FHCollector::collectTString(unsigned recordId, const std::vector<unsigned> &elements)
{
m_tStrings[recordId] = elements;
@@ -382,6 +388,17 @@ void libfreehand::FHCollector::collectPatternFill(unsigned recordId, const FHPat
m_patternFills[recordId] = fill;
}
+void libfreehand::FHCollector::collectLinePattern(unsigned recordId, const FHLinePattern &line)
+{
+ m_linePatterns[recordId] = line;
+}
+
+void libfreehand::FHCollector::collectArrowPath(unsigned recordId, const FHPath &path)
+{
+ // osnola: useme
+ m_arrowPaths[recordId] = path;
+}
+
void libfreehand::FHCollector::collectPropList(unsigned recordId, const FHPropList &propertyList)
{
m_propertyLists[recordId] = propertyList;
@@ -615,6 +632,14 @@ void libfreehand::FHCollector::_getBBofCompositePath(const FHCompositePath *comp
}
}
+void libfreehand::FHCollector::_getBBofPathText(const FHPathText *pathText, libfreehand::FHBoundingBox &bBox)
+{
+ if (!pathText)
+ return;
+
+ _getBBofDisplayText(_findDisplayText(pathText->m_displayTextId),bBox);
+}
+
void libfreehand::FHCollector::_getBBofTextObject(const FHTextObject *textObject, libfreehand::FHBoundingBox &bBox)
{
if (!textObject)
@@ -856,6 +881,7 @@ void libfreehand::FHCollector::_getBBofSomething(unsigned somethingId, libfreeha
FHBoundingBox tmpBBox;
_getBBofGroup(_findGroup(somethingId), tmpBBox);
_getBBofClipGroup(_findClipGroup(somethingId), tmpBBox);
+ _getBBofPathText(_findPathText(somethingId), tmpBBox);
_getBBofPath(_findPath(somethingId), tmpBBox);
_getBBofCompositePath(_findCompositePath(somethingId), tmpBBox);
_getBBofTextObject(_findTextObject(somethingId), tmpBBox);
@@ -989,6 +1015,7 @@ void libfreehand::FHCollector::_outputSomething(unsigned somethingId, librevenge
_outputGroup(_findGroup(somethingId), painter);
_outputClipGroup(_findClipGroup(somethingId), painter);
+ _outputPathText(_findPathText(somethingId), painter);
_outputPath(_findPath(somethingId), painter);
_outputCompositePath(_findCompositePath(somethingId), painter);
_outputTextObject(_findTextObject(somethingId), painter);
@@ -1147,6 +1174,14 @@ void libfreehand::FHCollector::_outputClipGroup(const libfreehand::FHGroup *grou
}
}
+void libfreehand::FHCollector::_outputPathText(const libfreehand::FHPathText *pathText, librevenge::RVNGDrawingInterface *painter)
+{
+ if (!painter || !pathText)
+ return;
+
+ _outputDisplayText(_findDisplayText(pathText->m_displayTextId), painter);
+}
+
void libfreehand::FHCollector::_outputNewBlend(const libfreehand::FHNewBlend *newBlend, librevenge::RVNGDrawingInterface *painter)
{
if (!painter || !newBlend)
@@ -1455,6 +1490,17 @@ void libfreehand::FHCollector::_appendCharacterProperties(librevenge::RVNGProper
propList.insert("fo:font-weight", "bold");
if (charProps.m_fontStyle & 2)
propList.insert("fo:font-style", "italic");
+ if (charProps.m_letterSpacing<0 || charProps.m_letterSpacing>0)
+ propList.insert("fo:letter-spacing", charProps.m_letterSpacing, librevenge::RVNG_POINT);
+ if (charProps.m_horizontalScale<1 || charProps.m_horizontalScale>1)
+ propList.insert("style:text-scale", charProps.m_horizontalScale, librevenge::RVNG_PERCENT);
+ if (charProps.m_baselineShift<0 || charProps.m_baselineShift>0)
+ {
+ librevenge::RVNGString value;
+ double fontSize=(charProps.m_fontSize>0) ? charProps.m_fontSize : 12.;
+ value.sprintf("%g%%",100.*charProps.m_baselineShift/fontSize);
+ propList.insert("style:text-position", value);
+ }
}
void libfreehand::FHCollector::_appendParagraphProperties(librevenge::RVNGPropertyList & /* propList */, const FH3ParaProperties & /* paraProps */)
@@ -1517,9 +1563,15 @@ void libfreehand::FHCollector::_outputDisplayText(const libfreehand::FHDisplayTe
textObjectProps.insert("svg:y", ymid + displayText->m_height / 2.0);
textObjectProps.insert("svg:height", height);
textObjectProps.insert("svg:width", width);
+ for (int i=0; i<4; ++i) // osnola: let assume that there is no padding
+ {
+ char const *(padding[])= {"fo:padding-left","fo:padding-right","fo:padding-top","fo:padding-bottom"};
+ textObjectProps.insert(padding[i],0,librevenge::RVNG_POINT);
+ }
if (!FH_ALMOST_ZERO(rotation))
textObjectProps.insert("librevenge:rotate", rotation * 180.0 / M_PI);
-
+ if (displayText->m_justify==4) // top-down: checkme do nothing
+ textObjectProps.insert("style:writing-mode", "tb-lr");
painter->startTextObject(textObjectProps);
std::vector<FH3ParaProperties>::const_iterator iterPara = displayText->m_paraProps.begin();
@@ -1532,6 +1584,27 @@ void libfreehand::FHCollector::_outputDisplayText(const libfreehand::FHDisplayTe
librevenge::RVNGPropertyList paraPropList;
_appendParagraphProperties(paraPropList, paraProps);
+ switch (displayText->m_justify)
+ {
+ case 0: // left
+ break;
+ case 1:
+ paraPropList.insert("fo:text-align", "center");
+ break;
+ case 2:
+ paraPropList.insert("fo:text-align", "end");
+ break;
+ case 3:
+ paraPropList.insert("fo:text-align", "justify");
+ break;
+ case 4:
+ default:
+ break;
+ }
+ if (charProps.m_leading>0)
+ paraPropList.insert("fo:line-height",charProps.m_leading,librevenge::RVNG_POINT);
+ else
+ paraPropList.insert("fo:line-height",1.,librevenge::RVNG_PERCENT);
painter->openParagraph(paraPropList);
bool isParagraphOpened = true;
@@ -1582,8 +1655,14 @@ void libfreehand::FHCollector::_outputDisplayText(const libfreehand::FHDisplayTe
break;
if (!isParagraphOpened)
{
+#if 0
paraPropList.clear();
_appendParagraphProperties(paraPropList, paraProps);
+#endif
+ if (charProps.m_leading>0)
+ paraPropList.insert("fo:line-height",charProps.m_leading,librevenge::RVNG_POINT);
+ else
+ paraPropList.insert("fo:line-height",1.,librevenge::RVNG_PERCENT);
painter->openParagraph(paraPropList);
isParagraphOpened = true;
if (!isSpanOpened)
@@ -2102,17 +2181,85 @@ void libfreehand::FHCollector::_appendPatternFill(librevenge::RVNGPropertyList &
propList.insert("style:repeat", "repeat");
}
+void libfreehand::FHCollector::_appendLinePattern(librevenge::RVNGPropertyList &propList, const libfreehand::FHLinePattern *linePattern)
+{
+ if (!linePattern || linePattern->m_dashes.size()<=1)
+ return;
+ int nDots1=0, nDots2=0;
+ double size1=0, size2=0, totalGap=0.0;
+ for (size_t c=0; c+1 < linePattern->m_dashes.size();)
+ {
+ double sz=linePattern->m_dashes[c++];
+ if (nDots2 && (sz<size2||sz>size2))
+ {
+ static bool first=true;
+ if (first)
+ {
+ FH_DEBUG_MSG(("libfreehand::FHCollector::_appendLinePattern: can not set some dash\n"));
+ first = false;
+ }
+ break;
+ }
+ if (nDots2)
+ nDots2++;
+ else if (!nDots1 || (sz>=size1 && sz <= size1))
+ {
+ nDots1++;
+ size1=sz;
+ }
+ else
+ {
+ nDots2=1;
+ size2=sz;
+ }
+ totalGap += linePattern->m_dashes[c++];
+ }
+ propList.insert("draw:stroke", "dash");
+ propList.insert("draw:dots1", nDots1);
+ propList.insert("draw:dots1-length", double(size1), librevenge::RVNG_POINT);
+ if (nDots2)
+ {
+ propList.insert("draw:dots2", nDots2);
+ propList.insert("draw:dots2-length", double(size2), librevenge::RVNG_POINT);
+ }
+ const double distance = ((nDots1 + nDots2) > 0) ? double(totalGap)/double(nDots1+nDots2) : double(totalGap);
+ propList.insert("draw:distance", distance, librevenge::RVNG_POINT);;
+}
+
+void libfreehand::FHCollector::_appendArrowPath(librevenge::RVNGPropertyList &propList, const FHPath *arrow, bool startArrow)
+{
+ if (!arrow)
+ return;
+
+ FHPath path=*arrow;
+ path.transform(FHTransform(0,-1,1,0,0,0));
+ std::string pString=path.getPathString();
+ if (pString.empty()) return;
+ std::string wh(startArrow ? "start" : "end");
+ propList.insert((std::string("draw:marker-")+wh+"-path").c_str(), pString.c_str());
+ FHBoundingBox box;
+ path.getBoundingBox(box.m_xmin, box.m_ymin, box.m_xmax, box.m_ymax);
+ librevenge::RVNGString boxString;
+ boxString.sprintf("%d %d %d %d", int(box.m_xmin*35), int(box.m_ymin*35), int(35*(box.m_xmax-box.m_xmin)), int(35*(box.m_ymax-box.m_ymin)));
+ propList.insert((std::string("draw:marker-")+wh+"-viewbox").c_str(), boxString);
+ propList.insert((std::string("draw:marker-")+wh+"-width").c_str(), 10, librevenge::RVNG_POINT); // change me
+}
+
void libfreehand::FHCollector::_appendBasicLine(librevenge::RVNGPropertyList &propList, const libfreehand::FHBasicLine *basicLine)
{
if (!basicLine)
return;
+ // osnola: we do not want to change draw:stroke, if stroke is defined recursively
propList.insert("draw:stroke", "solid");
librevenge::RVNGString color = getColorString(basicLine->m_colorId);
if (!color.empty())
propList.insert("svg:stroke-color", color);
- else
+ else if (!propList["svg:stroke-color"]) // set to default
propList.insert("svg:stroke-color", "#000000");
propList.insert("svg:stroke-width", basicLine->m_width);
+ _appendLinePattern(propList, _findLinePattern(basicLine->m_linePatternId));
+ _appendArrowPath(propList, _findArrowPath(basicLine->m_startArrowId), true);
+ _appendArrowPath(propList, _findArrowPath(basicLine->m_endArrowId), false);
}
const libfreehand::FHPath *libfreehand::FHCollector::_findPath(unsigned id)
@@ -2165,6 +2312,16 @@ const libfreehand::FHCompositePath *libfreehand::FHCollector::_findCompositePath
return 0;
}
+const libfreehand::FHPathText *libfreehand::FHCollector::_findPathText(unsigned id)
+{
+ if (!id)
+ return 0;
+ std::map<unsigned, FHPathText>::const_iterator iter = m_pathTexts.find(id);
+ if (iter != m_pathTexts.end())
+ return &(iter->second);
+ return 0;
+}
+
const libfreehand::FHTextObject *libfreehand::FHCollector::_findTextObject(unsigned id)
{
if (!id)
@@ -2285,6 +2442,26 @@ const libfreehand::FHPatternFill *libfreehand::FHCollector::_findPatternFill(uns
return 0;
}
+const libfreehand::FHLinePattern *libfreehand::FHCollector::_findLinePattern(unsigned id)
+{
+ if (!id)
+ return 0;
+ std::map<unsigned, FHLinePattern>::const_iterator iter = m_linePatterns.find(id);
+ if (iter != m_linePatterns.end())
+ return &(iter->second);
+ return 0;
+}
+
+const libfreehand::FHPath *libfreehand::FHCollector::_findArrowPath(unsigned id)
+{
+ if (!id)
+ return 0;
+ std::map<unsigned, FHPath>::const_iterator iter = m_arrowPaths.find(id);
+ if (iter != m_arrowPaths.end())
+ return &(iter->second);
+ return 0;
+}
+
const libfreehand::FHBasicLine *libfreehand::FHCollector::_findBasicLine(unsigned id)
{
if (!id)
diff --git a/src/lib/FHCollector.h b/src/lib/FHCollector.h
index 32b3a71..3150426 100644
--- a/src/lib/FHCollector.h
+++ b/src/lib/FHCollector.h
@@ -40,6 +40,7 @@ public:
void collectLayer(unsigned recordId, const FHLayer &layer);
void collectGroup(unsigned recordId, const FHGroup &group);
void collectClipGroup(unsigned recordId, const FHGroup &group);
+ void collectPathText(unsigned recordId, const FHPathText &group);
void collectCompositePath(unsigned recordId, const FHCompositePath &compositePath);
void collectTString(unsigned recordId, const std::vector<unsigned> &elements);
void collectAGDFont(unsigned recordId, const FHAGDFont &font);
@@ -72,6 +73,8 @@ public:
void collectBasicLine(unsigned recordId, const FHBasicLine &line);
void collectTileFill(unsigned recordId, const FHTileFill &fill);
void collectPatternFill(unsigned recordId, const FHPatternFill &fill);
+ void collectLinePattern(unsigned recordId, const FHLinePattern &line);
+ void collectArrowPath(unsigned recordId, const FHPath &path);
void collectSymbolClass(unsigned recordId, const FHSymbolClass &symbolClass);
void collectSymbolInstance(unsigned recordId, const FHSymbolInstance &symbolInstance);
@@ -90,6 +93,7 @@ private:
void _outputGroup(const FHGroup *group, librevenge::RVNGDrawingInterface *painter);
void _outputClipGroup(const FHGroup *group, librevenge::RVNGDrawingInterface *painter);
void _outputCompositePath(const FHCompositePath *compositePath, librevenge::RVNGDrawingInterface *painter);
+ void _outputPathText(const FHPathText *pathText, librevenge::RVNGDrawingInterface *painter);
void _outputTextObject(const FHTextObject *textObject, librevenge::RVNGDrawingInterface *painter);
void _outputParagraph(const FHParagraph *paragraph, librevenge::RVNGDrawingInterface *painter);
void _outputTextRun(const std::vector<unsigned short> *characters, unsigned offset, unsigned length,
@@ -104,6 +108,7 @@ private:
void _getBBofLayer(unsigned layerId,FHBoundingBox &bBox);
void _getBBofGroup(const FHGroup *group,FHBoundingBox &bBox);
void _getBBofClipGroup(const FHGroup *group,FHBoundingBox &bBox);
+ void _getBBofPathText(const FHPathText *pathText,FHBoundingBox &bBox);
void _getBBofCompositePath(const FHCompositePath *compositePath,FHBoundingBox &bBox);
void _getBBofTextObject(const FHTextObject *textObject,FHBoundingBox &bBox);
void _getBBofDisplayText(const FHDisplayText *displayText,FHBoundingBox &bBox);
@@ -127,6 +132,8 @@ private:
void _appendRadialFill(librevenge::RVNGPropertyList &propList, const FHRadialFill *radialFill);
void _appendTileFill(librevenge::RVNGPropertyList &propList, const FHTileFill *tileFill);
void _appendPatternFill(librevenge::RVNGPropertyList &propList, const FHPatternFill *patternFill);
+ void _appendLinePattern(librevenge::RVNGPropertyList &propList, const FHLinePattern *linePattern);
+ void _appendArrowPath(librevenge::RVNGPropertyList &propList, const FHPath *arrow, bool startArrow);
void _appendOpacity(librevenge::RVNGPropertyList &propList, const double *opacity);
void _appendShadow(librevenge::RVNGPropertyList &propList, const FWShadowFilter *filter);
void _appendGlow(librevenge::RVNGPropertyList &propList, const FWGlowFilter *filter);
@@ -137,6 +144,7 @@ private:
const FHGroup *_findGroup(unsigned id);
const FHGroup *_findClipGroup(unsigned id);
const FHCompositePath *_findCompositePath(unsigned id);
+ const FHPathText *_findPathText(unsigned id);
const FHTextObject *_findTextObject(unsigned id);
const FHTransform *_findTransform(unsigned id);
const FHParagraph *_findParagraph(unsigned id);
@@ -149,6 +157,8 @@ private:
const FHRadialFill *_findRadialFill(unsigned id);
const FHTileFill *_findTileFill(unsigned id);
const FHPatternFill *_findPatternFill(unsigned id);
+ const FHLinePattern *_findLinePattern(unsigned id);
+ const FHPath *_findArrowPath(unsigned id);
const FHBasicLine *_findBasicLine(unsigned id);
const FHRGBColor *_findRGBColor(unsigned id);
const FHTintColor *_findTintColor(unsigned id);
@@ -187,6 +197,7 @@ private:
std::stack<FHTransform> m_currentTransforms;
std::vector<FHTransform> m_fakeTransforms;
std::map<unsigned, FHCompositePath> m_compositePaths;
+ std::map<unsigned, FHPathText> m_pathTexts;
std::map<unsigned, std::vector<unsigned> > m_tStrings;
std::map<unsigned, FHAGDFont> m_fonts;
std::map<unsigned, FHParagraph> m_paragraphs;
@@ -217,6 +228,8 @@ private:
std::map<unsigned, FHSymbolClass> m_symbolClasses;
std::map<unsigned, FHSymbolInstance> m_symbolInstances;
std::map<unsigned, FHPatternFill> m_patternFills;
+ std::map<unsigned, FHLinePattern> m_linePatterns;
+ std::map<unsigned, FHPath> m_arrowPaths;
unsigned m_strokeId;
unsigned m_fillId;
diff --git a/src/lib/FHParser.cpp b/src/lib/FHParser.cpp
index 40d22ee..7cd4d54 100644
--- a/src/lib/FHParser.cpp
+++ b/src/lib/FHParser.cpp
@@ -391,6 +391,9 @@ void libfreehand::FHParser::parseRecord(librevenge::RVNGInputStream *input, libf
case FH_PATH:
readPath(input, collector);
break;
+ case FH_PATHTEXT:
+ readPathText(input, collector);
+ break;
case FH_PATHTEXTLINEINFO:
readPathTextLineInfo(input, collector);
break;
@@ -418,6 +421,9 @@ void libfreehand::FHParser::parseRecord(librevenge::RVNGInputStream *input, libf
case FH_PROPLST:
readPropLst(input, collector);
break;
+ case FH_PSFILL:
+ readPSFill(input, collector);
+ break;
case FH_PSLINE:
readPSLine(input, collector);
break;
@@ -575,16 +581,65 @@ void libfreehand::FHParser::readAGDSelection(librevenge::RVNGInputStream *input,
input->seek(6+size*4, librevenge::RVNG_SEEK_CUR);
}
-void libfreehand::FHParser::readArrowPath(librevenge::RVNGInputStream *input, libfreehand::FHCollector * /* collector */)
+void libfreehand::FHParser::readArrowPath(librevenge::RVNGInputStream *input, libfreehand::FHCollector *collector)
{
if (m_version > 8)
input->seek(20, librevenge::RVNG_SEEK_CUR);
- unsigned size = readU16(input);
+ unsigned numPoints = readU16(input);
if (m_version <= 8)
input->seek(20, librevenge::RVNG_SEEK_CUR);
if (m_version > 3)
input->seek(4, librevenge::RVNG_SEEK_CUR);
- input->seek(size*27+4, librevenge::RVNG_SEEK_CUR);
+ input->seek(4, librevenge::RVNG_SEEK_CUR);
+
+ long endPos=input->tell()+27*numPoints;
+ std::vector<unsigned char> ptrTypes;
+ std::vector<std::vector<std::pair<double, double> > > path;
+ try
+ {
+ for (unsigned short i = 0; i < numPoints && !input->isEnd(); ++i)
+ {
+ input->seek(1, librevenge::RVNG_SEEK_CUR);
+ ptrTypes.push_back(readU8(input));
+ input->seek(1, librevenge::RVNG_SEEK_CUR);
+ std::vector<std::pair<double, double> > segment;
+ for (unsigned short j = 0; j < 3 && !input->isEnd(); ++j)
+ {
+ double x = _readCoordinate(input);
+ double y = _readCoordinate(input);
+ std::pair<double, double> tmpPoint = std::make_pair(x, y);
+ segment.push_back(tmpPoint);
+ }
+ if (segment.size() == 3)
+ path.push_back(segment);
+ segment.clear();
+ }
+ }
+ catch (const EndOfStreamException &)
+ {
+ FH_DEBUG_MSG(("libfreehand::FHParser::readArrowPath:Caught EndOfStreamException, continuing\n"));
+ }
+ input->seek(endPos, librevenge::RVNG_SEEK_SET);
+
+ if (path.empty())
+ {
+ FH_DEBUG_MSG(("libfreehand::FHParser::readArrowPath:No path was read\n"));
+ return;
+ }
+
+ FHPath fhPath;
+ fhPath.appendMoveTo(path[0][0].first / 72.0, path[0][0].second / 72.0);
+ unsigned i = 0;
+ for (i = 0; i<path.size()-1; ++i)
+ fhPath.appendCubicBezierTo(path[i][2].first / 72.0, path[i][2].second / 72.0,
+ path[i+1][1].first / 72.0, path[i+1][1].second / 72.0,
+ path[i+1][0].first / 72.0, path[i+1][0].second / 72.0);
+ fhPath.appendCubicBezierTo(path[i][2].first / 72.0, path[i][2].second / 72.0,
+ path[0][1].first / 72.0, path[0][1].second / 72.0,
+ path[0][0].first / 72.0, path[0][0].second / 72.0);
+ fhPath.appendClosePath();
+ if (collector && !fhPath.empty())
+ collector->collectArrowPath(m_currentRecord+1, fhPath);
}
void libfreehand::FHParser::readAttributeHolder(librevenge::RVNGInputStream *input, libfreehand::FHCollector *collector)
@@ -872,25 +927,16 @@ void libfreehand::FHParser::readDisplayText(librevenge::RVNGInputStream *input,
displayText.m_height = dimT - dimB;
input->seek(32, librevenge::RVNG_SEEK_CUR);
unsigned short textLength = readU16(input);
- input->seek(2, librevenge::RVNG_SEEK_CUR);
- FH3CharProperties charProps;
- charProps.m_offset = readU16(input);
+ displayText.m_justify=readU8(input);
+ input->seek(1, librevenge::RVNG_SEEK_CUR);
- input->seek(6, librevenge::RVNG_SEEK_CUR);
- charProps.m_fontNameId = _readRecordId(input);
- charProps.m_fontSize = _readCoordinate(input);
-
- input->seek(4, librevenge::RVNG_SEEK_CUR);
- charProps.m_fontStyle = readU32(input);
- charProps.m_fontColorId = _readRecordId(input);
-
- input->seek(18, librevenge::RVNG_SEEK_CUR);
- displayText.m_charProps.push_back(charProps);
- while (charProps.m_offset < textLength)
+ FH3CharProperties charProps;
+ do
{
_readFH3CharProperties(input, charProps);
displayText.m_charProps.push_back(charProps);
}
+ while (charProps.m_offset < textLength);
FH3ParaProperties paraProps;
do
{
@@ -1210,13 +1256,23 @@ void libfreehand::FHParser::readLinearFill(librevenge::RVNGInputStream *input, l
collector->collectLinearFill(m_currentRecord+1, fill);
}
-void libfreehand::FHParser::readLinePat(librevenge::RVNGInputStream *input, libfreehand::FHCollector * /* collector */)
+void libfreehand::FHParser::readLinePat(librevenge::RVNGInputStream *input, libfreehand::FHCollector *collector)
{
unsigned short numStrokes = readU16(input);
if (!numStrokes && m_version == 8)
+ {
+ // osnola: does not seems logical, what is that ?
+ FH_DEBUG_MSG(("libfreehand::FHParser::readLinePat: checkme something is not right here"));
input->seek(26, librevenge::RVNG_SEEK_CUR);
- else
- input->seek(8+numStrokes*4, librevenge::RVNG_SEEK_CUR);
+ return;
+ }
+ input->seek(8, librevenge::RVNG_SEEK_CUR);
+ FHLinePattern pattern;
+ pattern.m_dashes.resize(size_t(numStrokes));
+ for (unsigned short i=0; i<numStrokes; ++i)
+ pattern.m_dashes[size_t(i)]=_readCoordinate(input);
+ if (collector)
+ collector->collectLinePattern(m_currentRecord+1, pattern);
}
void libfreehand::FHParser::readLineTable(librevenge::RVNGInputStream *input, libfreehand::FHCollector * /* collector */)
@@ -1604,6 +1660,21 @@ void libfreehand::FHParser::readPath(librevenge::RVNGInputStream *input, libfree
collector->collectPath(m_currentRecord+1, fhPath);
}
+void libfreehand::FHParser::readPathText(librevenge::RVNGInputStream *input, libfreehand::FHCollector *collector)
+{
+ FHPathText group;
+ group.m_elementsId=_readRecordId(input);
+ group.m_layerId=_readRecordId(input);
+ input->seek(2, librevenge::RVNG_SEEK_CUR); // debText?
+ group.m_textSize=readU16(input);
+ input->seek(4, librevenge::RVNG_SEEK_CUR); // 0,0
+ group.m_displayTextId=_readRecordId(input);
+ group.m_shapeId=_readRecordId(input);
+
+ if (collector)
+ collector->collectPathText(m_currentRecord+1, group);
+}
+
void libfreehand::FHParser::readPathTextLineInfo(librevenge::RVNGInputStream *input, libfreehand::FHCollector * /* collector */)
{
input->seek(46, librevenge::RVNG_SEEK_CUR);
@@ -1726,6 +1797,11 @@ void libfreehand::FHParser::readPropLst(librevenge::RVNGInputStream *input, libf
collector->collectPropList(m_currentRecord+1, propertyList);
}
+void libfreehand::FHParser::readPSFill(librevenge::RVNGInputStream *input, libfreehand::FHCollector * /* collector */)
+{
+ input->seek(4, librevenge::RVNG_SEEK_CUR);
+}
+
void libfreehand::FHParser::readPSLine(librevenge::RVNGInputStream *input, libfreehand::FHCollector * /* collector */)
{
input->seek(8, librevenge::RVNG_SEEK_CUR);
@@ -1736,8 +1812,16 @@ void libfreehand::FHParser::readRadialFill(librevenge::RVNGInputStream *input, l
FHRadialFill fill;
fill.m_color1Id = _readRecordId(input);
fill.m_color2Id = _readRecordId(input);
- fill.m_cx = _readCoordinate(input);
- fill.m_cy = 1.0 - _readCoordinate(input);
+ if (m_version==3) // 0,0 => center
+ {
+ fill.m_cx = 0.5+0.5*_readCoordinate(input);
+ fill.m_cy = 0.5+0.5*_readCoordinate(input);
+ }
+ else
+ {
+ fill.m_cx = _readCoordinate(input);
+ fill.m_cy = 1.0 - _readCoordinate(input);
+ }
input->seek(4, librevenge::RVNG_SEEK_CUR);
if (collector)
collector->collectRadialFill(m_currentRecord+1, fill);
@@ -1977,7 +2061,7 @@ void libfreehand::FHParser::readTaperedFill(librevenge::RVNGInputStream *input,
FHLinearFill fill;
fill.m_color1Id = _readRecordId(input);
fill.m_color2Id = _readRecordId(input);
- fill.m_angle = _readCoordinate(input);
+ fill.m_angle = -_readCoordinate(input);
input->seek(4, librevenge::RVNG_SEEK_CUR);
if (collector)
collector->collectLinearFill(m_currentRecord+1, fill);
@@ -2031,7 +2115,7 @@ void libfreehand::FHParser::readTextBlok(librevenge::RVNGInputStream *input, lib
void libfreehand::FHParser::readTextEffs(librevenge::RVNGInputStream *input, libfreehand::FHCollector * /* collector */)
{
unsigned num = readU16(input);
- input->seek(22, librevenge::RVNG_SEEK_CUR);
+ input->seek(num==0 ? 20 : 22, librevenge::RVNG_SEEK_CUR);
for (unsigned i = 0; i < num; ++i)
{
readU16(input);
@@ -2390,9 +2474,7 @@ unsigned libfreehand::FHParser::_xformCalc(unsigned char var1, unsigned char var
double libfreehand::FHParser::_readCoordinate(librevenge::RVNGInputStream *input)
{
- double value = (double)readS16(input);
- value += (double)readU16(input) / 65536.0;
- return value;
+ return (double)readS32(input)/65536.;
}
libfreehand::FHRGBColor libfreehand::FHParser::_readRGBColor(librevenge::RVNGInputStream *input)
@@ -2447,7 +2529,7 @@ void libfreehand::FHParser::_readFH3CharProperties(librevenge::RVNGInputStream *
{
charProps.m_offset = readU16(input);
unsigned flags = readU16(input);
- if (flags & 0x1)// some kind of float
+ if (flags & 0x1) // xPos
_readCoordinate(input);
if (flags & 0x2) // kerning
_readCoordinate(input);
@@ -2457,7 +2539,17 @@ void libfreehand::FHParser::_readFH3CharProperties(librevenge::RVNGInputStream *
charProps.m_fontSize = _readCoordinate(input);
if (flags & 0x10)
{
- FH_DEBUG_MSG(("FHParser::_readFH3CharProperties: NEW FLAG IN DISPLAY TEXT! %x\n", flags));
+ unsigned long leading=readU32(input);
+ if (leading==0xFFFF0000)
+ charProps.m_leading=-1;
+ else if (leading==0xFFFE0000)
+ charProps.m_leading=-1;
+ else if (leading&0x80000000)
+ {
+ FH_DEBUG_MSG(("FHParser::_readFH3CharProperties: unexpected! %lx\n", leading));
+ }
+ else
+ charProps.m_leading=double(leading)/65536.;
}
if (flags & 0x20)
charProps.m_fontStyle = readU32(input);
@@ -2466,11 +2558,11 @@ void libfreehand::FHParser::_readFH3CharProperties(librevenge::RVNGInputStream *
if (flags & 0x80)
charProps.m_textEffsId = _readRecordId(input);
if (flags & 0x100)
- _readCoordinate(input);
+ charProps.m_letterSpacing=_readCoordinate(input);
if (flags & 0x200)
- _readCoordinate(input);
- if (flags & 0x400)
- _readCoordinate(input);
+ charProps.m_wordSpacing=_readCoordinate(input);
+ if (flags & 0x400) // in percent
+ charProps.m_horizontalScale=_readCoordinate(input);
if (flags & 0x800)
charProps.m_baselineShift = _readCoordinate(input);
if (flags & 0x1000)
@@ -2483,6 +2575,7 @@ void libfreehand::FHParser::_readFH3ParaProperties(librevenge::RVNGInputStream *
{
paraProps.m_offset = readU16(input);
input->seek(28, librevenge::RVNG_SEEK_CUR);
+ // osnola: todo
}
diff --git a/src/lib/FHParser.h b/src/lib/FHParser.h
index 6d59d9b..a79ddfd 100644
--- a/src/lib/FHParser.h
+++ b/src/lib/FHParser.h
@@ -116,6 +116,7 @@ private:
void readPantoneColor(librevenge::RVNGInputStream *input, FHCollector *collector);
void readParagraph(librevenge::RVNGInputStream *input, FHCollector *collector);
void readPath(librevenge::RVNGInputStream *input, FHCollector *collector);
+ void readPathText(librevenge::RVNGInputStream *input, FHCollector *collector);
void readPathTextLineInfo(librevenge::RVNGInputStream *input, FHCollector *collector);
void readPatternFill(librevenge::RVNGInputStream *input, FHCollector *collector);
void readPatternLine(librevenge::RVNGInputStream *input, FHCollector *collector);
@@ -125,6 +126,7 @@ private:
void readProcedure(librevenge::RVNGInputStream *input, FHCollector *collector);
void readProcessColor(librevenge::RVNGInputStream *input, FHCollector *collector);
void readPropLst(librevenge::RVNGInputStream *input, FHCollector *collector);
+ void readPSFill(librevenge::RVNGInputStream *input, FHCollector *collector);
void readPSLine(librevenge::RVNGInputStream *input, FHCollector *collector);
void readRadialFill(librevenge::RVNGInputStream *input, FHCollector *collector);
void readRadialFillX(librevenge::RVNGInputStream *input, FHCollector *collector);
diff --git a/src/lib/FHPath.cpp b/src/lib/FHPath.cpp
index 8b52145..ee12860 100644
--- a/src/lib/FHPath.cpp
+++ b/src/lib/FHPath.cpp
@@ -9,6 +9,8 @@
#include <math.h>
#include <map>
+#include <sstream>
+
#include "FHPath.h"
#include "FHTypes.h"
#include "FHTransform.h"
@@ -231,6 +233,7 @@ public:
m_y(y) {}
~FHMoveToElement() {}
void writeOut(librevenge::RVNGPropertyListVector &vec) const;
+ void writeOut(std::ostream &o) const;
void transform(const FHTransform &trafo);
FHPathElement *clone();
void getBoundingBox(double x0, double y0, double &xmin, double &ymin, double &xmax, double &ymax) const;
@@ -255,6 +258,7 @@ public:
m_y(y) {}
~FHLineToElement() {}
void writeOut(librevenge::RVNGPropertyListVector &vec) const;
+ void writeOut(std::ostream &o) const;
void transform(const FHTransform &trafo);
FHPathElement *clone();
void getBoundingBox(double x0, double y0, double &xmin, double &ymin, double &xmax, double &ymax) const;
@@ -283,6 +287,7 @@ public:
m_y(y) {}
~FHCubicBezierToElement() {}
void writeOut(librevenge::RVNGPropertyListVector &vec) const;
+ void writeOut(std::ostream &o) const;
void transform(const FHTransform &trafo);
FHPathElement *clone();
void getBoundingBox(double x0, double y0, double &xmin, double &ymin, double &xmax, double &ymax) const;
@@ -313,6 +318,7 @@ public:
m_y(y) {}
~FHQuadraticBezierToElement() {}
void writeOut(librevenge::RVNGPropertyListVector &vec) const;
+ void writeOut(std::ostream &o) const;
void transform(const FHTransform &trafo);
FHPathElement *clone();
void getBoundingBox(double x0, double y0, double &xmin, double &ymin, double &xmax, double &ymax) const;
@@ -344,6 +350,7 @@ public:
m_y(y) {}
~FHArcToElement() {}
void writeOut(librevenge::RVNGPropertyListVector &vec) const;
+ void writeOut(std::ostream &o) const;
void transform(const FHTransform &trafo);
FHPathElement *clone();
void getBoundingBox(double x0, double y0, double &xmin, double &ymin, double &xmax, double &ymax) const;
@@ -377,6 +384,11 @@ void libfreehand::FHMoveToElement::writeOut(librevenge::RVNGPropertyListVector &
vec.append(node);
}
+void libfreehand::FHMoveToElement::writeOut(std::ostream &o) const
+{
+ o << "M " << int(35*m_x) << " " << int(35*m_y);
+}
+
void libfreehand::FHMoveToElement::transform(const FHTransform &trafo)
{
trafo.applyToPoint(m_x,m_y);
@@ -411,6 +423,11 @@ void libfreehand::FHLineToElement::writeOut(librevenge::RVNGPropertyListVector &
vec.append(node);
}
+void libfreehand::FHLineToElement::writeOut(std::ostream &o) const
+{
+ o << "L " << int(35*m_x) << " " << int(35*m_y);
+}
+
void libfreehand::FHLineToElement::transform(const FHTransform &trafo)
{
trafo.applyToPoint(m_x,m_y);
@@ -449,6 +466,12 @@ void libfreehand::FHCubicBezierToElement::writeOut(librevenge::RVNGPropertyListV
vec.append(node);
}
+void libfreehand::FHCubicBezierToElement::writeOut(std::ostream &o) const
+{
+ o << "C " << int(35*m_x1) << " " << int(35*m_y1) << " "
+ << int(35*m_x2) << " " << int(35*m_y2) << " " << int(35*m_x) << " " << int(35*m_y);
+}
+
void libfreehand::FHCubicBezierToElement::transform(const FHTransform &trafo)
{
trafo.applyToPoint(m_x1,m_y1);
@@ -498,6 +521,11 @@ void libfreehand::FHQuadraticBezierToElement::writeOut(librevenge::RVNGPropertyL
vec.append(node);
}
+void libfreehand::FHQuadraticBezierToElement::writeOut(std::ostream &o) const
+{
+ o << "Q " << int(35*m_x1) << " " << int(35*m_y1) << " " << int(35*m_x) << " " << int(35*m_y);
+}
+
void libfreehand::FHQuadraticBezierToElement::transform(const FHTransform &trafo)
{
trafo.applyToPoint(m_x1,m_y1);
@@ -554,6 +582,13 @@ void libfreehand::FHArcToElement::writeOut(librevenge::RVNGPropertyListVector &v
vec.append(node);
}
+void libfreehand::FHArcToElement::writeOut(std::ostream &o) const
+{
+ o << "A " << int(35*m_rx) << " " << int(35*m_ry) << " "
+ << int(m_rotation * 180 / M_PI) << " " << m_largeArc << " " << m_sweep << " "
+ << int(35*m_x) << " " << int(35*m_y);
+}
+
void libfreehand::FHArcToElement::transform(const FHTransform &trafo)
{
trafo.applyToArc(m_rx, m_ry, m_rotation, m_sweep, m_x, m_y);
@@ -662,15 +697,18 @@ void libfreehand::FHPath::writeOut(librevenge::RVNGPropertyListVector &vec) cons
element->writeOut(vec);
}
-void libfreehand::FHPath::transform(const FHTransform &trafo)
+std::string libfreehand::FHPath::getPathString() const
{
+ std::stringstream s;
for (const auto &element : m_elements)
- element->transform(trafo);
+ element->writeOut(s);
+ return s.str();
}
-libfreehand::FHPathElement *libfreehand::FHPath::clone()
+void libfreehand::FHPath::transform(const FHTransform &trafo)
{
- return new FHPath(*this);
+ for (const auto &element : m_elements)
+ element->transform(trafo);
}
void libfreehand::FHPath::clear()
diff --git a/src/lib/FHPath.h b/src/lib/FHPath.h
index 8493be5..16b6b92 100644
--- a/src/lib/FHPath.h
+++ b/src/lib/FHPath.h
@@ -12,6 +12,7 @@
#include <memory>
#include <vector>
+#include <ostream>
#include <librevenge/librevenge.h>
@@ -26,6 +27,7 @@ public:
FHPathElement() {}
virtual ~FHPathElement() {}
virtual void writeOut(librevenge::RVNGPropertyListVector &vec) const = 0;
+ virtual void writeOut(std::ostream &s) const = 0;
virtual void transform(const FHTransform &trafo) = 0;
virtual FHPathElement *clone() = 0;
virtual void getBoundingBox(double x0, double y0, double &px, double &py, double &qx, double &qy) const = 0;
@@ -34,7 +36,7 @@ public:
};
-class FHPath : public FHPathElement
+class FHPath
{
public:
FHPath() : m_elements(), m_isClosed(false), m_xFormId(0), m_graphicStyleId(0), m_evenOdd(false) {}
@@ -55,8 +57,8 @@ public:
void setEvenOdd(bool evenOdd);
void writeOut(librevenge::RVNGPropertyListVector &vec) const;
+ std::string getPathString() const;
void transform(const FHTransform &trafo);
- FHPathElement *clone();
void getBoundingBox(double x0, double y0, double &xmin, double &ymin, double &xmax, double &ymax) const;
double getX() const;
double getY() const;
diff --git a/src/lib/FHTypes.h b/src/lib/FHTypes.h
index 8ec4863..7b3db81 100644
--- a/src/lib/FHTypes.h
+++ b/src/lib/FHTypes.h
@@ -67,6 +67,16 @@ struct FHGroup
FHGroup() : m_graphicStyleId(0), m_elementsId(0), m_xFormId(0) {}
};
+struct FHPathText
+{
+ unsigned m_elementsId;
+ unsigned m_layerId;
+ unsigned m_displayTextId;
+ unsigned m_shapeId;
+ unsigned m_textSize;
+ FHPathText() : m_elementsId(0), m_layerId(0), m_displayTextId(0), m_shapeId(0), m_textSize(0) {}
+};
+
struct FHCompositePath
{
unsigned m_graphicStyleId;
@@ -213,10 +223,14 @@ struct FH3CharProperties
unsigned m_fontStyle;
unsigned m_fontColorId;
unsigned m_textEffsId;
+ double m_leading; // -1 solid, -2 auto, >0 interline in point
+ double m_letterSpacing;
+ double m_wordSpacing;
+ double m_horizontalScale;
double m_baselineShift;
FH3CharProperties()
: m_offset(0), m_fontNameId(0), m_fontSize(12.0), m_fontStyle(0),
- m_fontColorId(0), m_textEffsId(0), m_baselineShift(0.0) {}
+ m_fontColorId(0), m_textEffsId(0), m_leading(-1), m_letterSpacing(0), m_wordSpacing(0), m_horizontalScale(1), m_baselineShift(0.0) {}
};
struct FH3ParaProperties
@@ -234,12 +248,13 @@ struct FHDisplayText
double m_width;
double m_height;
std::vector<FH3CharProperties> m_charProps;
+ int m_justify;
std::vector<FH3ParaProperties> m_paraProps;
std::vector<unsigned char> m_characters;
FHDisplayText()
: m_graphicStyleId(0), m_xFormId(0),
m_startX(0.0), m_startY(0.0), m_width(0.0), m_height(0.0),
- m_charProps(), m_paraProps(), m_characters() {}
+ m_charProps(), m_justify(0), m_paraProps(), m_characters() {}
};
struct FHGraphicStyle
@@ -354,6 +369,13 @@ struct FHTileFill
m_offsetX(0.0), m_offsetY(0.0), m_angle(0.0) {}
};
+struct FHLinePattern
+{
+ std::vector<double> m_dashes;
+ FHLinePattern()
+ : m_dashes() {}
+};
+
struct FHSymbolClass
{
unsigned m_nameId;
diff --git a/src/lib/tokens.txt b/src/lib/tokens.txt
index a4764a1..97d1cb3 100644
--- a/src/lib/tokens.txt
+++ b/src/lib/tokens.txt
@@ -78,6 +78,7 @@ Oval
PantoneColor
Paragraph
Path
+PathText
PathTextLineInfo
PatternFill
PatternLine
@@ -87,6 +88,7 @@ PolygonFigure
Procedure
ProcessColor
PropLst
+PSFill
PSLine
RadialFill
RadialFillX