Warning, file /office/calligra/filters/karbon/xfig/XFigParser.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the Calligra project, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2012 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "XFigParser.h" 0010 0011 // filter 0012 #include "XFigDocument.h" 0013 // Qt 0014 #include <QTextStream> 0015 #include <QTextCodec> 0016 #include <QIODevice> 0017 #include <QFont> 0018 #include <QScopedPointer> 0019 0020 #include <QDebug> 0021 0022 0023 enum XFig3_2TextFlag { 0024 XFig3_2TextNotScaled = 1 << 0, 0025 XFig3_2TextForLaTeX = 1 << 1, 0026 XFig3_2TextPostScriptFont = 1 << 2, 0027 XFig3_2TextHidden = 1 << 3 0028 }; 0029 0030 enum XFig3_2ObjectCode 0031 { 0032 XFig3_2CompoundObjectEndId = -6, 0033 XFig3_2ColorObjectId = 0, 0034 XFig3_2EllipseObjectId = 1, 0035 XFig3_2PolylineObjectId = 2, 0036 XFig3_2SplineObjectId = 3, 0037 XFig3_2TextObjectId = 4, 0038 XFig3_2ArcObjectId = 5, 0039 XFig3_2CompoundObjectId = 6 0040 }; 0041 0042 enum XFig3_2ArcSubTypeCode 0043 { 0044 XFig3_2ArcOpenEndedId = 1, 0045 XFig3_2ArcPieWedgeId= 2 0046 }; 0047 0048 enum XFig3_2PolylineSubTypeCode 0049 { 0050 XFig3_2PolylinePolylineId = 1, 0051 XFig3_2PolylineBoxId = 2, 0052 XFig3_2PolylinePolygonId = 3, 0053 XFig3_2PolylineArcBoxId = 4, 0054 XFig3_2PolylinePictureBoundingBoxId = 5 0055 }; 0056 0057 enum XFig3_2SplineSubtypeCode 0058 { 0059 XFig3_2SplineOpenApproximatedId = 0, 0060 XFig3_2SplineClosedApproximatedId = 1, 0061 XFig3_2SplineOpenInterpolatedId = 2, 0062 XFig3_2SplineClosedInterpolatedId = 3, 0063 XFig3_2SplineOpenXId = 4, 0064 XFig3_2SplineClosedXId = 5 0065 }; 0066 0067 enum XFig3_2TextAlignment { 0068 XFig3_2TextLeftAligned = 0, 0069 XFig3_2TextCenterAligned = 1, 0070 XFig3_2TextRightAligned = 2 0071 }; 0072 0073 static const int arrowHeadTypeMapSize = 15; 0074 static const 0075 struct { XFigArrowHeadType style[2]; } 0076 arrowHeadTypeMap[arrowHeadTypeMapSize] = 0077 { 0078 { {XFigArrowHeadStick, XFigArrowHeadStick} }, 0079 { {XFigArrowHeadHollowTriangle, XFigArrowHeadFilledTriangle} }, 0080 { {XFigArrowHeadHollowConcaveSpear, XFigArrowHeadFilledConcaveSpear} }, 0081 { {XFigArrowHeadHollowConvexSpear, XFigArrowHeadFilledConvexSpear} }, 0082 { {XFigArrowHeadHollowDiamond, XFigArrowHeadFilledDiamond} }, 0083 { {XFigArrowHeadHollowCircle, XFigArrowHeadFilledCircle} }, 0084 { {XFigArrowHeadHollowHalfCircle, XFigArrowHeadFilledHalfCircle} }, 0085 { {XFigArrowHeadHollowSquare, XFigArrowHeadFilledSquare} }, 0086 { {XFigArrowHeadHollowReverseTriangle, XFigArrowHeadFilledReverseTriangle} }, 0087 { {XFigArrowHeadTopHalfFilledConcaveSpear, XFigArrowHeadBottomHalfFilledConcaveSpear} }, 0088 { {XFigArrowHeadHollowTopHalfTriangle, XFigArrowHeadFilledTopHalfTriangle} }, 0089 { {XFigArrowHeadHollowTopHalfConcaveSpear, XFigArrowHeadFilledTopHalfConcaveSpear} }, 0090 { {XFigArrowHeadHollowTopHalfConvexSpear, XFigArrowHeadFilledTopHalfConvexSpear} }, 0091 { {XFigArrowHeadWye, XFigArrowHeadBar} }, 0092 { {XFigArrowHeadTwoProngFork, XFigArrowHeadReverseTwoProngFork} } 0093 }; 0094 0095 static inline 0096 XFigArrowHeadType 0097 arrowHeadType( int type3_2, int style3_2 ) 0098 { 0099 XFigArrowHeadType result = XFigArrowHeadStick; 0100 if ((0<=type3_2) && (type3_2<arrowHeadTypeMapSize) && 0101 ((style3_2 == 0) || (style3_2 == 1))) { 0102 result = arrowHeadTypeMap[type3_2].style[style3_2]; 0103 } 0104 return result; 0105 } 0106 0107 enum XFig3_2LineType 0108 { 0109 XFig3_2LineDefault = -1, 0110 XFig3_2LineSolid = 0, 0111 XFig3_2LineDashed = 1, 0112 XFig3_2LineDotted = 2, 0113 XFig3_2LineDashDotted = 3, 0114 XFig3_2LineDashDoubleDotted = 4, 0115 XFig3_2LineDashTrippleDotted = 5 0116 }; 0117 0118 static const 0119 struct { int type3_2; XFigLineType type; } 0120 lineTypeMap[] = 0121 { 0122 { XFig3_2LineDefault, XFigLineDefault }, 0123 { XFig3_2LineSolid, XFigLineSolid }, 0124 { XFig3_2LineDashed,XFigLineDashed }, 0125 { XFig3_2LineDotted, XFigLineDotted }, 0126 { XFig3_2LineDashDotted, XFigLineDashDotted }, 0127 { XFig3_2LineDashDoubleDotted,XFigLineDashDoubleDotted }, 0128 { XFig3_2LineDashTrippleDotted, XFigLineDashTrippleDotted } 0129 }; 0130 static const int lineTypeMapSize = sizeof(lineTypeMap)/sizeof(lineTypeMap[0]); 0131 0132 static inline 0133 XFigLineType 0134 lineType( int type3_2 ) 0135 { 0136 XFigLineType result = XFigLineDefault; 0137 for (int i = 0; i<lineTypeMapSize; ++i) { 0138 if (lineTypeMap[i].type3_2 == type3_2) { 0139 result = lineTypeMap[i].type; 0140 break; 0141 } 0142 } 0143 return result; 0144 } 0145 0146 enum XFig3_2CapType 0147 { 0148 XFig3_2CapButt = 0, 0149 XFig3_2CapRound = 1, 0150 XFig3_2CapProjecting = 2, 0151 }; 0152 0153 static const 0154 struct { int type3_2; XFigCapType type; } 0155 capTypeMap[] = 0156 { 0157 {XFig3_2CapButt, XFigCapButt }, 0158 {XFig3_2CapRound, XFigCapRound}, 0159 {XFig3_2CapProjecting,XFigCapProjecting} 0160 }; 0161 static const int capTypeMapSize = sizeof(capTypeMap)/sizeof(capTypeMap[0]); 0162 0163 static inline 0164 XFigCapType 0165 capType( int type3_2 ) 0166 { 0167 XFigCapType result = XFigCapButt; 0168 for (int i = 0; i<capTypeMapSize; ++i) { 0169 if (capTypeMap[i].type3_2 == type3_2) { 0170 result = capTypeMap[i].type; 0171 break; 0172 } 0173 } 0174 return result; 0175 } 0176 0177 enum XFig3_2JoinType 0178 { 0179 XFig3_2JoinMiter = 0, 0180 XFig3_2JoinRound = 1, 0181 XFig3_2JoinBevel = 2, 0182 }; 0183 0184 static const 0185 struct { int type3_2; XFigJoinType type; } 0186 joinTypeMap[] = 0187 { 0188 {XFig3_2JoinMiter, XFigJoinMiter}, 0189 {XFig3_2JoinRound, XFigJoinRound}, 0190 {XFig3_2JoinBevel, XFigJoinBevel} 0191 }; 0192 static const int joinTypeMapSize = sizeof(joinTypeMap)/sizeof(joinTypeMap[0]); 0193 0194 static inline 0195 XFigJoinType 0196 joinType( int type3_2 ) 0197 { 0198 XFigJoinType result = XFigJoinMiter; 0199 for (int i = 0; i<joinTypeMapSize; ++i) { 0200 if (joinTypeMap[i].type3_2 == type3_2) { 0201 result = joinTypeMap[i].type; 0202 break; 0203 } 0204 } 0205 return result; 0206 } 0207 0208 static inline 0209 XFigFillType fillType(int type3_2) 0210 { 0211 return 0212 ((0 <= type3_2) && (type3_2 <= 40)) ? XFigFillSolid : 0213 ((41 <= type3_2) && (type3_2 <= 62)) ? XFigFillPattern : 0214 /*(type3_2 == -1) ?*/ XFigFillNone; 0215 } 0216 0217 enum XFig3_2FillPatternType 0218 { 0219 XFig3_2FillLeftDiagonal30Degree = 41, 0220 XFig3_2FillRightDiagonal30Degree = 42, 0221 XFig3_2FillCrossHatch30Degree = 43, 0222 XFig3_2FillLeftDiagonal45Degree = 44, 0223 XFig3_2FillRightDiagonal45Degree = 45, 0224 XFig3_2FillCrossHatch45Degree = 46, 0225 XFig3_2FillHorizontalBricks = 47, 0226 XFig3_2FillVerticalBricks = 48, 0227 XFig3_2FillHorizontalLines = 49, 0228 XFig3_2FillVerticalLines = 50, 0229 XFig3_2FillCrossHatch = 51, 0230 XFig3_2FillHorizontalShinglesSkewedRight = 52, 0231 XFig3_2FillHorizontalShinglesSkewedLeft = 53, 0232 XFig3_2FillVerticalShinglesSkewedDown = 54, 0233 XFig3_2FillVerticalShinglesSkewedUp = 55, 0234 XFig3_2FillFishScales = 56, 0235 XFig3_2FillSmallFishScales = 57, 0236 XFig3_2FillCircles = 58, 0237 XFig3_2FillHexagons = 59, 0238 XFig3_2FillOctagons = 60, 0239 XFig3_2FillHorizontalTireTreads = 61, 0240 XFig3_2FillVerticalTireTreads = 62 0241 }; 0242 static const 0243 struct { XFig3_2FillPatternType type3_2; XFigFillPatternType type; } 0244 fillPatternTypeMap[] = 0245 { 0246 {XFig3_2FillLeftDiagonal30Degree, XFigFillLeftDiagonal30Degree}, 0247 {XFig3_2FillRightDiagonal30Degree, XFigFillRightDiagonal30Degree}, 0248 {XFig3_2FillCrossHatch30Degree, XFigFillCrossHatch30Degree}, 0249 {XFig3_2FillLeftDiagonal45Degree, XFigFillLeftDiagonal45Degree}, 0250 {XFig3_2FillRightDiagonal45Degree, XFigFillRightDiagonal45Degree}, 0251 {XFig3_2FillCrossHatch45Degree, XFigFillCrossHatch45Degree}, 0252 {XFig3_2FillHorizontalBricks, XFigFillHorizontalBricks}, 0253 {XFig3_2FillVerticalBricks, XFigFillVerticalBricks}, 0254 {XFig3_2FillHorizontalLines, XFigFillHorizontalLines}, 0255 {XFig3_2FillVerticalLines, XFigFillVerticalLines}, 0256 {XFig3_2FillCrossHatch, XFigFillCrossHatch}, 0257 {XFig3_2FillHorizontalShinglesSkewedRight, XFigFillHorizontalShinglesSkewedRight}, 0258 {XFig3_2FillHorizontalShinglesSkewedLeft, XFigFillHorizontalShinglesSkewedLeft}, 0259 {XFig3_2FillVerticalShinglesSkewedDown, XFigFillVerticalShinglesSkewedDown}, 0260 {XFig3_2FillVerticalShinglesSkewedUp, XFigFillVerticalShinglesSkewedUp}, 0261 {XFig3_2FillFishScales, XFigFillFishScales}, 0262 {XFig3_2FillSmallFishScales, XFigFillSmallFishScales}, 0263 {XFig3_2FillCircles, XFigFillCircles}, 0264 {XFig3_2FillHexagons, XFigFillHexagons}, 0265 {XFig3_2FillOctagons, XFigFillOctagons}, 0266 {XFig3_2FillHorizontalTireTreads, XFigFillHorizontalTireTreads}, 0267 {XFig3_2FillVerticalTireTreads, XFigFillVerticalTireTreads} 0268 }; 0269 static const int fillPatternTypeMapSize = sizeof(fillPatternTypeMap)/sizeof(fillPatternTypeMap[0]); 0270 0271 static inline 0272 XFigFillPatternType fillPatternType(int type3_2) 0273 { 0274 XFigFillPatternType result = XFigFillLeftDiagonal30Degree; 0275 for (int i = 0; i<fillPatternTypeMapSize; ++i) { 0276 if (fillPatternTypeMap[i].type3_2 == type3_2) { 0277 result = fillPatternTypeMap[i].type; 0278 break; 0279 } 0280 } 0281 return result; 0282 } 0283 0284 static const 0285 struct XFig3_2PostScriptFontData { 0286 const char* family; 0287 QFont::Weight weight; 0288 QFont::Style style; 0289 } postScriptFontDataTable[35] = { 0290 { "times", QFont::Normal, QFont::StyleNormal }, // Times Roman 0291 { "times", QFont::Normal, QFont::StyleItalic }, // Times Italic 0292 { "times", QFont::Bold, QFont::StyleNormal }, // Times Bold 0293 { "times", QFont::Bold, QFont::StyleItalic }, // Times Bold Italic 0294 { "avantgarde", QFont::Normal, QFont::StyleNormal }, // AvantGarde Book 0295 { "avantgarde", QFont::Normal, QFont::StyleOblique }, // AvantGarde Book Oblique 0296 { "avantgarde", QFont::DemiBold, QFont::StyleNormal }, // AvantGarde Demi 0297 { "avantgarde", QFont::DemiBold, QFont::StyleOblique }, // AvantGarde Demi Oblique 0298 { "bookman", QFont::Light, QFont::StyleNormal }, // Bookman Light 0299 { "bookman", QFont::Light, QFont::StyleItalic }, // Bookman Light Italic 0300 { "bookman", QFont::DemiBold, QFont::StyleNormal }, // Bookman Demi 0301 { "bookman", QFont::DemiBold, QFont::StyleItalic }, // Bookman Demi Italic 0302 { "courier", QFont::Normal, QFont::StyleNormal }, // Courier 0303 { "courier", QFont::Normal, QFont::StyleOblique }, // Courier Oblique 0304 { "courier", QFont::Bold, QFont::StyleNormal }, // Courier Bold 0305 { "courier", QFont::Bold, QFont::StyleOblique }, // Courier Bold Oblique 0306 { "helvetica", QFont::Normal, QFont::StyleNormal }, // Helvetica 0307 { "helvetica", QFont::Normal, QFont::StyleOblique }, // Helvetica Oblique 0308 { "helvetica", QFont::Bold, QFont::StyleNormal }, // Helvetica Bold 0309 { "helvetica", QFont::Bold, QFont::StyleOblique }, // Helvetica Bold Oblique 0310 { "helvetica", QFont::Normal, QFont::StyleNormal }, // Helvetica Narrow 0311 { "helvetica", QFont::Normal, QFont::StyleOblique }, // Helvetica Narrow Oblique 0312 { "helvetica", QFont::Bold, QFont::StyleNormal }, // Helvetica Narrow Bold 0313 { "helvetica", QFont::Bold, QFont::StyleOblique }, // Helvetica Narrow Bold Oblique 0314 { "newcenturyschoolbook", QFont::Normal, QFont::StyleNormal }, // New Century Schoolbook 0315 { "newcenturyschoolbook", QFont::Normal, QFont::StyleItalic }, // New Century Italic 0316 { "newcenturyschoolbook", QFont::Bold, QFont::StyleNormal }, // New Century Bold 0317 { "newcenturyschoolbook", QFont::Bold, QFont::StyleItalic }, // New Century Bold Italic 0318 { "palatino", QFont::Normal, QFont::StyleNormal }, // Palatino Roman 0319 { "palatino", QFont::Normal, QFont::StyleItalic }, // Palatino Italic 0320 { "palatino", QFont::Bold, QFont::StyleNormal }, // Palatino Bold 0321 { "palatino", QFont::Bold, QFont::StyleItalic }, // Palatino Bold Italic 0322 { "symbol", QFont::Normal, QFont::StyleNormal }, // Symbol 0323 { "zapfchancery", QFont::Normal, QFont::StyleNormal }, // Zapf Chancery Medium Italic 0324 { "zapfdingbats", QFont::Normal, QFont::StyleNormal }, // Zapf Dingbats 0325 }; 0326 0327 enum XFig3_2LatexFontType{ 0328 XFig3_2LatexFontDefault = 0, 0329 XFig3_2LatexFontRoman = 1, 0330 XFig3_2LatexFontBold = 2, 0331 XFig3_2LatexFontItalic = 3, 0332 XFig3_2LatexFontSansSerif = 4, 0333 XFig3_2LatexFontTypewriter = 5 0334 }; 0335 0336 static const 0337 struct PaperSizeIdMap { 0338 const char* stringId; 0339 XFigPageSizeType type; 0340 } paperSizeTable[] = { 0341 { "Letter", XFigPageSizeLetter }, 0342 { "Legal", XFigPageSizeLegal }, 0343 { "Ledger", XFigPageSizeTabloid }, 0344 { "Tabloid", XFigPageSizeTabloid }, 0345 0346 { "A", XFigPageSizeA }, 0347 { "B", XFigPageSizeB }, 0348 { "C", XFigPageSizeC }, 0349 { "D", XFigPageSizeD }, 0350 { "E", XFigPageSizeE }, 0351 0352 { "A9", XFigPageSizeA9 }, 0353 { "A8", XFigPageSizeA8 }, 0354 { "A7", XFigPageSizeA7 }, 0355 { "A6", XFigPageSizeA6 }, 0356 { "A5", XFigPageSizeA5 }, 0357 { "A4", XFigPageSizeA4 }, 0358 { "A3", XFigPageSizeA3 }, 0359 { "A2", XFigPageSizeA2 }, 0360 { "A1", XFigPageSizeA1 }, 0361 { "A0", XFigPageSizeA0 }, 0362 0363 { "B10", XFigPageSizeB10 }, 0364 { "B9", XFigPageSizeB9 }, 0365 { "B8", XFigPageSizeB8 }, 0366 { "B7", XFigPageSizeB7 }, 0367 { "B6", XFigPageSizeB6 }, 0368 { "B5", XFigPageSizeB5 }, 0369 { "B4", XFigPageSizeB4 }, 0370 { "B3", XFigPageSizeB3 }, 0371 { "B2", XFigPageSizeB2 }, 0372 { "B1", XFigPageSizeB1 }, 0373 { "B0", XFigPageSizeB0 } 0374 }; 0375 static const int paperSizeCount = sizeof(paperSizeTable)/sizeof(paperSizeTable[0]); 0376 0377 static inline 0378 XFigPageSizeType 0379 pageSizeType( const QString& stringId ) 0380 { 0381 XFigPageSizeType result = XFigPageSizeUnknown; 0382 for( int i = 0; i<paperSizeCount; ++i) { 0383 const PaperSizeIdMap& idMap = paperSizeTable[i]; 0384 if (stringId == QLatin1String(idMap.stringId)) { 0385 result = idMap.type; 0386 break; 0387 } 0388 } 0389 return result; 0390 } 0391 0392 XFigDocument* 0393 XFigParser::parse( QIODevice* device ) 0394 { 0395 XFigParser parser(device); 0396 XFigDocument* document = parser.takeDocument(); 0397 return document; 0398 } 0399 0400 0401 XFigParser::XFigParser( QIODevice* device ) 0402 : m_Document(0) 0403 , m_XFigStreamLineReader( device ) 0404 { 0405 if( (device == 0) || (m_XFigStreamLineReader.hasError()) ) 0406 return; 0407 0408 const QTextCodec* codec = QTextCodec::codecForName("ISO 8859-1"); 0409 m_TextDecoder = codec->makeDecoder(); 0410 0411 // setup 0412 if (! parseHeader()) 0413 return; 0414 0415 XFigPage* page = new XFigPage; 0416 0417 while (! m_XFigStreamLineReader.readNextObjectLine()) { 0418 const int objectCode = m_XFigStreamLineReader.objectCode(); 0419 const QString objectComment = m_XFigStreamLineReader.comment(); 0420 0421 if (objectCode == XFig3_2ColorObjectId) { 0422 parseColorObject(); 0423 } else if ((XFig3_2EllipseObjectId<=objectCode) && (objectCode<=XFig3_2CompoundObjectId)) { 0424 XFigAbstractObject* object = 0425 (objectCode == XFig3_2EllipseObjectId) ? parseEllipse() : 0426 (objectCode == XFig3_2PolylineObjectId) ? parsePolyline() : 0427 (objectCode == XFig3_2SplineObjectId) ? parseSpline() : 0428 (objectCode == XFig3_2TextObjectId) ? parseText() : 0429 (objectCode == XFig3_2ArcObjectId) ? parseArc() : 0430 /*else XFig3_2CompoundObjectId)*/ parseCompoundObject(); 0431 if (object != 0) { 0432 object->setComment(objectComment); 0433 page->addObject(object); 0434 } 0435 } else { 0436 // should not occur 0437 qWarning() << "unknown object type:" << objectCode; 0438 } 0439 } 0440 0441 m_Document->addPage( page ); 0442 } 0443 0444 XFigParser::~XFigParser() 0445 { 0446 delete m_TextDecoder; 0447 delete m_Document; 0448 } 0449 0450 bool 0451 XFigParser::parseHeader() 0452 { 0453 // start to parse 0454 m_XFigStreamLineReader.readNextLine(XFigStreamLineReader::TakeComment); 0455 const QString versionString = m_XFigStreamLineReader.line(); 0456 if (! versionString.startsWith(QLatin1String("#FIG 3.")) || 0457 (versionString.length() < 8)) { 0458 qWarning() << "ERROR: no xfig file or wrong header"; 0459 return false; 0460 } 0461 0462 const QChar minorVersion = versionString.at(7); 0463 if (minorVersion == QLatin1Char('2')) { 0464 m_XFigVersion = 320; 0465 } else if (minorVersion == QLatin1Char('1')) { 0466 m_XFigVersion = 310; 0467 } else { 0468 qWarning() << "ERROR: unsupported xfig version"; 0469 return false; 0470 } 0471 0472 m_Document = new XFigDocument; 0473 0474 // assume header is broken by default 0475 bool isHeaderCorrect = false; 0476 do { 0477 // orientation 0478 if (m_XFigStreamLineReader.readNextLine()) { 0479 const QString orientationString = m_XFigStreamLineReader.line().trimmed(); 0480 const XFigPageOrientation pageOrientation = 0481 (orientationString == QLatin1String("Landscape")) ? XFigPageLandscape : 0482 (orientationString == QLatin1String("Portrait")) ? XFigPagePortrait : 0483 XFigPageOrientationUnknown; 0484 // qDebug()<<"orientation:"<<orientationString<<pageOrientation; 0485 if (pageOrientation == XFigPageOrientationUnknown) 0486 qWarning() << "ERROR: invalid orientation"; 0487 0488 m_Document->setPageOrientation( pageOrientation ); 0489 } else { 0490 break; 0491 } 0492 0493 // justification, ("Center" or "Flush Left") 0494 if (! m_XFigStreamLineReader.readNextLine()) { 0495 break; 0496 } 0497 0498 // units 0499 if (m_XFigStreamLineReader.readNextLine()) { 0500 const QString unitTypeString = m_XFigStreamLineReader.line().trimmed(); 0501 const XFigUnitType unitType = 0502 (unitTypeString == QLatin1String("Metric")) ? XFigUnitMetric : 0503 (unitTypeString == QLatin1String("Inches")) ? XFigUnitInches : 0504 XFigUnitTypeUnknown; 0505 // qDebug() << "unittype:"<<unitTypeString<<unitType; 0506 if (unitType == XFigUnitTypeUnknown) 0507 qWarning() << "ERROR: invalid units"; 0508 0509 m_Document->setUnitType( unitType ); 0510 } else { 0511 break; 0512 } 0513 0514 if (m_XFigVersion == 320) { 0515 if (m_XFigStreamLineReader.readNextLine()) { 0516 const QString pageSizeString = m_XFigStreamLineReader.line().trimmed(); 0517 const XFigPageSizeType pageSizeType = ::pageSizeType(pageSizeString); 0518 // qDebug() << "pagesize:"<<pageSizeString<<pageSizeType; 0519 m_Document->setPageSizeType(pageSizeType); 0520 } else { 0521 break; 0522 } 0523 0524 // export and print magnification, % 0525 if (m_XFigStreamLineReader.readNextLine()) { 0526 const QString magnificationString = m_XFigStreamLineReader.line(); 0527 const float magnification = magnificationString.toFloat(); 0528 // TODO 0529 Q_UNUSED(magnification); 0530 // qDebug() << "magnification:"<<magnificationString<<magnification; 0531 } else { 0532 break; 0533 } 0534 0535 // singe or multiple page 0536 if (m_XFigStreamLineReader.readNextLine()) { 0537 const QString singleOrMultiplePagesString = m_XFigStreamLineReader.line().trimmed(); 0538 // multiple pages not yet supported 0539 if (singleOrMultiplePagesString != QLatin1String("Single")) { 0540 break; 0541 } 0542 } else { 0543 break; 0544 } 0545 0546 // transparent color for GIF export: -3=background, -2=None, -1=Default, 0-31 for standard colors, 32- for user colors 0547 if (m_XFigStreamLineReader.readNextLine()) { 0548 const QString transparentColorString = m_XFigStreamLineReader.line(); 0549 const int transparentColor = transparentColorString.toInt(); 0550 // TODO 0551 Q_UNUSED(transparentColor); 0552 // qDebug() << "transparentColor:"<<transparentColorString<<transparentColor; 0553 } else { 0554 break; 0555 } 0556 } 0557 0558 // resolution and coordinate system 0559 if (m_XFigStreamLineReader.readNextLine(XFigStreamLineReader::CollectComments)) { 0560 qint32 coordinateSystemType; 0561 qint32 resolution; 0562 QString line = m_XFigStreamLineReader.line(); 0563 QTextStream textStream(&line, QIODevice::ReadOnly); 0564 textStream >> resolution >> coordinateSystemType; 0565 0566 const XFigCoordSystemOriginType coordSystemOriginType = 0567 (coordinateSystemType == 1) ? XFigCoordSystemOriginLowerLeft : 0568 (coordinateSystemType == 2) ? XFigCoordSystemOriginUpperLeft : 0569 XFigCoordSystemOriginTypeUnknown; 0570 m_Document->setCoordSystemOriginType( coordSystemOriginType ); // said to be ignored and always upper-left 0571 m_Document->setResolution(resolution); 0572 m_Document->setComment(m_XFigStreamLineReader.comment()); 0573 0574 // qDebug() << "resolution+coordinateSystemType:"<<resolution<<coordinateSystemType; 0575 } else { 0576 break; 0577 } 0578 isHeaderCorrect = true; 0579 } while (false); 0580 0581 if (! isHeaderCorrect) { 0582 delete m_Document; 0583 m_Document = 0; 0584 } 0585 0586 return isHeaderCorrect; 0587 } 0588 0589 0590 static inline 0591 int 0592 parseTwoDigitHexValue(QTextStream& textStream) 0593 { 0594 int result = 0; 0595 0596 char digit[2]; 0597 textStream >> digit[1] >> digit[0]; 0598 0599 int faktor = 1; 0600 for (int i = 0; i < 2; i++) { 0601 const int value = 0602 ('0' <= digit[i] && digit[i] <= '9') ? digit[i] - '0' : 0603 ('A' <= digit[i] && digit[i] <= 'F') ? digit[i] - 'A' + 10 : 0604 ('a' <= digit[i] && digit[i] <= 'f') ? digit[i] - 'a' + 10 : 0605 /* bogus data */ 0; 0606 result += value * faktor; 0607 faktor = 16; 0608 } 0609 0610 return result; 0611 }; 0612 0613 void XFigParser::parseColorObject() 0614 { 0615 int colorNumber; 0616 0617 QString line = m_XFigStreamLineReader.line(); 0618 QTextStream textStream(&line, QIODevice::ReadOnly); 0619 textStream >> colorNumber; 0620 if ((colorNumber < 32) || (543 < colorNumber)) { 0621 qWarning() << "bad colorNumber:" << colorNumber; 0622 return; 0623 } 0624 0625 QChar hashChar; 0626 textStream >> ws >> hashChar; 0627 const int red = parseTwoDigitHexValue(textStream); 0628 const int green = parseTwoDigitHexValue(textStream); 0629 const int blue = parseTwoDigitHexValue(textStream); 0630 0631 m_Document->setUserColor(colorNumber, QColor(red, green, blue)); 0632 } 0633 0634 XFigAbstractObject* 0635 XFigParser::parseArc() 0636 { 0637 // qDebug()<<"arc"; 0638 0639 QScopedPointer<XFigArcObject> arcObject(new XFigArcObject); 0640 0641 int sub_type, line_style, thickness, pen_color, fill_color, 0642 depth, pen_style, area_fill, cap_style, direction, 0643 forwardArrow, backwardArrow, x1, y1, x2, y2, x3, y3; 0644 float center_x, center_y; 0645 float style_val; 0646 0647 // first line 0648 QString line = m_XFigStreamLineReader.line(); 0649 QTextStream textStream(&line, QIODevice::ReadOnly); 0650 textStream 0651 >> sub_type >> line_style >> thickness >> pen_color >> fill_color 0652 >> depth >> pen_style >> area_fill >> style_val >> cap_style 0653 >> direction >> forwardArrow >> backwardArrow 0654 >> center_x >> center_y >> x1 >> y1 >> x2 >> y2 >> x3 >> y3; 0655 0656 if (forwardArrow > 0) { 0657 QScopedPointer<XFigArrowHead> arrowHead(parseArrowHead()); 0658 if (arrowHead.isNull()) { 0659 return 0; 0660 } 0661 arcObject->setForwardArrow(arrowHead.take()); 0662 } 0663 0664 if (backwardArrow > 0) { 0665 QScopedPointer<XFigArrowHead> arrowHead(parseArrowHead()); 0666 if (arrowHead.isNull()) { 0667 return 0; 0668 } 0669 arcObject->setBackwardArrow(arrowHead.take()); 0670 } 0671 0672 const XFigArcObject::Subtype subtype = 0673 (sub_type==1) ? XFigArcObject::OpenEnded : 0674 /*(sub_type==2)*/ XFigArcObject::PieWedgeClosed; 0675 arcObject->setSubtype(subtype); 0676 const XFigArcObject::Direction arcDirection = 0677 (direction==1) ? XFigArcObject::CounterClockwise : 0678 /*(direction==0)*/ XFigArcObject::Clockwise; 0679 arcObject->setDirection(arcDirection); 0680 arcObject->setCenterPoint(XFigPoint(center_x, center_y)); 0681 arcObject->setPoints(XFigPoint(x1, y1), XFigPoint(x2, y2), XFigPoint(x3, y3)); 0682 arcObject->setCapType(capType(cap_style)); 0683 arcObject->setDepth( depth ); 0684 const XFigFillType fillType = ::fillType(area_fill); 0685 if (fillType == XFigFillSolid) { 0686 arcObject->setFillTinting(area_fill); 0687 } else if (fillType == XFigFillPattern) { 0688 arcObject->setFillPatternType(::fillPatternType(area_fill)); 0689 } else { 0690 arcObject->setFillNone(); 0691 } 0692 arcObject->setFillColorId(fill_color); 0693 arcObject->setLine( lineType(line_style), thickness, style_val, pen_color ); 0694 0695 return arcObject.take(); 0696 } 0697 0698 XFigAbstractObject* 0699 XFigParser::parseEllipse() 0700 { 0701 // qDebug()<<"ellipse"; 0702 0703 QScopedPointer<XFigEllipseObject> ellipseObject(new XFigEllipseObject); 0704 0705 qint32 sub_type, line_style, thickness, pen_color, fill_color, 0706 depth, pen_style/*not used*/, area_fill, direction/*always 1*/, 0707 center_x, center_y, radius_x, radius_y, start_x, start_y, end_x, end_y; 0708 float style_val, angle; 0709 0710 // ellipse data line 0711 QString line = m_XFigStreamLineReader.line(); 0712 QTextStream textStream(&line, QIODevice::ReadOnly); 0713 textStream 0714 >> sub_type >> line_style >> thickness >> pen_color >> fill_color 0715 >> depth >> pen_style >> area_fill >> style_val >> direction 0716 >> angle >> center_x >> center_y >> radius_x >> radius_y 0717 >> start_x >> start_y >> end_x >> end_y; 0718 0719 const XFigEllipseObject::Subtype subtype = 0720 (sub_type==1) ? XFigEllipseObject::EllipseByRadii : 0721 (sub_type==2) ? XFigEllipseObject::EllipseByDiameter : 0722 (sub_type==3) ? XFigEllipseObject::CircleByRadius : 0723 /*(sub_type==4)*/ XFigEllipseObject::CircleByDiameter; 0724 ellipseObject->setSubtype(subtype); 0725 ellipseObject->setCenterPoint(XFigPoint(center_x, center_y)); 0726 ellipseObject->setStartEnd(XFigPoint(start_x,start_y), XFigPoint(end_x,end_y)); 0727 ellipseObject->setRadii(radius_x, radius_y); 0728 ellipseObject->setXAxisAngle(angle); 0729 0730 ellipseObject->setDepth( depth ); 0731 const XFigFillType fillType = ::fillType(area_fill); 0732 if (fillType == XFigFillSolid) { 0733 ellipseObject->setFillTinting(area_fill); 0734 } else if (fillType == XFigFillPattern) { 0735 ellipseObject->setFillPatternType(::fillPatternType(area_fill)); 0736 } else { 0737 ellipseObject->setFillNone(); 0738 } 0739 ellipseObject->setFillColorId(fill_color); 0740 ellipseObject->setLine( lineType(line_style), thickness, style_val, pen_color ); 0741 0742 return ellipseObject.take(); 0743 } 0744 0745 XFigAbstractObject* 0746 XFigParser::parsePolyline() 0747 { 0748 // qDebug()<<"polyline"; 0749 0750 QScopedPointer<XFigAbstractPolylineObject> abstractPolylineObject(0); 0751 0752 qint32 sub_type, line_style, thickness, pen_color, fill_color, 0753 depth, pen_style, area_fill, join_style, cap_style, radius, 0754 forward_arrow, backward_arrow, npoints; 0755 float style_val; 0756 0757 // polyline data line 0758 QString line = m_XFigStreamLineReader.line(); 0759 QTextStream textStream(&line, QIODevice::ReadOnly); 0760 textStream 0761 >> sub_type >> line_style >> thickness >> pen_color >> fill_color 0762 >> depth >> pen_style >> area_fill >> style_val >> join_style 0763 >> cap_style >> radius >> forward_arrow >> backward_arrow 0764 >> npoints; 0765 // qDebug() << sub_type << line_style << thickness << pen_color << fill_color << depth << pen_style 0766 // << area_fill << style_val << join_style << cap_style << radius << forward_arrow << backward_arrow << npoints; 0767 0768 // ignore line with useless point number 0769 if (npoints < 1) { 0770 return 0; 0771 } 0772 0773 if (sub_type==XFig3_2PolylinePolylineId) { 0774 XFigPolylineObject* polylineObject = new XFigPolylineObject; 0775 polylineObject->setCapType(capType(cap_style)); 0776 abstractPolylineObject.reset(polylineObject); 0777 } else if (sub_type==XFig3_2PolylinePolygonId) { 0778 abstractPolylineObject.reset(new XFigPolygonObject); 0779 } else if (sub_type==XFig3_2PolylineBoxId) { 0780 abstractPolylineObject.reset(new XFigBoxObject); 0781 } else if (sub_type==XFig3_2PolylineArcBoxId) { 0782 XFigBoxObject* boxObject = new XFigBoxObject; 0783 boxObject->setRadius(radius); 0784 abstractPolylineObject.reset(boxObject); 0785 } else if (sub_type==XFig3_2PolylinePictureBoundingBoxId) { 0786 XFigPictureBoxObject* pictureBoxObject = new XFigPictureBoxObject; 0787 if (! m_XFigStreamLineReader.readNextLine()) { 0788 return 0; 0789 } 0790 0791 QString line = m_XFigStreamLineReader.line(); 0792 QTextStream textStream(&line, QIODevice::ReadOnly); 0793 0794 int flipped; 0795 QString fileName; 0796 textStream >> flipped >> fileName; 0797 0798 pictureBoxObject->setIsFlipped( flipped != 0 ); 0799 pictureBoxObject->setFileName( fileName ); 0800 0801 abstractPolylineObject.reset(pictureBoxObject); 0802 } else { 0803 } 0804 0805 if (forward_arrow > 0) { 0806 QScopedPointer<XFigArrowHead> arrowHead(parseArrowHead()); 0807 if (arrowHead.isNull()) { 0808 return 0; 0809 } 0810 0811 if (abstractPolylineObject->typeId() == XFigAbstractObject::PolylineId) { 0812 XFigPolylineObject* polylineObject = 0813 static_cast<XFigPolylineObject*>(abstractPolylineObject.data()); 0814 polylineObject->setForwardArrow(arrowHead.take()); 0815 } 0816 } 0817 0818 if (backward_arrow > 0) { 0819 QScopedPointer<XFigArrowHead> arrowHead(parseArrowHead()); 0820 if (arrowHead.isNull()) { 0821 return 0; 0822 } 0823 0824 if (abstractPolylineObject->typeId() == XFigAbstractObject::PolylineId) { 0825 XFigPolylineObject* polylineObject = 0826 static_cast<XFigPolylineObject*>(abstractPolylineObject.data()); 0827 polylineObject->setBackwardArrow(arrowHead.take()); 0828 } 0829 } 0830 0831 // points line 0832 const QVector<XFigPoint> points = parsePoints(npoints); 0833 if (points.count() != npoints) { 0834 return 0; 0835 } 0836 0837 // check box: 0838 if ((abstractPolylineObject->typeId()==XFigAbstractObject::BoxId) && 0839 (points.count()!=5)) { 0840 qWarning() << "box object does not have 5 points, but points:" << points.count(); 0841 return 0; 0842 } 0843 abstractPolylineObject->setPoints(points); 0844 abstractPolylineObject->setDepth(depth); 0845 const XFigFillType fillType = ::fillType(area_fill); 0846 if (fillType == XFigFillSolid) { 0847 abstractPolylineObject->setFillTinting(area_fill); 0848 } else if (fillType == XFigFillPattern) { 0849 abstractPolylineObject->setFillPatternType(::fillPatternType(area_fill)); 0850 } else { 0851 abstractPolylineObject->setFillNone(); 0852 } 0853 abstractPolylineObject->setFillColorId(fill_color); 0854 abstractPolylineObject->setLine(lineType(line_style), thickness, style_val, pen_color); 0855 abstractPolylineObject->setJoinType(joinType(join_style)); 0856 0857 return abstractPolylineObject.take(); 0858 } 0859 0860 XFigAbstractObject* 0861 XFigParser::parseSpline() 0862 { 0863 // qDebug()<<"spline"; 0864 0865 qint32 sub_type, line_style, thickness, pen_color, fill_color, depth, 0866 pen_style, area_fill, cap_style, forward_arrow, backward_arrow, npoints; 0867 float style_val; 0868 0869 // this should be a spline 0870 QString line = m_XFigStreamLineReader.line(); 0871 QTextStream textStream(&line, QIODevice::ReadOnly); 0872 textStream 0873 >> sub_type >> line_style >> thickness >> pen_color >> fill_color 0874 >> depth >> pen_style >> area_fill >> style_val >> cap_style 0875 >> forward_arrow >> backward_arrow >> npoints; 0876 // qDebug() << sub_type << line_style << thickness << pen_color << fill_color << depth << pen_style 0877 // << area_fill << style_val << cap_style << forward_arrow << backward_arrow << npoints; 0878 0879 // ignore line with useless point number 0880 if (npoints < 1) { 0881 return 0; 0882 } 0883 0884 // TODO: no idea yet how to translate the xfig splines to odf ones 0885 // thus simply creating polygones/polylines for now :/ 0886 QScopedPointer<XFigAbstractPolylineObject> abstractPolylineObject(0); 0887 0888 if ((sub_type==XFig3_2SplineOpenApproximatedId) || 0889 (sub_type==XFig3_2SplineOpenInterpolatedId) || 0890 (sub_type==XFig3_2SplineOpenXId)) { 0891 XFigPolylineObject* polylineObject = new XFigPolylineObject; 0892 polylineObject->setCapType(capType(cap_style)); 0893 abstractPolylineObject.reset(polylineObject); 0894 } else { 0895 abstractPolylineObject.reset(new XFigPolygonObject); 0896 } 0897 0898 if (forward_arrow > 0) { 0899 QScopedPointer<XFigArrowHead> arrowHead(parseArrowHead()); 0900 if (arrowHead.isNull()) { 0901 return 0; 0902 } 0903 0904 if (abstractPolylineObject->typeId() == XFigAbstractObject::PolylineId) { 0905 XFigPolylineObject* polylineObject = 0906 static_cast<XFigPolylineObject*>(abstractPolylineObject.data()); 0907 polylineObject->setForwardArrow(arrowHead.take()); 0908 } 0909 } 0910 0911 if (backward_arrow > 0) { 0912 QScopedPointer<XFigArrowHead> arrowHead(parseArrowHead()); 0913 if (arrowHead.isNull()) { 0914 return 0; 0915 } 0916 0917 if (abstractPolylineObject->typeId() == XFigAbstractObject::PolylineId) { 0918 XFigPolylineObject* polylineObject = 0919 static_cast<XFigPolylineObject*>(abstractPolylineObject.data()); 0920 polylineObject->setBackwardArrow(arrowHead.take()); 0921 } 0922 } 0923 0924 // points line 0925 const QVector<XFigPoint> points = parsePoints(npoints); 0926 if (points.count() != npoints) { 0927 return 0; 0928 } 0929 0930 // control points line 0931 parseFactors(npoints); 0932 0933 abstractPolylineObject->setPoints(points); 0934 abstractPolylineObject->setDepth(depth); 0935 const XFigFillType fillType = ::fillType(area_fill); 0936 if (fillType == XFigFillSolid) { 0937 abstractPolylineObject->setFillTinting(area_fill); 0938 } else if (fillType == XFigFillPattern) { 0939 abstractPolylineObject->setFillPatternType(::fillPatternType(area_fill)); 0940 } else { 0941 abstractPolylineObject->setFillNone(); 0942 } 0943 abstractPolylineObject->setFillColorId(fill_color); 0944 abstractPolylineObject->setLine(lineType(line_style), thickness, style_val, pen_color); 0945 abstractPolylineObject->setJoinType(XFigJoinRound); 0946 0947 return abstractPolylineObject.take(); 0948 } 0949 0950 XFigAbstractObject* 0951 XFigParser::parseText() 0952 { 0953 // qDebug()<<"text"; 0954 0955 QScopedPointer<XFigTextObject> textObject(new XFigTextObject); 0956 0957 qint32 sub_type, color, depth, pen_style, font, font_flags, x, y; 0958 float font_size, angle, height, length; 0959 0960 QString line = m_XFigStreamLineReader.line(); 0961 QTextStream textStream(&line, QIODevice::ReadOnly); 0962 textStream 0963 >> sub_type >> color >> depth >> pen_style >> font >> font_size 0964 >> angle >> font_flags >> height >> length >> x >> y; 0965 0966 const XFigTextAlignment textAlignment = 0967 (sub_type == XFig3_2TextCenterAligned) ? XFigTextCenterAligned : 0968 (sub_type == XFig3_2TextRightAligned) ? XFigTextRightAligned : 0969 /*(sub_type == XFig3_2TextLeftAligned)*/ XFigTextLeftAligned; 0970 textObject->setTextAlignment(textAlignment); 0971 textObject->setBaselineStartPoint(XFigPoint(x,y)); 0972 textObject->setSize(length, height); 0973 textObject->setXAxisAngle(angle); 0974 textObject->setColorId(color); 0975 textObject->setDepth(depth); 0976 textObject->setIsHidden(font_flags&XFig3_2TextHidden); 0977 0978 XFigFontData fontData; 0979 if (font_flags&XFig3_2TextPostScriptFont) { 0980 if (font == -1) { 0981 /* default means */; 0982 } else { 0983 if ((0<=font) && (font<=34)) { 0984 const XFig3_2PostScriptFontData& postScriptFontData = postScriptFontDataTable[font]; 0985 fontData.mFamily = QLatin1String(postScriptFontData.family); 0986 fontData.mWeight = postScriptFontData.weight; 0987 fontData.mStyle = postScriptFontData.style; 0988 } 0989 } 0990 } else { 0991 // LaTeX font 0992 if (font == XFig3_2LatexFontSansSerif) { 0993 fontData.mFamily = QLatin1String("helvetica"); 0994 } else if (font == XFig3_2LatexFontTypewriter) { 0995 fontData.mFamily = QLatin1String("courier"); 0996 } else if ((XFig3_2LatexFontDefault<=font) && (font<=XFig3_2LatexFontItalic)) { 0997 fontData.mFamily = QLatin1String("times"); 0998 if (font==XFig3_2LatexFontBold) { 0999 fontData.mWeight = QFont::Bold; 1000 } else if (font==XFig3_2LatexFontItalic) { 1001 fontData.mStyle = QFont::StyleItalic; 1002 } 1003 } 1004 } 1005 fontData.mSize = font_size; 1006 textObject->setFontData(fontData); 1007 1008 // read text 1009 // skip one space char used as separator 1010 const QString textData = line.mid(textStream.pos()+1); 1011 1012 // TODO: improve this, not really sane yet 1013 QString text; 1014 for (int i = 0; i < textData.length(); ++i) { 1015 const QChar textChar = textData.at(i); 1016 if (textChar == QLatin1Char('\\')) { 1017 1018 if ((i+3) >= textData.length()) { 1019 // encoded char, especially end marker not possible, is broken 1020 break; 1021 } 1022 // read digits and check this is really about an octal encoded char 1023 int digitValues[3]; 1024 bool isOctalEncodedChar = true; 1025 for (int d = 0; d < 3; ++d) { 1026 const int digitValue = textData.at(i+1+d).digitValue(); 1027 if ((digitValue < 0) || (7 < digitValue)) { 1028 isOctalEncodedChar = false; 1029 break; 1030 } 1031 digitValues[d] = digitValue; 1032 } 1033 if (isOctalEncodedChar) { 1034 unsigned char charValue = 1035 digitValues[0] * 64 + 1036 digitValues[1] * 8 + 1037 digitValues[2]; 1038 // \001 is used as end marker 1039 if (charValue == 1) { 1040 break; 1041 } 1042 const char encodedChar = static_cast<char>(charValue); 1043 text.append( m_TextDecoder->toUnicode(&encodedChar,1) ); 1044 1045 // digits are consumed 1046 i += 3; 1047 } else if (textData.at(i+1) == QLatin1Char('\\')) { 1048 text.append( textChar ); 1049 // double \ is consumed 1050 ++i; 1051 } 1052 } else { 1053 text.append( textChar ); 1054 } 1055 } 1056 textObject->setText(text); 1057 1058 return textObject.take(); 1059 } 1060 1061 XFigAbstractObject* 1062 XFigParser::parseCompoundObject() 1063 { 1064 // qDebug()<<"compound"; 1065 1066 QScopedPointer<XFigCompoundObject> compoundObject(new XFigCompoundObject); 1067 1068 { 1069 qint32 upperLeftX, upperLeftY, lowerRightX, lowerRightY; 1070 1071 QString line = m_XFigStreamLineReader.line(); 1072 QTextStream textStream(&line, QIODevice::ReadOnly); 1073 textStream >> upperLeftX >> upperLeftY >> lowerRightX >> lowerRightY; 1074 1075 const XFigBoundingBox boundingBox( XFigPoint(upperLeftX, upperLeftY), 1076 XFigPoint(lowerRightX, lowerRightY) ); 1077 compoundObject->setBoundingBox( boundingBox ); 1078 } 1079 1080 while (! m_XFigStreamLineReader.readNextObjectLine()) { 1081 const int objectCode = m_XFigStreamLineReader.objectCode(); 1082 const QString objectComment = m_XFigStreamLineReader.comment(); 1083 1084 // end reached? 1085 if (objectCode == XFig3_2CompoundObjectEndId) { 1086 break; 1087 } 1088 1089 if (objectCode == XFig3_2ColorObjectId) { 1090 parseColorObject(); 1091 } else if ((XFig3_2EllipseObjectId<=objectCode) && (objectCode<=XFig3_2CompoundObjectId)) { 1092 XFigAbstractObject* object = 1093 (objectCode == XFig3_2EllipseObjectId) ? parseEllipse() : 1094 (objectCode == XFig3_2PolylineObjectId) ? parsePolyline() : 1095 (objectCode == XFig3_2SplineObjectId) ? parseSpline() : 1096 (objectCode == XFig3_2TextObjectId) ? parseText() : 1097 (objectCode == XFig3_2ArcObjectId) ? parseArc() : 1098 /*else XFig3_2CompoundObjectId)*/ parseCompoundObject(); 1099 if (object != 0) { 1100 object->setComment(objectComment); 1101 compoundObject->addObject(object); 1102 } 1103 } else { 1104 // should not occur 1105 qWarning() << "unknown object type:" << objectCode; 1106 } 1107 } 1108 // qDebug()<<"compound end"; 1109 1110 return compoundObject.take(); 1111 } 1112 1113 XFigArrowHead* XFigParser::parseArrowHead() 1114 { 1115 if (! m_XFigStreamLineReader.readNextLine()) { 1116 return 0; 1117 } 1118 1119 QString line = m_XFigStreamLineReader.line(); 1120 QTextStream textStream(&line, QIODevice::ReadOnly); 1121 1122 int arrow_type, arrow_style; 1123 float arrow_thickness, arrow_width, arrow_height; 1124 textStream 1125 >> arrow_type >> arrow_style >> arrow_thickness 1126 >> arrow_width >> arrow_height; 1127 1128 XFigArrowHead* arrowHead = new XFigArrowHead; 1129 arrowHead->setType(arrowHeadType(arrow_type, arrow_style)); 1130 arrowHead->setThickness(arrow_thickness ); 1131 arrowHead->setSize(arrow_width, arrow_height); 1132 1133 return arrowHead; 1134 } 1135 1136 QVector<XFigPoint> XFigParser::parsePoints(int pointCount) 1137 { 1138 QVector<XFigPoint> result; 1139 1140 QString pointsText; 1141 QTextStream pointsTextStream(&pointsText, QIODevice::ReadOnly); 1142 for (int i = 0; i < pointCount; i++) { 1143 if (pointsTextStream.atEnd()) { 1144 if (! m_XFigStreamLineReader.readNextLine()) { 1145 return QVector<XFigPoint>(); 1146 } 1147 1148 pointsText = m_XFigStreamLineReader.line(); 1149 pointsTextStream.setString(&pointsText, QIODevice::ReadOnly); 1150 } 1151 1152 qint32 x; 1153 qint32 y; 1154 pointsTextStream >> x >> y; 1155 // qDebug() << "point:" << i << x << y; 1156 1157 result.append(XFigPoint(x, y)); 1158 1159 pointsTextStream.skipWhiteSpace(); 1160 } 1161 1162 return result; 1163 } 1164 1165 QVector<double> XFigParser::parseFactors(int pointCount) 1166 { 1167 QVector<double> result; 1168 1169 QString factorsText; 1170 QTextStream factorsTextStream(&factorsText, QIODevice::ReadOnly); 1171 for (int i = 0; i < pointCount; i++) { 1172 if (factorsTextStream.atEnd()) { 1173 if (! m_XFigStreamLineReader.readNextLine()) { 1174 return QVector<double>(); 1175 } 1176 1177 factorsText = m_XFigStreamLineReader.line(); 1178 factorsTextStream.setString(&factorsText, QIODevice::ReadOnly); 1179 } 1180 1181 double factor; 1182 factorsTextStream >> factor; 1183 // qDebug() << "factor:" << i << factor; 1184 1185 result.append(factor); 1186 1187 factorsTextStream.skipWhiteSpace(); 1188 } 1189 1190 return result; 1191 }