diff options
author | osnola <alonso@loria.fr> | 2017-07-13 16:29:57 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2017-07-13 16:29:57 +0200 |
commit | fd69377a60eba6865e751ffbfaddc0666a1cb602 (patch) | |
tree | b5e6c26df30b6e36d4a3116ca661a2202408b849 | |
parent | 1e1bbbae0a929b0b421ce1f7793faf31d4f5eca8 (diff) |
try to improve the parsing of v3 files
Change-Id: I59011935ce87d14309ff0265218b3f383f857ebd
-rw-r--r-- | src/lib/FHCollector.cpp | 183 | ||||
-rw-r--r-- | src/lib/FHCollector.h | 13 | ||||
-rw-r--r-- | src/lib/FHParser.cpp | 159 | ||||
-rw-r--r-- | src/lib/FHParser.h | 2 | ||||
-rw-r--r-- | src/lib/FHPath.cpp | 46 | ||||
-rw-r--r-- | src/lib/FHPath.h | 6 | ||||
-rw-r--r-- | src/lib/FHTypes.h | 26 | ||||
-rw-r--r-- | src/lib/tokens.txt | 2 |
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 |