From 28999738a9a392a9e7a3e44e6f5d4410dd66a637 Mon Sep 17 00:00:00 2001 From: Javen O'Neal Date: Wed, 8 Feb 2017 07:47:30 +0000 Subject: [PATCH] Convert all *.java files to use native end of line character(s) $ dos2unix `find -name *.java` $ svn propset svn:eol-style native `find -name *.java` git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1782114 13f79535-47bb-0310-9956-ffa450edef68 --- .../usermodel/examples/EmbeddedObjects.java | 134 +- .../hssf/usermodel/examples/InCellLists.java | 1106 ++--- .../poi/ss/examples/AddDimensionedImage.java | 2050 ++++----- .../apache/poi/ss/examples/AligningCells.java | 148 +- .../poi/ss/examples/CellStyleDetails.java | 192 +- .../poi/ss/examples/ConditionalFormats.java | 1280 +++--- .../poi/ss/examples/ExcelComparator.java | 1226 ++--- .../poi/ss/examples/LinkedDropDownLists.java | 422 +- .../formula/SettingExternalFunction.java | 190 +- .../poi/xslf/usermodel/DataExtraction.java | 190 +- .../xslf/usermodel/MergePresentations.java | 108 +- .../poi/xslf/usermodel/PieChartDemo.java | 330 +- .../apache/poi/xslf/usermodel/Tutorial1.java | 148 +- .../apache/poi/xslf/usermodel/Tutorial2.java | 170 +- .../apache/poi/xslf/usermodel/Tutorial3.java | 102 +- .../apache/poi/xslf/usermodel/Tutorial4.java | 188 +- .../apache/poi/xslf/usermodel/Tutorial5.java | 102 +- .../apache/poi/xslf/usermodel/Tutorial6.java | 122 +- .../apache/poi/xslf/usermodel/Tutorial7.java | 180 +- .../xssf/usermodel/examples/CellComments.java | 180 +- .../usermodel/examples/CustomXMLMapping.java | 90 +- .../usermodel/examples/EmbeddedObjects.java | 132 +- .../usermodel/examples/HyperlinkExample.java | 14 +- .../xssf/usermodel/examples/LineChart.java | 186 +- .../usermodel/examples/UpdateEmbeddedDoc.java | 402 +- .../poi/ss/excelant/ExcelAntHandlerTask.java | 152 +- .../apache/poi/ss/excelant/ExcelAntSet.java | 96 +- .../ss/excelant/IExcelAntWorkbookHandler.java | 84 +- .../util/ExcelAntWorkbookUtilFactory.java | 120 +- .../apache/poi/ss/excelant/BuildFileTest.java | 1208 ++--- .../apache/poi/ss/excelant/TestBuildFile.java | 238 +- .../poi/stress/AbstractFileHandler.java | 284 +- .../apache/poi/stress/SlideShowHandler.java | 250 +- .../org/apache/poi/ddf/EscherColorRef.java | 592 +-- .../org/apache/poi/ddf/EscherPictBlip.java | 42 +- .../apache/poi/hssf/dev/BiffDrawingToXml.java | 328 +- .../poi/hssf/record/LbsDataSubRecord.java | 840 ++-- .../hssf/record/RecordFactoryInputStream.java | 16 +- .../record/cont/ContinuableRecordInput.java | 264 +- .../poi/hssf/usermodel/DummyGraphics2d.java | 1664 +++---- .../poi/hssf/usermodel/HSSFCombobox.java | 202 +- .../poi/hssf/usermodel/HSSFHyperlink.java | 70 +- .../poi/hssf/usermodel/HSSFShapeFactory.java | 284 +- .../apache/poi/poifs/crypt/ChainingMode.java | 64 +- .../poifs/crypt/ChunkedCipherInputStream.java | 560 +-- .../crypt/ChunkedCipherOutputStream.java | 600 +-- .../poi/poifs/crypt/CipherAlgorithm.java | 154 +- .../poi/poifs/crypt/CipherProvider.java | 80 +- .../poi/poifs/crypt/CryptoFunctions.java | 1152 ++--- .../poi/poifs/crypt/DataSpaceMapUtils.java | 740 +-- .../poifs/crypt/EncryptionInfoBuilder.java | 66 +- .../poi/poifs/crypt/EncryptionMode.java | 104 +- .../org/apache/poi/poifs/crypt/Encryptor.java | 208 +- .../apache/poi/poifs/crypt/HashAlgorithm.java | 148 +- .../crypt/binaryrc4/BinaryRC4Decryptor.java | 332 +- .../binaryrc4/BinaryRC4EncryptionHeader.java | 102 +- .../BinaryRC4EncryptionInfoBuilder.java | 118 +- .../BinaryRC4EncryptionVerifier.java | 178 +- .../crypt/binaryrc4/BinaryRC4Encryptor.java | 320 +- .../crypt/cryptoapi/CryptoAPIDecryptor.java | 510 +-- .../cryptoapi/CryptoAPIEncryptionHeader.java | 136 +- .../CryptoAPIEncryptionInfoBuilder.java | 148 +- .../CryptoAPIEncryptionVerifier.java | 116 +- .../crypt/cryptoapi/CryptoAPIEncryptor.java | 554 +-- .../crypt/standard/EncryptionRecord.java | 46 +- .../standard/StandardEncryptionHeader.java | 260 +- .../StandardEncryptionInfoBuilder.java | 192 +- .../crypt/standard/StandardEncryptor.java | 470 +- .../poi/poifs/filesystem/Ole10Native.java | 802 ++-- .../poi/poifs/macros/VBAMacroExtractor.java | 180 +- .../poi/sl/draw/BitmapImageRenderer.java | 612 +-- .../org/apache/poi/sl/draw/DrawAutoShape.java | 54 +- .../apache/poi/sl/draw/DrawBackground.java | 138 +- .../poi/sl/draw/DrawConnectorShape.java | 52 +- .../org/apache/poi/sl/draw/DrawFactory.java | 476 +- .../apache/poi/sl/draw/DrawFontManager.java | 112 +- .../apache/poi/sl/draw/DrawFreeformShape.java | 122 +- .../poi/sl/draw/DrawGraphicalFrame.java | 80 +- .../apache/poi/sl/draw/DrawGroupShape.java | 150 +- .../apache/poi/sl/draw/DrawMasterSheet.java | 106 +- .../poi/sl/draw/DrawNotImplemented.java | 70 +- .../org/apache/poi/sl/draw/DrawNothing.java | 94 +- .../org/apache/poi/sl/draw/DrawPaint.java | 1048 ++--- .../apache/poi/sl/draw/DrawPictureShape.java | 408 +- .../org/apache/poi/sl/draw/DrawShape.java | 482 +- .../org/apache/poi/sl/draw/DrawSheet.java | 194 +- .../apache/poi/sl/draw/DrawSimpleShape.java | 892 ++-- .../org/apache/poi/sl/draw/DrawSlide.java | 88 +- .../apache/poi/sl/draw/DrawTableShape.java | 514 +-- .../org/apache/poi/sl/draw/DrawTextBox.java | 52 +- .../apache/poi/sl/draw/DrawTextFragment.java | 210 +- .../apache/poi/sl/draw/DrawTextParagraph.java | 1462 +++--- .../org/apache/poi/sl/draw/DrawTextShape.java | 454 +- src/java/org/apache/poi/sl/draw/Drawable.java | 322 +- .../org/apache/poi/sl/draw/ImageRenderer.java | 258 +- .../apache/poi/sl/draw/PathGradientPaint.java | 376 +- .../org/apache/poi/sl/draw/SLGraphics.java | 3692 +++++++-------- .../poi/sl/draw/binding/CTAdjPoint2D.java | 218 +- .../sl/draw/binding/CTAdjustHandleList.java | 198 +- .../apache/poi/sl/draw/binding/CTAngle.java | 140 +- .../apache/poi/sl/draw/binding/CTColor.java | 474 +- .../poi/sl/draw/binding/CTColorMRU.java | 212 +- .../draw/binding/CTComplementTransform.java | 92 +- .../poi/sl/draw/binding/CTConnection.java | 190 +- .../poi/sl/draw/binding/CTConnectionSite.java | 228 +- .../sl/draw/binding/CTConnectionSiteList.java | 186 +- .../sl/draw/binding/CTCustomGeometry2D.java | 484 +- .../draw/binding/CTEmbeddedWAVAudioFile.java | 304 +- .../sl/draw/binding/CTFixedPercentage.java | 140 +- .../poi/sl/draw/binding/CTGammaTransform.java | 92 +- .../poi/sl/draw/binding/CTGeomGuide.java | 224 +- .../poi/sl/draw/binding/CTGeomGuideList.java | 186 +- .../poi/sl/draw/binding/CTGeomRect.java | 342 +- .../sl/draw/binding/CTGrayscaleTransform.java | 92 +- .../sl/draw/binding/CTGroupTransform2D.java | 592 +-- .../poi/sl/draw/binding/CTHslColor.java | 442 +- .../poi/sl/draw/binding/CTHyperlink.java | 806 ++-- .../draw/binding/CTInverseGammaTransform.java | 92 +- .../sl/draw/binding/CTInverseTransform.java | 92 +- .../sl/draw/binding/CTOfficeArtExtension.java | 244 +- .../binding/CTOfficeArtExtensionList.java | 186 +- .../apache/poi/sl/draw/binding/CTPath2D.java | 606 +-- .../poi/sl/draw/binding/CTPath2DArcTo.java | 342 +- .../poi/sl/draw/binding/CTPath2DClose.java | 92 +- .../draw/binding/CTPath2DCubicBezierTo.java | 186 +- .../poi/sl/draw/binding/CTPath2DLineTo.java | 164 +- .../poi/sl/draw/binding/CTPath2DList.java | 186 +- .../poi/sl/draw/binding/CTPath2DMoveTo.java | 164 +- .../sl/draw/binding/CTPath2DQuadBezierTo.java | 186 +- .../poi/sl/draw/binding/CTPercentage.java | 140 +- .../apache/poi/sl/draw/binding/CTPoint2D.java | 186 +- .../apache/poi/sl/draw/binding/CTPoint3D.java | 232 +- .../sl/draw/binding/CTPolarAdjustHandle.java | 546 +-- .../sl/draw/binding/CTPositiveFixedAngle.java | 140 +- .../binding/CTPositiveFixedPercentage.java | 140 +- .../sl/draw/binding/CTPositivePercentage.java | 140 +- .../poi/sl/draw/binding/CTPositiveSize2D.java | 186 +- .../poi/sl/draw/binding/CTPresetColor.java | 366 +- .../sl/draw/binding/CTPresetGeometry2D.java | 228 +- .../sl/draw/binding/CTPresetTextShape.java | 228 +- .../apache/poi/sl/draw/binding/CTRatio.java | 186 +- .../poi/sl/draw/binding/CTRelativeRect.java | 406 +- .../poi/sl/draw/binding/CTSRgbColor.java | 372 +- .../poi/sl/draw/binding/CTScRgbColor.java | 442 +- .../apache/poi/sl/draw/binding/CTScale2D.java | 228 +- .../poi/sl/draw/binding/CTSchemeColor.java | 366 +- .../poi/sl/draw/binding/CTSphereCoords.java | 232 +- .../poi/sl/draw/binding/CTSystemColor.java | 438 +- .../poi/sl/draw/binding/CTTransform2D.java | 464 +- .../poi/sl/draw/binding/CTVector3D.java | 232 +- .../poi/sl/draw/binding/CTXYAdjustHandle.java | 546 +-- .../poi/sl/draw/binding/ObjectFactory.java | 4046 ++++++++--------- .../poi/sl/draw/binding/STBlackWhiteMode.java | 298 +- .../poi/sl/draw/binding/STPathFillMode.java | 218 +- .../poi/sl/draw/binding/STPresetColorVal.java | 2362 +++++----- .../poi/sl/draw/binding/STRectAlignment.java | 266 +- .../poi/sl/draw/binding/STSchemeColorVal.java | 394 +- .../poi/sl/draw/binding/STShapeType.java | 3114 ++++++------- .../poi/sl/draw/binding/STTextShapeType.java | 778 ++-- .../poi/sl/usermodel/AutoNumberingScheme.java | 576 +-- .../apache/poi/sl/usermodel/ColorStyle.java | 218 +- .../poi/sl/usermodel/ConnectorShape.java | 50 +- .../apache/poi/sl/usermodel/FillStyle.java | 44 +- .../poi/sl/usermodel/FreeformShape.java | 90 +- .../poi/sl/usermodel/GraphicalFrame.java | 58 +- .../org/apache/poi/sl/usermodel/Insets2D.java | 280 +- .../poi/sl/usermodel/LineDecoration.java | 226 +- .../poi/sl/usermodel/PlaceableShape.java | 184 +- .../apache/poi/sl/usermodel/Placeholder.java | 310 +- .../apache/poi/sl/usermodel/PresetColor.java | 558 +-- .../org/apache/poi/sl/usermodel/Shadow.java | 106 +- .../poi/sl/usermodel/SlideShowFactory.java | 530 +-- .../apache/poi/sl/usermodel/TableCell.java | 228 +- .../apache/poi/sl/usermodel/TableShape.java | 160 +- .../poi/sl/usermodel/TextParagraph.java | 752 +-- .../apache/poi/sl/usermodel/TextShape.java | 514 +-- .../poi/sl/usermodel/VerticalAlignment.java | 148 +- .../poi/ss/format/CellNumberPartHandler.java | 328 +- .../poi/ss/format/CellNumberStringMod.java | 210 +- .../apache/poi/ss/formula/EvaluationCell.java | 12 +- .../apache/poi/ss/formula/SharedFormula.java | 196 +- .../poi/ss/formula/functions/Address.java | 206 +- .../ss/formula/functions/BaseNumberUtils.java | 156 +- .../poi/ss/formula/functions/Bin2Dec.java | 248 +- .../apache/poi/ss/formula/functions/Code.java | 108 +- .../poi/ss/formula/functions/Complex.java | 300 +- .../poi/ss/formula/functions/Dec2Bin.java | 262 +- .../poi/ss/formula/functions/Dec2Hex.java | 276 +- .../poi/ss/formula/functions/Delta.java | 168 +- .../poi/ss/formula/functions/EOMonth.java | 164 +- .../poi/ss/formula/functions/FactDouble.java | 172 +- .../poi/ss/formula/functions/Hex2Dec.java | 132 +- .../poi/ss/formula/functions/ImReal.java | 196 +- .../poi/ss/formula/functions/Imaginary.java | 218 +- .../apache/poi/ss/formula/functions/Mirr.java | 218 +- .../poi/ss/formula/functions/Oct2Dec.java | 128 +- .../poi/ss/formula/functions/Quotient.java | 146 +- .../apache/poi/ss/formula/functions/Rate.java | 246 +- .../apache/poi/ss/formula/functions/Rept.java | 148 +- .../poi/ss/formula/functions/Roman.java | 300 +- .../poi/ss/formula/functions/WeekNum.java | 178 +- .../apache/poi/ss/usermodel/AutoFilter.java | 158 +- .../poi/ss/usermodel/BorderFormatting.java | 516 +-- .../ss/usermodel/ColorScaleFormatting.java | 132 +- .../poi/ss/usermodel/ComparisonOperator.java | 140 +- .../poi/ss/usermodel/ConditionType.java | 184 +- .../ss/usermodel/ConditionalFormatting.java | 234 +- .../usermodel/ConditionalFormattingRule.java | 244 +- .../ConditionalFormattingThreshold.java | 220 +- .../poi/ss/usermodel/DataBarFormatting.java | 144 +- .../poi/ss/usermodel/FontFormatting.java | 302 +- .../poi/ss/usermodel/FractionFormat.java | 368 +- .../usermodel/IconMultiStateFormatting.java | 254 +- .../poi/ss/usermodel/PatternFormatting.java | 156 +- .../usermodel/SheetConditionalFormatting.java | 390 +- .../poi/ss/usermodel/charts/AxisTickMark.java | 60 +- .../poi/ss/usermodel/charts/ChartSeries.java | 110 +- .../poi/ss/usermodel/charts/LayoutMode.java | 70 +- .../poi/ss/usermodel/charts/LayoutTarget.java | 78 +- .../ss/usermodel/charts/LineChartData.java | 82 +- .../ss/usermodel/charts/LineChartSeries.java | 76 +- .../poi/ss/usermodel/charts/ManualLayout.java | 306 +- .../charts/ManuallyPositionable.java | 72 +- .../poi/ss/usermodel/charts/TitleType.java | 56 +- .../poi/ss/util/DateFormatConverter.java | 866 ++-- .../apache/poi/ss/util/ExpandedDouble.java | 196 +- .../org/apache/poi/ss/util/ImageUtils.java | 570 +-- .../apache/poi/ss/util/NormalisedDecimal.java | 542 +-- .../org/apache/poi/util/Configurator.java | 72 +- src/java/org/apache/poi/util/JvmBugs.java | 110 +- src/java/org/apache/poi/util/LocaleUtil.java | 282 +- src/java/org/apache/poi/util/PngUtils.java | 106 +- .../apache/poi/util/SuppressForbidden.java | 66 +- src/java/org/apache/poi/util/Units.java | 260 +- .../java/org/apache/poi/POIXMLTypeLoader.java | 348 +- .../org/apache/poi/dev/OOXMLPrettyPrint.java | 286 +- .../poi/openxml4j/util/ZipSecureFile.java | 618 +-- .../crypt/agile/AgileEncryptionHeader.java | 268 +- .../agile/AgileEncryptionInfoBuilder.java | 218 +- .../poi/poifs/crypt/agile/AgileEncryptor.java | 920 ++-- .../dsig/CertificateSecurityException.java | 76 +- .../poi/poifs/crypt/dsig/DigestInfo.java | 112 +- .../ExpiredCertificateSecurityException.java | 76 +- .../poifs/crypt/dsig/KeyInfoKeySelector.java | 206 +- .../crypt/dsig/OOXMLURIDereferencer.java | 260 +- .../RevokedCertificateSecurityException.java | 76 +- .../poi/poifs/crypt/dsig/SignatureConfig.java | 1794 ++++---- .../crypt/dsig/SignatureMarshalListener.java | 182 +- .../TrustCertificateSecurityException.java | 76 +- .../dsig/facets/EnvelopedSignatureFacet.java | 120 +- .../dsig/facets/KeyInfoSignatureFacet.java | 294 +- .../dsig/facets/OOXMLSignatureFacet.java | 948 ++-- .../dsig/facets/Office2010SignatureFacet.java | 156 +- .../crypt/dsig/facets/SignatureFacet.java | 378 +- .../dsig/facets/XAdESSignatureFacet.java | 570 +-- .../dsig/facets/XAdESXLSignatureFacet.java | 778 ++-- .../RelationshipTransformService.java | 496 +- .../crypt/dsig/services/RevocationData.java | 264 +- .../dsig/services/RevocationDataService.java | 94 +- .../dsig/services/SignaturePolicyService.java | 128 +- .../dsig/services/TSPTimeStampService.java | 520 +-- .../crypt/dsig/services/TimeStampService.java | 108 +- .../services/TimeStampServiceValidator.java | 102 +- .../apache/poi/util/IdentifierManager.java | 532 +-- .../java/org/apache/poi/util/XmlSort.java | 174 +- .../xslf/model/CharacterPropertyFetcher.java | 78 +- .../xslf/model/ParagraphPropertyFetcher.java | 102 +- .../poi/xslf/model/PropertyFetcher.java | 96 +- .../xslf/model/TextBodyPropertyFetcher.java | 102 +- .../poi/xslf/usermodel/XSLFAutoShape.java | 216 +- .../poi/xslf/usermodel/XSLFBackground.java | 224 +- .../apache/poi/xslf/usermodel/XSLFColor.java | 968 ++-- .../xslf/usermodel/XSLFConnectorShape.java | 154 +- .../poi/xslf/usermodel/XSLFDrawing.java | 226 +- .../poi/xslf/usermodel/XSLFFreeformShape.java | 418 +- .../poi/xslf/usermodel/XSLFGraphicFrame.java | 436 +- .../poi/xslf/usermodel/XSLFGroupShape.java | 756 +-- .../poi/xslf/usermodel/XSLFHyperlink.java | 332 +- .../poi/xslf/usermodel/XSLFLineBreak.java | 66 +- .../poi/xslf/usermodel/XSLFMetroShape.java | 124 +- .../poi/xslf/usermodel/XSLFPictureShape.java | 462 +- .../apache/poi/xslf/usermodel/XSLFShadow.java | 212 +- .../apache/poi/xslf/usermodel/XSLFShape.java | 1122 ++--- .../xslf/usermodel/XSLFSlideShowFactory.java | 200 +- .../apache/poi/xslf/usermodel/XSLFTable.java | 700 +-- .../poi/xslf/usermodel/XSLFTableCell.java | 1546 +++---- .../poi/xslf/usermodel/XSLFTableRow.java | 212 +- .../poi/xslf/usermodel/XSLFTableStyle.java | 168 +- .../poi/xslf/usermodel/XSLFTextBox.java | 120 +- .../poi/xslf/usermodel/XSLFTextRun.java | 1258 ++--- .../org/apache/poi/xslf/util/PPTX2PNG.java | 428 +- .../xssf/streaming/GZIPSheetDataWriter.java | 136 +- .../poi/xssf/streaming/SheetDataWriter.java | 874 ++-- .../xssf/usermodel/XSSFBorderFormatting.java | 734 +-- .../usermodel/XSSFColorScaleFormatting.java | 184 +- .../usermodel/XSSFConditionalFormatting.java | 262 +- .../XSSFConditionalFormattingRule.java | 722 +-- .../XSSFConditionalFormattingThreshold.java | 154 +- .../xssf/usermodel/XSSFDataBarFormatting.java | 166 +- .../xssf/usermodel/XSSFFontFormatting.java | 448 +- .../XSSFIconMultiStateFormatting.java | 168 +- .../xssf/usermodel/XSSFPatternFormatting.java | 216 +- .../XSSFSheetConditionalFormatting.java | 590 +-- .../charts/AbstractXSSFChartSeries.java | 158 +- .../usermodel/charts/XSSFLineChartData.java | 252 +- .../usermodel/charts/XSSFManualLayout.java | 494 +- .../poi/xwpf/usermodel/AbstractXWPFSDT.java | 214 +- .../poi/xwpf/usermodel/BodyElementType.java | 22 +- .../apache/poi/xwpf/usermodel/Borders.java | 76 +- .../apache/poi/xwpf/usermodel/BreakClear.java | 86 +- .../apache/poi/xwpf/usermodel/BreakType.java | 82 +- .../apache/poi/xwpf/usermodel/Document.java | 78 +- .../org/apache/poi/xwpf/usermodel/IBody.java | 180 +- .../poi/xwpf/usermodel/IBodyElement.java | 30 +- .../org/apache/poi/xwpf/usermodel/ICell.java | 20 +- .../poi/xwpf/usermodel/ISDTContent.java | 34 +- .../poi/xwpf/usermodel/LineSpacingRule.java | 72 +- .../xwpf/usermodel/ParagraphAlignment.java | 56 +- .../xwpf/usermodel/PositionInParagraph.java | 88 +- .../org/apache/poi/xwpf/usermodel/TOC.java | 164 +- .../poi/xwpf/usermodel/TextAlignment.java | 102 +- .../poi/xwpf/usermodel/TextSegement.java | 162 +- .../poi/xwpf/usermodel/UnderlinePatterns.java | 72 +- .../poi/xwpf/usermodel/VerticalAlign.java | 72 +- .../poi/xwpf/usermodel/XWPFAbstractNum.java | 80 +- .../usermodel/XWPFDefaultParagraphStyle.java | 30 +- .../xwpf/usermodel/XWPFDefaultRunStyle.java | 30 +- .../poi/xwpf/usermodel/XWPFFieldRun.java | 44 +- .../poi/xwpf/usermodel/XWPFFootnote.java | 754 +-- .../poi/xwpf/usermodel/XWPFFootnotes.java | 166 +- .../poi/xwpf/usermodel/XWPFHyperlinkRun.java | 84 +- .../poi/xwpf/usermodel/XWPFLatentStyles.java | 60 +- .../apache/poi/xwpf/usermodel/XWPFNum.java | 84 +- .../poi/xwpf/usermodel/XWPFNumbering.java | 436 +- .../poi/xwpf/usermodel/XWPFPicture.java | 82 +- .../apache/poi/xwpf/usermodel/XWPFSDT.java | 54 +- .../poi/xwpf/usermodel/XWPFSDTCell.java | 50 +- .../poi/xwpf/usermodel/XWPFSDTContent.java | 190 +- .../xwpf/usermodel/XWPFSDTContentCell.java | 232 +- .../apache/poi/xwpf/usermodel/XWPFStyle.java | 276 +- .../apache/poi/xwpf/usermodel/XWPFStyles.java | 380 +- .../poi/xwpf/usermodel/XWPFTableCell.java | 1036 ++--- .../poi/xwpf/usermodel/XWPFTableRow.java | 348 +- .../poi/openxml4j/opc/ZipFileAssert.java | 278 +- .../poi/poifs/crypt/AllPOIFSCryptoTests.java | 70 +- .../apache/poi/poifs/crypt/PkiTestUtils.java | 634 +-- .../crypt/TestAgileEncryptionParameters.java | 218 +- .../crypt/TestCertificateEncryption.java | 394 +- .../apache/poi/poifs/crypt/TestDecryptor.java | 368 +- .../poi/poifs/crypt/TestEncryptionInfo.java | 130 +- .../apache/poi/poifs/crypt/TestEncryptor.java | 1052 ++--- .../poi/poifs/crypt/TestSignatureInfo.java | 1448 +++--- .../org/apache/poi/sl/TestHeadersFooters.java | 206 +- .../org/apache/poi/sl/TestTable.java | 326 +- .../poi/util/TestIdentifierManager.java | 258 +- .../apache/poi/xslf/XSLFTestDataSamples.java | 144 +- .../poi/xslf/usermodel/TestPPTX2PNG.java | 206 +- .../poi/xslf/usermodel/TestXSLFAutoShape.java | 620 +-- .../poi/xslf/usermodel/TestXSLFChart.java | 262 +- .../poi/xslf/usermodel/TestXSLFColor.java | 366 +- .../usermodel/TestXSLFConnectorShape.java | 316 +- .../xslf/usermodel/TestXSLFFreeformShape.java | 108 +- .../xslf/usermodel/TestXSLFGroupShape.java | 214 +- .../poi/xslf/usermodel/TestXSLFHyperlink.java | 358 +- .../poi/xslf/usermodel/TestXSLFNotes.java | 212 +- .../xslf/usermodel/TestXSLFPictureShape.java | 420 +- .../poi/xslf/usermodel/TestXSLFShape.java | 214 +- .../usermodel/TestXSLFShapeContainer.java | 126 +- .../poi/xslf/usermodel/TestXSLFSheet.java | 148 +- .../xslf/usermodel/TestXSLFSimpleShape.java | 770 ++-- .../poi/xslf/usermodel/TestXSLFSlide.java | 392 +- .../poi/xslf/usermodel/TestXSLFSlideShow.java | 298 +- .../poi/xslf/usermodel/TestXSLFTable.java | 434 +- .../xslf/usermodel/TestXSLFTableStyles.java | 74 +- .../poi/xslf/usermodel/TestXSLFTextBox.java | 178 +- .../xslf/usermodel/TestXSLFTextParagraph.java | 788 ++-- .../poi/xslf/usermodel/TestXSLFTextRun.java | 160 +- .../poi/xslf/usermodel/TestXSLFTextShape.java | 1886 ++++---- .../poi/xslf/usermodel/TestXSLFTheme.java | 342 +- .../apache/poi/xssf/TestXSSFCloneSheet.java | 186 +- .../poi/xssf/model/TestThemesTable.java | 526 +-- .../streaming/TestSXSSFDataValidation.java | 124 +- .../poi/xssf/usermodel/TestUnfixedBugs.java | 800 ++-- .../TestXSSFConditionalFormatting.java | 118 +- .../charts/TestXSSFLineChartData.java | 152 +- .../charts/TestXSSFManualLayout.java | 240 +- .../org/apache/poi/xwpf/AllXWPFTests.java | 40 +- .../poi/xwpf/TestAllExtendedProperties.java | 158 +- .../TestPackageCorePropertiesGetKeywords.java | 56 +- .../org/apache/poi/xwpf/TestXWPFBugs.java | 252 +- .../apache/poi/xwpf/XWPFTestDataSamples.java | 106 +- .../poi/xwpf/model/TestXWPFDecorators.java | 114 +- .../apache/poi/hslf/model/HSLFMetroShape.java | 178 +- .../textproperties/TabStopPropCollection.java | 246 +- .../textproperties/WrapFlagsTextProp.java | 60 +- .../poi/hslf/record/EscherPlaceholder.java | 150 +- .../apache/poi/hslf/record/ExObjRefAtom.java | 188 +- .../record/HSLFEscherClientDataRecord.java | 240 +- .../hslf/record/HSLFEscherRecordFactory.java | 134 +- .../poi/hslf/record/SSSlideInfoAtom.java | 578 +-- .../poi/hslf/record/TextSpecInfoRun.java | 692 +-- .../hslf/usermodel/HSLFConnectorShape.java | 130 +- .../hslf/usermodel/HSLFShapeContainer.java | 98 +- .../hslf/usermodel/HSLFSlideShowFactory.java | 84 +- .../poi/hslf/usermodel/HSLFTextParagraph.java | 3298 +++++++------- .../poi/hwmf/draw/HwmfDrawProperties.java | 692 +-- .../apache/poi/hwmf/draw/HwmfGraphics.java | 888 ++-- .../poi/hwmf/draw/HwmfSLImageRenderer.java | 248 +- .../poi/hwmf/record/HwmfBinaryRasterOp.java | 224 +- .../apache/poi/hwmf/record/HwmfBitmap16.java | 176 +- .../apache/poi/hwmf/record/HwmfBitmapDib.java | 836 ++-- .../poi/hwmf/record/HwmfBrushStyle.java | 160 +- .../apache/poi/hwmf/record/HwmfColorRef.java | 144 +- .../org/apache/poi/hwmf/record/HwmfDraw.java | 1396 +++--- .../apache/poi/hwmf/record/HwmfEscape.java | 424 +- .../org/apache/poi/hwmf/record/HwmfFill.java | 2020 ++++---- .../org/apache/poi/hwmf/record/HwmfFont.java | 1190 ++--- .../poi/hwmf/record/HwmfHatchStyle.java | 94 +- .../apache/poi/hwmf/record/HwmfHeader.java | 154 +- .../apache/poi/hwmf/record/HwmfMapMode.java | 226 +- .../org/apache/poi/hwmf/record/HwmfMisc.java | 1160 ++--- .../poi/hwmf/record/HwmfObjectTableEntry.java | 56 +- .../apache/poi/hwmf/record/HwmfPalette.java | 650 +-- .../apache/poi/hwmf/record/HwmfPenStyle.java | 378 +- .../poi/hwmf/record/HwmfPlaceableHeader.java | 180 +- .../apache/poi/hwmf/record/HwmfRecord.java | 86 +- .../poi/hwmf/record/HwmfRecordType.java | 224 +- .../poi/hwmf/record/HwmfTernaryRasterOp.java | 796 ++-- .../org/apache/poi/hwmf/record/HwmfText.java | 1122 ++--- .../apache/poi/hwmf/record/HwmfWindowing.java | 1420 +++--- .../poi/hwmf/usermodel/HwmfPicture.java | 344 +- .../poi/hwpf/model/CharIndexTranslator.java | 188 +- .../src/org/apache/poi/hwpf/model/FFData.java | 460 +- .../org/apache/poi/hwpf/model/FFDataBase.java | 98 +- .../poi/hwpf/model/NilPICFAndBinData.java | 158 +- .../src/org/apache/poi/hwpf/model/Xstz.java | 174 +- .../poi/hwpf/model/types/BKFAbstractType.java | 384 +- .../model/types/FFDataBaseAbstractType.java | 856 ++-- .../poi/hwpf/model/types/FRDAbstractType.java | 182 +- .../hwpf/model/types/FSPAAbstractType.java | 822 ++-- .../hwpf/model/types/FibBaseAbstractType.java | 1674 +++---- .../model/types/FibRgLw95AbstractType.java | 936 ++-- .../model/types/FibRgLw97AbstractType.java | 1372 +++--- .../model/types/FibRgW97AbstractType.java | 830 ++-- .../hwpf/model/types/GrfhicAbstractType.java | 614 +-- .../hwpf/model/types/HRESIAbstractType.java | 272 +- .../poi/hwpf/model/types/LFOAbstractType.java | 580 +-- .../model/types/LFOLVLBaseAbstractType.java | 580 +-- .../hwpf/model/types/LSTFAbstractType.java | 758 +-- .../poi/hwpf/model/types/TLPAbstractType.java | 584 +-- .../org/apache/poi/hmef/TestBugs.java | 138 +- .../hslf/record/TestDocumentEncryption.java | 390 +- .../poi/hslf/usermodel/TestFontRendering.java | 242 +- .../poi/hsmf/TestMessageSubmissionChunk.java | 116 +- .../TestMessageSubmissionChunkY2KRead.java | 134 +- .../org/apache/poi/hwmf/TestHwmfParsing.java | 502 +- .../apache/poi/hwpf/HWPFTestDataSamples.java | 342 +- .../org/apache/poi/hwpf/model/PlfLfoTest.java | 110 +- .../org/apache/poi/hwpf/sprm/TestSprms.java | 200 +- .../poi/hwpf/usermodel/TestBug47563.java | 170 +- .../poi/hwpf/usermodel/TestBug49820.java | 124 +- .../poi/hwpf/usermodel/TestBug50075.java | 82 +- .../poi/hwpf/usermodel/TestRangeSymbols.java | 94 +- .../org/apache/poi/POIDataSamples.java | 562 +-- .../poi/hssf/model/TestDrawingAggregate.java | 1892 ++++---- .../hssf/model/TestEscherRecordFactory.java | 198 +- .../apache/poi/hssf/model/TestHSSFAnchor.java | 856 ++-- .../hssf/usermodel/TestEmbeddedObjects.java | 124 +- .../poi/hssf/usermodel/TestHSSFHyperlink.java | 26 +- .../poi/hssf/usermodel/TestPatriarch.java | 114 +- .../poi/hssf/usermodel/TestPolygon.java | 552 +-- .../poi/hssf/usermodel/TestShapeGroup.java | 530 +-- .../apache/poi/hssf/usermodel/TestText.java | 428 +- .../poi/poifs/crypt/TestXorEncryption.java | 150 +- .../org/apache/poi/sl/TestCommonSL.java | 76 +- .../poi/ss/formula/TestMissingWorkbook.java | 266 +- .../functions/AllSpreadsheetBasedTests.java | 96 +- .../BaseTestFunctionsFromSpreadsheet.java | 478 +- .../functions/RefEvalImplementation.java | 136 +- .../poi/ss/formula/functions/TestAddress.java | 158 +- .../poi/ss/formula/functions/TestClean.java | 132 +- .../poi/ss/formula/functions/TestCode.java | 118 +- .../TestCodeFunctionsFromSpreadsheet.java | 62 +- .../poi/ss/formula/functions/TestComplex.java | 136 +- .../TestComplexFunctionsFromSpreadsheet.java | 62 +- .../TestDeltaFunctionsFromSpreadsheet.java | 62 +- .../poi/ss/formula/functions/TestEOMonth.java | 304 +- ...estFactDoubleFunctionsFromSpreadsheet.java | 64 +- .../TestImRealFunctionsFromSpreadsheet.java | 64 +- ...TestImaginaryFunctionsFromSpreadsheet.java | 64 +- .../TestIndirectFunctionFromSpreadsheet.java | 72 +- .../functions/TestLogicalFunction.java | 214 +- .../TestMatchFunctionsFromSpreadsheet.java | 72 +- .../poi/ss/formula/functions/TestMirr.java | 336 +- .../ss/formula/functions/TestQuotient.java | 126 +- .../TestQuotientFunctionsFromSpreadsheet.java | 64 +- .../TestReptFunctionsFromSpreadsheet.java | 62 +- .../TestRomanFunctionsFromSpreadsheet.java | 64 +- .../TestWeekNumFunctionsFromSpreadsheet.java | 64 +- ...stWeekNumFunctionsFromSpreadsheet2013.java | 66 +- .../BaseTestConditionalFormatting.java | 2870 ++++++------ .../apache/poi/ss/util/BaseTestCellUtil.java | 832 ++-- 502 files changed, 89558 insertions(+), 89558 deletions(-) diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmbeddedObjects.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmbeddedObjects.java index 57df51c1af..4f0a707b2f 100644 --- a/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmbeddedObjects.java +++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmbeddedObjects.java @@ -1,67 +1,67 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hssf.usermodel.examples; - -import java.io.Closeable; -import java.io.FileInputStream; - -import org.apache.poi.hslf.usermodel.HSLFSlideShow; -import org.apache.poi.hssf.usermodel.HSSFObjectData; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.hwpf.HWPFDocument; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.Entry; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; - -/** - * Demonstrates how you can extract embedded data from a .xls file - */ -public class EmbeddedObjects { - @SuppressWarnings("unused") - public static void main(String[] args) throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(args[0])); - HSSFWorkbook workbook = new HSSFWorkbook(fs); - for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) { - //the OLE2 Class Name of the object - String oleName = obj.getOLE2ClassName(); - DirectoryNode dn = (obj.hasDirectoryEntry()) ? (DirectoryNode) obj.getDirectory() : null; - Closeable document = null; - if (oleName.equals("Worksheet")) { - document = new HSSFWorkbook(dn, fs, false); - } else if (oleName.equals("Document")) { - document = new HWPFDocument(dn); - } else if (oleName.equals("Presentation")) { - document = new HSLFSlideShow(dn); - } else { - if(dn != null){ - // The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is - for (Entry entry : dn) { - String name = entry.getName(); - } - } else { - // There is no DirectoryEntry - // Recover the object's data from the HSSFObjectData instance. - byte[] objectData = obj.getObjectData(); - } - } - if (document != null) { - document.close(); - } - } - workbook.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hssf.usermodel.examples; + +import java.io.Closeable; +import java.io.FileInputStream; + +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hssf.usermodel.HSSFObjectData; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.Entry; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +/** + * Demonstrates how you can extract embedded data from a .xls file + */ +public class EmbeddedObjects { + @SuppressWarnings("unused") + public static void main(String[] args) throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(args[0])); + HSSFWorkbook workbook = new HSSFWorkbook(fs); + for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) { + //the OLE2 Class Name of the object + String oleName = obj.getOLE2ClassName(); + DirectoryNode dn = (obj.hasDirectoryEntry()) ? (DirectoryNode) obj.getDirectory() : null; + Closeable document = null; + if (oleName.equals("Worksheet")) { + document = new HSSFWorkbook(dn, fs, false); + } else if (oleName.equals("Document")) { + document = new HWPFDocument(dn); + } else if (oleName.equals("Presentation")) { + document = new HSLFSlideShow(dn); + } else { + if(dn != null){ + // The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is + for (Entry entry : dn) { + String name = entry.getName(); + } + } else { + // There is no DirectoryEntry + // Recover the object's data from the HSSFObjectData instance. + byte[] objectData = obj.getObjectData(); + } + } + if (document != null) { + document.close(); + } + } + workbook.close(); + } +} diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java index e1d4cbcbf8..b250441110 100644 --- a/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java +++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java @@ -1,553 +1,553 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - - -package org.apache.poi.hssf.usermodel.examples; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; - -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFCellStyle; -import org.apache.poi.hssf.usermodel.HSSFDataFormat; -import org.apache.poi.hssf.usermodel.HSSFRichTextString; - -/** - * This class contains code that demonstrates how to insert plain, numbered - * and bulleted lists into an Excel spreadsheet cell. - * - * Look at the code contained in the demonstrateMethodCalls() method. It calls - * other methods that create plain, numbered and bulleted single and - * multi-level lists. The demonstrateMethodCalls() method appears at the top - * of the class definition. - * - * Though different methods are provided to construct single and multi-level - * plain, numbered and bulleted lists, close examination will reveal that they - * are not strictly necessary. If the inputs to the listInCell() and - * multilLevelListInCell() methods are constructed to include the bullet - * character or the item numbers then these methods alone may be sufficient. - * - * @author Mark Beardsley [msb at apache.org] - */ -public class InCellLists { - - // This character looks like a solid, black, loser case letter 'o' - // positioned up from the base line of the text. - private static final char BULLET_CHARACTER = '\u2022'; - - // The tab character - \t - cannot be used to create a tab space - // within a cell as it is rendered as a square. Therefore, four - // spaces are used to simulate that character. - private static final String TAB = " "; - - /** - * Call each of the list creation methods. - * - * @param outputFilename A String that encapsulates the name of and path to - * the Excel spreadsheet file this code will create. - */ - public void demonstrateMethodCalls(String outputFilename) throws IOException { - HSSFWorkbook workbook = new HSSFWorkbook(); - try { - HSSFSheet sheet = workbook.createSheet("In Cell Lists"); - HSSFRow row = sheet.createRow(0); - - // Create a cell at A1 and insert a single, bulleted, item into - // that cell. - HSSFCell cell = row.createCell(0); - this.bulletedItemInCell(workbook, "List Item", cell); - - // Create a cell at A2 and insert a plain list - that is one - // whose items are neither bulleted or numbered - into that cell. - row = sheet.createRow(1); - cell = row.createCell(0); - ArrayList listItems = new ArrayList(); - listItems.add("List Item One."); - listItems.add("List Item Two."); - listItems.add("List Item Three."); - listItems.add("List Item Four."); - this.listInCell(workbook, listItems, cell); - // The row height and cell width are set here to ensure that the - // list may be seen. - row.setHeight((short)1100); - sheet.setColumnWidth(0, 9500); - - // Create a cell at A3 and insert a numbered list into that cell. - // Note that a couple of items have been added to the listItems - // ArrayList - row = sheet.createRow(2); - cell = row.createCell(0); - listItems.add("List Item Five."); - listItems.add("List Item Six."); - this.numberedListInCell(workbook, listItems, cell, 1, 2); - row.setHeight((short)1550); - - // Create a cell at A4 and insert a numbered list into that cell. - // Note that a couple of items have been added to the listItems - // ArrayList - row = sheet.createRow(3); - cell = row.createCell(0); - listItems.add("List Item Seven."); - listItems.add("List Item Eight."); - listItems.add("List Item Nine."); - listItems.add("List Item Ten."); - this.bulletedListInCell(workbook, listItems, cell); - row.setHeight((short)2550); - - // Insert a plain, multi-level list into cell A5. Note that - // the major difference here is that the list items are passed as - // an ArrayList of MultiLevelListItems. Note that an ArrayList - // of instances of an inner class was used here in preference to - // a Hashtable or HashMap as the ArrayList will preserve the - // ordering of the items added to it; the first item added will - // be the first item recovered and the last item added, the last - // item recovered. Alternatively, a LinkedHashMap could be used - // to preserve order. - row = sheet.createRow(4); - cell = row.createCell(0); - ArrayList multiLevelListItems = new ArrayList(); - listItems = new ArrayList(); - listItems.add("ML List Item One - Sub Item One."); - listItems.add("ML List Item One - Sub Item Two."); - listItems.add("ML List Item One - Sub Item Three."); - listItems.add("ML List Item One - Sub Item Four."); - multiLevelListItems.add(new MultiLevelListItem("List Item One.", listItems)); - // Passing either null or an empty ArrayList will signal that - // there are no lower level items associated with the top level - // item - multiLevelListItems.add(new MultiLevelListItem("List Item Two.", null)); - multiLevelListItems.add(new MultiLevelListItem("List Item Three.", null)); - listItems = new ArrayList(); - listItems.add("ML List Item Four - Sub Item One."); - listItems.add("ML List Item Four - Sub Item Two."); - listItems.add("ML List Item Four - Sub Item Three."); - multiLevelListItems.add(new MultiLevelListItem("List Item Four.", listItems)); - this.multiLevelListInCell(workbook, multiLevelListItems, cell); - row.setHeight((short)2800); - - // Insert a numbered multi-level list into cell A6. Note that the - // same ArrayList as constructed for the above plain multi-level - // list example will be re-used - row = sheet.createRow(5); - cell = row.createCell(0); - this.multiLevelNumberedListInCell(workbook, multiLevelListItems, - cell, 1, 1, 1, 2); - row.setHeight((short)2800); - - // Insert a numbered multi-level list into cell A7. Note that the - // same ArrayList as constructed for the plain multi-level list - // example will be re-used - row = sheet.createRow(6); - cell = row.createCell(0); - this.multiLevelBulletedListInCell(workbook, multiLevelListItems, cell); - row.setHeight((short)2800); - - // Save the completed workbook - FileOutputStream fos = new FileOutputStream(new File(outputFilename)); - try { - workbook.write(fos); - } finally { - fos.close(); - } - } - catch(FileNotFoundException fnfEx) { - System.out.println("Caught a: " + fnfEx.getClass().getName()); - System.out.println("Message: " + fnfEx.getMessage()); - System.out.println("Stacktrace follows..........."); - fnfEx.printStackTrace(System.out); - } - catch(IOException ioEx) { - System.out.println("Caught a: " + ioEx.getClass().getName()); - System.out.println("Message: " + ioEx.getMessage()); - System.out.println("Stacktrace follows..........."); - ioEx.printStackTrace(System.out); - } - finally { - workbook.close(); - } - } - - /** - * Inserts a single bulleted item into a cell. - * - * @param workbook A reference to the HSSFWorkbook that 'contains' the - * cell. - * @param listItem An instance of the String class encapsulating the - * items text. - * @param cell An instance of the HSSFCell class that encapsulates a - * reference to the spreadsheet cell into which the list item - * will be written. - */ - public void bulletedItemInCell(HSSFWorkbook workbook, String listItem, HSSFCell cell) { - // A format String must be built to ensure that the contents of the - // cell appear as a bulleted item. - HSSFDataFormat format = workbook.createDataFormat(); - String formatString = InCellLists.BULLET_CHARACTER + " @"; - int formatIndex = format.getFormat(formatString); - - // Construct an HSSFCellStyle and set it's data formt to use the - // object created above. - HSSFCellStyle bulletStyle = workbook.createCellStyle(); - bulletStyle.setDataFormat((short)formatIndex); - - // Set the cells contents and style. - cell.setCellValue(new HSSFRichTextString(listItem)); - cell.setCellStyle(bulletStyle); - } - - /** - * Inserts a list of plain items - that is items that are neither - * numbered or bulleted - into a single cell. - * - * @param workbook A reference to the HSSFWorkbook that 'contains' the - * cell. - * @param listItems An ArrayList whose elements encapsulate the text for - * the list's items. - * @param cell An instance of the HSSFCell class that encapsulates a - * reference to the spreadsheet cell into which the list - * will be written. - */ - public void listInCell(HSSFWorkbook workbook, ArrayList listItems, HSSFCell cell) { - StringBuilder buffer = new StringBuilder(); - HSSFCellStyle wrapStyle = workbook.createCellStyle(); - wrapStyle.setWrapText(true); - for(String listItem : listItems) { - buffer.append(listItem); - buffer.append("\n"); - } - // The StringBuffer's contents are the source for the contents - // of the cell. - cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); - cell.setCellStyle(wrapStyle); - } - - /** - * Inserts a numbered list into a single cell. - * - * @param workbook A reference to the HSSFWorkbook that 'contains' the - * cell. - * @param listItems An ArrayList whose elements encapsulate the text for - * the lists items. - * @param cell An instance of the HSSFCell class that encapsulates a - * reference to the spreadsheet cell into which the list - * will be written. - * @param startingValue A primitive int containing the number for the first - * item in the list. - * @param increment A primitive int containing the value that should be used - * to calculate subsequent item numbers. - */ - public void numberedListInCell(HSSFWorkbook workbook, - ArrayList listItems, - HSSFCell cell, - int startingValue, - int increment) { - StringBuilder buffer = new StringBuilder(); - int itemNumber = startingValue; - // Note that again, an HSSFCellStye object is required and that - // it's wrap text property should be set to 'true' - HSSFCellStyle wrapStyle = workbook.createCellStyle(); - wrapStyle.setWrapText(true); - // Note that the basic method is identical to the listInCell() method - // with one difference; a number prefixed to the items text. - for(String listItem : listItems) { - buffer.append(itemNumber).append(". "); - buffer.append(listItem); - buffer.append("\n"); - itemNumber += increment; - } - // The StringBuffer's contents are the source for the contents - // of the cell. - cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); - cell.setCellStyle(wrapStyle); - } - - /** - * Insert a bulleted list into a cell. - * - * @param workbook A reference to the HSSFWorkbook that 'contains' the - * cell. - * @param listItems An ArrayList whose elements encapsulate the text for - * the lists items. - * @param cell An instance of the HSSFCell class that encapsulates a - * reference to the spreadsheet cell into which the list - * will be written. - */ - public void bulletedListInCell(HSSFWorkbook workbook, - ArrayList listItems, - HSSFCell cell) { - StringBuilder buffer = new StringBuilder(); - // Note that again, an HSSFCellStye object is required and that - // it's wrap text property should be set to 'true' - HSSFCellStyle wrapStyle = workbook.createCellStyle(); - wrapStyle.setWrapText(true); - // Note that the basic method is identical to the listInCell() method - // with one difference; the bullet character prefixed to the items text. - for(String listItem : listItems) { - buffer.append(InCellLists.BULLET_CHARACTER + " "); - buffer.append(listItem); - buffer.append("\n"); - } - // The StringBuffer's contents are the source for the contents - // of the cell. - cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); - cell.setCellStyle(wrapStyle); - } - - /** - * Insert a multi-level list into a cell. - * - * @param workbook A reference to the HSSFWorkbook that 'contains' the - * cell. - * @param multiLevelListItems An ArrayList whose elements contain instances - * of the MultiLevelListItem class. Each element - * encapsulates the text for the high level item - * along with an ArrayList. Each element of this - * ArrayList encapsulates the text for a lower - * level item. - * @param cell An instance of the HSSFCell class that encapsulates a - * reference to the spreadsheet cell into which the list - * will be written. - */ - public void multiLevelListInCell(HSSFWorkbook workbook, - ArrayList multiLevelListItems, - HSSFCell cell) { - StringBuilder buffer = new StringBuilder(); - // Note that again, an HSSFCellStye object is required and that - // it's wrap text property should be set to 'true' - HSSFCellStyle wrapStyle = workbook.createCellStyle(); - wrapStyle.setWrapText(true); - // Step through the ArrayList of MultilLevelListItem instances. - for(MultiLevelListItem multiLevelListItem : multiLevelListItems) { - // For each element in the ArrayList, get the text for the high - // level list item...... - buffer.append(multiLevelListItem.getItemText()); - buffer.append("\n"); - // and then an ArrayList whose elements encapsulate the text - // for the lower level list items. - ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); - if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { - for(String item : lowerLevelItems) { - buffer.append(InCellLists.TAB); - buffer.append(item); - buffer.append("\n"); - } - } - } - // The StringBuffer's contents are the source for the contents - // of the cell. - cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); - cell.setCellStyle(wrapStyle); - } - - /** - * Insert a multi-level list into a cell. - * - * @param workbook A reference to the HSSFWorkbook that 'contains' the - * cell. - * @param multiLevelListItems An ArrayList whose elements contain instances - * of the MultiLevelListItem class. Each element - * encapsulates the text for the high level item - * along with an ArrayList. Each element of this - * ArrayList encapsulates the text for a lower - * level item. - * @param cell An instance of the HSSFCell class that encapsulates a - * reference to the spreadsheet cell into which the list - * will be written. - * @param highLevelStartingValue A primitive int containing the number - * for the first high level item in the list. - * @param highLevelIncrement A primitive int containing the value that - * should be used to calculate the number of - * subsequent high level item. - * @param lowLevelStartingValue A primitive int will containing the number - * for the first low level item associated - * with a high level item. - * @param lowLevelIncrement A primitive int containing the value that - * should be used to calculate the number of - * subsequent low level item. - */ - public void multiLevelNumberedListInCell(HSSFWorkbook workbook, - ArrayList multiLevelListItems, - HSSFCell cell, - int highLevelStartingValue, - int highLevelIncrement, - int lowLevelStartingValue, - int lowLevelIncrement) { - StringBuilder buffer = new StringBuilder(); - int highLevelItemNumber = highLevelStartingValue; - // Note that again, an HSSFCellStye object is required and that - // it's wrap text property should be set to 'true' - HSSFCellStyle wrapStyle = workbook.createCellStyle(); - wrapStyle.setWrapText(true); - // Step through the ArrayList of MultilLevelListItem instances. - for(MultiLevelListItem multiLevelListItem : multiLevelListItems) { - // For each element in the ArrayList, get the text for the high - // level list item...... - buffer.append(highLevelItemNumber); - buffer.append(". "); - buffer.append(multiLevelListItem.getItemText()); - buffer.append("\n"); - // and then an ArrayList whose elements encapsulate the text - // for the lower level list items. - ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); - if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { - int lowLevelItemNumber = lowLevelStartingValue; - for(String item : lowerLevelItems) { - buffer.append(InCellLists.TAB); - buffer.append(highLevelItemNumber); - buffer.append("."); - buffer.append(lowLevelItemNumber); - buffer.append(" "); - buffer.append(item); - buffer.append("\n"); - lowLevelItemNumber += lowLevelIncrement; - } - } - highLevelItemNumber += highLevelIncrement; - } - // The StringBuffer's contents are the source for the contents - // of the cell. - cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); - cell.setCellStyle(wrapStyle); - } - - /** - * Insert a bulleted multi-level list into a cell. - * - * @param workbook A reference to the HSSFWorkbook that 'contains' the - * cell. - * @param multiLevelListItems An ArrayList whose elements contain instances - * of the MultiLevelListItem class. Each element - * encapsulates the text for the high level item - * along with an ArrayList. Each element of this - * ArrayList encapsulates the text for a lower - * level item. - * @param cell An instance of the HSSFCell class that encapsulates a - * reference to the spreadsheet cell into which the list - * will be written. - */ - public void multiLevelBulletedListInCell(HSSFWorkbook workbook, - ArrayList multiLevelListItems, - HSSFCell cell) { - StringBuilder buffer = new StringBuilder(); - // Note that again, an HSSFCellStye object is required and that - // it's wrap text property should be set to 'true' - HSSFCellStyle wrapStyle = workbook.createCellStyle(); - wrapStyle.setWrapText(true); - // Step through the ArrayList of MultilLevelListItem instances. - for(MultiLevelListItem multiLevelListItem : multiLevelListItems) { - // For each element in the ArrayList, get the text for the high - // level list item...... - buffer.append(InCellLists.BULLET_CHARACTER); - buffer.append(" "); - buffer.append(multiLevelListItem.getItemText()); - buffer.append("\n"); - // and then an ArrayList whose elements encapsulate the text - // for the lower level list items. - ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); - if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { - for(String item : lowerLevelItems) { - buffer.append(InCellLists.TAB); - buffer.append(InCellLists.BULLET_CHARACTER); - buffer.append(" "); - buffer.append(item); - buffer.append("\n"); - } - } - } - // The StringBuffer's contents are the source for the contents - // of the cell. - cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); - cell.setCellStyle(wrapStyle); - } - - /** - * The main entry point to the program. Demonstrates how to call the method - * that will create an Excel workbook containing many different sorts of - * lists. - * - * @param args the command line arguments. - */ - public static void main(String[] args) throws IOException { - new InCellLists().demonstrateMethodCalls("Latest In Cell List.xls"); - } - - /** - * An instance of this inner class models an item or element in a - * multi-level list. Each multi-level list item consists of the text for the - * high level items and an ArrayList containing the text for each of the - * associated lower level items. When written into a cell, each multi-level - * list item will have this general appearance. - * - * Item One - * Sub Item One. - * Sub Item Two. - * Item Two - * Sub Item One. - * Sub Item Two. - * etc. - * - * It would be quite possible to modify this class to model much more - * complex list structures descending through two, three or even more - * levels. - */ - public final class MultiLevelListItem { - - private String itemText = null; - private ArrayList lowerLevelItems = null; - - /** - * Create a new instance of the MultiLevelListItem class using the - * following parameters. - * - * @param itemText A String that encapsulates the text for the high - * level list item. - * @param lowerLevelItems An ArrayList whose elements encapsulate the - * text for the associated lower level list - * items. - */ - public MultiLevelListItem(String itemText, ArrayList lowerLevelItems) { - this.itemText = itemText; - this.lowerLevelItems = lowerLevelItems; - } - - /** - * Get the text for the high level list item. - * - * @return A String that encapsulates the text for the high level list - * item. - */ - public String getItemText() { - return(this.itemText); - } - - /** - * Get the text for the associated lower level list items. - * - * @return An ArrayList whose elements each encapsulate the text for a - * single associated lower level list item. - */ - public ArrayList getLowerLevelItems() { - return(this.lowerLevelItems); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.hssf.usermodel.examples; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFCellStyle; +import org.apache.poi.hssf.usermodel.HSSFDataFormat; +import org.apache.poi.hssf.usermodel.HSSFRichTextString; + +/** + * This class contains code that demonstrates how to insert plain, numbered + * and bulleted lists into an Excel spreadsheet cell. + * + * Look at the code contained in the demonstrateMethodCalls() method. It calls + * other methods that create plain, numbered and bulleted single and + * multi-level lists. The demonstrateMethodCalls() method appears at the top + * of the class definition. + * + * Though different methods are provided to construct single and multi-level + * plain, numbered and bulleted lists, close examination will reveal that they + * are not strictly necessary. If the inputs to the listInCell() and + * multilLevelListInCell() methods are constructed to include the bullet + * character or the item numbers then these methods alone may be sufficient. + * + * @author Mark Beardsley [msb at apache.org] + */ +public class InCellLists { + + // This character looks like a solid, black, loser case letter 'o' + // positioned up from the base line of the text. + private static final char BULLET_CHARACTER = '\u2022'; + + // The tab character - \t - cannot be used to create a tab space + // within a cell as it is rendered as a square. Therefore, four + // spaces are used to simulate that character. + private static final String TAB = " "; + + /** + * Call each of the list creation methods. + * + * @param outputFilename A String that encapsulates the name of and path to + * the Excel spreadsheet file this code will create. + */ + public void demonstrateMethodCalls(String outputFilename) throws IOException { + HSSFWorkbook workbook = new HSSFWorkbook(); + try { + HSSFSheet sheet = workbook.createSheet("In Cell Lists"); + HSSFRow row = sheet.createRow(0); + + // Create a cell at A1 and insert a single, bulleted, item into + // that cell. + HSSFCell cell = row.createCell(0); + this.bulletedItemInCell(workbook, "List Item", cell); + + // Create a cell at A2 and insert a plain list - that is one + // whose items are neither bulleted or numbered - into that cell. + row = sheet.createRow(1); + cell = row.createCell(0); + ArrayList listItems = new ArrayList(); + listItems.add("List Item One."); + listItems.add("List Item Two."); + listItems.add("List Item Three."); + listItems.add("List Item Four."); + this.listInCell(workbook, listItems, cell); + // The row height and cell width are set here to ensure that the + // list may be seen. + row.setHeight((short)1100); + sheet.setColumnWidth(0, 9500); + + // Create a cell at A3 and insert a numbered list into that cell. + // Note that a couple of items have been added to the listItems + // ArrayList + row = sheet.createRow(2); + cell = row.createCell(0); + listItems.add("List Item Five."); + listItems.add("List Item Six."); + this.numberedListInCell(workbook, listItems, cell, 1, 2); + row.setHeight((short)1550); + + // Create a cell at A4 and insert a numbered list into that cell. + // Note that a couple of items have been added to the listItems + // ArrayList + row = sheet.createRow(3); + cell = row.createCell(0); + listItems.add("List Item Seven."); + listItems.add("List Item Eight."); + listItems.add("List Item Nine."); + listItems.add("List Item Ten."); + this.bulletedListInCell(workbook, listItems, cell); + row.setHeight((short)2550); + + // Insert a plain, multi-level list into cell A5. Note that + // the major difference here is that the list items are passed as + // an ArrayList of MultiLevelListItems. Note that an ArrayList + // of instances of an inner class was used here in preference to + // a Hashtable or HashMap as the ArrayList will preserve the + // ordering of the items added to it; the first item added will + // be the first item recovered and the last item added, the last + // item recovered. Alternatively, a LinkedHashMap could be used + // to preserve order. + row = sheet.createRow(4); + cell = row.createCell(0); + ArrayList multiLevelListItems = new ArrayList(); + listItems = new ArrayList(); + listItems.add("ML List Item One - Sub Item One."); + listItems.add("ML List Item One - Sub Item Two."); + listItems.add("ML List Item One - Sub Item Three."); + listItems.add("ML List Item One - Sub Item Four."); + multiLevelListItems.add(new MultiLevelListItem("List Item One.", listItems)); + // Passing either null or an empty ArrayList will signal that + // there are no lower level items associated with the top level + // item + multiLevelListItems.add(new MultiLevelListItem("List Item Two.", null)); + multiLevelListItems.add(new MultiLevelListItem("List Item Three.", null)); + listItems = new ArrayList(); + listItems.add("ML List Item Four - Sub Item One."); + listItems.add("ML List Item Four - Sub Item Two."); + listItems.add("ML List Item Four - Sub Item Three."); + multiLevelListItems.add(new MultiLevelListItem("List Item Four.", listItems)); + this.multiLevelListInCell(workbook, multiLevelListItems, cell); + row.setHeight((short)2800); + + // Insert a numbered multi-level list into cell A6. Note that the + // same ArrayList as constructed for the above plain multi-level + // list example will be re-used + row = sheet.createRow(5); + cell = row.createCell(0); + this.multiLevelNumberedListInCell(workbook, multiLevelListItems, + cell, 1, 1, 1, 2); + row.setHeight((short)2800); + + // Insert a numbered multi-level list into cell A7. Note that the + // same ArrayList as constructed for the plain multi-level list + // example will be re-used + row = sheet.createRow(6); + cell = row.createCell(0); + this.multiLevelBulletedListInCell(workbook, multiLevelListItems, cell); + row.setHeight((short)2800); + + // Save the completed workbook + FileOutputStream fos = new FileOutputStream(new File(outputFilename)); + try { + workbook.write(fos); + } finally { + fos.close(); + } + } + catch(FileNotFoundException fnfEx) { + System.out.println("Caught a: " + fnfEx.getClass().getName()); + System.out.println("Message: " + fnfEx.getMessage()); + System.out.println("Stacktrace follows..........."); + fnfEx.printStackTrace(System.out); + } + catch(IOException ioEx) { + System.out.println("Caught a: " + ioEx.getClass().getName()); + System.out.println("Message: " + ioEx.getMessage()); + System.out.println("Stacktrace follows..........."); + ioEx.printStackTrace(System.out); + } + finally { + workbook.close(); + } + } + + /** + * Inserts a single bulleted item into a cell. + * + * @param workbook A reference to the HSSFWorkbook that 'contains' the + * cell. + * @param listItem An instance of the String class encapsulating the + * items text. + * @param cell An instance of the HSSFCell class that encapsulates a + * reference to the spreadsheet cell into which the list item + * will be written. + */ + public void bulletedItemInCell(HSSFWorkbook workbook, String listItem, HSSFCell cell) { + // A format String must be built to ensure that the contents of the + // cell appear as a bulleted item. + HSSFDataFormat format = workbook.createDataFormat(); + String formatString = InCellLists.BULLET_CHARACTER + " @"; + int formatIndex = format.getFormat(formatString); + + // Construct an HSSFCellStyle and set it's data formt to use the + // object created above. + HSSFCellStyle bulletStyle = workbook.createCellStyle(); + bulletStyle.setDataFormat((short)formatIndex); + + // Set the cells contents and style. + cell.setCellValue(new HSSFRichTextString(listItem)); + cell.setCellStyle(bulletStyle); + } + + /** + * Inserts a list of plain items - that is items that are neither + * numbered or bulleted - into a single cell. + * + * @param workbook A reference to the HSSFWorkbook that 'contains' the + * cell. + * @param listItems An ArrayList whose elements encapsulate the text for + * the list's items. + * @param cell An instance of the HSSFCell class that encapsulates a + * reference to the spreadsheet cell into which the list + * will be written. + */ + public void listInCell(HSSFWorkbook workbook, ArrayList listItems, HSSFCell cell) { + StringBuilder buffer = new StringBuilder(); + HSSFCellStyle wrapStyle = workbook.createCellStyle(); + wrapStyle.setWrapText(true); + for(String listItem : listItems) { + buffer.append(listItem); + buffer.append("\n"); + } + // The StringBuffer's contents are the source for the contents + // of the cell. + cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); + cell.setCellStyle(wrapStyle); + } + + /** + * Inserts a numbered list into a single cell. + * + * @param workbook A reference to the HSSFWorkbook that 'contains' the + * cell. + * @param listItems An ArrayList whose elements encapsulate the text for + * the lists items. + * @param cell An instance of the HSSFCell class that encapsulates a + * reference to the spreadsheet cell into which the list + * will be written. + * @param startingValue A primitive int containing the number for the first + * item in the list. + * @param increment A primitive int containing the value that should be used + * to calculate subsequent item numbers. + */ + public void numberedListInCell(HSSFWorkbook workbook, + ArrayList listItems, + HSSFCell cell, + int startingValue, + int increment) { + StringBuilder buffer = new StringBuilder(); + int itemNumber = startingValue; + // Note that again, an HSSFCellStye object is required and that + // it's wrap text property should be set to 'true' + HSSFCellStyle wrapStyle = workbook.createCellStyle(); + wrapStyle.setWrapText(true); + // Note that the basic method is identical to the listInCell() method + // with one difference; a number prefixed to the items text. + for(String listItem : listItems) { + buffer.append(itemNumber).append(". "); + buffer.append(listItem); + buffer.append("\n"); + itemNumber += increment; + } + // The StringBuffer's contents are the source for the contents + // of the cell. + cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); + cell.setCellStyle(wrapStyle); + } + + /** + * Insert a bulleted list into a cell. + * + * @param workbook A reference to the HSSFWorkbook that 'contains' the + * cell. + * @param listItems An ArrayList whose elements encapsulate the text for + * the lists items. + * @param cell An instance of the HSSFCell class that encapsulates a + * reference to the spreadsheet cell into which the list + * will be written. + */ + public void bulletedListInCell(HSSFWorkbook workbook, + ArrayList listItems, + HSSFCell cell) { + StringBuilder buffer = new StringBuilder(); + // Note that again, an HSSFCellStye object is required and that + // it's wrap text property should be set to 'true' + HSSFCellStyle wrapStyle = workbook.createCellStyle(); + wrapStyle.setWrapText(true); + // Note that the basic method is identical to the listInCell() method + // with one difference; the bullet character prefixed to the items text. + for(String listItem : listItems) { + buffer.append(InCellLists.BULLET_CHARACTER + " "); + buffer.append(listItem); + buffer.append("\n"); + } + // The StringBuffer's contents are the source for the contents + // of the cell. + cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); + cell.setCellStyle(wrapStyle); + } + + /** + * Insert a multi-level list into a cell. + * + * @param workbook A reference to the HSSFWorkbook that 'contains' the + * cell. + * @param multiLevelListItems An ArrayList whose elements contain instances + * of the MultiLevelListItem class. Each element + * encapsulates the text for the high level item + * along with an ArrayList. Each element of this + * ArrayList encapsulates the text for a lower + * level item. + * @param cell An instance of the HSSFCell class that encapsulates a + * reference to the spreadsheet cell into which the list + * will be written. + */ + public void multiLevelListInCell(HSSFWorkbook workbook, + ArrayList multiLevelListItems, + HSSFCell cell) { + StringBuilder buffer = new StringBuilder(); + // Note that again, an HSSFCellStye object is required and that + // it's wrap text property should be set to 'true' + HSSFCellStyle wrapStyle = workbook.createCellStyle(); + wrapStyle.setWrapText(true); + // Step through the ArrayList of MultilLevelListItem instances. + for(MultiLevelListItem multiLevelListItem : multiLevelListItems) { + // For each element in the ArrayList, get the text for the high + // level list item...... + buffer.append(multiLevelListItem.getItemText()); + buffer.append("\n"); + // and then an ArrayList whose elements encapsulate the text + // for the lower level list items. + ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); + if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { + for(String item : lowerLevelItems) { + buffer.append(InCellLists.TAB); + buffer.append(item); + buffer.append("\n"); + } + } + } + // The StringBuffer's contents are the source for the contents + // of the cell. + cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); + cell.setCellStyle(wrapStyle); + } + + /** + * Insert a multi-level list into a cell. + * + * @param workbook A reference to the HSSFWorkbook that 'contains' the + * cell. + * @param multiLevelListItems An ArrayList whose elements contain instances + * of the MultiLevelListItem class. Each element + * encapsulates the text for the high level item + * along with an ArrayList. Each element of this + * ArrayList encapsulates the text for a lower + * level item. + * @param cell An instance of the HSSFCell class that encapsulates a + * reference to the spreadsheet cell into which the list + * will be written. + * @param highLevelStartingValue A primitive int containing the number + * for the first high level item in the list. + * @param highLevelIncrement A primitive int containing the value that + * should be used to calculate the number of + * subsequent high level item. + * @param lowLevelStartingValue A primitive int will containing the number + * for the first low level item associated + * with a high level item. + * @param lowLevelIncrement A primitive int containing the value that + * should be used to calculate the number of + * subsequent low level item. + */ + public void multiLevelNumberedListInCell(HSSFWorkbook workbook, + ArrayList multiLevelListItems, + HSSFCell cell, + int highLevelStartingValue, + int highLevelIncrement, + int lowLevelStartingValue, + int lowLevelIncrement) { + StringBuilder buffer = new StringBuilder(); + int highLevelItemNumber = highLevelStartingValue; + // Note that again, an HSSFCellStye object is required and that + // it's wrap text property should be set to 'true' + HSSFCellStyle wrapStyle = workbook.createCellStyle(); + wrapStyle.setWrapText(true); + // Step through the ArrayList of MultilLevelListItem instances. + for(MultiLevelListItem multiLevelListItem : multiLevelListItems) { + // For each element in the ArrayList, get the text for the high + // level list item...... + buffer.append(highLevelItemNumber); + buffer.append(". "); + buffer.append(multiLevelListItem.getItemText()); + buffer.append("\n"); + // and then an ArrayList whose elements encapsulate the text + // for the lower level list items. + ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); + if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { + int lowLevelItemNumber = lowLevelStartingValue; + for(String item : lowerLevelItems) { + buffer.append(InCellLists.TAB); + buffer.append(highLevelItemNumber); + buffer.append("."); + buffer.append(lowLevelItemNumber); + buffer.append(" "); + buffer.append(item); + buffer.append("\n"); + lowLevelItemNumber += lowLevelIncrement; + } + } + highLevelItemNumber += highLevelIncrement; + } + // The StringBuffer's contents are the source for the contents + // of the cell. + cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); + cell.setCellStyle(wrapStyle); + } + + /** + * Insert a bulleted multi-level list into a cell. + * + * @param workbook A reference to the HSSFWorkbook that 'contains' the + * cell. + * @param multiLevelListItems An ArrayList whose elements contain instances + * of the MultiLevelListItem class. Each element + * encapsulates the text for the high level item + * along with an ArrayList. Each element of this + * ArrayList encapsulates the text for a lower + * level item. + * @param cell An instance of the HSSFCell class that encapsulates a + * reference to the spreadsheet cell into which the list + * will be written. + */ + public void multiLevelBulletedListInCell(HSSFWorkbook workbook, + ArrayList multiLevelListItems, + HSSFCell cell) { + StringBuilder buffer = new StringBuilder(); + // Note that again, an HSSFCellStye object is required and that + // it's wrap text property should be set to 'true' + HSSFCellStyle wrapStyle = workbook.createCellStyle(); + wrapStyle.setWrapText(true); + // Step through the ArrayList of MultilLevelListItem instances. + for(MultiLevelListItem multiLevelListItem : multiLevelListItems) { + // For each element in the ArrayList, get the text for the high + // level list item...... + buffer.append(InCellLists.BULLET_CHARACTER); + buffer.append(" "); + buffer.append(multiLevelListItem.getItemText()); + buffer.append("\n"); + // and then an ArrayList whose elements encapsulate the text + // for the lower level list items. + ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); + if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { + for(String item : lowerLevelItems) { + buffer.append(InCellLists.TAB); + buffer.append(InCellLists.BULLET_CHARACTER); + buffer.append(" "); + buffer.append(item); + buffer.append("\n"); + } + } + } + // The StringBuffer's contents are the source for the contents + // of the cell. + cell.setCellValue(new HSSFRichTextString(buffer.toString().trim())); + cell.setCellStyle(wrapStyle); + } + + /** + * The main entry point to the program. Demonstrates how to call the method + * that will create an Excel workbook containing many different sorts of + * lists. + * + * @param args the command line arguments. + */ + public static void main(String[] args) throws IOException { + new InCellLists().demonstrateMethodCalls("Latest In Cell List.xls"); + } + + /** + * An instance of this inner class models an item or element in a + * multi-level list. Each multi-level list item consists of the text for the + * high level items and an ArrayList containing the text for each of the + * associated lower level items. When written into a cell, each multi-level + * list item will have this general appearance. + * + * Item One + * Sub Item One. + * Sub Item Two. + * Item Two + * Sub Item One. + * Sub Item Two. + * etc. + * + * It would be quite possible to modify this class to model much more + * complex list structures descending through two, three or even more + * levels. + */ + public final class MultiLevelListItem { + + private String itemText = null; + private ArrayList lowerLevelItems = null; + + /** + * Create a new instance of the MultiLevelListItem class using the + * following parameters. + * + * @param itemText A String that encapsulates the text for the high + * level list item. + * @param lowerLevelItems An ArrayList whose elements encapsulate the + * text for the associated lower level list + * items. + */ + public MultiLevelListItem(String itemText, ArrayList lowerLevelItems) { + this.itemText = itemText; + this.lowerLevelItems = lowerLevelItems; + } + + /** + * Get the text for the high level list item. + * + * @return A String that encapsulates the text for the high level list + * item. + */ + public String getItemText() { + return(this.itemText); + } + + /** + * Get the text for the associated lower level list items. + * + * @return An ArrayList whose elements each encapsulate the text for a + * single associated lower level list item. + */ + public ArrayList getLowerLevelItems() { + return(this.lowerLevelItems); + } + } +} diff --git a/src/examples/src/org/apache/poi/ss/examples/AddDimensionedImage.java b/src/examples/src/org/apache/poi/ss/examples/AddDimensionedImage.java index 227216df0d..4e644cda8b 100644 --- a/src/examples/src/org/apache/poi/ss/examples/AddDimensionedImage.java +++ b/src/examples/src/org/apache/poi/ss/examples/AddDimensionedImage.java @@ -1,1025 +1,1025 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - - -package org.apache.poi.ss.examples; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.util.Locale; - -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.util.IOUtils; - - -/** - * Demonstrates how to add an image to a worksheet and set that images size - * to a specific number of millimetres irrespective of the width of the columns - * or height of the rows. Overridden methods are provided so that the location - * of the image - the cells row and column coordinates that define the top - * left hand corners of the image - can be identified either in the familiar - * Excel manner - A1 for instance - or using POI's methodology of a column and - * row index where 0, 0 would indicate cell A1. - * - * The best way to make use of these techniques is to delay adding the image to - * the sheet until all other work has been completed. That way, the sizes of - * all rows and columns will have been adjusted - assuming that step was - * necessary. Even though the anchors type is set to prevent the image moving - * or re-sizing, this setting does not have any effect until the sheet is being - * viewed using the Excel application. - * - * The key to the process is the ClientAnchor class. It defines methods that allow - * us to define the location of an image by specifying the following; - * - * * How far - in terms of coordinate positions - the image should be inset - * from the left hand border of a cell. - * * How far - in terms of coordinate positions - the image should be inset - * from the from the top of the cell. - * * How far - in terms of coordinate positions - the right hand edge of - * the image should protrude into a cell (measured from the cells left hand - * edge to the images right hand edge). - * * How far - in terms of coordinate positions - the bottom edge of the - * image should protrude into a row (measured from the cells top edge to - * the images bottom edge). - * * The index of the column that contains the cell whose top left hand - * corner should be aligned with the top left hand corner of the image. - * * The index of the row that contains the cell whose top left hand corner - * should be aligned with the images top left hand corner. - * * The index of the column that contains the cell whose top left hand - * corner should be aligned with the images bottom right hand corner - * * The index number of the row that contains the cell whose top left - * hand corner should be aligned with the images bottom right hand corner. - * - * It can be used to add an image into cell A1, for example, in the following - * manner; - * - * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor(); - * - * anchor.setDx1(0); - * anchor.setDy1(0); - * anchor.setDx2(0); - * anchor.setDy2(0); - * anchor.setCol1(0); - * anchor.setRow1(0); - * anchor.setCol2(1); - * anchor.setRow2(1); - * - * Taken together, the first four methods define the locations of the top left - * and bottom right hand corners of the image if you imagine that the image is - * represented by a simple rectangle. The setDx1() and setDy1() methods locate - * the top left hand corner of the image while setDx2() and and Dy2() locate the - * bottom right hand corner of the image. An individual image can be inserted - * into a single cell or is can lie across many cells and the latter four methods - * are used to define just where the image should be positioned. They do this by - * again by identifying where the top left and bottom right hand corners of the - * image should be located but this time in terms of the indexes of the cells - * in which those corners should be located. The setCol1() and setRow1() methods - * together identify the cell that should contain the top left hand corner of - * the image while setCol2() and setRow2() do the same for the images bottom - * right hand corner. - * - * Knowing that, it is possible to look again at the example above and to see - * that the top left hand corner of the image will be located in cell A1 (0, 0) - * and it will be aligned with the very top left hand corner of the cell. Likewise, - * the bottom right hand corner of the image will be located in cell B2 (1, 1) and - * it will again be aligned with the top left hand corner of the cell. This has the - * effect of making the image seem to occupy the whole of cell A1. Interestingly, it - * also has an effect on the images resizing behaviour because testing has - * demonstrated that if the image is wholly contained within one cell and is not - * 'attached' for want of a better word, to a neighbouring cell, then that image - * will not increase in size in response to the user dragging the column wider - * or the cell higher. - * - * The following example demonstrates a slightly different way to insert an - * image into cell A1 and to ensure that it occupies the whole of the cell. This - * is accomplished by specifying the the images bottom right hand corner should be - * aligned with the bottom right hand corner of the cell. It is also a case - * where the image will not increase in size if the user increases the size of - * the enclosing cell - irrespective of the anchors type - but it will reduce in - * size if the cell is made smaller. - * - * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor(); - * - * anchor.setDx1(0); - * anchor.setDy1(0); - * anchor.setDx2(1023); - * anchor.setDy2(255); - * anchor.setCol1(0); - * anchor.setRow1(0); - * anchor.setCol2(0); - * anchor.setRow2(0); - * - * Note that the final four method calls all pass the same value and seem to - * indicate that the images top left hand corner is aligned with the top left - * hand corner of cell A1 and that it's bottom right hand corner is also - * aligned with the top left hand corner of cell A1. Yet, running this code - * would see the image fully occupying cell A1. That is the result of the - * values passed to parameters three and four; these I have referred to as - * determining the images coordinates within the cell. They indicate that the - * image should occupy - in order - the full width of the column and the full - * height of the row. - * - * The co-ordinate values shown are the maxima; and they are independent of - * row height/column width and of the font used. Passing 255 will always result - * in the image occupying the full height of the row and passing 1023 will - * always result in the image occupying the full width of the column. They help - * in situations where an image is larger than a column/row and must overlap - * into the next column/row. Using them does mean, however, that it is often - * necessary to perform conversions between Excels characters units, points, - * pixels and millimetres in order to establish how many rows/columns an image - * should occupy and just what the various insets ought to be. - * - * Note that the setDx1(int) and setDy1(int) methods of the ClientAchor class - * are not made use of in the code that follows. It would be fairly trivial - * however to extend this example further and provide methods that would centre - * an image within a cell or allow the user to specify that a plain border a - * fixed number of millimetres wide should wrap around the image. Those first - * two parameters would make this sort of functionality perfectly possible. - * - * Owing to the various conversions used, the actual size of the image may vary - * from that required; testing has so far found this to be in the region of - * plus or minus two millimetres. Most likely by modifying the way the - * calculations are performed - possibly using double(s) throughout and - * rounding the values at the correct point - it is likely that these errors - * could be reduced or removed. - * - * A note concerning Excels image resizing behaviour. The ClientAnchor - * class contains a method called setAnchorType(int) which can be used to - * determine how Excel will resize an image in response to the user increasing - * or decreasing the dimensions of the cell containing the image. There are - * three values that can be passed to this method; 0 = To move and size the - * image with the cell, 2 = To move but don't size the image with the cell, - * 3 = To prevent the image from moving or being resized along with the cell. If - * an image is inserted using this class and placed into a single cell then if - * the setAnchorType(int) method is called and a value of either 0 or 2 passed - * to it, the resultant resizing behaviour may be a surprise. The image will not - * grow in size of the column is made wider or the row higher but it will shrink - * if the columns width or rows height are reduced. - * - * @author Mark Beardsley [msb at apache.org] and Mark Southern [southern at scripps.edu] - * @version 1.00 5th August 2009. - * 2.00 26th February 2010. - * Ported to make use of the the SS usermodel classes. - * Ability to reuse the Drawing Patriarch so that multiple images - * can be inserted without unintentionally erasing earlier images. - * Check on image type added; i.e. jpg, jpeg or png. - * The String used to contain the files name is now converted - * into a URL. - * 2.10 17th May 2012 - * Corrected gross error that occurred when using the code with - * XSSF or SXSSF workbooks. In short, the code did not correctly - * calculate the size of the image(s) owing to the use of EMUs - * within the OOXML file format. That problem has largely been - * corrected although it should be mentioned that images are not - * sized with the same level of accuracy. Discrepancies of up to - * 2mm have been noted in testing. Further investigation will - * continue to rectify this issue. - */ -public class AddDimensionedImage { - - // Four constants that determine how - and indeed whether - the rows - // and columns an image may overlie should be expanded to accomodate that - // image. - // Passing EXPAND_ROW will result in the height of a row being increased - // to accomodate the image if it is not already larger. The image will - // be layed across one or more columns. - // Passing EXPAND_COLUMN will result in the width of the column being - // increased to accomodate the image if it is not already larger. The image - // will be layed across one or many rows. - // Passing EXPAND_ROW_AND_COLUMN will result in the height of the row - // bing increased along with the width of the column to accomdate the - // image if either is not already larger. - // Passing OVERLAY_ROW_AND_COLUMN will result in the image being layed - // over one or more rows and columns. No row or column will be resized, - // instead, code will determine how many rows and columns the image should - // overlie. - public static final int EXPAND_ROW = 1; - public static final int EXPAND_COLUMN = 2; - public static final int EXPAND_ROW_AND_COLUMN = 3; - public static final int OVERLAY_ROW_AND_COLUMN = 7; - - // Modified to support EMU - English Metric Units - used within the OOXML - // workbooks, this multoplier is used to convert between measurements in - // millimetres and in EMUs - private static final int EMU_PER_MM = 36000; - - /** - * Add an image to a worksheet. - * - * @param cellNumber A String that contains the location of the cell whose - * top left hand corner should be aligned with the top - * left hand corner of the image; for example "A1", "A2" - * etc. This is to support the familiar Excel syntax. - * Whilst images are are not actually inserted into cells - * this provides a convenient method of indicating where - * the image should be positioned on the sheet. - * @param sheet A reference to the sheet that contains the cell referenced - * above. - * @param drawing An instance of the DrawingPatriarch class. This is now - * passed into the method where it was, previously, recovered - * from the sheet in order to allow multiple pictures be - * inserted. If the patriarch was not 'cached in this manner - * each time it was created any previously positioned images - * would be simply over-written. - * @param imageFile An instance of the URL class that encapsulates the name - * of and path to the image that is to be 'inserted into' - * the sheet. - * @param reqImageWidthMM A primitive double that contains the required - * width of the image in millimetres. - * @param reqImageHeightMM A primitive double that contains the required - * height of the image in millimetres. - * @param resizeBehaviour A primitive int whose value will determine how - * the code should react if the image is larger than - * the cell referenced by the cellNumber parameter. - * Four constants are provided to determine what - * should happen; - * AddDimensionedImage.EXPAND_ROW - * AddDimensionedImage.EXPAND_COLUMN - * AddDimensionedImage.EXPAND_ROW_AND_COLUMN - * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN - * @throws java.io.FileNotFoundException If the file containing the image - * cannot be located. - * @throws java.io.IOException If a problem occurs whilst reading the file - * of image data. - * @throws java.lang.IllegalArgumentException If an invalid value is passed - * to the resizeBehaviour - * parameter. - */ - public void addImageToSheet(String cellNumber, Sheet sheet, Drawing drawing, - URL imageFile, double reqImageWidthMM, double reqImageHeightMM, - int resizeBehaviour) throws IOException, IllegalArgumentException { - // Convert the String into column and row indices then chain the - // call to the overridden addImageToSheet() method. - CellReference cellRef = new CellReference(cellNumber); - this.addImageToSheet(cellRef.getCol(), cellRef.getRow(), sheet, drawing, - imageFile, reqImageWidthMM, reqImageHeightMM,resizeBehaviour); - } - - /** - * Add an image to a worksheet. - * - * @param colNumber A primitive int that contains the index number of a - * column on the worksheet; POI column indices are zero - * based. Together with the rowNumber parameter's value, - * this parameter identifies a cell on the worksheet. The - * images top left hand corner will be aligned with the - * top left hand corner of this cell. - * @param rowNumber A primitive int that contains the index number of a row - * on the worksheet; POI row indices are zero based. - * Together with the rowNumber parameter's value, this - * parameter identifies a cell on the worksheet. The - * images top left hand corner will be aligned with the - * top left hand corner of this cell. - * @param sheet A reference to the sheet that contains the cell identified - * by the two parameters above. - * @param drawing An instance of the DrawingPatriarch class. This is now - * passed into the method where it was, previously, recovered - * from the sheet in order to allow multiple pictures be - * inserted. If the patriarch was not 'cached in this manner - * each time it was created any previously positioned images - * would be simply over-written. - * @param imageFile An instance of the URL class that encapsulates the name - * of and path to the image that is to be 'inserted into' - * the sheet. - * @param reqImageWidthMM A primitive double that contains the required - * width of the image in millimetres. - * @param reqImageHeightMM A primitive double that contains the required - * height of the image in millimetres. - * @param resizeBehaviour A primitive int whose value will determine how - * the code should react if the image is larger than - * the cell referenced by the colNumber and - * rowNumber parameters. Four constants are provided - * to determine what should happen; - * AddDimensionedImage.EXPAND_ROW - * AddDimensionedImage.EXPAND_COLUMN - * AddDimensionedImage.EXPAND_ROW_AND_COLUMN - * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN - * @throws java.io.FileNotFoundException If the file containing the image - * cannot be located. - * @throws java.io.IOException If a problem occurs whilst reading the file - * of image data. - * @throws java.lang.IllegalArgumentException If an invalid value is passed - * to the resizeBehaviour - * parameter or if the extension - * of the image file indicates that - * it is of a type that cannot - * currently be added to the worksheet. - */ - public void addImageToSheet(int colNumber, int rowNumber, Sheet sheet, Drawing drawing, - URL imageFile, double reqImageWidthMM, double reqImageHeightMM, - int resizeBehaviour) throws IOException, - IllegalArgumentException { - ClientAnchor anchor = null; - ClientAnchorDetail rowClientAnchorDetail = null; - ClientAnchorDetail colClientAnchorDetail = null; - int imageType = 0; - - // Validate the resizeBehaviour parameter. - if((resizeBehaviour != AddDimensionedImage.EXPAND_COLUMN) && - (resizeBehaviour != AddDimensionedImage.EXPAND_ROW) && - (resizeBehaviour != AddDimensionedImage.EXPAND_ROW_AND_COLUMN) && - (resizeBehaviour != AddDimensionedImage.OVERLAY_ROW_AND_COLUMN)) { - throw new IllegalArgumentException("Invalid value passed to the " + - "resizeBehaviour parameter of AddDimensionedImage.addImageToSheet()"); - } - - // Call methods to calculate how the image and sheet should be - // manipulated to accomodate the image; columns and then rows. - colClientAnchorDetail = this.fitImageToColumns(sheet, colNumber, - reqImageWidthMM, resizeBehaviour); - rowClientAnchorDetail = this.fitImageToRows(sheet, rowNumber, - reqImageHeightMM, resizeBehaviour); - - // Having determined if and how to resize the rows, columns and/or the - // image, create the ClientAnchor object to position the image on - // the worksheet. Note how the two ClientAnchorDetail records are - // interrogated to recover the row/column co-ordinates and any insets. - // The first two parameters are not used currently but could be if the - // need arose to extend the functionality of this code by adding the - // ability to specify that a clear 'border' be placed around the image. - anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor(); - - anchor.setDx1(0); - anchor.setDy1(0); - anchor.setDx2(colClientAnchorDetail.getInset()); - anchor.setDy2(rowClientAnchorDetail.getInset()); - anchor.setCol1(colClientAnchorDetail.getFromIndex()); - anchor.setRow1(rowClientAnchorDetail.getFromIndex()); - anchor.setCol2(colClientAnchorDetail.getToIndex()); - anchor.setRow2(rowClientAnchorDetail.getToIndex()); - - // For now, set the anchor type to do not move or resize the - // image as the size of the row/column is adjusted. This could easily - // become another parameter passed to the method. Please read the note - // above regarding the behaviour of image resizing. - anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE); - - // Now, add the picture to the workbook. Note that unlike the similar - // method in the HSSF Examples section, the image type is checked. First, - // the image files location is identified by interrogating the URL passed - // to the method, the images type is identified before it is added to the - // sheet. - String sURL = imageFile.toString().toLowerCase(Locale.ROOT); - if( sURL.endsWith(".png") ) { - imageType = Workbook.PICTURE_TYPE_PNG; - } - else if( sURL.endsWith(".jpg") || sURL.endsWith(".jpeg") ) { - imageType = Workbook.PICTURE_TYPE_JPEG; - } - else { - throw new IllegalArgumentException("Invalid Image file : " + - sURL); - } - int index = sheet.getWorkbook().addPicture( - IOUtils.toByteArray(imageFile.openStream()), imageType); - drawing.createPicture(anchor, index); - } - - /** - * Determines whether the sheets columns should be re-sized to accommodate - * the image, adjusts the columns width if necessary and creates then - * returns a ClientAnchorDetail object that facilitates construction of - * an ClientAnchor that will fix the image on the sheet and establish - * it's size. - * - * @param sheet A reference to the sheet that will 'contain' the image. - * @param colNumber A primitive int that contains the index number of a - * column on the sheet. - * @param reqImageWidthMM A primitive double that contains the required - * width of the image in millimetres - * @param resizeBehaviour A primitive int whose value will indicate how the - * width of the column should be adjusted if the - * required width of the image is greater than the - * width of the column. - * @return An instance of the ClientAnchorDetail class that will contain - * the index number of the column containing the cell whose top - * left hand corner also defines the top left hand corner of the - * image, the index number column containing the cell whose top - * left hand corner also defines the bottom right hand corner of - * the image and an inset that determines how far the right hand - * edge of the image can protrude into the next column - expressed - * as a specific number of coordinate positions. - */ - private ClientAnchorDetail fitImageToColumns(Sheet sheet, int colNumber, - double reqImageWidthMM, int resizeBehaviour) { - - double colWidthMM = 0.0D; - double colCoordinatesPerMM = 0.0D; - int pictureWidthCoordinates = 0; - ClientAnchorDetail colClientAnchorDetail = null; - - // Get the colum's width in millimetres - colWidthMM = ConvertImageUnits.widthUnits2Millimetres( - (short)sheet.getColumnWidth(colNumber)); - - // Check that the column's width will accomodate the image at the - // required dimension. If the width of the column is LESS than the - // required width of the image, decide how the application should - // respond - resize the column or overlay the image across one or more - // columns. - if(colWidthMM < reqImageWidthMM) { - - // Should the column's width simply be expanded? - if((resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN) || - (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) { - // Set the width of the column by converting the required image - // width from millimetres into Excel's column width units. - sheet.setColumnWidth(colNumber, - ConvertImageUnits.millimetres2WidthUnits(reqImageWidthMM)); - // To make the image occupy the full width of the column, convert - // the required width of the image into co-ordinates. This value - // will become the inset for the ClientAnchorDetail class that - // is then instantiated. - if(sheet instanceof HSSFSheet) { - colWidthMM = reqImageWidthMM; - colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / - colWidthMM; - pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM); - - } - else { - pictureWidthCoordinates = (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM; - } - colClientAnchorDetail = new ClientAnchorDetail(colNumber, - colNumber, pictureWidthCoordinates); - } - // If the user has chosen to overlay both rows and columns or just - // to expand ONLY the size of the rows, then calculate how to lay - // the image out across one or more columns. - else if ((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) || - (resizeBehaviour == AddDimensionedImage.EXPAND_ROW)) { - colClientAnchorDetail = this.calculateColumnLocation(sheet, - colNumber, reqImageWidthMM); - } - } - // If the column is wider than the image. - else { - if(sheet instanceof HSSFSheet) { - // Mow many co-ordinate positions are there per millimetre? - colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / - colWidthMM; - // Given the width of the image, what should be it's co-ordinate? - pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM); - } - else { - pictureWidthCoordinates = (int)reqImageWidthMM * - AddDimensionedImage.EMU_PER_MM; - } - colClientAnchorDetail = new ClientAnchorDetail(colNumber, - colNumber, pictureWidthCoordinates); - } - return(colClientAnchorDetail); - } - - /** - * Determines whether the sheets row should be re-sized to accomodate - * the image, adjusts the rows height if necessary and creates then - * returns a ClientAnchorDetail object that facilitates construction of - * a ClientAnchor that will fix the image on the sheet and establish - * it's size. - * - * @param sheet A reference to the sheet that will 'contain' the image. - * @param rowNumber A primitive int that contains the index number of a - * row on the sheet. - * @param reqImageHeightMM A primitive double that contains the required - * height of the image in millimetres - * @param resizeBehaviour A primitive int whose value will indicate how the - * height of the row should be adjusted if the - * required height of the image is greater than the - * height of the row. - * @return An instance of the ClientAnchorDetail class that will contain - * the index number of the row containing the cell whose top - * left hand corner also defines the top left hand corner of the - * image, the index number of the row containing the cell whose - * top left hand corner also defines the bottom right hand - * corner of the image and an inset that determines how far the - * bottom edge of the image can protrude into the next (lower) - * row - expressed as a specific number of coordinate positions. - */ - private ClientAnchorDetail fitImageToRows(Sheet sheet, int rowNumber, - double reqImageHeightMM, int resizeBehaviour) { - Row row = null; - double rowHeightMM = 0.0D; - double rowCoordinatesPerMM = 0.0D; - int pictureHeightCoordinates = 0; - ClientAnchorDetail rowClientAnchorDetail = null; - - // Get the row and it's height - row = sheet.getRow(rowNumber); - if(row == null) { - // Create row if it does not exist. - row = sheet.createRow(rowNumber); - } - - // Get the row's height in millimetres - rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE; - - // Check that the row's height will accomodate the image at the required - // dimensions. If the height of the row is LESS than the required height - // of the image, decide how the application should respond - resize the - // row or overlay the image across a series of rows. - if(rowHeightMM < reqImageHeightMM) { - if((resizeBehaviour == AddDimensionedImage.EXPAND_ROW) || - (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) { - row.setHeightInPoints((float)(reqImageHeightMM * - ConvertImageUnits.POINTS_PER_MILLIMETRE)); - if(sheet instanceof HSSFSheet) { - rowHeightMM = reqImageHeightMM; - rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / - rowHeightMM; - pictureHeightCoordinates = (int)(reqImageHeightMM * - rowCoordinatesPerMM); - } - else { - pictureHeightCoordinates = (int)(reqImageHeightMM * - AddDimensionedImage.EMU_PER_MM); - } - rowClientAnchorDetail = new ClientAnchorDetail(rowNumber, - rowNumber, pictureHeightCoordinates); - } - // If the user has chosen to overlay both rows and columns or just - // to expand ONLY the size of the columns, then calculate how to lay - // the image out ver one or more rows. - else if((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) || - (resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN)) { - rowClientAnchorDetail = this.calculateRowLocation(sheet, - rowNumber, reqImageHeightMM); - } - } - // Else, if the image is smaller than the space available - else { - if(sheet instanceof HSSFSheet) { - rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / - rowHeightMM; - pictureHeightCoordinates = (int)(reqImageHeightMM * rowCoordinatesPerMM); - } - else { - pictureHeightCoordinates = (int)(reqImageHeightMM * - AddDimensionedImage.EMU_PER_MM); - } - rowClientAnchorDetail = new ClientAnchorDetail(rowNumber, - rowNumber, pictureHeightCoordinates); - } - return(rowClientAnchorDetail); - } - - /** - * If the image is to overlie more than one column, calculations need to be - * performed to determine how many columns and whether the image will - * overlie just a part of one column in order to be presented at the - * required size. - * - * @param sheet The sheet that will 'contain' the image. - * @param startingColumn A primitive int whose value is the index of the - * column that contains the cell whose top left hand - * corner should be aligned with the top left hand - * corner of the image. - * @param reqImageWidthMM A primitive double whose value will indicate the - * required width of the image in millimetres. - * @return An instance of the ClientAnchorDetail class that will contain - * the index number of the column containing the cell whose top - * left hand corner also defines the top left hand corner of the - * image, the index number column containing the cell whose top - * left hand corner also defines the bottom right hand corner of - * the image and an inset that determines how far the right hand - * edge of the image can protrude into the next column - expressed - * as a specific number of coordinate positions. - */ - private ClientAnchorDetail calculateColumnLocation(Sheet sheet, - int startingColumn, - double reqImageWidthMM) { - ClientAnchorDetail anchorDetail = null; - double totalWidthMM = 0.0D; - double colWidthMM = 0.0D; - double overlapMM = 0.0D; - double coordinatePositionsPerMM = 0.0D; - int toColumn = startingColumn; - int inset = 0; - - // Calculate how many columns the image will have to - // span in order to be presented at the required size. - while(totalWidthMM < reqImageWidthMM) { - colWidthMM = ConvertImageUnits.widthUnits2Millimetres( - (short)(sheet.getColumnWidth(toColumn))); - // Note use of the cell border width constant. Testing with an image - // declared to fit exactly into one column demonstrated that it's - // width was greater than the width of the column the POI returned. - // Further, this difference was a constant value that I am assuming - // related to the cell's borders. Either way, that difference needs - // to be allowed for in this calculation. - totalWidthMM += (colWidthMM + ConvertImageUnits.CELL_BORDER_WIDTH_MILLIMETRES); - toColumn++; - } - // De-crement by one the last column value. - toColumn--; - // Highly unlikely that this will be true but, if the width of a series - // of columns is exactly equal to the required width of the image, then - // simply build a ClientAnchorDetail object with an inset equal to the - // total number of co-ordinate positions available in a column, a - // from column co-ordinate (top left hand corner) equal to the value - // of the startingColumn parameter and a to column co-ordinate equal - // to the toColumn variable. - // - // Convert both values to ints to perform the test. - if((int)totalWidthMM == (int)reqImageWidthMM) { - // A problem could occur if the image is sized to fit into one or - // more columns. If that occurs, the value in the toColumn variable - // will be in error. To overcome this, there are two options, to - // ibcrement the toColumn variable's value by one or to pass the - // total number of co-ordinate positions to the third paramater - // of the ClientAnchorDetail constructor. For no sepcific reason, - // the latter option is used below. - if(sheet instanceof HSSFSheet) { - anchorDetail = new ClientAnchorDetail(startingColumn, - toColumn, ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS); - } - else { - anchorDetail = new ClientAnchorDetail(startingColumn, - toColumn, (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM); - } - } - // In this case, the image will overlap part of another column and it is - // necessary to calculate just how much - this will become the inset - // for the ClientAnchorDetail object. - else { - // Firstly, claculate how much of the image should overlap into - // the next column. - overlapMM = reqImageWidthMM - (totalWidthMM - colWidthMM); - - // When the required size is very close indded to the column size, - // the calcaulation above can produce a negative value. To prevent - // problems occuring in later caculations, this is simply removed - // be setting the overlapMM value to zero. - if(overlapMM < 0) { - overlapMM = 0.0D; - } - - if(sheet instanceof HSSFSheet) { - // Next, from the columns width, calculate how many co-ordinate - // positons there are per millimetre - coordinatePositionsPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / - colWidthMM; - // From this figure, determine how many co-ordinat positions to - // inset the left hand or bottom edge of the image. - inset = (int)(coordinatePositionsPerMM * overlapMM); - } - else { - inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM; - } - - // Now create the ClientAnchorDetail object, setting the from and to - // columns and the inset. - anchorDetail = new ClientAnchorDetail(startingColumn, toColumn, inset); - } - return(anchorDetail); - } - - /** - * If the image is to overlie more than one rows, calculations need to be - * performed to determine how many rows and whether the image will - * overlie just a part of one row in order to be presented at the - * required size. - * - * @param sheet The sheet that will 'contain' the image. - * @param startingRow A primitive int whose value is the index of the row - * that contains the cell whose top left hand corner - * should be aligned with the top left hand corner of - * the image. - * @param reqImageHeightMM A primitive double whose value will indicate the - * required height of the image in millimetres. - * @return An instance of the ClientAnchorDetail class that will contain - * the index number of the row containing the cell whose top - * left hand corner also defines the top left hand corner of the - * image, the index number of the row containing the cell whose top - * left hand corner also defines the bottom right hand corner of - * the image and an inset that determines how far the bottom edge - * can protrude into the next (lower) row - expressed as a specific - * number of co-ordinate positions. - */ - private ClientAnchorDetail calculateRowLocation(Sheet sheet, - int startingRow, double reqImageHeightMM) { - ClientAnchorDetail clientAnchorDetail = null; - Row row = null; - double rowHeightMM = 0.0D; - double totalRowHeightMM = 0.0D; - double overlapMM = 0.0D; - double rowCoordinatesPerMM = 0.0D; - int toRow = startingRow; - int inset = 0; - - // Step through the rows in the sheet and accumulate a total of their - // heights. - while(totalRowHeightMM < reqImageHeightMM) { - row = sheet.getRow(toRow); - // Note, if the row does not already exist on the sheet then create - // it here. - if(row == null) { - row = sheet.createRow(toRow); - } - // Get the row's height in millimetres and add to the running total. - rowHeightMM = row.getHeightInPoints() / - ConvertImageUnits.POINTS_PER_MILLIMETRE; - totalRowHeightMM += rowHeightMM; - toRow++; - } - // Owing to the way the loop above works, the rowNumber will have been - // incremented one row too far. Undo that here. - toRow--; - // Check to see whether the image should occupy an exact number of - // rows. If so, build the ClientAnchorDetail record to point - // to those rows and with an inset of the total number of co-ordinate - // position in the row. - // - // To overcome problems that can occur with comparing double values for - // equality, cast both to int(s) to truncate the value; VERY crude and - // I do not really like it!! - if((int)totalRowHeightMM == (int)reqImageHeightMM) { - if(sheet instanceof HSSFSheet) { - clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow, - ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS); - } - else { - clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow, - (int)reqImageHeightMM * AddDimensionedImage.EMU_PER_MM); - } - } - else { - // Calculate how far the image will project into the next row. Note - // that the height of the last row assessed is subtracted from the - // total height of all rows assessed so far. - overlapMM = reqImageHeightMM - (totalRowHeightMM - rowHeightMM); - - // To prevent an exception being thrown when the required width of - // the image is very close indeed to the column size. - if(overlapMM < 0) { - overlapMM = 0.0D; - } - - if(sheet instanceof HSSFSheet) { - rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / - rowHeightMM; - inset = (int)(overlapMM * rowCoordinatesPerMM); - } - else { - inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM; - } - clientAnchorDetail = new ClientAnchorDetail(startingRow, - toRow, inset); - } - return(clientAnchorDetail); - } - - /** - * The main entry point to the program. It contains code that demonstrates - * one way to use the program. - * - * Note, the code is not restricted to use on new workbooks only. If an - * image is to be inserted into an existing workbook. just open that - * workbook, gat a reference to a sheet and pass that; - * - * AddDimensionedImage addImage = new AddDimensionedImage(); - * - * File file = new File("....... Existing Workbook ......."); - * FileInputStream fis = new FileInputStream(file); - * Workbook workbook = new HSSFWorkbook(fis); - * HSSFSheet sheet = workbook.getSheetAt(0); - * addImage.addImageToSheet("C3", sheet, "image.jpg", 30, 20, - * AddDimensionedImage.EXPAND.ROW); - * - * @param args the command line arguments - */ - public static void main(String[] args) throws IOException { - String imageFile = null; - String outputFile = null; - FileOutputStream fos = null; - Workbook workbook = null; - Sheet sheet = null; - - if(args.length < 2){ - System.err.println("Usage: AddDimensionedImage imageFile outputFile"); - return; - } - workbook = new HSSFWorkbook(); // OR XSSFWorkbook - sheet = workbook.createSheet("Picture Test"); - imageFile = args[0]; - outputFile = args[1]; - new AddDimensionedImage().addImageToSheet("B5", sheet, sheet.createDrawingPatriarch(), - new File(imageFile).toURI().toURL(), 100, 40, - AddDimensionedImage.EXPAND_ROW_AND_COLUMN); - fos = new FileOutputStream(outputFile); - workbook.write(fos); - fos.close(); - workbook.close(); - } - - /** - * The HSSFClientAnchor class accepts eight arguments. In order, these are; - * - * * How far the left hand edge of the image is inset from the left hand - * edge of the cell - * * How far the top edge of the image is inset from the top of the cell - * * How far the right hand edge of the image is inset from the left - * hand edge of the cell - * * How far the bottom edge of the image is inset from the top of the - * cell. - * * Together, arguments five and six determine the column and row - * coordinates of the cell whose top left hand corner will be aligned - * with the images top left hand corner. - * * Together, arguments seven and eight determine the column and row - * coordinates of the cell whose top left hand corner will be aligned - * with the images bottom right hand corner. - * - * An instance of the ClientAnchorDetail class provides three of the eight - * parameters, one of the coordinates for the images top left hand corner, - * one of the coordinates for the images bottom right hand corner and - * either how far the image should be inset from the top or the left hand - * edge of the cell. - * - * @author Mark Beardsley [msb at apache.org] - * @version 1.00 5th August 2009. - */ - public class ClientAnchorDetail { - - public int fromIndex = 0; - public int toIndex = 0; - public int inset = 0; - - /** - * Create a new instance of the ClientAnchorDetail class using the - * following parameters. - * - * @param fromIndex A primitive int that contains one of the - * coordinates (row or column index) for the top left - * hand corner of the image. - * @param toIndex A primitive int that contains one of the - * coordinates (row or column index) for the bottom - * right hand corner of the image. - * @param inset A primitive int that contains a value which indicates - * how far the image should be inset from the top or the - * left hand edge of a cell. - */ - public ClientAnchorDetail(int fromIndex, int toIndex, int inset) { - this.fromIndex = fromIndex; - this.toIndex = toIndex; - this.inset = inset; - } - - /** - * Get one of the number of the column or row that contains the cell - * whose top left hand corner will be aligned with the top left hand - * corner of the image. - * - * @return The value - row or column index - for one of the coordinates - * of the top left hand corner of the image. - */ - public int getFromIndex() { - return(this.fromIndex); - } - - /** - * Get one of the number of the column or row that contains the cell - * whose top left hand corner will be aligned with the bottom right hand - * corner of the image. - * - * @return The value - row or column index - for one of the coordinates - * of the bottom right hand corner of the image. - */ - public int getToIndex() { - return(this.toIndex); - } - - /** - * Get the images offset from the edge of a cell. - * - * @return How far either the right hand or bottom edge of the image is - * inset from the left hand or top edge of a cell. - */ - public int getInset() { - return(this.inset); - } - } - - /** - * Utility methods used to convert Excels character based column and row - * size measurements into pixels and/or millimetres. The class also contains - * various constants that are required in other calculations. - * - * @author xio[darjino@hotmail.com] - * @version 1.01 30th July 2009. - * Added by Mark Beardsley [msb at apache.org]. - * Additional constants. - * widthUnits2Millimetres() and millimetres2Units() methods. - */ - public static class ConvertImageUnits { - - // Each cell conatins a fixed number of co-ordinate points; this number - // does not vary with row height or column width or with font. These two - // constants are defined below. - public static final int TOTAL_COLUMN_COORDINATE_POSITIONS = 1023; // MB - public static final int TOTAL_ROW_COORDINATE_POSITIONS = 255; // MB - // The resoultion of an image can be expressed as a specific number - // of pixels per inch. Displays and printers differ but 96 pixels per - // inch is an acceptable standard to beging with. - public static final int PIXELS_PER_INCH = 96; // MB - // Cnstants that defines how many pixels and points there are in a - // millimetre. These values are required for the conversion algorithm. - public static final double PIXELS_PER_MILLIMETRES = 3.78; // MB - public static final double POINTS_PER_MILLIMETRE = 2.83; // MB - // The column width returned by HSSF and the width of a picture when - // positioned to exactly cover one cell are different by almost exactly - // 2mm - give or take rounding errors. This constant allows that - // additional amount to be accounted for when calculating how many - // celles the image ought to overlie. - public static final double CELL_BORDER_WIDTH_MILLIMETRES = 2.0D; // MB - public static final short EXCEL_COLUMN_WIDTH_FACTOR = 256; - public static final int UNIT_OFFSET_LENGTH = 7; - public static final int[] UNIT_OFFSET_MAP = new int[] - { 0, 36, 73, 109, 146, 182, 219 }; - - /** - * pixel units to excel width units(units of 1/256th of a character width) - * @param pxs - * @return - */ - public static short pixel2WidthUnits(int pxs) { - short widthUnits = (short) (EXCEL_COLUMN_WIDTH_FACTOR * - (pxs / UNIT_OFFSET_LENGTH)); - widthUnits += UNIT_OFFSET_MAP[(pxs % UNIT_OFFSET_LENGTH)]; - return widthUnits; - } - - /** - * excel width units(units of 1/256th of a character width) to pixel - * units. - * - * @param widthUnits - * @return - */ - public static int widthUnits2Pixel(short widthUnits) { - int pixels = (widthUnits / EXCEL_COLUMN_WIDTH_FACTOR) - * UNIT_OFFSET_LENGTH; - int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR; - pixels += Math.round(offsetWidthUnits / - ((float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH)); - return pixels; - } - - /** - * Convert Excels width units into millimetres. - * - * @param widthUnits The width of the column or the height of the - * row in Excels units. - * @return A primitive double that contains the columns width or rows - * height in millimetres. - */ - public static double widthUnits2Millimetres(short widthUnits) { - return(ConvertImageUnits.widthUnits2Pixel(widthUnits) / - ConvertImageUnits.PIXELS_PER_MILLIMETRES); - } - - /** - * Convert into millimetres Excels width units.. - * - * @param millimetres A primitive double that contains the columns - * width or rows height in millimetres. - * @return A primitive int that contains the columns width or rows - * height in Excels units. - */ - public static int millimetres2WidthUnits(double millimetres) { - return(ConvertImageUnits.pixel2WidthUnits((int)(millimetres * - ConvertImageUnits.PIXELS_PER_MILLIMETRES))); - } - - public static int pointsToPixels(double points) { - return (int) Math.round(points / 72D * PIXELS_PER_INCH); - } - - public static double pointsToMillimeters(double points) { - return points / 72D * 25.4; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.ss.examples; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Locale; + +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.util.IOUtils; + + +/** + * Demonstrates how to add an image to a worksheet and set that images size + * to a specific number of millimetres irrespective of the width of the columns + * or height of the rows. Overridden methods are provided so that the location + * of the image - the cells row and column coordinates that define the top + * left hand corners of the image - can be identified either in the familiar + * Excel manner - A1 for instance - or using POI's methodology of a column and + * row index where 0, 0 would indicate cell A1. + * + * The best way to make use of these techniques is to delay adding the image to + * the sheet until all other work has been completed. That way, the sizes of + * all rows and columns will have been adjusted - assuming that step was + * necessary. Even though the anchors type is set to prevent the image moving + * or re-sizing, this setting does not have any effect until the sheet is being + * viewed using the Excel application. + * + * The key to the process is the ClientAnchor class. It defines methods that allow + * us to define the location of an image by specifying the following; + * + * * How far - in terms of coordinate positions - the image should be inset + * from the left hand border of a cell. + * * How far - in terms of coordinate positions - the image should be inset + * from the from the top of the cell. + * * How far - in terms of coordinate positions - the right hand edge of + * the image should protrude into a cell (measured from the cells left hand + * edge to the images right hand edge). + * * How far - in terms of coordinate positions - the bottom edge of the + * image should protrude into a row (measured from the cells top edge to + * the images bottom edge). + * * The index of the column that contains the cell whose top left hand + * corner should be aligned with the top left hand corner of the image. + * * The index of the row that contains the cell whose top left hand corner + * should be aligned with the images top left hand corner. + * * The index of the column that contains the cell whose top left hand + * corner should be aligned with the images bottom right hand corner + * * The index number of the row that contains the cell whose top left + * hand corner should be aligned with the images bottom right hand corner. + * + * It can be used to add an image into cell A1, for example, in the following + * manner; + * + * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor(); + * + * anchor.setDx1(0); + * anchor.setDy1(0); + * anchor.setDx2(0); + * anchor.setDy2(0); + * anchor.setCol1(0); + * anchor.setRow1(0); + * anchor.setCol2(1); + * anchor.setRow2(1); + * + * Taken together, the first four methods define the locations of the top left + * and bottom right hand corners of the image if you imagine that the image is + * represented by a simple rectangle. The setDx1() and setDy1() methods locate + * the top left hand corner of the image while setDx2() and and Dy2() locate the + * bottom right hand corner of the image. An individual image can be inserted + * into a single cell or is can lie across many cells and the latter four methods + * are used to define just where the image should be positioned. They do this by + * again by identifying where the top left and bottom right hand corners of the + * image should be located but this time in terms of the indexes of the cells + * in which those corners should be located. The setCol1() and setRow1() methods + * together identify the cell that should contain the top left hand corner of + * the image while setCol2() and setRow2() do the same for the images bottom + * right hand corner. + * + * Knowing that, it is possible to look again at the example above and to see + * that the top left hand corner of the image will be located in cell A1 (0, 0) + * and it will be aligned with the very top left hand corner of the cell. Likewise, + * the bottom right hand corner of the image will be located in cell B2 (1, 1) and + * it will again be aligned with the top left hand corner of the cell. This has the + * effect of making the image seem to occupy the whole of cell A1. Interestingly, it + * also has an effect on the images resizing behaviour because testing has + * demonstrated that if the image is wholly contained within one cell and is not + * 'attached' for want of a better word, to a neighbouring cell, then that image + * will not increase in size in response to the user dragging the column wider + * or the cell higher. + * + * The following example demonstrates a slightly different way to insert an + * image into cell A1 and to ensure that it occupies the whole of the cell. This + * is accomplished by specifying the the images bottom right hand corner should be + * aligned with the bottom right hand corner of the cell. It is also a case + * where the image will not increase in size if the user increases the size of + * the enclosing cell - irrespective of the anchors type - but it will reduce in + * size if the cell is made smaller. + * + * ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor(); + * + * anchor.setDx1(0); + * anchor.setDy1(0); + * anchor.setDx2(1023); + * anchor.setDy2(255); + * anchor.setCol1(0); + * anchor.setRow1(0); + * anchor.setCol2(0); + * anchor.setRow2(0); + * + * Note that the final four method calls all pass the same value and seem to + * indicate that the images top left hand corner is aligned with the top left + * hand corner of cell A1 and that it's bottom right hand corner is also + * aligned with the top left hand corner of cell A1. Yet, running this code + * would see the image fully occupying cell A1. That is the result of the + * values passed to parameters three and four; these I have referred to as + * determining the images coordinates within the cell. They indicate that the + * image should occupy - in order - the full width of the column and the full + * height of the row. + * + * The co-ordinate values shown are the maxima; and they are independent of + * row height/column width and of the font used. Passing 255 will always result + * in the image occupying the full height of the row and passing 1023 will + * always result in the image occupying the full width of the column. They help + * in situations where an image is larger than a column/row and must overlap + * into the next column/row. Using them does mean, however, that it is often + * necessary to perform conversions between Excels characters units, points, + * pixels and millimetres in order to establish how many rows/columns an image + * should occupy and just what the various insets ought to be. + * + * Note that the setDx1(int) and setDy1(int) methods of the ClientAchor class + * are not made use of in the code that follows. It would be fairly trivial + * however to extend this example further and provide methods that would centre + * an image within a cell or allow the user to specify that a plain border a + * fixed number of millimetres wide should wrap around the image. Those first + * two parameters would make this sort of functionality perfectly possible. + * + * Owing to the various conversions used, the actual size of the image may vary + * from that required; testing has so far found this to be in the region of + * plus or minus two millimetres. Most likely by modifying the way the + * calculations are performed - possibly using double(s) throughout and + * rounding the values at the correct point - it is likely that these errors + * could be reduced or removed. + * + * A note concerning Excels image resizing behaviour. The ClientAnchor + * class contains a method called setAnchorType(int) which can be used to + * determine how Excel will resize an image in response to the user increasing + * or decreasing the dimensions of the cell containing the image. There are + * three values that can be passed to this method; 0 = To move and size the + * image with the cell, 2 = To move but don't size the image with the cell, + * 3 = To prevent the image from moving or being resized along with the cell. If + * an image is inserted using this class and placed into a single cell then if + * the setAnchorType(int) method is called and a value of either 0 or 2 passed + * to it, the resultant resizing behaviour may be a surprise. The image will not + * grow in size of the column is made wider or the row higher but it will shrink + * if the columns width or rows height are reduced. + * + * @author Mark Beardsley [msb at apache.org] and Mark Southern [southern at scripps.edu] + * @version 1.00 5th August 2009. + * 2.00 26th February 2010. + * Ported to make use of the the SS usermodel classes. + * Ability to reuse the Drawing Patriarch so that multiple images + * can be inserted without unintentionally erasing earlier images. + * Check on image type added; i.e. jpg, jpeg or png. + * The String used to contain the files name is now converted + * into a URL. + * 2.10 17th May 2012 + * Corrected gross error that occurred when using the code with + * XSSF or SXSSF workbooks. In short, the code did not correctly + * calculate the size of the image(s) owing to the use of EMUs + * within the OOXML file format. That problem has largely been + * corrected although it should be mentioned that images are not + * sized with the same level of accuracy. Discrepancies of up to + * 2mm have been noted in testing. Further investigation will + * continue to rectify this issue. + */ +public class AddDimensionedImage { + + // Four constants that determine how - and indeed whether - the rows + // and columns an image may overlie should be expanded to accomodate that + // image. + // Passing EXPAND_ROW will result in the height of a row being increased + // to accomodate the image if it is not already larger. The image will + // be layed across one or more columns. + // Passing EXPAND_COLUMN will result in the width of the column being + // increased to accomodate the image if it is not already larger. The image + // will be layed across one or many rows. + // Passing EXPAND_ROW_AND_COLUMN will result in the height of the row + // bing increased along with the width of the column to accomdate the + // image if either is not already larger. + // Passing OVERLAY_ROW_AND_COLUMN will result in the image being layed + // over one or more rows and columns. No row or column will be resized, + // instead, code will determine how many rows and columns the image should + // overlie. + public static final int EXPAND_ROW = 1; + public static final int EXPAND_COLUMN = 2; + public static final int EXPAND_ROW_AND_COLUMN = 3; + public static final int OVERLAY_ROW_AND_COLUMN = 7; + + // Modified to support EMU - English Metric Units - used within the OOXML + // workbooks, this multoplier is used to convert between measurements in + // millimetres and in EMUs + private static final int EMU_PER_MM = 36000; + + /** + * Add an image to a worksheet. + * + * @param cellNumber A String that contains the location of the cell whose + * top left hand corner should be aligned with the top + * left hand corner of the image; for example "A1", "A2" + * etc. This is to support the familiar Excel syntax. + * Whilst images are are not actually inserted into cells + * this provides a convenient method of indicating where + * the image should be positioned on the sheet. + * @param sheet A reference to the sheet that contains the cell referenced + * above. + * @param drawing An instance of the DrawingPatriarch class. This is now + * passed into the method where it was, previously, recovered + * from the sheet in order to allow multiple pictures be + * inserted. If the patriarch was not 'cached in this manner + * each time it was created any previously positioned images + * would be simply over-written. + * @param imageFile An instance of the URL class that encapsulates the name + * of and path to the image that is to be 'inserted into' + * the sheet. + * @param reqImageWidthMM A primitive double that contains the required + * width of the image in millimetres. + * @param reqImageHeightMM A primitive double that contains the required + * height of the image in millimetres. + * @param resizeBehaviour A primitive int whose value will determine how + * the code should react if the image is larger than + * the cell referenced by the cellNumber parameter. + * Four constants are provided to determine what + * should happen; + * AddDimensionedImage.EXPAND_ROW + * AddDimensionedImage.EXPAND_COLUMN + * AddDimensionedImage.EXPAND_ROW_AND_COLUMN + * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN + * @throws java.io.FileNotFoundException If the file containing the image + * cannot be located. + * @throws java.io.IOException If a problem occurs whilst reading the file + * of image data. + * @throws java.lang.IllegalArgumentException If an invalid value is passed + * to the resizeBehaviour + * parameter. + */ + public void addImageToSheet(String cellNumber, Sheet sheet, Drawing drawing, + URL imageFile, double reqImageWidthMM, double reqImageHeightMM, + int resizeBehaviour) throws IOException, IllegalArgumentException { + // Convert the String into column and row indices then chain the + // call to the overridden addImageToSheet() method. + CellReference cellRef = new CellReference(cellNumber); + this.addImageToSheet(cellRef.getCol(), cellRef.getRow(), sheet, drawing, + imageFile, reqImageWidthMM, reqImageHeightMM,resizeBehaviour); + } + + /** + * Add an image to a worksheet. + * + * @param colNumber A primitive int that contains the index number of a + * column on the worksheet; POI column indices are zero + * based. Together with the rowNumber parameter's value, + * this parameter identifies a cell on the worksheet. The + * images top left hand corner will be aligned with the + * top left hand corner of this cell. + * @param rowNumber A primitive int that contains the index number of a row + * on the worksheet; POI row indices are zero based. + * Together with the rowNumber parameter's value, this + * parameter identifies a cell on the worksheet. The + * images top left hand corner will be aligned with the + * top left hand corner of this cell. + * @param sheet A reference to the sheet that contains the cell identified + * by the two parameters above. + * @param drawing An instance of the DrawingPatriarch class. This is now + * passed into the method where it was, previously, recovered + * from the sheet in order to allow multiple pictures be + * inserted. If the patriarch was not 'cached in this manner + * each time it was created any previously positioned images + * would be simply over-written. + * @param imageFile An instance of the URL class that encapsulates the name + * of and path to the image that is to be 'inserted into' + * the sheet. + * @param reqImageWidthMM A primitive double that contains the required + * width of the image in millimetres. + * @param reqImageHeightMM A primitive double that contains the required + * height of the image in millimetres. + * @param resizeBehaviour A primitive int whose value will determine how + * the code should react if the image is larger than + * the cell referenced by the colNumber and + * rowNumber parameters. Four constants are provided + * to determine what should happen; + * AddDimensionedImage.EXPAND_ROW + * AddDimensionedImage.EXPAND_COLUMN + * AddDimensionedImage.EXPAND_ROW_AND_COLUMN + * AddDimensionedImage.OVERLAY_ROW_AND_COLUMN + * @throws java.io.FileNotFoundException If the file containing the image + * cannot be located. + * @throws java.io.IOException If a problem occurs whilst reading the file + * of image data. + * @throws java.lang.IllegalArgumentException If an invalid value is passed + * to the resizeBehaviour + * parameter or if the extension + * of the image file indicates that + * it is of a type that cannot + * currently be added to the worksheet. + */ + public void addImageToSheet(int colNumber, int rowNumber, Sheet sheet, Drawing drawing, + URL imageFile, double reqImageWidthMM, double reqImageHeightMM, + int resizeBehaviour) throws IOException, + IllegalArgumentException { + ClientAnchor anchor = null; + ClientAnchorDetail rowClientAnchorDetail = null; + ClientAnchorDetail colClientAnchorDetail = null; + int imageType = 0; + + // Validate the resizeBehaviour parameter. + if((resizeBehaviour != AddDimensionedImage.EXPAND_COLUMN) && + (resizeBehaviour != AddDimensionedImage.EXPAND_ROW) && + (resizeBehaviour != AddDimensionedImage.EXPAND_ROW_AND_COLUMN) && + (resizeBehaviour != AddDimensionedImage.OVERLAY_ROW_AND_COLUMN)) { + throw new IllegalArgumentException("Invalid value passed to the " + + "resizeBehaviour parameter of AddDimensionedImage.addImageToSheet()"); + } + + // Call methods to calculate how the image and sheet should be + // manipulated to accomodate the image; columns and then rows. + colClientAnchorDetail = this.fitImageToColumns(sheet, colNumber, + reqImageWidthMM, resizeBehaviour); + rowClientAnchorDetail = this.fitImageToRows(sheet, rowNumber, + reqImageHeightMM, resizeBehaviour); + + // Having determined if and how to resize the rows, columns and/or the + // image, create the ClientAnchor object to position the image on + // the worksheet. Note how the two ClientAnchorDetail records are + // interrogated to recover the row/column co-ordinates and any insets. + // The first two parameters are not used currently but could be if the + // need arose to extend the functionality of this code by adding the + // ability to specify that a clear 'border' be placed around the image. + anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor(); + + anchor.setDx1(0); + anchor.setDy1(0); + anchor.setDx2(colClientAnchorDetail.getInset()); + anchor.setDy2(rowClientAnchorDetail.getInset()); + anchor.setCol1(colClientAnchorDetail.getFromIndex()); + anchor.setRow1(rowClientAnchorDetail.getFromIndex()); + anchor.setCol2(colClientAnchorDetail.getToIndex()); + anchor.setRow2(rowClientAnchorDetail.getToIndex()); + + // For now, set the anchor type to do not move or resize the + // image as the size of the row/column is adjusted. This could easily + // become another parameter passed to the method. Please read the note + // above regarding the behaviour of image resizing. + anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE); + + // Now, add the picture to the workbook. Note that unlike the similar + // method in the HSSF Examples section, the image type is checked. First, + // the image files location is identified by interrogating the URL passed + // to the method, the images type is identified before it is added to the + // sheet. + String sURL = imageFile.toString().toLowerCase(Locale.ROOT); + if( sURL.endsWith(".png") ) { + imageType = Workbook.PICTURE_TYPE_PNG; + } + else if( sURL.endsWith(".jpg") || sURL.endsWith(".jpeg") ) { + imageType = Workbook.PICTURE_TYPE_JPEG; + } + else { + throw new IllegalArgumentException("Invalid Image file : " + + sURL); + } + int index = sheet.getWorkbook().addPicture( + IOUtils.toByteArray(imageFile.openStream()), imageType); + drawing.createPicture(anchor, index); + } + + /** + * Determines whether the sheets columns should be re-sized to accommodate + * the image, adjusts the columns width if necessary and creates then + * returns a ClientAnchorDetail object that facilitates construction of + * an ClientAnchor that will fix the image on the sheet and establish + * it's size. + * + * @param sheet A reference to the sheet that will 'contain' the image. + * @param colNumber A primitive int that contains the index number of a + * column on the sheet. + * @param reqImageWidthMM A primitive double that contains the required + * width of the image in millimetres + * @param resizeBehaviour A primitive int whose value will indicate how the + * width of the column should be adjusted if the + * required width of the image is greater than the + * width of the column. + * @return An instance of the ClientAnchorDetail class that will contain + * the index number of the column containing the cell whose top + * left hand corner also defines the top left hand corner of the + * image, the index number column containing the cell whose top + * left hand corner also defines the bottom right hand corner of + * the image and an inset that determines how far the right hand + * edge of the image can protrude into the next column - expressed + * as a specific number of coordinate positions. + */ + private ClientAnchorDetail fitImageToColumns(Sheet sheet, int colNumber, + double reqImageWidthMM, int resizeBehaviour) { + + double colWidthMM = 0.0D; + double colCoordinatesPerMM = 0.0D; + int pictureWidthCoordinates = 0; + ClientAnchorDetail colClientAnchorDetail = null; + + // Get the colum's width in millimetres + colWidthMM = ConvertImageUnits.widthUnits2Millimetres( + (short)sheet.getColumnWidth(colNumber)); + + // Check that the column's width will accomodate the image at the + // required dimension. If the width of the column is LESS than the + // required width of the image, decide how the application should + // respond - resize the column or overlay the image across one or more + // columns. + if(colWidthMM < reqImageWidthMM) { + + // Should the column's width simply be expanded? + if((resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN) || + (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) { + // Set the width of the column by converting the required image + // width from millimetres into Excel's column width units. + sheet.setColumnWidth(colNumber, + ConvertImageUnits.millimetres2WidthUnits(reqImageWidthMM)); + // To make the image occupy the full width of the column, convert + // the required width of the image into co-ordinates. This value + // will become the inset for the ClientAnchorDetail class that + // is then instantiated. + if(sheet instanceof HSSFSheet) { + colWidthMM = reqImageWidthMM; + colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / + colWidthMM; + pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM); + + } + else { + pictureWidthCoordinates = (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM; + } + colClientAnchorDetail = new ClientAnchorDetail(colNumber, + colNumber, pictureWidthCoordinates); + } + // If the user has chosen to overlay both rows and columns or just + // to expand ONLY the size of the rows, then calculate how to lay + // the image out across one or more columns. + else if ((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) || + (resizeBehaviour == AddDimensionedImage.EXPAND_ROW)) { + colClientAnchorDetail = this.calculateColumnLocation(sheet, + colNumber, reqImageWidthMM); + } + } + // If the column is wider than the image. + else { + if(sheet instanceof HSSFSheet) { + // Mow many co-ordinate positions are there per millimetre? + colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / + colWidthMM; + // Given the width of the image, what should be it's co-ordinate? + pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM); + } + else { + pictureWidthCoordinates = (int)reqImageWidthMM * + AddDimensionedImage.EMU_PER_MM; + } + colClientAnchorDetail = new ClientAnchorDetail(colNumber, + colNumber, pictureWidthCoordinates); + } + return(colClientAnchorDetail); + } + + /** + * Determines whether the sheets row should be re-sized to accomodate + * the image, adjusts the rows height if necessary and creates then + * returns a ClientAnchorDetail object that facilitates construction of + * a ClientAnchor that will fix the image on the sheet and establish + * it's size. + * + * @param sheet A reference to the sheet that will 'contain' the image. + * @param rowNumber A primitive int that contains the index number of a + * row on the sheet. + * @param reqImageHeightMM A primitive double that contains the required + * height of the image in millimetres + * @param resizeBehaviour A primitive int whose value will indicate how the + * height of the row should be adjusted if the + * required height of the image is greater than the + * height of the row. + * @return An instance of the ClientAnchorDetail class that will contain + * the index number of the row containing the cell whose top + * left hand corner also defines the top left hand corner of the + * image, the index number of the row containing the cell whose + * top left hand corner also defines the bottom right hand + * corner of the image and an inset that determines how far the + * bottom edge of the image can protrude into the next (lower) + * row - expressed as a specific number of coordinate positions. + */ + private ClientAnchorDetail fitImageToRows(Sheet sheet, int rowNumber, + double reqImageHeightMM, int resizeBehaviour) { + Row row = null; + double rowHeightMM = 0.0D; + double rowCoordinatesPerMM = 0.0D; + int pictureHeightCoordinates = 0; + ClientAnchorDetail rowClientAnchorDetail = null; + + // Get the row and it's height + row = sheet.getRow(rowNumber); + if(row == null) { + // Create row if it does not exist. + row = sheet.createRow(rowNumber); + } + + // Get the row's height in millimetres + rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE; + + // Check that the row's height will accomodate the image at the required + // dimensions. If the height of the row is LESS than the required height + // of the image, decide how the application should respond - resize the + // row or overlay the image across a series of rows. + if(rowHeightMM < reqImageHeightMM) { + if((resizeBehaviour == AddDimensionedImage.EXPAND_ROW) || + (resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) { + row.setHeightInPoints((float)(reqImageHeightMM * + ConvertImageUnits.POINTS_PER_MILLIMETRE)); + if(sheet instanceof HSSFSheet) { + rowHeightMM = reqImageHeightMM; + rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / + rowHeightMM; + pictureHeightCoordinates = (int)(reqImageHeightMM * + rowCoordinatesPerMM); + } + else { + pictureHeightCoordinates = (int)(reqImageHeightMM * + AddDimensionedImage.EMU_PER_MM); + } + rowClientAnchorDetail = new ClientAnchorDetail(rowNumber, + rowNumber, pictureHeightCoordinates); + } + // If the user has chosen to overlay both rows and columns or just + // to expand ONLY the size of the columns, then calculate how to lay + // the image out ver one or more rows. + else if((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) || + (resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN)) { + rowClientAnchorDetail = this.calculateRowLocation(sheet, + rowNumber, reqImageHeightMM); + } + } + // Else, if the image is smaller than the space available + else { + if(sheet instanceof HSSFSheet) { + rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / + rowHeightMM; + pictureHeightCoordinates = (int)(reqImageHeightMM * rowCoordinatesPerMM); + } + else { + pictureHeightCoordinates = (int)(reqImageHeightMM * + AddDimensionedImage.EMU_PER_MM); + } + rowClientAnchorDetail = new ClientAnchorDetail(rowNumber, + rowNumber, pictureHeightCoordinates); + } + return(rowClientAnchorDetail); + } + + /** + * If the image is to overlie more than one column, calculations need to be + * performed to determine how many columns and whether the image will + * overlie just a part of one column in order to be presented at the + * required size. + * + * @param sheet The sheet that will 'contain' the image. + * @param startingColumn A primitive int whose value is the index of the + * column that contains the cell whose top left hand + * corner should be aligned with the top left hand + * corner of the image. + * @param reqImageWidthMM A primitive double whose value will indicate the + * required width of the image in millimetres. + * @return An instance of the ClientAnchorDetail class that will contain + * the index number of the column containing the cell whose top + * left hand corner also defines the top left hand corner of the + * image, the index number column containing the cell whose top + * left hand corner also defines the bottom right hand corner of + * the image and an inset that determines how far the right hand + * edge of the image can protrude into the next column - expressed + * as a specific number of coordinate positions. + */ + private ClientAnchorDetail calculateColumnLocation(Sheet sheet, + int startingColumn, + double reqImageWidthMM) { + ClientAnchorDetail anchorDetail = null; + double totalWidthMM = 0.0D; + double colWidthMM = 0.0D; + double overlapMM = 0.0D; + double coordinatePositionsPerMM = 0.0D; + int toColumn = startingColumn; + int inset = 0; + + // Calculate how many columns the image will have to + // span in order to be presented at the required size. + while(totalWidthMM < reqImageWidthMM) { + colWidthMM = ConvertImageUnits.widthUnits2Millimetres( + (short)(sheet.getColumnWidth(toColumn))); + // Note use of the cell border width constant. Testing with an image + // declared to fit exactly into one column demonstrated that it's + // width was greater than the width of the column the POI returned. + // Further, this difference was a constant value that I am assuming + // related to the cell's borders. Either way, that difference needs + // to be allowed for in this calculation. + totalWidthMM += (colWidthMM + ConvertImageUnits.CELL_BORDER_WIDTH_MILLIMETRES); + toColumn++; + } + // De-crement by one the last column value. + toColumn--; + // Highly unlikely that this will be true but, if the width of a series + // of columns is exactly equal to the required width of the image, then + // simply build a ClientAnchorDetail object with an inset equal to the + // total number of co-ordinate positions available in a column, a + // from column co-ordinate (top left hand corner) equal to the value + // of the startingColumn parameter and a to column co-ordinate equal + // to the toColumn variable. + // + // Convert both values to ints to perform the test. + if((int)totalWidthMM == (int)reqImageWidthMM) { + // A problem could occur if the image is sized to fit into one or + // more columns. If that occurs, the value in the toColumn variable + // will be in error. To overcome this, there are two options, to + // ibcrement the toColumn variable's value by one or to pass the + // total number of co-ordinate positions to the third paramater + // of the ClientAnchorDetail constructor. For no sepcific reason, + // the latter option is used below. + if(sheet instanceof HSSFSheet) { + anchorDetail = new ClientAnchorDetail(startingColumn, + toColumn, ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS); + } + else { + anchorDetail = new ClientAnchorDetail(startingColumn, + toColumn, (int)reqImageWidthMM * AddDimensionedImage.EMU_PER_MM); + } + } + // In this case, the image will overlap part of another column and it is + // necessary to calculate just how much - this will become the inset + // for the ClientAnchorDetail object. + else { + // Firstly, claculate how much of the image should overlap into + // the next column. + overlapMM = reqImageWidthMM - (totalWidthMM - colWidthMM); + + // When the required size is very close indded to the column size, + // the calcaulation above can produce a negative value. To prevent + // problems occuring in later caculations, this is simply removed + // be setting the overlapMM value to zero. + if(overlapMM < 0) { + overlapMM = 0.0D; + } + + if(sheet instanceof HSSFSheet) { + // Next, from the columns width, calculate how many co-ordinate + // positons there are per millimetre + coordinatePositionsPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / + colWidthMM; + // From this figure, determine how many co-ordinat positions to + // inset the left hand or bottom edge of the image. + inset = (int)(coordinatePositionsPerMM * overlapMM); + } + else { + inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM; + } + + // Now create the ClientAnchorDetail object, setting the from and to + // columns and the inset. + anchorDetail = new ClientAnchorDetail(startingColumn, toColumn, inset); + } + return(anchorDetail); + } + + /** + * If the image is to overlie more than one rows, calculations need to be + * performed to determine how many rows and whether the image will + * overlie just a part of one row in order to be presented at the + * required size. + * + * @param sheet The sheet that will 'contain' the image. + * @param startingRow A primitive int whose value is the index of the row + * that contains the cell whose top left hand corner + * should be aligned with the top left hand corner of + * the image. + * @param reqImageHeightMM A primitive double whose value will indicate the + * required height of the image in millimetres. + * @return An instance of the ClientAnchorDetail class that will contain + * the index number of the row containing the cell whose top + * left hand corner also defines the top left hand corner of the + * image, the index number of the row containing the cell whose top + * left hand corner also defines the bottom right hand corner of + * the image and an inset that determines how far the bottom edge + * can protrude into the next (lower) row - expressed as a specific + * number of co-ordinate positions. + */ + private ClientAnchorDetail calculateRowLocation(Sheet sheet, + int startingRow, double reqImageHeightMM) { + ClientAnchorDetail clientAnchorDetail = null; + Row row = null; + double rowHeightMM = 0.0D; + double totalRowHeightMM = 0.0D; + double overlapMM = 0.0D; + double rowCoordinatesPerMM = 0.0D; + int toRow = startingRow; + int inset = 0; + + // Step through the rows in the sheet and accumulate a total of their + // heights. + while(totalRowHeightMM < reqImageHeightMM) { + row = sheet.getRow(toRow); + // Note, if the row does not already exist on the sheet then create + // it here. + if(row == null) { + row = sheet.createRow(toRow); + } + // Get the row's height in millimetres and add to the running total. + rowHeightMM = row.getHeightInPoints() / + ConvertImageUnits.POINTS_PER_MILLIMETRE; + totalRowHeightMM += rowHeightMM; + toRow++; + } + // Owing to the way the loop above works, the rowNumber will have been + // incremented one row too far. Undo that here. + toRow--; + // Check to see whether the image should occupy an exact number of + // rows. If so, build the ClientAnchorDetail record to point + // to those rows and with an inset of the total number of co-ordinate + // position in the row. + // + // To overcome problems that can occur with comparing double values for + // equality, cast both to int(s) to truncate the value; VERY crude and + // I do not really like it!! + if((int)totalRowHeightMM == (int)reqImageHeightMM) { + if(sheet instanceof HSSFSheet) { + clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow, + ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS); + } + else { + clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow, + (int)reqImageHeightMM * AddDimensionedImage.EMU_PER_MM); + } + } + else { + // Calculate how far the image will project into the next row. Note + // that the height of the last row assessed is subtracted from the + // total height of all rows assessed so far. + overlapMM = reqImageHeightMM - (totalRowHeightMM - rowHeightMM); + + // To prevent an exception being thrown when the required width of + // the image is very close indeed to the column size. + if(overlapMM < 0) { + overlapMM = 0.0D; + } + + if(sheet instanceof HSSFSheet) { + rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / + rowHeightMM; + inset = (int)(overlapMM * rowCoordinatesPerMM); + } + else { + inset = (int)overlapMM * AddDimensionedImage.EMU_PER_MM; + } + clientAnchorDetail = new ClientAnchorDetail(startingRow, + toRow, inset); + } + return(clientAnchorDetail); + } + + /** + * The main entry point to the program. It contains code that demonstrates + * one way to use the program. + * + * Note, the code is not restricted to use on new workbooks only. If an + * image is to be inserted into an existing workbook. just open that + * workbook, gat a reference to a sheet and pass that; + * + * AddDimensionedImage addImage = new AddDimensionedImage(); + * + * File file = new File("....... Existing Workbook ......."); + * FileInputStream fis = new FileInputStream(file); + * Workbook workbook = new HSSFWorkbook(fis); + * HSSFSheet sheet = workbook.getSheetAt(0); + * addImage.addImageToSheet("C3", sheet, "image.jpg", 30, 20, + * AddDimensionedImage.EXPAND.ROW); + * + * @param args the command line arguments + */ + public static void main(String[] args) throws IOException { + String imageFile = null; + String outputFile = null; + FileOutputStream fos = null; + Workbook workbook = null; + Sheet sheet = null; + + if(args.length < 2){ + System.err.println("Usage: AddDimensionedImage imageFile outputFile"); + return; + } + workbook = new HSSFWorkbook(); // OR XSSFWorkbook + sheet = workbook.createSheet("Picture Test"); + imageFile = args[0]; + outputFile = args[1]; + new AddDimensionedImage().addImageToSheet("B5", sheet, sheet.createDrawingPatriarch(), + new File(imageFile).toURI().toURL(), 100, 40, + AddDimensionedImage.EXPAND_ROW_AND_COLUMN); + fos = new FileOutputStream(outputFile); + workbook.write(fos); + fos.close(); + workbook.close(); + } + + /** + * The HSSFClientAnchor class accepts eight arguments. In order, these are; + * + * * How far the left hand edge of the image is inset from the left hand + * edge of the cell + * * How far the top edge of the image is inset from the top of the cell + * * How far the right hand edge of the image is inset from the left + * hand edge of the cell + * * How far the bottom edge of the image is inset from the top of the + * cell. + * * Together, arguments five and six determine the column and row + * coordinates of the cell whose top left hand corner will be aligned + * with the images top left hand corner. + * * Together, arguments seven and eight determine the column and row + * coordinates of the cell whose top left hand corner will be aligned + * with the images bottom right hand corner. + * + * An instance of the ClientAnchorDetail class provides three of the eight + * parameters, one of the coordinates for the images top left hand corner, + * one of the coordinates for the images bottom right hand corner and + * either how far the image should be inset from the top or the left hand + * edge of the cell. + * + * @author Mark Beardsley [msb at apache.org] + * @version 1.00 5th August 2009. + */ + public class ClientAnchorDetail { + + public int fromIndex = 0; + public int toIndex = 0; + public int inset = 0; + + /** + * Create a new instance of the ClientAnchorDetail class using the + * following parameters. + * + * @param fromIndex A primitive int that contains one of the + * coordinates (row or column index) for the top left + * hand corner of the image. + * @param toIndex A primitive int that contains one of the + * coordinates (row or column index) for the bottom + * right hand corner of the image. + * @param inset A primitive int that contains a value which indicates + * how far the image should be inset from the top or the + * left hand edge of a cell. + */ + public ClientAnchorDetail(int fromIndex, int toIndex, int inset) { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + this.inset = inset; + } + + /** + * Get one of the number of the column or row that contains the cell + * whose top left hand corner will be aligned with the top left hand + * corner of the image. + * + * @return The value - row or column index - for one of the coordinates + * of the top left hand corner of the image. + */ + public int getFromIndex() { + return(this.fromIndex); + } + + /** + * Get one of the number of the column or row that contains the cell + * whose top left hand corner will be aligned with the bottom right hand + * corner of the image. + * + * @return The value - row or column index - for one of the coordinates + * of the bottom right hand corner of the image. + */ + public int getToIndex() { + return(this.toIndex); + } + + /** + * Get the images offset from the edge of a cell. + * + * @return How far either the right hand or bottom edge of the image is + * inset from the left hand or top edge of a cell. + */ + public int getInset() { + return(this.inset); + } + } + + /** + * Utility methods used to convert Excels character based column and row + * size measurements into pixels and/or millimetres. The class also contains + * various constants that are required in other calculations. + * + * @author xio[darjino@hotmail.com] + * @version 1.01 30th July 2009. + * Added by Mark Beardsley [msb at apache.org]. + * Additional constants. + * widthUnits2Millimetres() and millimetres2Units() methods. + */ + public static class ConvertImageUnits { + + // Each cell conatins a fixed number of co-ordinate points; this number + // does not vary with row height or column width or with font. These two + // constants are defined below. + public static final int TOTAL_COLUMN_COORDINATE_POSITIONS = 1023; // MB + public static final int TOTAL_ROW_COORDINATE_POSITIONS = 255; // MB + // The resoultion of an image can be expressed as a specific number + // of pixels per inch. Displays and printers differ but 96 pixels per + // inch is an acceptable standard to beging with. + public static final int PIXELS_PER_INCH = 96; // MB + // Cnstants that defines how many pixels and points there are in a + // millimetre. These values are required for the conversion algorithm. + public static final double PIXELS_PER_MILLIMETRES = 3.78; // MB + public static final double POINTS_PER_MILLIMETRE = 2.83; // MB + // The column width returned by HSSF and the width of a picture when + // positioned to exactly cover one cell are different by almost exactly + // 2mm - give or take rounding errors. This constant allows that + // additional amount to be accounted for when calculating how many + // celles the image ought to overlie. + public static final double CELL_BORDER_WIDTH_MILLIMETRES = 2.0D; // MB + public static final short EXCEL_COLUMN_WIDTH_FACTOR = 256; + public static final int UNIT_OFFSET_LENGTH = 7; + public static final int[] UNIT_OFFSET_MAP = new int[] + { 0, 36, 73, 109, 146, 182, 219 }; + + /** + * pixel units to excel width units(units of 1/256th of a character width) + * @param pxs + * @return + */ + public static short pixel2WidthUnits(int pxs) { + short widthUnits = (short) (EXCEL_COLUMN_WIDTH_FACTOR * + (pxs / UNIT_OFFSET_LENGTH)); + widthUnits += UNIT_OFFSET_MAP[(pxs % UNIT_OFFSET_LENGTH)]; + return widthUnits; + } + + /** + * excel width units(units of 1/256th of a character width) to pixel + * units. + * + * @param widthUnits + * @return + */ + public static int widthUnits2Pixel(short widthUnits) { + int pixels = (widthUnits / EXCEL_COLUMN_WIDTH_FACTOR) + * UNIT_OFFSET_LENGTH; + int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR; + pixels += Math.round(offsetWidthUnits / + ((float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH)); + return pixels; + } + + /** + * Convert Excels width units into millimetres. + * + * @param widthUnits The width of the column or the height of the + * row in Excels units. + * @return A primitive double that contains the columns width or rows + * height in millimetres. + */ + public static double widthUnits2Millimetres(short widthUnits) { + return(ConvertImageUnits.widthUnits2Pixel(widthUnits) / + ConvertImageUnits.PIXELS_PER_MILLIMETRES); + } + + /** + * Convert into millimetres Excels width units.. + * + * @param millimetres A primitive double that contains the columns + * width or rows height in millimetres. + * @return A primitive int that contains the columns width or rows + * height in Excels units. + */ + public static int millimetres2WidthUnits(double millimetres) { + return(ConvertImageUnits.pixel2WidthUnits((int)(millimetres * + ConvertImageUnits.PIXELS_PER_MILLIMETRES))); + } + + public static int pointsToPixels(double points) { + return (int) Math.round(points / 72D * PIXELS_PER_INCH); + } + + public static double pointsToMillimeters(double points) { + return points / 72D * 25.4; + } + } +} diff --git a/src/examples/src/org/apache/poi/ss/examples/AligningCells.java b/src/examples/src/org/apache/poi/ss/examples/AligningCells.java index 8ee6440fdc..c767f24d96 100644 --- a/src/examples/src/org/apache/poi/ss/examples/AligningCells.java +++ b/src/examples/src/org/apache/poi/ss/examples/AligningCells.java @@ -1,75 +1,75 @@ -/* ==================================================================== -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==================================================================== */ -package org.apache.poi.ss.examples; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -/** - * Shows how various alignment options work. - */ -public class AligningCells { - - public static void main(String[] args) throws IOException { - Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook(); - - Sheet sheet = wb.createSheet(); - Row row = sheet.createRow(2); - row.setHeightInPoints(30); - for (int i = 0; i < 8; i++) { - //column width is set in units of 1/256th of a character width - sheet.setColumnWidth(i, 256 * 15); - } - - createCell(wb, row, 0, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); - createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM); - createCell(wb, row, 2, HorizontalAlignment.FILL, VerticalAlignment.CENTER); - createCell(wb, row, 3, HorizontalAlignment.GENERAL, VerticalAlignment.CENTER); - createCell(wb, row, 4, HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY); - createCell(wb, row, 5, HorizontalAlignment.LEFT, VerticalAlignment.TOP); - createCell(wb, row, 6, HorizontalAlignment.RIGHT, VerticalAlignment.TOP); - - // Write the output to a file - OutputStream fileOut = new FileOutputStream("ss-example-align.xlsx"); - wb.write(fileOut); - fileOut.close(); - - wb.close(); - } - - /** - * Creates a cell and aligns it a certain way. - * - * @param wb the workbook - * @param row the row to create the cell in - * @param column the column number to create the cell in - * @param halign the horizontal alignment for the cell. - */ - private static void createCell(Workbook wb, Row row, int column, HorizontalAlignment halign, VerticalAlignment valign) { - CreationHelper ch = wb.getCreationHelper(); - Cell cell = row.createCell(column); - cell.setCellValue(ch.createRichTextString("Align It")); - CellStyle cellStyle = wb.createCellStyle(); - cellStyle.setAlignment(halign); - cellStyle.setVerticalAlignment(valign); - cell.setCellStyle(cellStyle); - } +/* ==================================================================== +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==================================================================== */ +package org.apache.poi.ss.examples; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Shows how various alignment options work. + */ +public class AligningCells { + + public static void main(String[] args) throws IOException { + Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook(); + + Sheet sheet = wb.createSheet(); + Row row = sheet.createRow(2); + row.setHeightInPoints(30); + for (int i = 0; i < 8; i++) { + //column width is set in units of 1/256th of a character width + sheet.setColumnWidth(i, 256 * 15); + } + + createCell(wb, row, 0, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + createCell(wb, row, 1, HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM); + createCell(wb, row, 2, HorizontalAlignment.FILL, VerticalAlignment.CENTER); + createCell(wb, row, 3, HorizontalAlignment.GENERAL, VerticalAlignment.CENTER); + createCell(wb, row, 4, HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY); + createCell(wb, row, 5, HorizontalAlignment.LEFT, VerticalAlignment.TOP); + createCell(wb, row, 6, HorizontalAlignment.RIGHT, VerticalAlignment.TOP); + + // Write the output to a file + OutputStream fileOut = new FileOutputStream("ss-example-align.xlsx"); + wb.write(fileOut); + fileOut.close(); + + wb.close(); + } + + /** + * Creates a cell and aligns it a certain way. + * + * @param wb the workbook + * @param row the row to create the cell in + * @param column the column number to create the cell in + * @param halign the horizontal alignment for the cell. + */ + private static void createCell(Workbook wb, Row row, int column, HorizontalAlignment halign, VerticalAlignment valign) { + CreationHelper ch = wb.getCreationHelper(); + Cell cell = row.createCell(column); + cell.setCellValue(ch.createRichTextString("Align It")); + CellStyle cellStyle = wb.createCellStyle(); + cellStyle.setAlignment(halign); + cellStyle.setVerticalAlignment(valign); + cell.setCellStyle(cellStyle); + } } \ No newline at end of file diff --git a/src/examples/src/org/apache/poi/ss/examples/CellStyleDetails.java b/src/examples/src/org/apache/poi/ss/examples/CellStyleDetails.java index 7bf8c55e85..55b85a291b 100644 --- a/src/examples/src/org/apache/poi/ss/examples/CellStyleDetails.java +++ b/src/examples/src/org/apache/poi/ss/examples/CellStyleDetails.java @@ -1,96 +1,96 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.examples; - -import java.io.File; - -import org.apache.poi.hssf.usermodel.HSSFFont; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.hssf.util.HSSFColor; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.DataFormatter; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookFactory; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.usermodel.XSSFColor; -import org.apache.poi.xssf.usermodel.XSSFFont; - -/** - * Demonstrates how to read excel styles for cells - */ -public class CellStyleDetails { - public static void main(String[] args) throws Exception { - if(args.length == 0) { - throw new IllegalArgumentException("Filename must be given"); - } - - Workbook wb = WorkbookFactory.create(new File(args[0])); - DataFormatter formatter = new DataFormatter(); - - for(int sn=0; sn - * Partly based on the code snippets from - * http://www.contextures.com/xlcondformat03.html - *

- */ -public class ConditionalFormats { - - public static void main(String[] args) throws IOException { - Workbook wb; - - if(args.length > 0 && args[0].equals("-xls")) { - wb = new HSSFWorkbook(); - } else { - wb = new XSSFWorkbook(); - } - - sameCell(wb.createSheet("Same Cell")); - multiCell(wb.createSheet("MultiCell")); - overlapping(wb.createSheet("Overlapping")); - errors(wb.createSheet("Errors")); - hideDupplicates(wb.createSheet("Hide Dups")); - formatDuplicates(wb.createSheet("Duplicates")); - inList(wb.createSheet("In List")); - expiry(wb.createSheet("Expiry")); - shadeAlt(wb.createSheet("Shade Alt")); - shadeBands(wb.createSheet("Shade Bands")); - iconSets(wb.createSheet("Icon Sets")); - colourScales(wb.createSheet("Colour Scales")); - dataBars(wb.createSheet("Data Bars")); - - // Write the output to a file - String file = "cf-poi.xls"; - if(wb instanceof XSSFWorkbook) { - file += "x"; - } - FileOutputStream out = new FileOutputStream(file); - wb.write(out); - out.close(); - System.out.println("Generated: " + file); - wb.close(); - } - - /** - * Highlight cells based on their values - */ - static void sameCell(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue(84); - sheet.createRow(1).createCell(0).setCellValue(74); - sheet.createRow(2).createCell(0).setCellValue(50); - sheet.createRow(3).createCell(0).setCellValue(51); - sheet.createRow(4).createCell(0).setCellValue(49); - sheet.createRow(5).createCell(0).setCellValue(41); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Cell Value Is greater than 70 (Blue Fill) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(ComparisonOperator.GT, "70"); - PatternFormatting fill1 = rule1.createPatternFormatting(); - fill1.setFillBackgroundColor(IndexedColors.BLUE.index); - fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - // Condition 2: Cell Value Is less than 50 (Green Fill) - ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.LT, "50"); - PatternFormatting fill2 = rule2.createPatternFormatting(); - fill2.setFillBackgroundColor(IndexedColors.GREEN.index); - fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A1:A6") - }; - - sheetCF.addConditionalFormatting(regions, rule1, rule2); - - sheet.getRow(0).createCell(2).setCellValue("<== Condition 1: Cell Value Is greater than 70 (Blue Fill)"); - sheet.getRow(4).createCell(2).setCellValue("<== Condition 2: Cell Value Is less than 50 (Green Fill)"); - } - - /** - * Highlight multiple cells based on a formula - */ - static void multiCell(Sheet sheet) { - // header row - Row row0 = sheet.createRow(0); - row0.createCell(0).setCellValue("Units"); - row0.createCell(1).setCellValue("Cost"); - row0.createCell(2).setCellValue("Total"); - - Row row1 = sheet.createRow(1); - row1.createCell(0).setCellValue(71); - row1.createCell(1).setCellValue(29); - row1.createCell(2).setCellValue(2059); - - Row row2 = sheet.createRow(2); - row2.createCell(0).setCellValue(85); - row2.createCell(1).setCellValue(29); - row2.createCell(2).setCellValue(2059); - - Row row3 = sheet.createRow(3); - row3.createCell(0).setCellValue(71); - row3.createCell(1).setCellValue(29); - row3.createCell(2).setCellValue(2059); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Formula Is =$B2>75 (Blue Fill) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("$A2>75"); - PatternFormatting fill1 = rule1.createPatternFormatting(); - fill1.setFillBackgroundColor(IndexedColors.BLUE.index); - fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A2:C4") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.getRow(2).createCell(4).setCellValue("<== Condition 1: Formula Is =$B2>75 (Blue Fill)"); - } - - /** - * Multiple conditional formatting rules can apply to - * one cell, some combining, some beating others. - * Done in order of the rules added to the - * SheetConditionalFormatting object - */ - static void overlapping(Sheet sheet) { - for (int i=0; i<40; i++) { - int rn = i+1; - Row r = sheet.createRow(i); - r.createCell(0).setCellValue("This is row " + rn + " (" + i + ")"); - String str = ""; - if (rn%2 == 0) { - str = str + "even "; - } - if (rn%3 == 0) { - str = str + "x3 "; - } - if (rn%5 == 0) { - str = str + "x5 "; - } - if (rn%10 == 0) { - str = str + "x10 "; - } - if (str.length() == 0) { - str = "nothing special..."; - } - r.createCell(1).setCellValue("It is " + str); - } - sheet.autoSizeColumn(0); - sheet.autoSizeColumn(1); - - sheet.getRow(1).createCell(3).setCellValue("Even rows are blue"); - sheet.getRow(2).createCell(3).setCellValue("Multiples of 3 have a grey background"); - sheet.getRow(4).createCell(3).setCellValue("Multiples of 5 are bold"); - sheet.getRow(9).createCell(3).setCellValue("Multiples of 10 are red (beats even)"); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Row divides by 10, red (will beat #1) - ConditionalFormattingRule rule1 = - sheetCF.createConditionalFormattingRule("MOD(ROW(),10)=0"); - FontFormatting font1 = rule1.createFontFormatting(); - font1.setFontColorIndex(IndexedColors.RED.index); - - // Condition 2: Row is even, blue - ConditionalFormattingRule rule2 = - sheetCF.createConditionalFormattingRule("MOD(ROW(),2)=0"); - FontFormatting font2 = rule2.createFontFormatting(); - font2.setFontColorIndex(IndexedColors.BLUE.index); - - // Condition 3: Row divides by 5, bold - ConditionalFormattingRule rule3 = - sheetCF.createConditionalFormattingRule("MOD(ROW(),5)=0"); - FontFormatting font3 = rule3.createFontFormatting(); - font3.setFontStyle(false, true); - - // Condition 4: Row divides by 3, grey background - ConditionalFormattingRule rule4 = - sheetCF.createConditionalFormattingRule("MOD(ROW(),3)=0"); - PatternFormatting fill4 = rule4.createPatternFormatting(); - fill4.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index); - fill4.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - // Apply - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A1:F41") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - sheetCF.addConditionalFormatting(regions, rule2); - sheetCF.addConditionalFormatting(regions, rule3); - sheetCF.addConditionalFormatting(regions, rule4); - } - - /** - * Use Excel conditional formatting to check for errors, - * and change the font colour to match the cell colour. - * In this example, if formula result is #DIV/0! then it will have white font colour. - */ - static void errors(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue(84); - sheet.createRow(1).createCell(0).setCellValue(0); - sheet.createRow(2).createCell(0).setCellFormula("ROUND(A1/A2,0)"); - sheet.createRow(3).createCell(0).setCellValue(0); - sheet.createRow(4).createCell(0).setCellFormula("ROUND(A6/A4,0)"); - sheet.createRow(5).createCell(0).setCellValue(41); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Formula Is =ISERROR(C2) (White Font) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("ISERROR(A1)"); - FontFormatting font = rule1.createFontFormatting(); - font.setFontColorIndex(IndexedColors.WHITE.index); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A1:A6") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.getRow(2).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)"); - sheet.getRow(4).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)"); - } - - /** - * Use Excel conditional formatting to hide the duplicate values, - * and make the list easier to read. In this example, when the table is sorted by Region, - * the second (and subsequent) occurences of each region name will have white font colour. - */ - static void hideDupplicates(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue("City"); - sheet.createRow(1).createCell(0).setCellValue("Boston"); - sheet.createRow(2).createCell(0).setCellValue("Boston"); - sheet.createRow(3).createCell(0).setCellValue("Chicago"); - sheet.createRow(4).createCell(0).setCellValue("Chicago"); - sheet.createRow(5).createCell(0).setCellValue("New York"); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Formula Is =A2=A1 (White Font) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("A2=A1"); - FontFormatting font = rule1.createFontFormatting(); - font.setFontColorIndex(IndexedColors.WHITE.index); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A2:A6") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.getRow(1).createCell(1).setCellValue("<== the second (and subsequent) " + - "occurences of each region name will have white font colour. " + - "Condition: Formula Is =A2=A1 (White Font)"); - } - - /** - * Use Excel conditional formatting to highlight duplicate entries in a column. - */ - static void formatDuplicates(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue("Code"); - sheet.createRow(1).createCell(0).setCellValue(4); - sheet.createRow(2).createCell(0).setCellValue(3); - sheet.createRow(3).createCell(0).setCellValue(6); - sheet.createRow(4).createCell(0).setCellValue(3); - sheet.createRow(5).createCell(0).setCellValue(5); - sheet.createRow(6).createCell(0).setCellValue(8); - sheet.createRow(7).createCell(0).setCellValue(0); - sheet.createRow(8).createCell(0).setCellValue(2); - sheet.createRow(9).createCell(0).setCellValue(8); - sheet.createRow(10).createCell(0).setCellValue(6); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Formula Is =A2=A1 (White Font) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($A$2:$A$11,A2)>1"); - FontFormatting font = rule1.createFontFormatting(); - font.setFontStyle(false, true); - font.setFontColorIndex(IndexedColors.BLUE.index); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A2:A11") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.getRow(2).createCell(1).setCellValue("<== Duplicates numbers in the column are highlighted. " + - "Condition: Formula Is =COUNTIF($A$2:$A$11,A2)>1 (Blue Font)"); - } - - /** - * Use Excel conditional formatting to highlight items that are in a list on the worksheet. - */ - static void inList(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue("Codes"); - sheet.createRow(1).createCell(0).setCellValue("AA"); - sheet.createRow(2).createCell(0).setCellValue("BB"); - sheet.createRow(3).createCell(0).setCellValue("GG"); - sheet.createRow(4).createCell(0).setCellValue("AA"); - sheet.createRow(5).createCell(0).setCellValue("FF"); - sheet.createRow(6).createCell(0).setCellValue("XX"); - sheet.createRow(7).createCell(0).setCellValue("CC"); - - sheet.getRow(0).createCell(2).setCellValue("Valid"); - sheet.getRow(1).createCell(2).setCellValue("AA"); - sheet.getRow(2).createCell(2).setCellValue("BB"); - sheet.getRow(3).createCell(2).setCellValue("CC"); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Formula Is =A2=A1 (White Font) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($C$2:$C$4,A2)"); - PatternFormatting fill1 = rule1.createPatternFormatting(); - fill1.setFillBackgroundColor(IndexedColors.LIGHT_BLUE.index); - fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A2:A8") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.getRow(2).createCell(3).setCellValue("<== Use Excel conditional formatting to highlight items that are in a list on the worksheet"); - } - - /** - * Use Excel conditional formatting to highlight payments that are due in the next thirty days. - * In this example, Due dates are entered in cells A2:A4. - */ - static void expiry(Sheet sheet) { - CellStyle style = sheet.getWorkbook().createCellStyle(); - style.setDataFormat((short)BuiltinFormats.getBuiltinFormat("d-mmm")); - - sheet.createRow(0).createCell(0).setCellValue("Date"); - sheet.createRow(1).createCell(0).setCellFormula("TODAY()+29"); - sheet.createRow(2).createCell(0).setCellFormula("A2+1"); - sheet.createRow(3).createCell(0).setCellFormula("A3+1"); - - for(int rownum = 1; rownum <= 3; rownum++) { - sheet.getRow(rownum).getCell(0).setCellStyle(style); - } - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Formula Is =A2=A1 (White Font) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("AND(A2-TODAY()>=0,A2-TODAY()<=30)"); - FontFormatting font = rule1.createFontFormatting(); - font.setFontStyle(false, true); - font.setFontColorIndex(IndexedColors.BLUE.index); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A2:A4") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.getRow(0).createCell(1).setCellValue("Dates within the next 30 days are highlighted"); - } - - /** - * Use Excel conditional formatting to shade alternating rows on the worksheet - */ - static void shadeAlt(Sheet sheet) { - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - // Condition 1: Formula Is =A2=A1 (White Font) - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),2)"); - PatternFormatting fill1 = rule1.createPatternFormatting(); - fill1.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.index); - fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A1:Z100") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.createRow(0).createCell(1).setCellValue("Shade Alternating Rows"); - sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),2) (Light Green Fill)"); - } - - /** - * You can use Excel conditional formatting to shade bands of rows on the worksheet. - * In this example, 3 rows are shaded light grey, and 3 are left with no shading. - * In the MOD function, the total number of rows in the set of banded rows (6) is entered. - */ - static void shadeBands(Sheet sheet) { - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),6)<3"); - PatternFormatting fill1 = rule1.createPatternFormatting(); - fill1.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index); - fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - CellRangeAddress[] regions = { - CellRangeAddress.valueOf("A1:Z100") - }; - - sheetCF.addConditionalFormatting(regions, rule1); - - sheet.createRow(0).createCell(1).setCellValue("Shade Bands of Rows"); - sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),6)<2 (Light Grey Fill)"); - } - - /** - * Icon Sets / Multi-States allow you to have icons shown which vary - * based on the values, eg Red traffic light / Yellow traffic light / - * Green traffic light - */ - static void iconSets(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue("Icon Sets"); - Row r = sheet.createRow(1); - r.createCell(0).setCellValue("Reds"); - r.createCell(1).setCellValue(0); - r.createCell(2).setCellValue(0); - r.createCell(3).setCellValue(0); - r = sheet.createRow(2); - r.createCell(0).setCellValue("Yellows"); - r.createCell(1).setCellValue(5); - r.createCell(2).setCellValue(5); - r.createCell(3).setCellValue(5); - r = sheet.createRow(3); - r.createCell(0).setCellValue("Greens"); - r.createCell(1).setCellValue(10); - r.createCell(2).setCellValue(10); - r.createCell(3).setCellValue(10); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - CellRangeAddress[] regions = { CellRangeAddress.valueOf("B1:B4") }; - ConditionalFormattingRule rule1 = - sheetCF.createConditionalFormattingRule(IconSet.GYR_3_TRAFFIC_LIGHTS); - IconMultiStateFormatting im1 = rule1.getMultiStateFormatting(); - im1.getThresholds()[0].setRangeType(RangeType.MIN); - im1.getThresholds()[1].setRangeType(RangeType.PERCENT); - im1.getThresholds()[1].setValue(33d); - im1.getThresholds()[2].setRangeType(RangeType.MAX); - sheetCF.addConditionalFormatting(regions, rule1); - - regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C1:C4") }; - ConditionalFormattingRule rule2 = - sheetCF.createConditionalFormattingRule(IconSet.GYR_3_FLAGS); - IconMultiStateFormatting im2 = rule1.getMultiStateFormatting(); - im2.getThresholds()[0].setRangeType(RangeType.PERCENT); - im2.getThresholds()[0].setValue(0d); - im2.getThresholds()[1].setRangeType(RangeType.PERCENT); - im2.getThresholds()[1].setValue(33d); - im2.getThresholds()[2].setRangeType(RangeType.PERCENT); - im2.getThresholds()[2].setValue(67d); - sheetCF.addConditionalFormatting(regions, rule2); - - regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D1:D4") }; - ConditionalFormattingRule rule3 = - sheetCF.createConditionalFormattingRule(IconSet.GYR_3_SYMBOLS_CIRCLE); - IconMultiStateFormatting im3 = rule1.getMultiStateFormatting(); - im3.setIconOnly(true); - im3.getThresholds()[0].setRangeType(RangeType.MIN); - im3.getThresholds()[1].setRangeType(RangeType.NUMBER); - im3.getThresholds()[1].setValue(3d); - im3.getThresholds()[2].setRangeType(RangeType.NUMBER); - im3.getThresholds()[2].setValue(7d); - sheetCF.addConditionalFormatting(regions, rule3); - } - - /** - * Color Scales / Colour Scales / Colour Gradients allow you shade the - * background colour of the cell based on the values, eg from Red to - * Yellow to Green. - */ - static void colourScales(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue("Colour Scales"); - Row r = sheet.createRow(1); - r.createCell(0).setCellValue("Red-Yellow-Green"); - for (int i=1; i<=7; i++) { - r.createCell(i).setCellValue((i-1)*5); - } - r = sheet.createRow(2); - r.createCell(0).setCellValue("Red-White-Blue"); - for (int i=1; i<=9; i++) { - r.createCell(i).setCellValue((i-1)*5); - } - r = sheet.createRow(3); - r.createCell(0).setCellValue("Blue-Green"); - for (int i=1; i<=16; i++) { - r.createCell(i).setCellValue((i-1)); - } - sheet.setColumnWidth(0, 5000); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:H2") }; - ConditionalFormattingRule rule1 = - sheetCF.createConditionalFormattingColorScaleRule(); - ColorScaleFormatting cs1 = rule1.getColorScaleFormatting(); - cs1.getThresholds()[0].setRangeType(RangeType.MIN); - cs1.getThresholds()[1].setRangeType(RangeType.PERCENTILE); - cs1.getThresholds()[1].setValue(50d); - cs1.getThresholds()[2].setRangeType(RangeType.MAX); - ((ExtendedColor)cs1.getColors()[0]).setARGBHex("FFF8696B"); - ((ExtendedColor)cs1.getColors()[1]).setARGBHex("FFFFEB84"); - ((ExtendedColor)cs1.getColors()[2]).setARGBHex("FF63BE7B"); - sheetCF.addConditionalFormatting(regions, rule1); - - regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B3:J3") }; - ConditionalFormattingRule rule2 = - sheetCF.createConditionalFormattingColorScaleRule(); - ColorScaleFormatting cs2 = rule2.getColorScaleFormatting(); - cs2.getThresholds()[0].setRangeType(RangeType.MIN); - cs2.getThresholds()[1].setRangeType(RangeType.PERCENTILE); - cs2.getThresholds()[1].setValue(50d); - cs2.getThresholds()[2].setRangeType(RangeType.MAX); - ((ExtendedColor)cs2.getColors()[0]).setARGBHex("FFF8696B"); - ((ExtendedColor)cs2.getColors()[1]).setARGBHex("FFFCFCFF"); - ((ExtendedColor)cs2.getColors()[2]).setARGBHex("FF5A8AC6"); - sheetCF.addConditionalFormatting(regions, rule2); - - regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B4:Q4") }; - ConditionalFormattingRule rule3= - sheetCF.createConditionalFormattingColorScaleRule(); - ColorScaleFormatting cs3 = rule3.getColorScaleFormatting(); - cs3.setNumControlPoints(2); - cs3.getThresholds()[0].setRangeType(RangeType.MIN); - cs3.getThresholds()[1].setRangeType(RangeType.MAX); - ((ExtendedColor)cs3.getColors()[0]).setARGBHex("FF5A8AC6"); - ((ExtendedColor)cs3.getColors()[1]).setARGBHex("FF63BE7B"); - sheetCF.addConditionalFormatting(regions, rule3); - } - - /** - * DataBars / Data-Bars allow you to have bars shown vary - * based on the values, from full to empty - */ - static void dataBars(Sheet sheet) { - sheet.createRow(0).createCell(0).setCellValue("Data Bars"); - Row r = sheet.createRow(1); - r.createCell(1).setCellValue("Green Positive"); - r.createCell(2).setCellValue("Blue Mix"); - r.createCell(3).setCellValue("Red Negative"); - r = sheet.createRow(2); - r.createCell(1).setCellValue(0); - r.createCell(2).setCellValue(0); - r.createCell(3).setCellValue(0); - r = sheet.createRow(3); - r.createCell(1).setCellValue(5); - r.createCell(2).setCellValue(-5); - r.createCell(3).setCellValue(-5); - r = sheet.createRow(4); - r.createCell(1).setCellValue(10); - r.createCell(2).setCellValue(10); - r.createCell(3).setCellValue(-10); - r = sheet.createRow(5); - r.createCell(1).setCellValue(5); - r.createCell(2).setCellValue(5); - r.createCell(3).setCellValue(-5); - r = sheet.createRow(6); - r.createCell(1).setCellValue(20); - r.createCell(2).setCellValue(-10); - r.createCell(3).setCellValue(-20); - sheet.setColumnWidth(0, 3000); - sheet.setColumnWidth(1, 5000); - sheet.setColumnWidth(2, 5000); - sheet.setColumnWidth(3, 5000); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - ExtendedColor color = sheet.getWorkbook().getCreationHelper().createExtendedColor(); - color.setARGBHex("FF63BE7B"); - CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:B7") }; - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(color); - DataBarFormatting db1 = rule1.getDataBarFormatting(); - db1.getMinThreshold().setRangeType(RangeType.MIN); - db1.getMaxThreshold().setRangeType(RangeType.MAX); - sheetCF.addConditionalFormatting(regions, rule1); - - color = sheet.getWorkbook().getCreationHelper().createExtendedColor(); - color.setARGBHex("FF5A8AC6"); - regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C2:C7") }; - ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(color); - DataBarFormatting db2 = rule2.getDataBarFormatting(); - db2.getMinThreshold().setRangeType(RangeType.MIN); - db2.getMaxThreshold().setRangeType(RangeType.MAX); - sheetCF.addConditionalFormatting(regions, rule2); - - color = sheet.getWorkbook().getCreationHelper().createExtendedColor(); - color.setARGBHex("FFF8696B"); - regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D2:D7") }; - ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule(color); - DataBarFormatting db3 = rule3.getDataBarFormatting(); - db3.getMinThreshold().setRangeType(RangeType.MIN); - db3.getMaxThreshold().setRangeType(RangeType.MAX); - sheetCF.addConditionalFormatting(regions, rule3); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.examples; + +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.BuiltinFormats; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.ColorScaleFormatting; +import org.apache.poi.ss.usermodel.ComparisonOperator; +import org.apache.poi.ss.usermodel.ConditionalFormattingRule; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; +import org.apache.poi.ss.usermodel.DataBarFormatting; +import org.apache.poi.ss.usermodel.ExtendedColor; +import org.apache.poi.ss.usermodel.FontFormatting; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.PatternFormatting; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.SheetConditionalFormatting; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Excel Conditional Formatting -- Examples + * + *

+ * Partly based on the code snippets from + * http://www.contextures.com/xlcondformat03.html + *

+ */ +public class ConditionalFormats { + + public static void main(String[] args) throws IOException { + Workbook wb; + + if(args.length > 0 && args[0].equals("-xls")) { + wb = new HSSFWorkbook(); + } else { + wb = new XSSFWorkbook(); + } + + sameCell(wb.createSheet("Same Cell")); + multiCell(wb.createSheet("MultiCell")); + overlapping(wb.createSheet("Overlapping")); + errors(wb.createSheet("Errors")); + hideDupplicates(wb.createSheet("Hide Dups")); + formatDuplicates(wb.createSheet("Duplicates")); + inList(wb.createSheet("In List")); + expiry(wb.createSheet("Expiry")); + shadeAlt(wb.createSheet("Shade Alt")); + shadeBands(wb.createSheet("Shade Bands")); + iconSets(wb.createSheet("Icon Sets")); + colourScales(wb.createSheet("Colour Scales")); + dataBars(wb.createSheet("Data Bars")); + + // Write the output to a file + String file = "cf-poi.xls"; + if(wb instanceof XSSFWorkbook) { + file += "x"; + } + FileOutputStream out = new FileOutputStream(file); + wb.write(out); + out.close(); + System.out.println("Generated: " + file); + wb.close(); + } + + /** + * Highlight cells based on their values + */ + static void sameCell(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue(84); + sheet.createRow(1).createCell(0).setCellValue(74); + sheet.createRow(2).createCell(0).setCellValue(50); + sheet.createRow(3).createCell(0).setCellValue(51); + sheet.createRow(4).createCell(0).setCellValue(49); + sheet.createRow(5).createCell(0).setCellValue(41); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Cell Value Is greater than 70 (Blue Fill) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(ComparisonOperator.GT, "70"); + PatternFormatting fill1 = rule1.createPatternFormatting(); + fill1.setFillBackgroundColor(IndexedColors.BLUE.index); + fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + // Condition 2: Cell Value Is less than 50 (Green Fill) + ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.LT, "50"); + PatternFormatting fill2 = rule2.createPatternFormatting(); + fill2.setFillBackgroundColor(IndexedColors.GREEN.index); + fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A1:A6") + }; + + sheetCF.addConditionalFormatting(regions, rule1, rule2); + + sheet.getRow(0).createCell(2).setCellValue("<== Condition 1: Cell Value Is greater than 70 (Blue Fill)"); + sheet.getRow(4).createCell(2).setCellValue("<== Condition 2: Cell Value Is less than 50 (Green Fill)"); + } + + /** + * Highlight multiple cells based on a formula + */ + static void multiCell(Sheet sheet) { + // header row + Row row0 = sheet.createRow(0); + row0.createCell(0).setCellValue("Units"); + row0.createCell(1).setCellValue("Cost"); + row0.createCell(2).setCellValue("Total"); + + Row row1 = sheet.createRow(1); + row1.createCell(0).setCellValue(71); + row1.createCell(1).setCellValue(29); + row1.createCell(2).setCellValue(2059); + + Row row2 = sheet.createRow(2); + row2.createCell(0).setCellValue(85); + row2.createCell(1).setCellValue(29); + row2.createCell(2).setCellValue(2059); + + Row row3 = sheet.createRow(3); + row3.createCell(0).setCellValue(71); + row3.createCell(1).setCellValue(29); + row3.createCell(2).setCellValue(2059); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Formula Is =$B2>75 (Blue Fill) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("$A2>75"); + PatternFormatting fill1 = rule1.createPatternFormatting(); + fill1.setFillBackgroundColor(IndexedColors.BLUE.index); + fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A2:C4") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.getRow(2).createCell(4).setCellValue("<== Condition 1: Formula Is =$B2>75 (Blue Fill)"); + } + + /** + * Multiple conditional formatting rules can apply to + * one cell, some combining, some beating others. + * Done in order of the rules added to the + * SheetConditionalFormatting object + */ + static void overlapping(Sheet sheet) { + for (int i=0; i<40; i++) { + int rn = i+1; + Row r = sheet.createRow(i); + r.createCell(0).setCellValue("This is row " + rn + " (" + i + ")"); + String str = ""; + if (rn%2 == 0) { + str = str + "even "; + } + if (rn%3 == 0) { + str = str + "x3 "; + } + if (rn%5 == 0) { + str = str + "x5 "; + } + if (rn%10 == 0) { + str = str + "x10 "; + } + if (str.length() == 0) { + str = "nothing special..."; + } + r.createCell(1).setCellValue("It is " + str); + } + sheet.autoSizeColumn(0); + sheet.autoSizeColumn(1); + + sheet.getRow(1).createCell(3).setCellValue("Even rows are blue"); + sheet.getRow(2).createCell(3).setCellValue("Multiples of 3 have a grey background"); + sheet.getRow(4).createCell(3).setCellValue("Multiples of 5 are bold"); + sheet.getRow(9).createCell(3).setCellValue("Multiples of 10 are red (beats even)"); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Row divides by 10, red (will beat #1) + ConditionalFormattingRule rule1 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),10)=0"); + FontFormatting font1 = rule1.createFontFormatting(); + font1.setFontColorIndex(IndexedColors.RED.index); + + // Condition 2: Row is even, blue + ConditionalFormattingRule rule2 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),2)=0"); + FontFormatting font2 = rule2.createFontFormatting(); + font2.setFontColorIndex(IndexedColors.BLUE.index); + + // Condition 3: Row divides by 5, bold + ConditionalFormattingRule rule3 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),5)=0"); + FontFormatting font3 = rule3.createFontFormatting(); + font3.setFontStyle(false, true); + + // Condition 4: Row divides by 3, grey background + ConditionalFormattingRule rule4 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),3)=0"); + PatternFormatting fill4 = rule4.createPatternFormatting(); + fill4.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index); + fill4.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + // Apply + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A1:F41") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + sheetCF.addConditionalFormatting(regions, rule2); + sheetCF.addConditionalFormatting(regions, rule3); + sheetCF.addConditionalFormatting(regions, rule4); + } + + /** + * Use Excel conditional formatting to check for errors, + * and change the font colour to match the cell colour. + * In this example, if formula result is #DIV/0! then it will have white font colour. + */ + static void errors(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue(84); + sheet.createRow(1).createCell(0).setCellValue(0); + sheet.createRow(2).createCell(0).setCellFormula("ROUND(A1/A2,0)"); + sheet.createRow(3).createCell(0).setCellValue(0); + sheet.createRow(4).createCell(0).setCellFormula("ROUND(A6/A4,0)"); + sheet.createRow(5).createCell(0).setCellValue(41); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Formula Is =ISERROR(C2) (White Font) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("ISERROR(A1)"); + FontFormatting font = rule1.createFontFormatting(); + font.setFontColorIndex(IndexedColors.WHITE.index); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A1:A6") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.getRow(2).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)"); + sheet.getRow(4).createCell(1).setCellValue("<== The error in this cell is hidden. Condition: Formula Is =ISERROR(C2) (White Font)"); + } + + /** + * Use Excel conditional formatting to hide the duplicate values, + * and make the list easier to read. In this example, when the table is sorted by Region, + * the second (and subsequent) occurences of each region name will have white font colour. + */ + static void hideDupplicates(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue("City"); + sheet.createRow(1).createCell(0).setCellValue("Boston"); + sheet.createRow(2).createCell(0).setCellValue("Boston"); + sheet.createRow(3).createCell(0).setCellValue("Chicago"); + sheet.createRow(4).createCell(0).setCellValue("Chicago"); + sheet.createRow(5).createCell(0).setCellValue("New York"); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Formula Is =A2=A1 (White Font) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("A2=A1"); + FontFormatting font = rule1.createFontFormatting(); + font.setFontColorIndex(IndexedColors.WHITE.index); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A2:A6") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.getRow(1).createCell(1).setCellValue("<== the second (and subsequent) " + + "occurences of each region name will have white font colour. " + + "Condition: Formula Is =A2=A1 (White Font)"); + } + + /** + * Use Excel conditional formatting to highlight duplicate entries in a column. + */ + static void formatDuplicates(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue("Code"); + sheet.createRow(1).createCell(0).setCellValue(4); + sheet.createRow(2).createCell(0).setCellValue(3); + sheet.createRow(3).createCell(0).setCellValue(6); + sheet.createRow(4).createCell(0).setCellValue(3); + sheet.createRow(5).createCell(0).setCellValue(5); + sheet.createRow(6).createCell(0).setCellValue(8); + sheet.createRow(7).createCell(0).setCellValue(0); + sheet.createRow(8).createCell(0).setCellValue(2); + sheet.createRow(9).createCell(0).setCellValue(8); + sheet.createRow(10).createCell(0).setCellValue(6); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Formula Is =A2=A1 (White Font) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($A$2:$A$11,A2)>1"); + FontFormatting font = rule1.createFontFormatting(); + font.setFontStyle(false, true); + font.setFontColorIndex(IndexedColors.BLUE.index); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A2:A11") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.getRow(2).createCell(1).setCellValue("<== Duplicates numbers in the column are highlighted. " + + "Condition: Formula Is =COUNTIF($A$2:$A$11,A2)>1 (Blue Font)"); + } + + /** + * Use Excel conditional formatting to highlight items that are in a list on the worksheet. + */ + static void inList(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue("Codes"); + sheet.createRow(1).createCell(0).setCellValue("AA"); + sheet.createRow(2).createCell(0).setCellValue("BB"); + sheet.createRow(3).createCell(0).setCellValue("GG"); + sheet.createRow(4).createCell(0).setCellValue("AA"); + sheet.createRow(5).createCell(0).setCellValue("FF"); + sheet.createRow(6).createCell(0).setCellValue("XX"); + sheet.createRow(7).createCell(0).setCellValue("CC"); + + sheet.getRow(0).createCell(2).setCellValue("Valid"); + sheet.getRow(1).createCell(2).setCellValue("AA"); + sheet.getRow(2).createCell(2).setCellValue("BB"); + sheet.getRow(3).createCell(2).setCellValue("CC"); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Formula Is =A2=A1 (White Font) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($C$2:$C$4,A2)"); + PatternFormatting fill1 = rule1.createPatternFormatting(); + fill1.setFillBackgroundColor(IndexedColors.LIGHT_BLUE.index); + fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A2:A8") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.getRow(2).createCell(3).setCellValue("<== Use Excel conditional formatting to highlight items that are in a list on the worksheet"); + } + + /** + * Use Excel conditional formatting to highlight payments that are due in the next thirty days. + * In this example, Due dates are entered in cells A2:A4. + */ + static void expiry(Sheet sheet) { + CellStyle style = sheet.getWorkbook().createCellStyle(); + style.setDataFormat((short)BuiltinFormats.getBuiltinFormat("d-mmm")); + + sheet.createRow(0).createCell(0).setCellValue("Date"); + sheet.createRow(1).createCell(0).setCellFormula("TODAY()+29"); + sheet.createRow(2).createCell(0).setCellFormula("A2+1"); + sheet.createRow(3).createCell(0).setCellFormula("A3+1"); + + for(int rownum = 1; rownum <= 3; rownum++) { + sheet.getRow(rownum).getCell(0).setCellStyle(style); + } + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Formula Is =A2=A1 (White Font) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("AND(A2-TODAY()>=0,A2-TODAY()<=30)"); + FontFormatting font = rule1.createFontFormatting(); + font.setFontStyle(false, true); + font.setFontColorIndex(IndexedColors.BLUE.index); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A2:A4") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.getRow(0).createCell(1).setCellValue("Dates within the next 30 days are highlighted"); + } + + /** + * Use Excel conditional formatting to shade alternating rows on the worksheet + */ + static void shadeAlt(Sheet sheet) { + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Formula Is =A2=A1 (White Font) + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),2)"); + PatternFormatting fill1 = rule1.createPatternFormatting(); + fill1.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.index); + fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A1:Z100") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.createRow(0).createCell(1).setCellValue("Shade Alternating Rows"); + sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),2) (Light Green Fill)"); + } + + /** + * You can use Excel conditional formatting to shade bands of rows on the worksheet. + * In this example, 3 rows are shaded light grey, and 3 are left with no shading. + * In the MOD function, the total number of rows in the set of banded rows (6) is entered. + */ + static void shadeBands(Sheet sheet) { + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),6)<3"); + PatternFormatting fill1 = rule1.createPatternFormatting(); + fill1.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index); + fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A1:Z100") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + + sheet.createRow(0).createCell(1).setCellValue("Shade Bands of Rows"); + sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),6)<2 (Light Grey Fill)"); + } + + /** + * Icon Sets / Multi-States allow you to have icons shown which vary + * based on the values, eg Red traffic light / Yellow traffic light / + * Green traffic light + */ + static void iconSets(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue("Icon Sets"); + Row r = sheet.createRow(1); + r.createCell(0).setCellValue("Reds"); + r.createCell(1).setCellValue(0); + r.createCell(2).setCellValue(0); + r.createCell(3).setCellValue(0); + r = sheet.createRow(2); + r.createCell(0).setCellValue("Yellows"); + r.createCell(1).setCellValue(5); + r.createCell(2).setCellValue(5); + r.createCell(3).setCellValue(5); + r = sheet.createRow(3); + r.createCell(0).setCellValue("Greens"); + r.createCell(1).setCellValue(10); + r.createCell(2).setCellValue(10); + r.createCell(3).setCellValue(10); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + CellRangeAddress[] regions = { CellRangeAddress.valueOf("B1:B4") }; + ConditionalFormattingRule rule1 = + sheetCF.createConditionalFormattingRule(IconSet.GYR_3_TRAFFIC_LIGHTS); + IconMultiStateFormatting im1 = rule1.getMultiStateFormatting(); + im1.getThresholds()[0].setRangeType(RangeType.MIN); + im1.getThresholds()[1].setRangeType(RangeType.PERCENT); + im1.getThresholds()[1].setValue(33d); + im1.getThresholds()[2].setRangeType(RangeType.MAX); + sheetCF.addConditionalFormatting(regions, rule1); + + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C1:C4") }; + ConditionalFormattingRule rule2 = + sheetCF.createConditionalFormattingRule(IconSet.GYR_3_FLAGS); + IconMultiStateFormatting im2 = rule1.getMultiStateFormatting(); + im2.getThresholds()[0].setRangeType(RangeType.PERCENT); + im2.getThresholds()[0].setValue(0d); + im2.getThresholds()[1].setRangeType(RangeType.PERCENT); + im2.getThresholds()[1].setValue(33d); + im2.getThresholds()[2].setRangeType(RangeType.PERCENT); + im2.getThresholds()[2].setValue(67d); + sheetCF.addConditionalFormatting(regions, rule2); + + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D1:D4") }; + ConditionalFormattingRule rule3 = + sheetCF.createConditionalFormattingRule(IconSet.GYR_3_SYMBOLS_CIRCLE); + IconMultiStateFormatting im3 = rule1.getMultiStateFormatting(); + im3.setIconOnly(true); + im3.getThresholds()[0].setRangeType(RangeType.MIN); + im3.getThresholds()[1].setRangeType(RangeType.NUMBER); + im3.getThresholds()[1].setValue(3d); + im3.getThresholds()[2].setRangeType(RangeType.NUMBER); + im3.getThresholds()[2].setValue(7d); + sheetCF.addConditionalFormatting(regions, rule3); + } + + /** + * Color Scales / Colour Scales / Colour Gradients allow you shade the + * background colour of the cell based on the values, eg from Red to + * Yellow to Green. + */ + static void colourScales(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue("Colour Scales"); + Row r = sheet.createRow(1); + r.createCell(0).setCellValue("Red-Yellow-Green"); + for (int i=1; i<=7; i++) { + r.createCell(i).setCellValue((i-1)*5); + } + r = sheet.createRow(2); + r.createCell(0).setCellValue("Red-White-Blue"); + for (int i=1; i<=9; i++) { + r.createCell(i).setCellValue((i-1)*5); + } + r = sheet.createRow(3); + r.createCell(0).setCellValue("Blue-Green"); + for (int i=1; i<=16; i++) { + r.createCell(i).setCellValue((i-1)); + } + sheet.setColumnWidth(0, 5000); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:H2") }; + ConditionalFormattingRule rule1 = + sheetCF.createConditionalFormattingColorScaleRule(); + ColorScaleFormatting cs1 = rule1.getColorScaleFormatting(); + cs1.getThresholds()[0].setRangeType(RangeType.MIN); + cs1.getThresholds()[1].setRangeType(RangeType.PERCENTILE); + cs1.getThresholds()[1].setValue(50d); + cs1.getThresholds()[2].setRangeType(RangeType.MAX); + ((ExtendedColor)cs1.getColors()[0]).setARGBHex("FFF8696B"); + ((ExtendedColor)cs1.getColors()[1]).setARGBHex("FFFFEB84"); + ((ExtendedColor)cs1.getColors()[2]).setARGBHex("FF63BE7B"); + sheetCF.addConditionalFormatting(regions, rule1); + + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B3:J3") }; + ConditionalFormattingRule rule2 = + sheetCF.createConditionalFormattingColorScaleRule(); + ColorScaleFormatting cs2 = rule2.getColorScaleFormatting(); + cs2.getThresholds()[0].setRangeType(RangeType.MIN); + cs2.getThresholds()[1].setRangeType(RangeType.PERCENTILE); + cs2.getThresholds()[1].setValue(50d); + cs2.getThresholds()[2].setRangeType(RangeType.MAX); + ((ExtendedColor)cs2.getColors()[0]).setARGBHex("FFF8696B"); + ((ExtendedColor)cs2.getColors()[1]).setARGBHex("FFFCFCFF"); + ((ExtendedColor)cs2.getColors()[2]).setARGBHex("FF5A8AC6"); + sheetCF.addConditionalFormatting(regions, rule2); + + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("B4:Q4") }; + ConditionalFormattingRule rule3= + sheetCF.createConditionalFormattingColorScaleRule(); + ColorScaleFormatting cs3 = rule3.getColorScaleFormatting(); + cs3.setNumControlPoints(2); + cs3.getThresholds()[0].setRangeType(RangeType.MIN); + cs3.getThresholds()[1].setRangeType(RangeType.MAX); + ((ExtendedColor)cs3.getColors()[0]).setARGBHex("FF5A8AC6"); + ((ExtendedColor)cs3.getColors()[1]).setARGBHex("FF63BE7B"); + sheetCF.addConditionalFormatting(regions, rule3); + } + + /** + * DataBars / Data-Bars allow you to have bars shown vary + * based on the values, from full to empty + */ + static void dataBars(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue("Data Bars"); + Row r = sheet.createRow(1); + r.createCell(1).setCellValue("Green Positive"); + r.createCell(2).setCellValue("Blue Mix"); + r.createCell(3).setCellValue("Red Negative"); + r = sheet.createRow(2); + r.createCell(1).setCellValue(0); + r.createCell(2).setCellValue(0); + r.createCell(3).setCellValue(0); + r = sheet.createRow(3); + r.createCell(1).setCellValue(5); + r.createCell(2).setCellValue(-5); + r.createCell(3).setCellValue(-5); + r = sheet.createRow(4); + r.createCell(1).setCellValue(10); + r.createCell(2).setCellValue(10); + r.createCell(3).setCellValue(-10); + r = sheet.createRow(5); + r.createCell(1).setCellValue(5); + r.createCell(2).setCellValue(5); + r.createCell(3).setCellValue(-5); + r = sheet.createRow(6); + r.createCell(1).setCellValue(20); + r.createCell(2).setCellValue(-10); + r.createCell(3).setCellValue(-20); + sheet.setColumnWidth(0, 3000); + sheet.setColumnWidth(1, 5000); + sheet.setColumnWidth(2, 5000); + sheet.setColumnWidth(3, 5000); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + ExtendedColor color = sheet.getWorkbook().getCreationHelper().createExtendedColor(); + color.setARGBHex("FF63BE7B"); + CellRangeAddress[] regions = { CellRangeAddress.valueOf("B2:B7") }; + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(color); + DataBarFormatting db1 = rule1.getDataBarFormatting(); + db1.getMinThreshold().setRangeType(RangeType.MIN); + db1.getMaxThreshold().setRangeType(RangeType.MAX); + sheetCF.addConditionalFormatting(regions, rule1); + + color = sheet.getWorkbook().getCreationHelper().createExtendedColor(); + color.setARGBHex("FF5A8AC6"); + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C2:C7") }; + ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(color); + DataBarFormatting db2 = rule2.getDataBarFormatting(); + db2.getMinThreshold().setRangeType(RangeType.MIN); + db2.getMaxThreshold().setRangeType(RangeType.MAX); + sheetCF.addConditionalFormatting(regions, rule2); + + color = sheet.getWorkbook().getCreationHelper().createExtendedColor(); + color.setARGBHex("FFF8696B"); + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D2:D7") }; + ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule(color); + DataBarFormatting db3 = rule3.getDataBarFormatting(); + db3.getMinThreshold().setRangeType(RangeType.MIN); + db3.getMaxThreshold().setRangeType(RangeType.MAX); + sheetCF.addConditionalFormatting(regions, rule3); + } +} diff --git a/src/examples/src/org/apache/poi/ss/examples/ExcelComparator.java b/src/examples/src/org/apache/poi/ss/examples/ExcelComparator.java index 5ed404e2d3..645e798a0d 100644 --- a/src/examples/src/org/apache/poi/ss/examples/ExcelComparator.java +++ b/src/examples/src/org/apache/poi/ss/examples/ExcelComparator.java @@ -1,614 +1,614 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.examples; - -import java.io.File; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; - -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookFactory; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.usermodel.XSSFCell; -import org.apache.poi.xssf.usermodel.XSSFCellStyle; -import org.apache.poi.xssf.usermodel.XSSFColor; - -/** - * Utility to compare Excel File Contents cell by cell for all sheets. - * - *

This utility will be used to compare Excel File Contents cell by cell for all sheets programmatically.

- * - *

Below are the list of Attribute comparison supported in this version.

- * - *
    - *
  • Cell Alignment
  • - *
  • Cell Border Attributes
  • - *
  • Cell Data
  • - *
  • Cell Data-Type
  • - *
  • Cell Fill Color
  • - *
  • Cell Fill pattern
  • - *
  • Cell Font Attributes
  • - *
  • Cell Font Family
  • - *
  • Cell Font Size
  • - *
  • Cell Protection
  • - *
  • Name of the sheets
  • - *
  • Number of Columns
  • - *
  • Number of Rows
  • - *
  • Number of Sheet
  • - *
- * - *

(Some of the above attribute comparison only work for *.xlsx format currently. In future it can be enhanced.)

- * - *

Usage:

- * - *
- * {@code
- *  Workbook wb1 = WorkbookFactory.create(new File("workBook1.xls"));
- *  Workbook wb2 = WorkbookFactory.create(new File("workBook2.xls"));
- *  List listOfDifferences = ExcelComparator.compare(wb1, wb2);
- *  for (String differences : listOfDifferences)
- *      System.out.println(differences);
- *  System.out.println("DifferenceFound = "+ excelFileDifference.isDifferenceFound);
- *  }
- * 
- */ -public class ExcelComparator { - - private static final String CELL_DATA_DOES_NOT_MATCH = "Cell Data does not Match ::"; - private static final String CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH = "Cell Font Attributes does not Match ::"; - - private static class Locator { - Workbook workbook; - Sheet sheet; - Row row; - Cell cell; - } - - List listOfDifferences = new ArrayList(); - - public static void main(String args[]) throws Exception { - if (args.length != 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) { - System.err.println("java -cp "+ExcelComparator.class.getCanonicalName()+" compare(Workbook wb1, Workbook wb2) { - Locator loc1 = new Locator(); - Locator loc2 = new Locator(); - loc1.workbook = wb1; - loc2.workbook = wb2; - - ExcelComparator excelComparator = new ExcelComparator(); - excelComparator.compareNumberOfSheets(loc1, loc2 ); - excelComparator.compareSheetNames(loc1, loc2); - excelComparator.compareSheetData(loc1, loc2); - - return excelComparator.listOfDifferences; - } - - /** - * Compare data in all sheets. - * - * @param workbook1 the workbook1 - * @param workbook2 the workbook2 - * @param listOfDifferences the list of differences - * @throws ExcelCompareException the excel compare exception - */ - private void compareDataInAllSheets(Locator loc1, Locator loc2) { - for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { - if (loc2.workbook.getNumberOfSheets() <= i) return; - - loc1.sheet = loc1.workbook.getSheetAt(i); - loc2.sheet = loc2.workbook.getSheetAt(i); - - compareDataInSheet(loc1, loc2); - } - } - - private void compareDataInSheet(Locator loc1, Locator loc2) { - for (int j = 0; j < loc1.sheet.getPhysicalNumberOfRows(); j++) { - if (loc2.sheet.getPhysicalNumberOfRows() <= j) return; - - loc1.row = loc1.sheet.getRow(j); - loc2.row = loc2.sheet.getRow(j); - - if ((loc1.row == null) || (loc2.row == null)) { - continue; - } - - compareDataInRow(loc1, loc2); - } - } - - private void compareDataInRow(Locator loc1, Locator loc2) { - for (int k = 0; k < loc1.row.getLastCellNum(); k++) { - if (loc2.row.getPhysicalNumberOfCells() <= k) return; - - loc1.cell = loc1.row.getCell(k); - loc2.cell = loc2.row.getCell(k); - - if ((loc1.cell == null) || (loc2.cell == null)) { - continue; - } - - compareDataInCell(loc1, loc2); - } - } - - private void compareDataInCell(Locator loc1, Locator loc2) { - if (isCellTypeMatches(loc1, loc2)) { - final CellType loc1cellType = loc1.cell.getCellTypeEnum(); - switch(loc1cellType) { - case BLANK: - case STRING: - case ERROR: - isCellContentMatches(loc1,loc2); - break; - case BOOLEAN: - isCellContentMatchesForBoolean(loc1,loc2); - break; - case FORMULA: - isCellContentMatchesForFormula(loc1,loc2); - break; - case NUMERIC: - if (DateUtil.isCellDateFormatted(loc1.cell)) { - isCellContentMatchesForDate(loc1,loc2); - } else { - isCellContentMatchesForNumeric(loc1,loc2); - } - break; - default: - throw new IllegalStateException("Unexpected cell type: " + loc1cellType); - } - } - - isCellFillPatternMatches(loc1,loc2); - isCellAlignmentMatches(loc1,loc2); - isCellHiddenMatches(loc1,loc2); - isCellLockedMatches(loc1,loc2); - isCellFontFamilyMatches(loc1,loc2); - isCellFontSizeMatches(loc1,loc2); - isCellFontBoldMatches(loc1,loc2); - isCellUnderLineMatches(loc1,loc2); - isCellFontItalicsMatches(loc1,loc2); - isCellBorderMatches(loc1,loc2,'t'); - isCellBorderMatches(loc1,loc2,'l'); - isCellBorderMatches(loc1,loc2,'b'); - isCellBorderMatches(loc1,loc2,'r'); - isCellFillBackGroundMatches(loc1,loc2); - } - - /** - * Compare number of columns in sheets. - */ - private void compareNumberOfColumnsInSheets(Locator loc1, Locator loc2) { - for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { - if (loc2.workbook.getNumberOfSheets() <= i) return; - - loc1.sheet = loc1.workbook.getSheetAt(i); - loc2.sheet = loc2.workbook.getSheetAt(i); - - Iterator ri1 = loc1.sheet.rowIterator(); - Iterator ri2 = loc2.sheet.rowIterator(); - - int num1 = (ri1.hasNext()) ? ri1.next().getPhysicalNumberOfCells() : 0; - int num2 = (ri2.hasNext()) ? ri2.next().getPhysicalNumberOfCells() : 0; - - if (num1 != num2) { - String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]", - "Number Of Columns does not Match ::", - loc1.sheet.getSheetName(), num1, - loc2.sheet.getSheetName(), num2 - ); - listOfDifferences.add(str); - } - } - } - - /** - * Compare number of rows in sheets. - */ - private void compareNumberOfRowsInSheets(Locator loc1, Locator loc2) { - for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { - if (loc2.workbook.getNumberOfSheets() <= i) return; - - loc1.sheet = loc1.workbook.getSheetAt(i); - loc2.sheet = loc2.workbook.getSheetAt(i); - - int num1 = loc1.sheet.getPhysicalNumberOfRows(); - int num2 = loc2.sheet.getPhysicalNumberOfRows(); - - if (num1 != num2) { - String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]", - "Number Of Rows does not Match ::", - loc1.sheet.getSheetName(), num1, - loc2.sheet.getSheetName(), num2 - ); - listOfDifferences.add(str); - } - } - - } - - /** - * Compare number of sheets. - */ - private void compareNumberOfSheets(Locator loc1, Locator loc2) { - int num1 = loc1.workbook.getNumberOfSheets(); - int num2 = loc2.workbook.getNumberOfSheets(); - if (num1 != num2) { - String str = String.format(Locale.ROOT, "%s\nworkbook1 [%d] != workbook2 [%d]", - "Number of Sheets do not match ::", - num1, num2 - ); - - listOfDifferences.add(str); - - } - } - - /** - * Compare sheet data. - * - * @param workbook1 - * the workbook1 - * @param workbook2 - * the workbook2 - * @param listOfDifferences - * - * @throws ExcelCompareException - * the excel compare exception - */ - private void compareSheetData(Locator loc1, Locator loc2) { - compareNumberOfRowsInSheets(loc1, loc2); - compareNumberOfColumnsInSheets(loc1, loc2); - compareDataInAllSheets(loc1, loc2); - - } - - /** - * Compare sheet names. - */ - private void compareSheetNames(Locator loc1, Locator loc2) { - for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { - String name1 = loc1.workbook.getSheetName(i); - String name2 = (loc2.workbook.getNumberOfSheets() > i) ? loc2.workbook.getSheetName(i) : ""; - - if (!name1.equals(name2)) { - String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]", - "Name of the sheets do not match ::", name1, i+1, name2, i+1 - ); - listOfDifferences.add(str); - } - } - } - - /** - * Formats the message. - */ - private void addMessage(Locator loc1, Locator loc2, String messageStart, String value1, String value2) { - String str = - String.format(Locale.ROOT, "%s\nworkbook1 -> %s -> %s [%s] != workbook2 -> %s -> %s [%s]", - messageStart, - loc1.sheet.getSheetName(), new CellReference(loc1.cell).formatAsString(), value1, - loc2.sheet.getSheetName(), new CellReference(loc2.cell).formatAsString(), value2 - ); - listOfDifferences.add(str); - } - - /** - * Checks if cell alignment matches. - */ - private void isCellAlignmentMatches(Locator loc1, Locator loc2) { - // TODO: check for NPE - short align1 = loc1.cell.getCellStyle().getAlignment(); - short align2 = loc2.cell.getCellStyle().getAlignment(); - if (align1 != align2) { - addMessage(loc1, loc2, - "Cell Alignment does not Match ::", - Short.toString(align1), - Short.toString(align2) - ); - } - } - - /** - * Checks if cell border bottom matches. - */ - private void isCellBorderMatches(Locator loc1, Locator loc2, char borderSide) { - if (!(loc1.cell instanceof XSSFCell)) return; - XSSFCellStyle style1 = ((XSSFCell)loc1.cell).getCellStyle(); - XSSFCellStyle style2 = ((XSSFCell)loc2.cell).getCellStyle(); - boolean b1, b2; - String borderName; - switch (borderSide) { - case 't': default: - b1 = style1.getBorderTopEnum() == BorderStyle.THIN; - b2 = style2.getBorderTopEnum() == BorderStyle.THIN; - borderName = "TOP"; - break; - case 'b': - b1 = style1.getBorderBottomEnum() == BorderStyle.THIN; - b2 = style2.getBorderBottomEnum() == BorderStyle.THIN; - borderName = "BOTTOM"; - break; - case 'l': - b1 = style1.getBorderLeftEnum() == BorderStyle.THIN; - b2 = style2.getBorderLeftEnum() == BorderStyle.THIN; - borderName = "LEFT"; - break; - case 'r': - b1 = style1.getBorderRightEnum() == BorderStyle.THIN; - b2 = style2.getBorderRightEnum() == BorderStyle.THIN; - borderName = "RIGHT"; - break; - } - if (b1 != b2) { - addMessage(loc1, loc2, - "Cell Border Attributes does not Match ::", - (b1 ? "" : "NOT ")+borderName+" BORDER", - (b2 ? "" : "NOT ")+borderName+" BORDER" - ); - } - } - - /** - * Checks if cell content matches. - */ - private void isCellContentMatches(Locator loc1, Locator loc2) { - // TODO: check for null and non-rich-text cells - String str1 = loc1.cell.getRichStringCellValue().getString(); - String str2 = loc2.cell.getRichStringCellValue().getString(); - if (!str1.equals(str2)) { - addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,str1,str2); - } - } - - /** - * Checks if cell content matches for boolean. - */ - private void isCellContentMatchesForBoolean(Locator loc1, Locator loc2) { - boolean b1 = loc1.cell.getBooleanCellValue(); - boolean b2 = loc2.cell.getBooleanCellValue(); - if (b1 != b2) { - addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,Boolean.toString(b1),Boolean.toString(b2)); - } - } - - /** - * Checks if cell content matches for date. - */ - private void isCellContentMatchesForDate(Locator loc1, Locator loc2) { - Date date1 = loc1.cell.getDateCellValue(); - Date date2 = loc2.cell.getDateCellValue(); - if (!date1.equals(date2)) { - addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, date1.toGMTString(), date2.toGMTString()); - } - } - - - /** - * Checks if cell content matches for formula. - */ - private void isCellContentMatchesForFormula(Locator loc1, Locator loc2) { - // TODO: actually evaluate the formula / NPE checks - String form1 = loc1.cell.getCellFormula(); - String form2 = loc2.cell.getCellFormula(); - if (!form1.equals(form2)) { - addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, form1, form2); - } - } - - /** - * Checks if cell content matches for numeric. - */ - private void isCellContentMatchesForNumeric(Locator loc1, Locator loc2) { - // TODO: Check for NaN - double num1 = loc1.cell.getNumericCellValue(); - double num2 = loc2.cell.getNumericCellValue(); - if (num1 != num2) { - addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, Double.toString(num1), Double.toString(num2)); - } - } - - private String getCellFillBackground(Locator loc) { - Color col = loc.cell.getCellStyle().getFillForegroundColorColor(); - return (col instanceof XSSFColor) ? ((XSSFColor)col).getARGBHex() : "NO COLOR"; - } - - /** - * Checks if cell file back ground matches. - */ - private void isCellFillBackGroundMatches(Locator loc1, Locator loc2) { - String col1 = getCellFillBackground(loc1); - String col2 = getCellFillBackground(loc2); - if (!col1.equals(col2)) { - addMessage(loc1, loc2, "Cell Fill Color does not Match ::", col1, col2); - } - } - /** - * Checks if cell fill pattern matches. - */ - private void isCellFillPatternMatches(Locator loc1, Locator loc2) { - // TOOO: Check for NPE - short fill1 = loc1.cell.getCellStyle().getFillPattern(); - short fill2 = loc2.cell.getCellStyle().getFillPattern(); - if (fill1 != fill2) { - addMessage(loc1, loc2, - "Cell Fill pattern does not Match ::", - Short.toString(fill1), - Short.toString(fill2) - ); - } - } - - /** - * Checks if cell font bold matches. - */ - private void isCellFontBoldMatches(Locator loc1, Locator loc2) { - if (!(loc1.cell instanceof XSSFCell)) return; - boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getBold(); - boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getBold(); - if (b1 != b2) { - addMessage(loc1, loc2, - CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, - (b1 ? "" : "NOT ")+"BOLD", - (b2 ? "" : "NOT ")+"BOLD" - ); - } - } - - /** - * Checks if cell font family matches. - */ - private void isCellFontFamilyMatches(Locator loc1, Locator loc2) { - // TODO: Check for NPEs - if (!(loc1.cell instanceof XSSFCell)) return; - String family1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontName(); - String family2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontName(); - if (!family1.equals(family2)) { - addMessage(loc1, loc2, "Cell Font Family does not Match ::", family1, family2); - } - } - - /** - * Checks if cell font italics matches. - */ - private void isCellFontItalicsMatches(Locator loc1, Locator loc2) { - if (!(loc1.cell instanceof XSSFCell)) return; - boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getItalic(); - boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getItalic(); - if (b1 != b2) { - addMessage(loc1, loc2, - CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, - (b1 ? "" : "NOT ")+"ITALICS", - (b2 ? "" : "NOT ")+"ITALICS" - ); - } - } - - /** - * Checks if cell font size matches. - */ - private void isCellFontSizeMatches(Locator loc1, Locator loc2) { - if (!(loc1.cell instanceof XSSFCell)) return; - short size1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontHeightInPoints(); - short size2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontHeightInPoints(); - if (size1 != size2) { - addMessage(loc1, loc2, - "Cell Font Size does not Match ::", - Short.toString(size1), - Short.toString(size2) - ); - } - } - - /** - * Checks if cell hidden matches. - */ - private void isCellHiddenMatches(Locator loc1, Locator loc2) { - boolean b1 = loc1.cell.getCellStyle().getHidden(); - boolean b2 = loc1.cell.getCellStyle().getHidden(); - if (b1 != b2) { - addMessage(loc1, loc2, - "Cell Visibility does not Match ::", - (b1 ? "" : "NOT ")+"HIDDEN", - (b2 ? "" : "NOT ")+"HIDDEN" - ); - } - } - - /** - * Checks if cell locked matches. - */ - private void isCellLockedMatches(Locator loc1, Locator loc2) { - boolean b1 = loc1.cell.getCellStyle().getLocked(); - boolean b2 = loc1.cell.getCellStyle().getLocked(); - if (b1 != b2) { - addMessage(loc1, loc2, - "Cell Protection does not Match ::", - (b1 ? "" : "NOT ")+"LOCKED", - (b2 ? "" : "NOT ")+"LOCKED" - ); - } - } - - /** - * Checks if cell type matches. - */ - private boolean isCellTypeMatches(Locator loc1, Locator loc2) { - CellType type1 = loc1.cell.getCellTypeEnum(); - CellType type2 = loc2.cell.getCellTypeEnum(); - if (type1 == type2) return true; - addMessage(loc1, loc2, - "Cell Data-Type does not Match in :: ", - type1.name(), type2.name() - ); - return false; - } - - /** - * Checks if cell under line matches. - * - * @param cellWorkBook1 - * the cell work book1 - * @param cellWorkBook2 - * the cell work book2 - * @return true, if cell under line matches - */ - private void isCellUnderLineMatches(Locator loc1, Locator loc2) { - // TOOO: distinguish underline type - if (!(loc1.cell instanceof XSSFCell)) return; - byte b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getUnderline(); - byte b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getUnderline(); - if (b1 != b2) { - addMessage(loc1, loc2, - CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, - (b1 == 1 ? "" : "NOT ")+"UNDERLINE", - (b2 == 1 ? "" : "NOT ")+"UNDERLINE" - ); - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.examples; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Color; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; + +/** + * Utility to compare Excel File Contents cell by cell for all sheets. + * + *

This utility will be used to compare Excel File Contents cell by cell for all sheets programmatically.

+ * + *

Below are the list of Attribute comparison supported in this version.

+ * + *
    + *
  • Cell Alignment
  • + *
  • Cell Border Attributes
  • + *
  • Cell Data
  • + *
  • Cell Data-Type
  • + *
  • Cell Fill Color
  • + *
  • Cell Fill pattern
  • + *
  • Cell Font Attributes
  • + *
  • Cell Font Family
  • + *
  • Cell Font Size
  • + *
  • Cell Protection
  • + *
  • Name of the sheets
  • + *
  • Number of Columns
  • + *
  • Number of Rows
  • + *
  • Number of Sheet
  • + *
+ * + *

(Some of the above attribute comparison only work for *.xlsx format currently. In future it can be enhanced.)

+ * + *

Usage:

+ * + *
+ * {@code
+ *  Workbook wb1 = WorkbookFactory.create(new File("workBook1.xls"));
+ *  Workbook wb2 = WorkbookFactory.create(new File("workBook2.xls"));
+ *  List listOfDifferences = ExcelComparator.compare(wb1, wb2);
+ *  for (String differences : listOfDifferences)
+ *      System.out.println(differences);
+ *  System.out.println("DifferenceFound = "+ excelFileDifference.isDifferenceFound);
+ *  }
+ * 
+ */ +public class ExcelComparator { + + private static final String CELL_DATA_DOES_NOT_MATCH = "Cell Data does not Match ::"; + private static final String CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH = "Cell Font Attributes does not Match ::"; + + private static class Locator { + Workbook workbook; + Sheet sheet; + Row row; + Cell cell; + } + + List listOfDifferences = new ArrayList(); + + public static void main(String args[]) throws Exception { + if (args.length != 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) { + System.err.println("java -cp "+ExcelComparator.class.getCanonicalName()+" compare(Workbook wb1, Workbook wb2) { + Locator loc1 = new Locator(); + Locator loc2 = new Locator(); + loc1.workbook = wb1; + loc2.workbook = wb2; + + ExcelComparator excelComparator = new ExcelComparator(); + excelComparator.compareNumberOfSheets(loc1, loc2 ); + excelComparator.compareSheetNames(loc1, loc2); + excelComparator.compareSheetData(loc1, loc2); + + return excelComparator.listOfDifferences; + } + + /** + * Compare data in all sheets. + * + * @param workbook1 the workbook1 + * @param workbook2 the workbook2 + * @param listOfDifferences the list of differences + * @throws ExcelCompareException the excel compare exception + */ + private void compareDataInAllSheets(Locator loc1, Locator loc2) { + for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { + if (loc2.workbook.getNumberOfSheets() <= i) return; + + loc1.sheet = loc1.workbook.getSheetAt(i); + loc2.sheet = loc2.workbook.getSheetAt(i); + + compareDataInSheet(loc1, loc2); + } + } + + private void compareDataInSheet(Locator loc1, Locator loc2) { + for (int j = 0; j < loc1.sheet.getPhysicalNumberOfRows(); j++) { + if (loc2.sheet.getPhysicalNumberOfRows() <= j) return; + + loc1.row = loc1.sheet.getRow(j); + loc2.row = loc2.sheet.getRow(j); + + if ((loc1.row == null) || (loc2.row == null)) { + continue; + } + + compareDataInRow(loc1, loc2); + } + } + + private void compareDataInRow(Locator loc1, Locator loc2) { + for (int k = 0; k < loc1.row.getLastCellNum(); k++) { + if (loc2.row.getPhysicalNumberOfCells() <= k) return; + + loc1.cell = loc1.row.getCell(k); + loc2.cell = loc2.row.getCell(k); + + if ((loc1.cell == null) || (loc2.cell == null)) { + continue; + } + + compareDataInCell(loc1, loc2); + } + } + + private void compareDataInCell(Locator loc1, Locator loc2) { + if (isCellTypeMatches(loc1, loc2)) { + final CellType loc1cellType = loc1.cell.getCellTypeEnum(); + switch(loc1cellType) { + case BLANK: + case STRING: + case ERROR: + isCellContentMatches(loc1,loc2); + break; + case BOOLEAN: + isCellContentMatchesForBoolean(loc1,loc2); + break; + case FORMULA: + isCellContentMatchesForFormula(loc1,loc2); + break; + case NUMERIC: + if (DateUtil.isCellDateFormatted(loc1.cell)) { + isCellContentMatchesForDate(loc1,loc2); + } else { + isCellContentMatchesForNumeric(loc1,loc2); + } + break; + default: + throw new IllegalStateException("Unexpected cell type: " + loc1cellType); + } + } + + isCellFillPatternMatches(loc1,loc2); + isCellAlignmentMatches(loc1,loc2); + isCellHiddenMatches(loc1,loc2); + isCellLockedMatches(loc1,loc2); + isCellFontFamilyMatches(loc1,loc2); + isCellFontSizeMatches(loc1,loc2); + isCellFontBoldMatches(loc1,loc2); + isCellUnderLineMatches(loc1,loc2); + isCellFontItalicsMatches(loc1,loc2); + isCellBorderMatches(loc1,loc2,'t'); + isCellBorderMatches(loc1,loc2,'l'); + isCellBorderMatches(loc1,loc2,'b'); + isCellBorderMatches(loc1,loc2,'r'); + isCellFillBackGroundMatches(loc1,loc2); + } + + /** + * Compare number of columns in sheets. + */ + private void compareNumberOfColumnsInSheets(Locator loc1, Locator loc2) { + for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { + if (loc2.workbook.getNumberOfSheets() <= i) return; + + loc1.sheet = loc1.workbook.getSheetAt(i); + loc2.sheet = loc2.workbook.getSheetAt(i); + + Iterator ri1 = loc1.sheet.rowIterator(); + Iterator ri2 = loc2.sheet.rowIterator(); + + int num1 = (ri1.hasNext()) ? ri1.next().getPhysicalNumberOfCells() : 0; + int num2 = (ri2.hasNext()) ? ri2.next().getPhysicalNumberOfCells() : 0; + + if (num1 != num2) { + String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]", + "Number Of Columns does not Match ::", + loc1.sheet.getSheetName(), num1, + loc2.sheet.getSheetName(), num2 + ); + listOfDifferences.add(str); + } + } + } + + /** + * Compare number of rows in sheets. + */ + private void compareNumberOfRowsInSheets(Locator loc1, Locator loc2) { + for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { + if (loc2.workbook.getNumberOfSheets() <= i) return; + + loc1.sheet = loc1.workbook.getSheetAt(i); + loc2.sheet = loc2.workbook.getSheetAt(i); + + int num1 = loc1.sheet.getPhysicalNumberOfRows(); + int num2 = loc2.sheet.getPhysicalNumberOfRows(); + + if (num1 != num2) { + String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]", + "Number Of Rows does not Match ::", + loc1.sheet.getSheetName(), num1, + loc2.sheet.getSheetName(), num2 + ); + listOfDifferences.add(str); + } + } + + } + + /** + * Compare number of sheets. + */ + private void compareNumberOfSheets(Locator loc1, Locator loc2) { + int num1 = loc1.workbook.getNumberOfSheets(); + int num2 = loc2.workbook.getNumberOfSheets(); + if (num1 != num2) { + String str = String.format(Locale.ROOT, "%s\nworkbook1 [%d] != workbook2 [%d]", + "Number of Sheets do not match ::", + num1, num2 + ); + + listOfDifferences.add(str); + + } + } + + /** + * Compare sheet data. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param listOfDifferences + * + * @throws ExcelCompareException + * the excel compare exception + */ + private void compareSheetData(Locator loc1, Locator loc2) { + compareNumberOfRowsInSheets(loc1, loc2); + compareNumberOfColumnsInSheets(loc1, loc2); + compareDataInAllSheets(loc1, loc2); + + } + + /** + * Compare sheet names. + */ + private void compareSheetNames(Locator loc1, Locator loc2) { + for (int i = 0; i < loc1.workbook.getNumberOfSheets(); i++) { + String name1 = loc1.workbook.getSheetName(i); + String name2 = (loc2.workbook.getNumberOfSheets() > i) ? loc2.workbook.getSheetName(i) : ""; + + if (!name1.equals(name2)) { + String str = String.format(Locale.ROOT, "%s\nworkbook1 -> %s [%d] != workbook2 -> %s [%d]", + "Name of the sheets do not match ::", name1, i+1, name2, i+1 + ); + listOfDifferences.add(str); + } + } + } + + /** + * Formats the message. + */ + private void addMessage(Locator loc1, Locator loc2, String messageStart, String value1, String value2) { + String str = + String.format(Locale.ROOT, "%s\nworkbook1 -> %s -> %s [%s] != workbook2 -> %s -> %s [%s]", + messageStart, + loc1.sheet.getSheetName(), new CellReference(loc1.cell).formatAsString(), value1, + loc2.sheet.getSheetName(), new CellReference(loc2.cell).formatAsString(), value2 + ); + listOfDifferences.add(str); + } + + /** + * Checks if cell alignment matches. + */ + private void isCellAlignmentMatches(Locator loc1, Locator loc2) { + // TODO: check for NPE + short align1 = loc1.cell.getCellStyle().getAlignment(); + short align2 = loc2.cell.getCellStyle().getAlignment(); + if (align1 != align2) { + addMessage(loc1, loc2, + "Cell Alignment does not Match ::", + Short.toString(align1), + Short.toString(align2) + ); + } + } + + /** + * Checks if cell border bottom matches. + */ + private void isCellBorderMatches(Locator loc1, Locator loc2, char borderSide) { + if (!(loc1.cell instanceof XSSFCell)) return; + XSSFCellStyle style1 = ((XSSFCell)loc1.cell).getCellStyle(); + XSSFCellStyle style2 = ((XSSFCell)loc2.cell).getCellStyle(); + boolean b1, b2; + String borderName; + switch (borderSide) { + case 't': default: + b1 = style1.getBorderTopEnum() == BorderStyle.THIN; + b2 = style2.getBorderTopEnum() == BorderStyle.THIN; + borderName = "TOP"; + break; + case 'b': + b1 = style1.getBorderBottomEnum() == BorderStyle.THIN; + b2 = style2.getBorderBottomEnum() == BorderStyle.THIN; + borderName = "BOTTOM"; + break; + case 'l': + b1 = style1.getBorderLeftEnum() == BorderStyle.THIN; + b2 = style2.getBorderLeftEnum() == BorderStyle.THIN; + borderName = "LEFT"; + break; + case 'r': + b1 = style1.getBorderRightEnum() == BorderStyle.THIN; + b2 = style2.getBorderRightEnum() == BorderStyle.THIN; + borderName = "RIGHT"; + break; + } + if (b1 != b2) { + addMessage(loc1, loc2, + "Cell Border Attributes does not Match ::", + (b1 ? "" : "NOT ")+borderName+" BORDER", + (b2 ? "" : "NOT ")+borderName+" BORDER" + ); + } + } + + /** + * Checks if cell content matches. + */ + private void isCellContentMatches(Locator loc1, Locator loc2) { + // TODO: check for null and non-rich-text cells + String str1 = loc1.cell.getRichStringCellValue().getString(); + String str2 = loc2.cell.getRichStringCellValue().getString(); + if (!str1.equals(str2)) { + addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,str1,str2); + } + } + + /** + * Checks if cell content matches for boolean. + */ + private void isCellContentMatchesForBoolean(Locator loc1, Locator loc2) { + boolean b1 = loc1.cell.getBooleanCellValue(); + boolean b2 = loc2.cell.getBooleanCellValue(); + if (b1 != b2) { + addMessage(loc1,loc2,CELL_DATA_DOES_NOT_MATCH,Boolean.toString(b1),Boolean.toString(b2)); + } + } + + /** + * Checks if cell content matches for date. + */ + private void isCellContentMatchesForDate(Locator loc1, Locator loc2) { + Date date1 = loc1.cell.getDateCellValue(); + Date date2 = loc2.cell.getDateCellValue(); + if (!date1.equals(date2)) { + addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, date1.toGMTString(), date2.toGMTString()); + } + } + + + /** + * Checks if cell content matches for formula. + */ + private void isCellContentMatchesForFormula(Locator loc1, Locator loc2) { + // TODO: actually evaluate the formula / NPE checks + String form1 = loc1.cell.getCellFormula(); + String form2 = loc2.cell.getCellFormula(); + if (!form1.equals(form2)) { + addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, form1, form2); + } + } + + /** + * Checks if cell content matches for numeric. + */ + private void isCellContentMatchesForNumeric(Locator loc1, Locator loc2) { + // TODO: Check for NaN + double num1 = loc1.cell.getNumericCellValue(); + double num2 = loc2.cell.getNumericCellValue(); + if (num1 != num2) { + addMessage(loc1, loc2, CELL_DATA_DOES_NOT_MATCH, Double.toString(num1), Double.toString(num2)); + } + } + + private String getCellFillBackground(Locator loc) { + Color col = loc.cell.getCellStyle().getFillForegroundColorColor(); + return (col instanceof XSSFColor) ? ((XSSFColor)col).getARGBHex() : "NO COLOR"; + } + + /** + * Checks if cell file back ground matches. + */ + private void isCellFillBackGroundMatches(Locator loc1, Locator loc2) { + String col1 = getCellFillBackground(loc1); + String col2 = getCellFillBackground(loc2); + if (!col1.equals(col2)) { + addMessage(loc1, loc2, "Cell Fill Color does not Match ::", col1, col2); + } + } + /** + * Checks if cell fill pattern matches. + */ + private void isCellFillPatternMatches(Locator loc1, Locator loc2) { + // TOOO: Check for NPE + short fill1 = loc1.cell.getCellStyle().getFillPattern(); + short fill2 = loc2.cell.getCellStyle().getFillPattern(); + if (fill1 != fill2) { + addMessage(loc1, loc2, + "Cell Fill pattern does not Match ::", + Short.toString(fill1), + Short.toString(fill2) + ); + } + } + + /** + * Checks if cell font bold matches. + */ + private void isCellFontBoldMatches(Locator loc1, Locator loc2) { + if (!(loc1.cell instanceof XSSFCell)) return; + boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getBold(); + boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getBold(); + if (b1 != b2) { + addMessage(loc1, loc2, + CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, + (b1 ? "" : "NOT ")+"BOLD", + (b2 ? "" : "NOT ")+"BOLD" + ); + } + } + + /** + * Checks if cell font family matches. + */ + private void isCellFontFamilyMatches(Locator loc1, Locator loc2) { + // TODO: Check for NPEs + if (!(loc1.cell instanceof XSSFCell)) return; + String family1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontName(); + String family2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontName(); + if (!family1.equals(family2)) { + addMessage(loc1, loc2, "Cell Font Family does not Match ::", family1, family2); + } + } + + /** + * Checks if cell font italics matches. + */ + private void isCellFontItalicsMatches(Locator loc1, Locator loc2) { + if (!(loc1.cell instanceof XSSFCell)) return; + boolean b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getItalic(); + boolean b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getItalic(); + if (b1 != b2) { + addMessage(loc1, loc2, + CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, + (b1 ? "" : "NOT ")+"ITALICS", + (b2 ? "" : "NOT ")+"ITALICS" + ); + } + } + + /** + * Checks if cell font size matches. + */ + private void isCellFontSizeMatches(Locator loc1, Locator loc2) { + if (!(loc1.cell instanceof XSSFCell)) return; + short size1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getFontHeightInPoints(); + short size2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getFontHeightInPoints(); + if (size1 != size2) { + addMessage(loc1, loc2, + "Cell Font Size does not Match ::", + Short.toString(size1), + Short.toString(size2) + ); + } + } + + /** + * Checks if cell hidden matches. + */ + private void isCellHiddenMatches(Locator loc1, Locator loc2) { + boolean b1 = loc1.cell.getCellStyle().getHidden(); + boolean b2 = loc1.cell.getCellStyle().getHidden(); + if (b1 != b2) { + addMessage(loc1, loc2, + "Cell Visibility does not Match ::", + (b1 ? "" : "NOT ")+"HIDDEN", + (b2 ? "" : "NOT ")+"HIDDEN" + ); + } + } + + /** + * Checks if cell locked matches. + */ + private void isCellLockedMatches(Locator loc1, Locator loc2) { + boolean b1 = loc1.cell.getCellStyle().getLocked(); + boolean b2 = loc1.cell.getCellStyle().getLocked(); + if (b1 != b2) { + addMessage(loc1, loc2, + "Cell Protection does not Match ::", + (b1 ? "" : "NOT ")+"LOCKED", + (b2 ? "" : "NOT ")+"LOCKED" + ); + } + } + + /** + * Checks if cell type matches. + */ + private boolean isCellTypeMatches(Locator loc1, Locator loc2) { + CellType type1 = loc1.cell.getCellTypeEnum(); + CellType type2 = loc2.cell.getCellTypeEnum(); + if (type1 == type2) return true; + addMessage(loc1, loc2, + "Cell Data-Type does not Match in :: ", + type1.name(), type2.name() + ); + return false; + } + + /** + * Checks if cell under line matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell under line matches + */ + private void isCellUnderLineMatches(Locator loc1, Locator loc2) { + // TOOO: distinguish underline type + if (!(loc1.cell instanceof XSSFCell)) return; + byte b1 = ((XSSFCell)loc1.cell).getCellStyle().getFont().getUnderline(); + byte b2 = ((XSSFCell)loc2.cell).getCellStyle().getFont().getUnderline(); + if (b1 != b2) { + addMessage(loc1, loc2, + CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, + (b1 == 1 ? "" : "NOT ")+"UNDERLINE", + (b2 == 1 ? "" : "NOT ")+"UNDERLINE" + ); + } + } } \ No newline at end of file diff --git a/src/examples/src/org/apache/poi/ss/examples/LinkedDropDownLists.java b/src/examples/src/org/apache/poi/ss/examples/LinkedDropDownLists.java index 7b672b792c..8f43b4bf66 100644 --- a/src/examples/src/org/apache/poi/ss/examples/LinkedDropDownLists.java +++ b/src/examples/src/org/apache/poi/ss/examples/LinkedDropDownLists.java @@ -1,211 +1,211 @@ - /* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ==================================================================== */ - -package org.apache.poi.ss.examples; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.DataValidation; -import org.apache.poi.ss.usermodel.DataValidationConstraint; -import org.apache.poi.ss.usermodel.DataValidationHelper; -import org.apache.poi.ss.usermodel.Name; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -/** - * Demonstrates one technique that may be used to create linked or dependent - * drop down lists. This refers to a situation in which the selection made - * in one drop down list affects the options that are displayed in the second - * or subsequent drop down list(s). In this example, the value the user selects - * from the down list in cell A1 will affect the values displayed in the linked - * drop down list in cell B1. For the sake of simplicity, the data for the drop - * down lists is included on the same worksheet but this does not have to be the - * case; the data could appear on a separate sheet. If this were done, then the - * names for the regions would have to be different, they would have to include - * the name of the sheet. - * - * There are two keys to this technique. The first is the use of named area or - * regions of cells to hold the data for the drop down lists and the second is - * making use of the INDIRECT() function to convert a name into the addresses - * of the cells it refers to. - * - * Note that whilst this class builds just two linked drop down lists, there is - * nothing to prevent more being created. Quite simply, use the value selected - * by the user in one drop down list to determine what is shown in another and the - * value selected in that drop down list to determine what is shown in a third, - * and so on. Also, note that the data for the drop down lists is contained on - * contained on the same sheet as the validations themselves. This is done simply - * for simplicity and there is nothing to prevent a separate sheet being created - * and used to hold the data. If this is done then problems may be encountered - * if the sheet is opened with OpenOffice Calc. To prevent these problems, it is - * better to include the name of the sheet when calling the setRefersToFormula() - * method. - * - * @author Mark Beardsley [msb at apache.org] - * @version 1.00 30th March 2012 - */ -public class LinkedDropDownLists { - - LinkedDropDownLists(String workbookName) throws IOException { - // Using the ss.usermodel allows this class to support both binary - // and xml based workbooks. The choice of which one to create is - // made by checking the file extension. - Workbook workbook; - if (workbookName.endsWith(".xlsx")) { - workbook = new XSSFWorkbook(); - } else { - workbook = new HSSFWorkbook(); - } - - // Build the sheet that will hold the data for the validations. This - // must be done first as it will create names that are referenced - // later. - Sheet sheet = workbook.createSheet("Linked Validations"); - LinkedDropDownLists.buildDataSheet(sheet); - - // Build the first data validation to occupy cell A1. Note - // that it retrieves it's data from the named area or region called - // CHOICES. Further information about this can be found in the - // static buildDataSheet() method below. - CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0); - DataValidationHelper dvHelper = sheet.getDataValidationHelper(); - DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint("CHOICES"); - DataValidation validation = dvHelper.createValidation(dvConstraint, addressList); - sheet.addValidationData(validation); - - // Now, build the linked or dependent drop down list that will - // occupy cell B1. The key to the whole process is the use of the - // INDIRECT() function. In the buildDataSheet(0 method, a series of - // named regions are created and the names of three of them mirror - // the options available to the user in the first drop down list - // (in cell A1). Using the INDIRECT() function makes it possible - // to convert the selection the user makes in that first drop down - // into the addresses of a named region of cells and then to use - // those cells to populate the second drop down list. - addressList = new CellRangeAddressList(0, 0, 1, 1); - dvConstraint = dvHelper.createFormulaListConstraint( - "INDIRECT(UPPER($A$1))"); - validation = dvHelper.createValidation(dvConstraint, addressList); - sheet.addValidationData(validation); - - FileOutputStream fos = new FileOutputStream(workbookName); - workbook.write(fos); - fos.close(); - workbook.close(); - } - - /** - * Called to populate the named areas/regions. The contents of the cells on - * row one will be used to populate the first drop down list. The contents of - * the cells on rows two, three and four will be used to populate the second - * drop down list, just which row will be determined by the choice the user - * makes in the first drop down list. - * - * In all cases, the approach is to create a row, create and populate cells - * with data and then specify a name that identifies those cells. With the - * exception of the first range, the names that are chosen for each range - * of cells are quite important. In short, each of the options the user - * could select in the first drop down list is used as the name for another - * range of cells. Thus, in this example, the user can select either - * 'Animal', 'Vegetable' or 'Mineral' in the first drop down and so the - * sheet contains ranges named 'ANIMAL', 'VEGETABLE' and 'MINERAL'. - * - * @param dataSheet An instance of a class that implements the Sheet Sheet - * interface (HSSFSheet or XSSFSheet). - */ - private static final void buildDataSheet(Sheet dataSheet) { - Row row = null; - Cell cell = null; - Name name = null; - - // The first row will hold the data for the first validation. - row = dataSheet.createRow(10); - cell = row.createCell(0); - cell.setCellValue("Animal"); - cell = row.createCell(1); - cell.setCellValue("Vegetable"); - cell = row.createCell(2); - cell.setCellValue("Mineral"); - name = dataSheet.getWorkbook().createName(); - name.setRefersToFormula("$A$11:$C$11"); - name.setNameName("CHOICES"); - - // The next three rows will hold the data that will be used to - // populate the second, or linked, drop down list. - row = dataSheet.createRow(11); - cell = row.createCell(0); - cell.setCellValue("Lion"); - cell = row.createCell(1); - cell.setCellValue("Tiger"); - cell = row.createCell(2); - cell.setCellValue("Leopard"); - cell = row.createCell(3); - cell.setCellValue("Elephant"); - cell = row.createCell(4); - cell.setCellValue("Eagle"); - cell = row.createCell(5); - cell.setCellValue("Horse"); - cell = row.createCell(6); - cell.setCellValue("Zebra"); - name = dataSheet.getWorkbook().createName(); - name.setRefersToFormula("$A$12:$G$12"); - name.setNameName("ANIMAL"); - - row = dataSheet.createRow(12); - cell = row.createCell(0); - cell.setCellValue("Cabbage"); - cell = row.createCell(1); - cell.setCellValue("Cauliflower"); - cell = row.createCell(2); - cell.setCellValue("Potato"); - cell = row.createCell(3); - cell.setCellValue("Onion"); - cell = row.createCell(4); - cell.setCellValue("Beetroot"); - cell = row.createCell(5); - cell.setCellValue("Asparagus"); - cell = row.createCell(6); - cell.setCellValue("Spinach"); - cell = row.createCell(7); - cell.setCellValue("Chard"); - name = dataSheet.getWorkbook().createName(); - name.setRefersToFormula("$A$13:$H$13"); - name.setNameName("VEGETABLE"); - - row = dataSheet.createRow(13); - cell = row.createCell(0); - cell.setCellValue("Bauxite"); - cell = row.createCell(1); - cell.setCellValue("Quartz"); - cell = row.createCell(2); - cell.setCellValue("Feldspar"); - cell = row.createCell(3); - cell.setCellValue("Shist"); - cell = row.createCell(4); - cell.setCellValue("Shale"); - cell = row.createCell(5); - cell.setCellValue("Mica"); - name = dataSheet.getWorkbook().createName(); - name.setRefersToFormula("$A$14:$F$14"); - name.setNameName("MINERAL"); - } -} + /* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==================================================================== */ + +package org.apache.poi.ss.examples; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Demonstrates one technique that may be used to create linked or dependent + * drop down lists. This refers to a situation in which the selection made + * in one drop down list affects the options that are displayed in the second + * or subsequent drop down list(s). In this example, the value the user selects + * from the down list in cell A1 will affect the values displayed in the linked + * drop down list in cell B1. For the sake of simplicity, the data for the drop + * down lists is included on the same worksheet but this does not have to be the + * case; the data could appear on a separate sheet. If this were done, then the + * names for the regions would have to be different, they would have to include + * the name of the sheet. + * + * There are two keys to this technique. The first is the use of named area or + * regions of cells to hold the data for the drop down lists and the second is + * making use of the INDIRECT() function to convert a name into the addresses + * of the cells it refers to. + * + * Note that whilst this class builds just two linked drop down lists, there is + * nothing to prevent more being created. Quite simply, use the value selected + * by the user in one drop down list to determine what is shown in another and the + * value selected in that drop down list to determine what is shown in a third, + * and so on. Also, note that the data for the drop down lists is contained on + * contained on the same sheet as the validations themselves. This is done simply + * for simplicity and there is nothing to prevent a separate sheet being created + * and used to hold the data. If this is done then problems may be encountered + * if the sheet is opened with OpenOffice Calc. To prevent these problems, it is + * better to include the name of the sheet when calling the setRefersToFormula() + * method. + * + * @author Mark Beardsley [msb at apache.org] + * @version 1.00 30th March 2012 + */ +public class LinkedDropDownLists { + + LinkedDropDownLists(String workbookName) throws IOException { + // Using the ss.usermodel allows this class to support both binary + // and xml based workbooks. The choice of which one to create is + // made by checking the file extension. + Workbook workbook; + if (workbookName.endsWith(".xlsx")) { + workbook = new XSSFWorkbook(); + } else { + workbook = new HSSFWorkbook(); + } + + // Build the sheet that will hold the data for the validations. This + // must be done first as it will create names that are referenced + // later. + Sheet sheet = workbook.createSheet("Linked Validations"); + LinkedDropDownLists.buildDataSheet(sheet); + + // Build the first data validation to occupy cell A1. Note + // that it retrieves it's data from the named area or region called + // CHOICES. Further information about this can be found in the + // static buildDataSheet() method below. + CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0); + DataValidationHelper dvHelper = sheet.getDataValidationHelper(); + DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint("CHOICES"); + DataValidation validation = dvHelper.createValidation(dvConstraint, addressList); + sheet.addValidationData(validation); + + // Now, build the linked or dependent drop down list that will + // occupy cell B1. The key to the whole process is the use of the + // INDIRECT() function. In the buildDataSheet(0 method, a series of + // named regions are created and the names of three of them mirror + // the options available to the user in the first drop down list + // (in cell A1). Using the INDIRECT() function makes it possible + // to convert the selection the user makes in that first drop down + // into the addresses of a named region of cells and then to use + // those cells to populate the second drop down list. + addressList = new CellRangeAddressList(0, 0, 1, 1); + dvConstraint = dvHelper.createFormulaListConstraint( + "INDIRECT(UPPER($A$1))"); + validation = dvHelper.createValidation(dvConstraint, addressList); + sheet.addValidationData(validation); + + FileOutputStream fos = new FileOutputStream(workbookName); + workbook.write(fos); + fos.close(); + workbook.close(); + } + + /** + * Called to populate the named areas/regions. The contents of the cells on + * row one will be used to populate the first drop down list. The contents of + * the cells on rows two, three and four will be used to populate the second + * drop down list, just which row will be determined by the choice the user + * makes in the first drop down list. + * + * In all cases, the approach is to create a row, create and populate cells + * with data and then specify a name that identifies those cells. With the + * exception of the first range, the names that are chosen for each range + * of cells are quite important. In short, each of the options the user + * could select in the first drop down list is used as the name for another + * range of cells. Thus, in this example, the user can select either + * 'Animal', 'Vegetable' or 'Mineral' in the first drop down and so the + * sheet contains ranges named 'ANIMAL', 'VEGETABLE' and 'MINERAL'. + * + * @param dataSheet An instance of a class that implements the Sheet Sheet + * interface (HSSFSheet or XSSFSheet). + */ + private static final void buildDataSheet(Sheet dataSheet) { + Row row = null; + Cell cell = null; + Name name = null; + + // The first row will hold the data for the first validation. + row = dataSheet.createRow(10); + cell = row.createCell(0); + cell.setCellValue("Animal"); + cell = row.createCell(1); + cell.setCellValue("Vegetable"); + cell = row.createCell(2); + cell.setCellValue("Mineral"); + name = dataSheet.getWorkbook().createName(); + name.setRefersToFormula("$A$11:$C$11"); + name.setNameName("CHOICES"); + + // The next three rows will hold the data that will be used to + // populate the second, or linked, drop down list. + row = dataSheet.createRow(11); + cell = row.createCell(0); + cell.setCellValue("Lion"); + cell = row.createCell(1); + cell.setCellValue("Tiger"); + cell = row.createCell(2); + cell.setCellValue("Leopard"); + cell = row.createCell(3); + cell.setCellValue("Elephant"); + cell = row.createCell(4); + cell.setCellValue("Eagle"); + cell = row.createCell(5); + cell.setCellValue("Horse"); + cell = row.createCell(6); + cell.setCellValue("Zebra"); + name = dataSheet.getWorkbook().createName(); + name.setRefersToFormula("$A$12:$G$12"); + name.setNameName("ANIMAL"); + + row = dataSheet.createRow(12); + cell = row.createCell(0); + cell.setCellValue("Cabbage"); + cell = row.createCell(1); + cell.setCellValue("Cauliflower"); + cell = row.createCell(2); + cell.setCellValue("Potato"); + cell = row.createCell(3); + cell.setCellValue("Onion"); + cell = row.createCell(4); + cell.setCellValue("Beetroot"); + cell = row.createCell(5); + cell.setCellValue("Asparagus"); + cell = row.createCell(6); + cell.setCellValue("Spinach"); + cell = row.createCell(7); + cell.setCellValue("Chard"); + name = dataSheet.getWorkbook().createName(); + name.setRefersToFormula("$A$13:$H$13"); + name.setNameName("VEGETABLE"); + + row = dataSheet.createRow(13); + cell = row.createCell(0); + cell.setCellValue("Bauxite"); + cell = row.createCell(1); + cell.setCellValue("Quartz"); + cell = row.createCell(2); + cell.setCellValue("Feldspar"); + cell = row.createCell(3); + cell.setCellValue("Shist"); + cell = row.createCell(4); + cell.setCellValue("Shale"); + cell = row.createCell(5); + cell.setCellValue("Mica"); + name = dataSheet.getWorkbook().createName(); + name.setRefersToFormula("$A$14:$F$14"); + name.setNameName("MINERAL"); + } +} diff --git a/src/examples/src/org/apache/poi/ss/examples/formula/SettingExternalFunction.java b/src/examples/src/org/apache/poi/ss/examples/formula/SettingExternalFunction.java index b9e1f2d37b..51f7c03670 100644 --- a/src/examples/src/org/apache/poi/ss/examples/formula/SettingExternalFunction.java +++ b/src/examples/src/org/apache/poi/ss/examples/formula/SettingExternalFunction.java @@ -1,95 +1,95 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.examples.formula; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.ValueEval; -import org.apache.poi.ss.formula.functions.FreeRefFunction; -import org.apache.poi.ss.formula.udf.UDFFinder; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -/** - * Demonstrates how to use functions provided by third-party add-ins, e.g. Bloomberg Excel Add-in. - * - * There can be situations when you are not interested in formula evaluation, - * you just need to set the formula and the workbook will be evaluation by the client. - */ -public class SettingExternalFunction { - - /** - * wrap external functions in a plugin - */ - public static class BloombergAddIn implements UDFFinder { - private final Map _functionsByName; - - public BloombergAddIn() { - // dummy function that returns NA - // don't care about the implementation, we are not interested in evaluation - // and this method will never be called - FreeRefFunction NA = new FreeRefFunction() { - @Override - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - return ErrorEval.NA; - } - }; - _functionsByName = new HashMap(); - _functionsByName.put("BDP", NA); - _functionsByName.put("BDH", NA); - _functionsByName.put("BDS", NA); - } - - @Override - public FreeRefFunction findFunction(String name) { - return _functionsByName.get(name.toUpperCase(Locale.ROOT)); - } - - } - - public static void main( String[] args ) throws IOException { - - Workbook wb = new XSSFWorkbook(); // or new HSSFWorkbook() - - // register the add-in - wb.addToolPack(new BloombergAddIn()); - - Sheet sheet = wb.createSheet(); - Row row = sheet.createRow(0); - row.createCell(0).setCellFormula("BDP(\"GOOG Equity\",\"CHG_PCT_YTD\")/100"); - row.createCell(1).setCellFormula("BDH(\"goog us equity\",\"EBIT\",\"1/1/2005\",\"12/31/2009\",\"per=cy\",\"curr=USD\") "); - row.createCell(2).setCellFormula("BDS(\"goog us equity\",\"top_20_holders_public_filings\") "); - - FileOutputStream out = new FileOutputStream("bloomberg-demo.xlsx"); - wb.write(out); - out.close(); - - wb.close(); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.examples.formula; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.formula.functions.FreeRefFunction; +import org.apache.poi.ss.formula.udf.UDFFinder; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Demonstrates how to use functions provided by third-party add-ins, e.g. Bloomberg Excel Add-in. + * + * There can be situations when you are not interested in formula evaluation, + * you just need to set the formula and the workbook will be evaluation by the client. + */ +public class SettingExternalFunction { + + /** + * wrap external functions in a plugin + */ + public static class BloombergAddIn implements UDFFinder { + private final Map _functionsByName; + + public BloombergAddIn() { + // dummy function that returns NA + // don't care about the implementation, we are not interested in evaluation + // and this method will never be called + FreeRefFunction NA = new FreeRefFunction() { + @Override + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + return ErrorEval.NA; + } + }; + _functionsByName = new HashMap(); + _functionsByName.put("BDP", NA); + _functionsByName.put("BDH", NA); + _functionsByName.put("BDS", NA); + } + + @Override + public FreeRefFunction findFunction(String name) { + return _functionsByName.get(name.toUpperCase(Locale.ROOT)); + } + + } + + public static void main( String[] args ) throws IOException { + + Workbook wb = new XSSFWorkbook(); // or new HSSFWorkbook() + + // register the add-in + wb.addToolPack(new BloombergAddIn()); + + Sheet sheet = wb.createSheet(); + Row row = sheet.createRow(0); + row.createCell(0).setCellFormula("BDP(\"GOOG Equity\",\"CHG_PCT_YTD\")/100"); + row.createCell(1).setCellFormula("BDH(\"goog us equity\",\"EBIT\",\"1/1/2005\",\"12/31/2009\",\"per=cy\",\"curr=USD\") "); + row.createCell(2).setCellFormula("BDS(\"goog us equity\",\"top_20_holders_public_filings\") "); + + FileOutputStream out = new FileOutputStream("bloomberg-demo.xlsx"); + wb.write(out); + out.close(); + + wb.close(); + } + +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java b/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java index 3358406858..ec8fe23428 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java @@ -1,95 +1,95 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Dimension; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; - -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; - -/** - * Demonstrates how you can extract data from a .pptx file - */ -public final class DataExtraction { - - public static void main(String args[]) throws IOException, OpenXML4JException { - - PrintStream out = System.out; - - if (args.length == 0) { - out.println("Input file is required"); - return; - } - - FileInputStream is = new FileInputStream(args[0]); - XMLSlideShow ppt = new XMLSlideShow(is); - is.close(); - - // Get the document's embedded files. - for (PackagePart p : ppt.getAllEmbedds()) { - String type = p.getContentType(); - // typically file name - String name = p.getPartName().getName(); - out.println("Embedded file ("+type+"): "+name); - - InputStream pIs = p.getInputStream(); - // make sense of the part data - pIs.close(); - - } - - // Get the document's embedded files. - for (XSLFPictureData data : ppt.getPictureData()) { - String type = data.getContentType(); - String name = data.getFileName(); - out.println("Picture ("+type+"): "+name); - - InputStream pIs = data.getInputStream(); - // make sense of the image data - pIs.close(); - } - - // size of the canvas in points - Dimension pageSize = ppt.getPageSize(); - out.println("Pagesize: "+pageSize); - - for(XSLFSlide slide : ppt.getSlides()) { - for(XSLFShape shape : slide){ - if(shape instanceof XSLFTextShape) { - XSLFTextShape txShape = (XSLFTextShape)shape; - out.println(txShape.getText()); - } else if (shape instanceof XSLFPictureShape){ - XSLFPictureShape pShape = (XSLFPictureShape)shape; - XSLFPictureData pData = pShape.getPictureData(); - out.println(pData.getFileName()); - } else { - out.println("Process me: " + shape.getClass()); - } - } - } - - ppt.close(); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Dimension; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; + +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; + +/** + * Demonstrates how you can extract data from a .pptx file + */ +public final class DataExtraction { + + public static void main(String args[]) throws IOException, OpenXML4JException { + + PrintStream out = System.out; + + if (args.length == 0) { + out.println("Input file is required"); + return; + } + + FileInputStream is = new FileInputStream(args[0]); + XMLSlideShow ppt = new XMLSlideShow(is); + is.close(); + + // Get the document's embedded files. + for (PackagePart p : ppt.getAllEmbedds()) { + String type = p.getContentType(); + // typically file name + String name = p.getPartName().getName(); + out.println("Embedded file ("+type+"): "+name); + + InputStream pIs = p.getInputStream(); + // make sense of the part data + pIs.close(); + + } + + // Get the document's embedded files. + for (XSLFPictureData data : ppt.getPictureData()) { + String type = data.getContentType(); + String name = data.getFileName(); + out.println("Picture ("+type+"): "+name); + + InputStream pIs = data.getInputStream(); + // make sense of the image data + pIs.close(); + } + + // size of the canvas in points + Dimension pageSize = ppt.getPageSize(); + out.println("Pagesize: "+pageSize); + + for(XSLFSlide slide : ppt.getSlides()) { + for(XSLFShape shape : slide){ + if(shape instanceof XSLFTextShape) { + XSLFTextShape txShape = (XSLFTextShape)shape; + out.println(txShape.getText()); + } else if (shape instanceof XSLFPictureShape){ + XSLFPictureShape pShape = (XSLFPictureShape)shape; + XSLFPictureData pData = pShape.getPictureData(); + out.println(pData.getFileName()); + } else { + out.println("Process me: " + shape.getClass()); + } + } + } + + ppt.close(); + } + +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/MergePresentations.java b/src/examples/src/org/apache/poi/xslf/usermodel/MergePresentations.java index 38e9285013..73f195eb76 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/MergePresentations.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/MergePresentations.java @@ -1,54 +1,54 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.io.FileInputStream; -import java.io.FileOutputStream; - -/** - * Merge multiple pptx presentations together - * - * @author Yegor Kozlov - */ -public final class MergePresentations { - - public static void main(String args[]) throws Exception { - XMLSlideShow ppt = new XMLSlideShow(); - - for(String arg : args){ - FileInputStream is = new FileInputStream(arg); - XMLSlideShow src = new XMLSlideShow(is); - is.close(); - - for(XSLFSlide srcSlide : src.getSlides()){ - ppt.createSlide().importContent(srcSlide); - } - - src.close(); - } - - FileOutputStream out = new FileOutputStream("merged.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.io.FileInputStream; +import java.io.FileOutputStream; + +/** + * Merge multiple pptx presentations together + * + * @author Yegor Kozlov + */ +public final class MergePresentations { + + public static void main(String args[]) throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + + for(String arg : args){ + FileInputStream is = new FileInputStream(arg); + XMLSlideShow src = new XMLSlideShow(is); + is.close(); + + for(XSLFSlide srcSlide : src.getSlides()){ + ppt.createSlide().importContent(srcSlide); + } + + src.close(); + } + + FileOutputStream out = new FileOutputStream("merged.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } + +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/PieChartDemo.java b/src/examples/src/org/apache/poi/xslf/usermodel/PieChartDemo.java index df98b92964..4ea36e56ec 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/PieChartDemo.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/PieChartDemo.java @@ -1,165 +1,165 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumData; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumVal; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrData; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrVal; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.OutputStream; - -/** - * Build a pie chart from a template pptx - * - * @author Yegor Kozlov - */ -public class PieChartDemo { - private static void usage(){ - System.out.println("Usage: PieChartDemo "); - System.out.println(" pie-chart-template.pptx template with a pie chart"); - System.out.println(" pie-chart-data.txt the model to set. First line is chart title, " + - "then go pairs {axis-label value}"); - } - - public static void main(String[] args) throws Exception { - if(args.length < 2) { - usage(); - return; - } - - BufferedReader modelReader = new BufferedReader(new FileReader(args[1])); - XMLSlideShow pptx = null; - try { - String chartTitle = modelReader.readLine(); // first line is chart title - - pptx = new XMLSlideShow(new FileInputStream(args[0])); - XSLFSlide slide = pptx.getSlides().get(0); - - // find chart in the slide - XSLFChart chart = null; - for(POIXMLDocumentPart part : slide.getRelations()){ - if(part instanceof XSLFChart){ - chart = (XSLFChart) part; - break; - } - } - - if(chart == null) throw new IllegalStateException("chart not found in the template"); - - // embedded Excel workbook that holds the chart data - POIXMLDocumentPart xlsPart = chart.getRelations().get(0); - XSSFWorkbook wb = new XSSFWorkbook(); - try { - XSSFSheet sheet = wb.createSheet(); - - CTChart ctChart = chart.getCTChart(); - CTPlotArea plotArea = ctChart.getPlotArea(); - - CTPieChart pieChart = plotArea.getPieChartArray(0); - //Pie Chart Series - CTPieSer ser = pieChart.getSerArray(0); - - // Series Text - CTSerTx tx = ser.getTx(); - tx.getStrRef().getStrCache().getPtArray(0).setV(chartTitle); - sheet.createRow(0).createCell(1).setCellValue(chartTitle); - String titleRef = new CellReference(sheet.getSheetName(), 0, 1, true, true).formatAsString(); - tx.getStrRef().setF(titleRef); - - // Category Axis Data - CTAxDataSource cat = ser.getCat(); - CTStrData strData = cat.getStrRef().getStrCache(); - - // Values - CTNumDataSource val = ser.getVal(); - CTNumData numData = val.getNumRef().getNumCache(); - - strData.setPtArray(null); // unset old axis text - numData.setPtArray(null); // unset old values - - // set model - int idx = 0; - int rownum = 1; - String ln; - while((ln = modelReader.readLine()) != null){ - String[] vals = ln.split("\\s+"); - CTNumVal numVal = numData.addNewPt(); - numVal.setIdx(idx); - numVal.setV(vals[1]); - - CTStrVal sVal = strData.addNewPt(); - sVal.setIdx(idx); - sVal.setV(vals[0]); - - idx++; - XSSFRow row = sheet.createRow(rownum++); - row.createCell(0).setCellValue(vals[0]); - row.createCell(1).setCellValue(Double.valueOf(vals[1])); - } - numData.getPtCount().setVal(idx); - strData.getPtCount().setVal(idx); - - String numDataRange = new CellRangeAddress(1, rownum-1, 1, 1).formatAsString(sheet.getSheetName(), true); - val.getNumRef().setF(numDataRange); - String axisDataRange = new CellRangeAddress(1, rownum-1, 0, 0).formatAsString(sheet.getSheetName(), true); - cat.getStrRef().setF(axisDataRange); - - // updated the embedded workbook with the data - OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream(); - try { - wb.write(xlsOut); - } finally { - xlsOut.close(); - } - - // save the result - OutputStream out = new FileOutputStream("pie-chart-demo-output.pptx"); - try { - pptx.write(out); - } finally { - out.close(); - } - } finally { - wb.close(); - } - } finally { - if (pptx != null) pptx.close(); - modelReader.close(); - } - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumData; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumVal; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrData; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrVal; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.OutputStream; + +/** + * Build a pie chart from a template pptx + * + * @author Yegor Kozlov + */ +public class PieChartDemo { + private static void usage(){ + System.out.println("Usage: PieChartDemo "); + System.out.println(" pie-chart-template.pptx template with a pie chart"); + System.out.println(" pie-chart-data.txt the model to set. First line is chart title, " + + "then go pairs {axis-label value}"); + } + + public static void main(String[] args) throws Exception { + if(args.length < 2) { + usage(); + return; + } + + BufferedReader modelReader = new BufferedReader(new FileReader(args[1])); + XMLSlideShow pptx = null; + try { + String chartTitle = modelReader.readLine(); // first line is chart title + + pptx = new XMLSlideShow(new FileInputStream(args[0])); + XSLFSlide slide = pptx.getSlides().get(0); + + // find chart in the slide + XSLFChart chart = null; + for(POIXMLDocumentPart part : slide.getRelations()){ + if(part instanceof XSLFChart){ + chart = (XSLFChart) part; + break; + } + } + + if(chart == null) throw new IllegalStateException("chart not found in the template"); + + // embedded Excel workbook that holds the chart data + POIXMLDocumentPart xlsPart = chart.getRelations().get(0); + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet(); + + CTChart ctChart = chart.getCTChart(); + CTPlotArea plotArea = ctChart.getPlotArea(); + + CTPieChart pieChart = plotArea.getPieChartArray(0); + //Pie Chart Series + CTPieSer ser = pieChart.getSerArray(0); + + // Series Text + CTSerTx tx = ser.getTx(); + tx.getStrRef().getStrCache().getPtArray(0).setV(chartTitle); + sheet.createRow(0).createCell(1).setCellValue(chartTitle); + String titleRef = new CellReference(sheet.getSheetName(), 0, 1, true, true).formatAsString(); + tx.getStrRef().setF(titleRef); + + // Category Axis Data + CTAxDataSource cat = ser.getCat(); + CTStrData strData = cat.getStrRef().getStrCache(); + + // Values + CTNumDataSource val = ser.getVal(); + CTNumData numData = val.getNumRef().getNumCache(); + + strData.setPtArray(null); // unset old axis text + numData.setPtArray(null); // unset old values + + // set model + int idx = 0; + int rownum = 1; + String ln; + while((ln = modelReader.readLine()) != null){ + String[] vals = ln.split("\\s+"); + CTNumVal numVal = numData.addNewPt(); + numVal.setIdx(idx); + numVal.setV(vals[1]); + + CTStrVal sVal = strData.addNewPt(); + sVal.setIdx(idx); + sVal.setV(vals[0]); + + idx++; + XSSFRow row = sheet.createRow(rownum++); + row.createCell(0).setCellValue(vals[0]); + row.createCell(1).setCellValue(Double.valueOf(vals[1])); + } + numData.getPtCount().setVal(idx); + strData.getPtCount().setVal(idx); + + String numDataRange = new CellRangeAddress(1, rownum-1, 1, 1).formatAsString(sheet.getSheetName(), true); + val.getNumRef().setF(numDataRange); + String axisDataRange = new CellRangeAddress(1, rownum-1, 0, 0).formatAsString(sheet.getSheetName(), true); + cat.getStrRef().setF(axisDataRange); + + // updated the embedded workbook with the data + OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream(); + try { + wb.write(xlsOut); + } finally { + xlsOut.close(); + } + + // save the result + OutputStream out = new FileOutputStream("pie-chart-demo-output.pptx"); + try { + pptx.write(out); + } finally { + out.close(); + } + } finally { + wb.close(); + } + } finally { + if (pptx != null) pptx.close(); + modelReader.close(); + } + } +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial1.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial1.java index 60f5d7121d..714ebb8121 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial1.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial1.java @@ -1,74 +1,74 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * Demonstrates how to create slides with predefined layout - * and fill the placeholder shapes - * - * @author Yegor Kozlov - */ -public class Tutorial1 { - - public static void main(String[] args) throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - - // XSLFSlide#createSlide() with no arguments creates a blank slide - /*XSLFSlide blankSlide =*/ ppt.createSlide(); - - - XSLFSlideMaster master = ppt.getSlideMasters().get(0); - - XSLFSlideLayout layout1 = master.getLayout(SlideLayout.TITLE); - XSLFSlide slide1 = ppt.createSlide(layout1) ; - XSLFTextShape[] ph1 = slide1.getPlaceholders(); - XSLFTextShape titlePlaceholder1 = ph1[0]; - titlePlaceholder1.setText("This is a title"); - XSLFTextShape subtitlePlaceholder1 = ph1[1]; - subtitlePlaceholder1.setText("this is a subtitle"); - - XSLFSlideLayout layout2 = master.getLayout(SlideLayout.TITLE_AND_CONTENT); - XSLFSlide slide2 = ppt.createSlide(layout2) ; - XSLFTextShape[] ph2 = slide2.getPlaceholders(); - XSLFTextShape titlePlaceholder2 = ph2[0]; - titlePlaceholder2.setText("This is a title"); - XSLFTextShape bodyPlaceholder = ph2[1]; - // we are going to add text by paragraphs. Clear the default placehoder text before that - bodyPlaceholder.clearText(); - XSLFTextParagraph p1 = bodyPlaceholder.addNewTextParagraph(); - p1.setIndentLevel(0); - p1.addNewTextRun().setText("Level1 text"); - XSLFTextParagraph p2 = bodyPlaceholder.addNewTextParagraph(); - p2.setIndentLevel(1); - p2.addNewTextRun().setText("Level2 text"); - XSLFTextParagraph p3 = bodyPlaceholder.addNewTextParagraph(); - p3.setIndentLevel(2); - p3.addNewTextRun().setText("Level3 text"); - - FileOutputStream out = new FileOutputStream("slides.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Demonstrates how to create slides with predefined layout + * and fill the placeholder shapes + * + * @author Yegor Kozlov + */ +public class Tutorial1 { + + public static void main(String[] args) throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + + // XSLFSlide#createSlide() with no arguments creates a blank slide + /*XSLFSlide blankSlide =*/ ppt.createSlide(); + + + XSLFSlideMaster master = ppt.getSlideMasters().get(0); + + XSLFSlideLayout layout1 = master.getLayout(SlideLayout.TITLE); + XSLFSlide slide1 = ppt.createSlide(layout1) ; + XSLFTextShape[] ph1 = slide1.getPlaceholders(); + XSLFTextShape titlePlaceholder1 = ph1[0]; + titlePlaceholder1.setText("This is a title"); + XSLFTextShape subtitlePlaceholder1 = ph1[1]; + subtitlePlaceholder1.setText("this is a subtitle"); + + XSLFSlideLayout layout2 = master.getLayout(SlideLayout.TITLE_AND_CONTENT); + XSLFSlide slide2 = ppt.createSlide(layout2) ; + XSLFTextShape[] ph2 = slide2.getPlaceholders(); + XSLFTextShape titlePlaceholder2 = ph2[0]; + titlePlaceholder2.setText("This is a title"); + XSLFTextShape bodyPlaceholder = ph2[1]; + // we are going to add text by paragraphs. Clear the default placehoder text before that + bodyPlaceholder.clearText(); + XSLFTextParagraph p1 = bodyPlaceholder.addNewTextParagraph(); + p1.setIndentLevel(0); + p1.addNewTextRun().setText("Level1 text"); + XSLFTextParagraph p2 = bodyPlaceholder.addNewTextParagraph(); + p2.setIndentLevel(1); + p2.addNewTextRun().setText("Level2 text"); + XSLFTextParagraph p3 = bodyPlaceholder.addNewTextParagraph(); + p3.setIndentLevel(2); + p3.addNewTextRun().setText("Level3 text"); + + FileOutputStream out = new FileOutputStream("slides.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java index af05962eeb..3f1402ae62 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java @@ -1,85 +1,85 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; -import java.awt.Rectangle; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * Basic paragraph and text formatting - * - * @author Yegor Kozlov - */ -public class Tutorial2 { - - public static void main(String[] args) throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlide slide1 = ppt.createSlide(); - XSLFTextBox shape1 = slide1.createTextBox(); - // initial height of the text box is 100 pt but - Rectangle anchor = new Rectangle(10, 100, 300, 100); - shape1.setAnchor(anchor); - - XSLFTextParagraph p1 = shape1.addNewTextParagraph(); - XSLFTextRun r1 = p1.addNewTextRun(); - r1.setText("Paragraph Formatting"); - r1.setFontSize(24d); - r1.setFontColor(new Color(85, 142, 213)); - - XSLFTextParagraph p2 = shape1.addNewTextParagraph(); - // If spaceBefore >= 0, then space is a percentage of normal line height. - // If spaceBefore < 0, the absolute value of linespacing is the spacing in points - p2.setSpaceBefore(-20d); // 20 pt from the previous paragraph - p2.setSpaceAfter(300d); // 3 lines after the paragraph - XSLFTextRun r2 = p2.addNewTextRun(); - r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph."); - r2.setFontSize(16d); - - XSLFTextParagraph p3 = shape1.addNewTextParagraph(); - - XSLFTextRun r3 = p3.addNewTextRun(); - r3.setText("Run Formatting"); - r3.setFontSize(24d); - r3.setFontColor(new Color(85, 142, 213)); - - XSLFTextParagraph p4 = shape1.addNewTextParagraph(); - p4.setSpaceBefore(-20d); // 20 pt from the previous paragraph - p4.setSpaceAfter(300d); // 3 lines after the paragraph - XSLFTextRun r4 = p4.addNewTextRun(); - r4.setFontSize(16d); - r4.setText( - "Run level formatting is the most granular property level and allows " + - "for the specifying of all low level text properties. The text run is " + - "what all paragraphs are derived from and thus specifying various " + - "properties per run will allow for a diversely formatted text paragraph."); - - // resize the shape to fit text - shape1.resizeToFitText(); - - FileOutputStream out = new FileOutputStream("text.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; +import java.awt.Rectangle; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Basic paragraph and text formatting + * + * @author Yegor Kozlov + */ +public class Tutorial2 { + + public static void main(String[] args) throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + + XSLFSlide slide1 = ppt.createSlide(); + XSLFTextBox shape1 = slide1.createTextBox(); + // initial height of the text box is 100 pt but + Rectangle anchor = new Rectangle(10, 100, 300, 100); + shape1.setAnchor(anchor); + + XSLFTextParagraph p1 = shape1.addNewTextParagraph(); + XSLFTextRun r1 = p1.addNewTextRun(); + r1.setText("Paragraph Formatting"); + r1.setFontSize(24d); + r1.setFontColor(new Color(85, 142, 213)); + + XSLFTextParagraph p2 = shape1.addNewTextParagraph(); + // If spaceBefore >= 0, then space is a percentage of normal line height. + // If spaceBefore < 0, the absolute value of linespacing is the spacing in points + p2.setSpaceBefore(-20d); // 20 pt from the previous paragraph + p2.setSpaceAfter(300d); // 3 lines after the paragraph + XSLFTextRun r2 = p2.addNewTextRun(); + r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph."); + r2.setFontSize(16d); + + XSLFTextParagraph p3 = shape1.addNewTextParagraph(); + + XSLFTextRun r3 = p3.addNewTextRun(); + r3.setText("Run Formatting"); + r3.setFontSize(24d); + r3.setFontColor(new Color(85, 142, 213)); + + XSLFTextParagraph p4 = shape1.addNewTextParagraph(); + p4.setSpaceBefore(-20d); // 20 pt from the previous paragraph + p4.setSpaceAfter(300d); // 3 lines after the paragraph + XSLFTextRun r4 = p4.addNewTextRun(); + r4.setFontSize(16d); + r4.setText( + "Run level formatting is the most granular property level and allows " + + "for the specifying of all low level text properties. The text run is " + + "what all paragraphs are derived from and thus specifying various " + + "properties per run will allow for a diversely formatted text paragraph."); + + // resize the shape to fit text + shape1.resizeToFitText(); + + FileOutputStream out = new FileOutputStream("text.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java index 4433605f34..4cab79d886 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java @@ -1,51 +1,51 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Rectangle; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.sl.usermodel.Placeholder; - -/** - * How to set slide title - * - * @author Yegor Kozlov - */ -public class Tutorial3 { - - public static void main(String[] args) throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlide slide = ppt.createSlide(); - - XSLFTextShape titleShape = slide.createTextBox(); - titleShape.setPlaceholder(Placeholder.TITLE); - titleShape.setText("This is a slide title"); - titleShape.setAnchor(new Rectangle(50, 50, 400, 100)); - - FileOutputStream out = new FileOutputStream("title.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Rectangle; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.sl.usermodel.Placeholder; + +/** + * How to set slide title + * + * @author Yegor Kozlov + */ +public class Tutorial3 { + + public static void main(String[] args) throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + + XSLFSlide slide = ppt.createSlide(); + + XSLFTextShape titleShape = slide.createTextBox(); + titleShape.setPlaceholder(Placeholder.TITLE); + titleShape.setText("This is a slide title"); + titleShape.setAnchor(new Rectangle(50, 50, 400, 100)); + + FileOutputStream out = new FileOutputStream("title.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java index 94082a2ef9..0cf0fd667d 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java @@ -1,94 +1,94 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; -import java.awt.Rectangle; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.sl.usermodel.TableCell.BorderEdge; -import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; - -/** - * PPTX Tables - * - * @author Yegor Kozlov - */ -public class Tutorial4 { - - public static void main(String[] args) throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - - // XSLFSlide#createSlide() with no arguments creates a blank slide - XSLFSlide slide = ppt.createSlide(); - - XSLFTable tbl = slide.createTable(); - tbl.setAnchor(new Rectangle(50, 50, 450, 300)); - - int numColumns = 3; - int numRows = 5; - XSLFTableRow headerRow = tbl.addRow(); - headerRow.setHeight(50); - // header - for(int i = 0; i < numColumns; i++) { - XSLFTableCell th = headerRow.addCell(); - XSLFTextParagraph p = th.addNewTextParagraph(); - p.setTextAlign(TextAlign.CENTER); - XSLFTextRun r = p.addNewTextRun(); - r.setText("Header " + (i+1)); - r.setBold(true); - r.setFontColor(Color.white); - th.setFillColor(new Color(79, 129, 189)); - th.setBorderWidth(BorderEdge.bottom, 2.0); - th.setBorderColor(BorderEdge.bottom, Color.white); - - tbl.setColumnWidth(i, 150); // all columns are equally sized - } - - // rows - - for(int rownum = 0; rownum < numRows; rownum ++){ - XSLFTableRow tr = tbl.addRow(); - tr.setHeight(50); - // header - for(int i = 0; i < numColumns; i++) { - XSLFTableCell cell = tr.addCell(); - XSLFTextParagraph p = cell.addNewTextParagraph(); - XSLFTextRun r = p.addNewTextRun(); - - r.setText("Cell " + (i+1)); - if(rownum % 2 == 0) - cell.setFillColor(new Color(208, 216, 232)); - else - cell.setFillColor(new Color(233, 247, 244)); - - } - - } - - - FileOutputStream out = new FileOutputStream("table.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; +import java.awt.Rectangle; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.sl.usermodel.TableCell.BorderEdge; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; + +/** + * PPTX Tables + * + * @author Yegor Kozlov + */ +public class Tutorial4 { + + public static void main(String[] args) throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + + // XSLFSlide#createSlide() with no arguments creates a blank slide + XSLFSlide slide = ppt.createSlide(); + + XSLFTable tbl = slide.createTable(); + tbl.setAnchor(new Rectangle(50, 50, 450, 300)); + + int numColumns = 3; + int numRows = 5; + XSLFTableRow headerRow = tbl.addRow(); + headerRow.setHeight(50); + // header + for(int i = 0; i < numColumns; i++) { + XSLFTableCell th = headerRow.addCell(); + XSLFTextParagraph p = th.addNewTextParagraph(); + p.setTextAlign(TextAlign.CENTER); + XSLFTextRun r = p.addNewTextRun(); + r.setText("Header " + (i+1)); + r.setBold(true); + r.setFontColor(Color.white); + th.setFillColor(new Color(79, 129, 189)); + th.setBorderWidth(BorderEdge.bottom, 2.0); + th.setBorderColor(BorderEdge.bottom, Color.white); + + tbl.setColumnWidth(i, 150); // all columns are equally sized + } + + // rows + + for(int rownum = 0; rownum < numRows; rownum ++){ + XSLFTableRow tr = tbl.addRow(); + tr.setHeight(50); + // header + for(int i = 0; i < numColumns; i++) { + XSLFTableCell cell = tr.addCell(); + XSLFTextParagraph p = cell.addNewTextParagraph(); + XSLFTextRun r = p.addNewTextRun(); + + r.setText("Cell " + (i+1)); + if(rownum % 2 == 0) + cell.setFillColor(new Color(208, 216, 232)); + else + cell.setFillColor(new Color(233, 247, 244)); + + } + + } + + + FileOutputStream out = new FileOutputStream("table.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial5.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial5.java index 06542afd9e..988caee2e5 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial5.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial5.java @@ -1,51 +1,51 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.sl.usermodel.PictureData.PictureType; - -/** - * Images - * - * @author Yegor Kozlov - */ -public class Tutorial5 { - - public static void main(String[] args) throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlide slide = ppt.createSlide(); - - File img = new File(System.getProperty("POI.testdata.path", "test-data"), "slideshow/clock.jpg"); - XSLFPictureData pictureData = ppt.addPicture(img, PictureType.PNG); - - /*XSLFPictureShape shape =*/ slide.createPicture(pictureData); - - FileOutputStream out = new FileOutputStream("images.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.sl.usermodel.PictureData.PictureType; + +/** + * Images + * + * @author Yegor Kozlov + */ +public class Tutorial5 { + + public static void main(String[] args) throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + + XSLFSlide slide = ppt.createSlide(); + + File img = new File(System.getProperty("POI.testdata.path", "test-data"), "slideshow/clock.jpg"); + XSLFPictureData pictureData = ppt.addPicture(img, PictureType.PNG); + + /*XSLFPictureShape shape =*/ slide.createPicture(pictureData); + + FileOutputStream out = new FileOutputStream("images.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial6.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial6.java index 73a59d0b81..020089555d 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial6.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial6.java @@ -1,61 +1,61 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Rectangle; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * Hyperlinks - * - * @author Yegor Kozlov - */ -public class Tutorial6 { - - public static void main(String[] args) throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlide slide1 = ppt.createSlide(); - XSLFSlide slide2 = ppt.createSlide(); - - XSLFTextBox shape1 = slide1.createTextBox(); - shape1.setAnchor(new Rectangle(50, 50, 200, 50)); - XSLFTextRun r1 = shape1.addNewTextParagraph().addNewTextRun(); - XSLFHyperlink link1 = r1.createHyperlink(); - r1.setText("http://poi.apache.org"); // visible text - link1.setAddress("http://poi.apache.org"); // link address - - XSLFTextBox shape2 = slide1.createTextBox(); - shape2.setAnchor(new Rectangle(300, 50, 200, 50)); - XSLFTextRun r2 = shape2.addNewTextParagraph().addNewTextRun(); - XSLFHyperlink link2 = r2.createHyperlink(); - r2.setText("Go to the second slide"); // visible text - link2.linkToSlide(slide2); // link address - - - - FileOutputStream out = new FileOutputStream("hyperlinks.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Rectangle; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Hyperlinks + * + * @author Yegor Kozlov + */ +public class Tutorial6 { + + public static void main(String[] args) throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + + XSLFSlide slide1 = ppt.createSlide(); + XSLFSlide slide2 = ppt.createSlide(); + + XSLFTextBox shape1 = slide1.createTextBox(); + shape1.setAnchor(new Rectangle(50, 50, 200, 50)); + XSLFTextRun r1 = shape1.addNewTextParagraph().addNewTextRun(); + XSLFHyperlink link1 = r1.createHyperlink(); + r1.setText("http://poi.apache.org"); // visible text + link1.setAddress("http://poi.apache.org"); // link address + + XSLFTextBox shape2 = slide1.createTextBox(); + shape2.setAnchor(new Rectangle(300, 50, 200, 50)); + XSLFTextRun r2 = shape2.addNewTextParagraph().addNewTextRun(); + XSLFHyperlink link2 = r2.createHyperlink(); + r2.setText("Go to the second slide"); // visible text + link2.linkToSlide(slide2); // link address + + + + FileOutputStream out = new FileOutputStream("hyperlinks.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java index 26f822d1c7..647fef7583 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java @@ -1,90 +1,90 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; -import java.awt.Rectangle; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.sl.usermodel.AutoNumberingScheme; - -/** - * Bullets and numbering - * - * @author Yegor Kozlov - */ -public class Tutorial7 { - - public static void main(String[] args) throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlide slide = ppt.createSlide(); - XSLFTextBox shape = slide.createTextBox(); - shape.setAnchor(new Rectangle(50, 50, 400, 200)); - - XSLFTextParagraph p1 = shape.addNewTextParagraph(); - p1.setIndentLevel(0); - p1.setBullet(true); - XSLFTextRun r1 = p1.addNewTextRun(); - r1.setText("Bullet1"); - - XSLFTextParagraph p2 = shape.addNewTextParagraph(); - // indentation before text - p2.setLeftMargin(60d); - // the bullet is set 40 pt before the text - p2.setIndent(-40d); - p2.setBullet(true); - // customize bullets - p2.setBulletFontColor(Color.red); - p2.setBulletFont("Wingdings"); - p2.setBulletCharacter("\u0075"); - p2.setIndentLevel(1); - XSLFTextRun r2 = p2.addNewTextRun(); - r2.setText("Bullet2"); - - // the next three paragraphs form an auto-numbered list - XSLFTextParagraph p3 = shape.addNewTextParagraph(); - p3.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 1); - p3.setIndentLevel(2); - XSLFTextRun r3 = p3.addNewTextRun(); - r3.setText("Numbered List Item - 1"); - - XSLFTextParagraph p4 = shape.addNewTextParagraph(); - p4.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 2); - p4.setIndentLevel(2); - XSLFTextRun r4 = p4.addNewTextRun(); - r4.setText("Numbered List Item - 2"); - - XSLFTextParagraph p5 = shape.addNewTextParagraph(); - p5.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 3); - p5.setIndentLevel(2); - XSLFTextRun r5 = p5.addNewTextRun(); - r5.setText("Numbered List Item - 3"); - - shape.resizeToFitText(); - - FileOutputStream out = new FileOutputStream("list.pptx"); - ppt.write(out); - out.close(); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; +import java.awt.Rectangle; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.sl.usermodel.AutoNumberingScheme; + +/** + * Bullets and numbering + * + * @author Yegor Kozlov + */ +public class Tutorial7 { + + public static void main(String[] args) throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + + XSLFSlide slide = ppt.createSlide(); + XSLFTextBox shape = slide.createTextBox(); + shape.setAnchor(new Rectangle(50, 50, 400, 200)); + + XSLFTextParagraph p1 = shape.addNewTextParagraph(); + p1.setIndentLevel(0); + p1.setBullet(true); + XSLFTextRun r1 = p1.addNewTextRun(); + r1.setText("Bullet1"); + + XSLFTextParagraph p2 = shape.addNewTextParagraph(); + // indentation before text + p2.setLeftMargin(60d); + // the bullet is set 40 pt before the text + p2.setIndent(-40d); + p2.setBullet(true); + // customize bullets + p2.setBulletFontColor(Color.red); + p2.setBulletFont("Wingdings"); + p2.setBulletCharacter("\u0075"); + p2.setIndentLevel(1); + XSLFTextRun r2 = p2.addNewTextRun(); + r2.setText("Bullet2"); + + // the next three paragraphs form an auto-numbered list + XSLFTextParagraph p3 = shape.addNewTextParagraph(); + p3.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 1); + p3.setIndentLevel(2); + XSLFTextRun r3 = p3.addNewTextRun(); + r3.setText("Numbered List Item - 1"); + + XSLFTextParagraph p4 = shape.addNewTextParagraph(); + p4.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 2); + p4.setIndentLevel(2); + XSLFTextRun r4 = p4.addNewTextRun(); + r4.setText("Numbered List Item - 2"); + + XSLFTextParagraph p5 = shape.addNewTextParagraph(); + p5.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenRight, 3); + p5.setIndentLevel(2); + XSLFTextRun r5 = p5.addNewTextRun(); + r5.setText("Numbered List Item - 3"); + + shape.resizeToFitText(); + + FileOutputStream out = new FileOutputStream("list.pptx"); + ppt.write(out); + out.close(); + + ppt.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java index ffc3ff5236..e2eab81f53 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/CellComments.java @@ -1,90 +1,90 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel.examples; - -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Comment; -import org.apache.poi.ss.usermodel.CreationHelper; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.RichTextString; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellAddress; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -/** - * Demonstrates how to work with excel cell comments. - * - *

- * Excel comment is a kind of a text shape, - * so inserting a comment is very similar to placing a text box in a worksheet - *

- * - * @author Yegor Kozlov - */ -public class CellComments { - public static void main(String[] args) throws IOException { - Workbook wb = new XSSFWorkbook(); - - CreationHelper factory = wb.getCreationHelper(); - - Sheet sheet = wb.createSheet(); - - Cell cell1 = sheet.createRow(3).createCell(5); - cell1.setCellValue("F4"); - - Drawing drawing = sheet.createDrawingPatriarch(); - - ClientAnchor anchor = factory.createClientAnchor(); - - Comment comment1 = drawing.createCellComment(anchor); - RichTextString str1 = factory.createRichTextString("Hello, World!"); - comment1.setString(str1); - comment1.setAuthor("Apache POI"); - cell1.setCellComment(comment1); - - Cell cell2 = sheet.createRow(2).createCell(2); - cell2.setCellValue("C3"); - - Comment comment2 = drawing.createCellComment(anchor); - RichTextString str2 = factory.createRichTextString("XSSF can set cell comments"); - //apply custom font to the text in the comment - Font font = wb.createFont(); - font.setFontName("Arial"); - font.setFontHeightInPoints((short)14); - font.setBold(true); - font.setColor(IndexedColors.RED.getIndex()); - str2.applyFont(font); - - comment2.setString(str2); - comment2.setAuthor("Apache POI"); - comment2.setAddress(new CellAddress("C3")); - - String fname = "comments.xlsx"; - FileOutputStream out = new FileOutputStream(fname); - wb.write(out); - out.close(); - - wb.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel.examples; + +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Demonstrates how to work with excel cell comments. + * + *

+ * Excel comment is a kind of a text shape, + * so inserting a comment is very similar to placing a text box in a worksheet + *

+ * + * @author Yegor Kozlov + */ +public class CellComments { + public static void main(String[] args) throws IOException { + Workbook wb = new XSSFWorkbook(); + + CreationHelper factory = wb.getCreationHelper(); + + Sheet sheet = wb.createSheet(); + + Cell cell1 = sheet.createRow(3).createCell(5); + cell1.setCellValue("F4"); + + Drawing drawing = sheet.createDrawingPatriarch(); + + ClientAnchor anchor = factory.createClientAnchor(); + + Comment comment1 = drawing.createCellComment(anchor); + RichTextString str1 = factory.createRichTextString("Hello, World!"); + comment1.setString(str1); + comment1.setAuthor("Apache POI"); + cell1.setCellComment(comment1); + + Cell cell2 = sheet.createRow(2).createCell(2); + cell2.setCellValue("C3"); + + Comment comment2 = drawing.createCellComment(anchor); + RichTextString str2 = factory.createRichTextString("XSSF can set cell comments"); + //apply custom font to the text in the comment + Font font = wb.createFont(); + font.setFontName("Arial"); + font.setFontHeightInPoints((short)14); + font.setBold(true); + font.setColor(IndexedColors.RED.getIndex()); + str2.applyFont(font); + + comment2.setString(str2); + comment2.setAuthor("Apache POI"); + comment2.setAddress(new CellAddress("C3")); + + String fname = "comments.xlsx"; + FileOutputStream out = new FileOutputStream(fname); + wb.write(out); + out.close(); + + wb.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/CustomXMLMapping.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/CustomXMLMapping.java index 1add0d2fb3..9fb6409ae3 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/CustomXMLMapping.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/CustomXMLMapping.java @@ -1,45 +1,45 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel.examples; - -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.xssf.extractor.XSSFExportToXml; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFMap; - -import java.io.ByteArrayOutputStream; - -/** - * Print all custom XML mappings registered in the given workbook - */ -public class CustomXMLMapping { - - public static void main(String[] args) throws Exception { - OPCPackage pkg = OPCPackage.open(args[0]); - XSSFWorkbook wb = new XSSFWorkbook(pkg); - - for (XSSFMap map : wb.getCustomXMLMappings()) { - XSSFExportToXml exporter = new XSSFExportToXml(map); - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - exporter.exportToXML(os, true); - String xml = os.toString("UTF-8"); - System.out.println(xml); - } - pkg.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel.examples; + +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.xssf.extractor.XSSFExportToXml; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFMap; + +import java.io.ByteArrayOutputStream; + +/** + * Print all custom XML mappings registered in the given workbook + */ +public class CustomXMLMapping { + + public static void main(String[] args) throws Exception { + OPCPackage pkg = OPCPackage.open(args[0]); + XSSFWorkbook wb = new XSSFWorkbook(pkg); + + for (XSSFMap map : wb.getCustomXMLMappings()) { + XSSFExportToXml exporter = new XSSFExportToXml(map); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + exporter.exportToXML(os, true); + String xml = os.toString("UTF-8"); + System.out.println(xml); + } + pkg.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java index 4f65e1a73b..916c2ec50d 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java @@ -1,67 +1,67 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel.examples; - -import java.io.Closeable; -import java.io.InputStream; - -import org.apache.poi.hslf.usermodel.HSLFSlideShow; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.hwpf.HWPFDocument; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.xslf.usermodel.XMLSlideShow; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.xwpf.usermodel.XWPFDocument; - -/** - * Demonstrates how you can extract embedded data from a .xlsx file - */ -public class EmbeddedObjects { - public static void main(String[] args) throws Exception { - XSSFWorkbook workbook = new XSSFWorkbook(args[0]); - for (PackagePart pPart : workbook.getAllEmbedds()) { - String contentType = pPart.getContentType(); - InputStream is = pPart.getInputStream(); - Closeable document; - if (contentType.equals("application/vnd.ms-excel")) { - // Excel Workbook - either binary or OpenXML - document = new HSSFWorkbook(is); - } else if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) { - // Excel Workbook - OpenXML file format - document = new XSSFWorkbook(is); - } else if (contentType.equals("application/msword")) { - // Word Document - binary (OLE2CDF) file format - document = new HWPFDocument(is); - } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) { - // Word Document - OpenXML file format - document = new XWPFDocument(is); - } else if (contentType.equals("application/vnd.ms-powerpoint")) { - // PowerPoint Document - binary file format - document = new HSLFSlideShow(is); - } else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) { - // PowerPoint Document - OpenXML file format - document = new XMLSlideShow(is); - } else { - // Any other type of embedded object. - document = is; - } - document.close(); - is.close(); - } - workbook.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel.examples; + +import java.io.Closeable; +import java.io.InputStream; + +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +/** + * Demonstrates how you can extract embedded data from a .xlsx file + */ +public class EmbeddedObjects { + public static void main(String[] args) throws Exception { + XSSFWorkbook workbook = new XSSFWorkbook(args[0]); + for (PackagePart pPart : workbook.getAllEmbedds()) { + String contentType = pPart.getContentType(); + InputStream is = pPart.getInputStream(); + Closeable document; + if (contentType.equals("application/vnd.ms-excel")) { + // Excel Workbook - either binary or OpenXML + document = new HSSFWorkbook(is); + } else if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) { + // Excel Workbook - OpenXML file format + document = new XSSFWorkbook(is); + } else if (contentType.equals("application/msword")) { + // Word Document - binary (OLE2CDF) file format + document = new HWPFDocument(is); + } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) { + // Word Document - OpenXML file format + document = new XWPFDocument(is); + } else if (contentType.equals("application/vnd.ms-powerpoint")) { + // PowerPoint Document - binary file format + document = new HSLFSlideShow(is); + } else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) { + // PowerPoint Document - OpenXML file format + document = new XMLSlideShow(is); + } else { + // Any other type of embedded object. + document = is; + } + document.close(); + is.close(); + } + workbook.close(); + } } \ No newline at end of file diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/HyperlinkExample.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/HyperlinkExample.java index a84d32a193..bd86e7129c 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/HyperlinkExample.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/HyperlinkExample.java @@ -38,13 +38,13 @@ public class HyperlinkExample { public static void main(String[]args) throws IOException { Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook(); - CreationHelper createHelper = wb.getCreationHelper(); - - //cell style for hyperlinks - //by default hyperlinks are blue and underlined - CellStyle hlink_style = wb.createCellStyle(); - Font hlink_font = wb.createFont(); - hlink_font.setUnderline(Font.U_SINGLE); + CreationHelper createHelper = wb.getCreationHelper(); + + //cell style for hyperlinks + //by default hyperlinks are blue and underlined + CellStyle hlink_style = wb.createCellStyle(); + Font hlink_font = wb.createFont(); + hlink_font.setUnderline(Font.U_SINGLE); hlink_font.setColor(IndexedColors.BLUE.getIndex()); hlink_style.setFont(hlink_font); diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java index d6d5e8ed08..051af64ec7 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/LineChart.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel.examples; - -import java.io.FileOutputStream; -import java.io.IOException; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Chart; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.charts.AxisCrosses; -import org.apache.poi.ss.usermodel.charts.AxisPosition; -import org.apache.poi.ss.usermodel.charts.ChartAxis; -import org.apache.poi.ss.usermodel.charts.ChartDataSource; -import org.apache.poi.ss.usermodel.charts.ChartLegend; -import org.apache.poi.ss.usermodel.charts.DataSources; -import org.apache.poi.ss.usermodel.charts.LegendPosition; -import org.apache.poi.ss.usermodel.charts.LineChartData; -import org.apache.poi.ss.usermodel.charts.ValueAxis; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -/** - * Line chart example. - */ -public class LineChart { - - public static void main(String[] args) throws IOException { - Workbook wb = new XSSFWorkbook(); - Sheet sheet = wb.createSheet("linechart"); - final int NUM_OF_ROWS = 3; - final int NUM_OF_COLUMNS = 10; - - // Create a row and put some cells in it. Rows are 0 based. - Row row; - Cell cell; - for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) { - row = sheet.createRow((short) rowIndex); - for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) { - cell = row.createCell((short) colIndex); - cell.setCellValue(colIndex * (rowIndex + 1)); - } - } - - Drawing drawing = sheet.createDrawingPatriarch(); - ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15); - - Chart chart = drawing.createChart(anchor); - ChartLegend legend = chart.getOrCreateLegend(); - legend.setPosition(LegendPosition.TOP_RIGHT); - - LineChartData data = chart.getChartDataFactory().createLineChartData(); - - // Use a category axis for the bottom axis. - ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); - ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); - leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); - - ChartDataSource xs = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1)); - ChartDataSource ys1 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1)); - ChartDataSource ys2 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1)); - - - data.addSeries(xs, ys1); - data.addSeries(xs, ys2); - - chart.plot(data, bottomAxis, leftAxis); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx"); - wb.write(fileOut); - fileOut.close(); - wb.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel.examples; + +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Chart; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.charts.AxisCrosses; +import org.apache.poi.ss.usermodel.charts.AxisPosition; +import org.apache.poi.ss.usermodel.charts.ChartAxis; +import org.apache.poi.ss.usermodel.charts.ChartDataSource; +import org.apache.poi.ss.usermodel.charts.ChartLegend; +import org.apache.poi.ss.usermodel.charts.DataSources; +import org.apache.poi.ss.usermodel.charts.LegendPosition; +import org.apache.poi.ss.usermodel.charts.LineChartData; +import org.apache.poi.ss.usermodel.charts.ValueAxis; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Line chart example. + */ +public class LineChart { + + public static void main(String[] args) throws IOException { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet("linechart"); + final int NUM_OF_ROWS = 3; + final int NUM_OF_COLUMNS = 10; + + // Create a row and put some cells in it. Rows are 0 based. + Row row; + Cell cell; + for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) { + row = sheet.createRow((short) rowIndex); + for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) { + cell = row.createCell((short) colIndex); + cell.setCellValue(colIndex * (rowIndex + 1)); + } + } + + Drawing drawing = sheet.createDrawingPatriarch(); + ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15); + + Chart chart = drawing.createChart(anchor); + ChartLegend legend = chart.getOrCreateLegend(); + legend.setPosition(LegendPosition.TOP_RIGHT); + + LineChartData data = chart.getChartDataFactory().createLineChartData(); + + // Use a category axis for the bottom axis. + ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); + ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); + leftAxis.setCrosses(AxisCrosses.AUTO_ZERO); + + ChartDataSource xs = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1)); + ChartDataSource ys1 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1)); + ChartDataSource ys2 = DataSources.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1)); + + + data.addSeries(xs, ys1); + data.addSeries(xs, ys2); + + chart.plot(data, bottomAxis, leftAxis); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx"); + wb.write(fileOut); + fileOut.close(); + wb.close(); + } +} diff --git a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/UpdateEmbeddedDoc.java b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/UpdateEmbeddedDoc.java index 166f39cdab..251b4568f6 100644 --- a/src/examples/src/org/apache/poi/xwpf/usermodel/examples/UpdateEmbeddedDoc.java +++ b/src/examples/src/org/apache/poi/xwpf/usermodel/examples/UpdateEmbeddedDoc.java @@ -1,201 +1,201 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xwpf.usermodel.examples; - -import static org.junit.Assert.assertEquals; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.List; - -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookFactory; -import org.apache.poi.util.IOUtils; -import org.apache.poi.xwpf.usermodel.XWPFDocument; - -/** - * Tests whether it is possible to successfully update an Excel workbook that is - * embedded into a WordprocessingML document. Note that the test has currently - * only been conducted with a binary Excel workbook and NOT yet with a - * SpreadsheetML workbook embedded into the document.

- * - * This code was successfully tested with the following file from the POI test collection: - * http://svn.apache.org/repos/asf/poi/trunk/test-data/document/EmbeddedDocument.docx - */ -public class UpdateEmbeddedDoc { - - private XWPFDocument doc = null; - private File docFile = null; - - private static final int SHEET_NUM = 0; - private static final int ROW_NUM = 0; - private static final int CELL_NUM = 0; - private static final double NEW_VALUE = 100.98D; - private static final String BINARY_EXTENSION = "xls"; - private static final String OPENXML_EXTENSION = "xlsx"; - - /** - * Create a new instance of the UpdateEmbeddedDoc class using the following - * parameters; - * - * @param filename An instance of the String class that encapsulates the name - * of and path to a WordprocessingML Word document that contains an - * embedded binary Excel workbook. - * @throws java.io.FileNotFoundException Thrown if the file cannot be found - * on the underlying file system. - * @throws java.io.IOException Thrown if a problem occurs in the underlying - * file system. - */ - public UpdateEmbeddedDoc(String filename) throws FileNotFoundException, IOException { - this.docFile = new File(filename); - FileInputStream fis = null; - if (!this.docFile.exists()) { - throw new FileNotFoundException("The Word dcoument " + filename + " does not exist."); - } - try { - // Open the Word document file and instantiate the XWPFDocument - // class. - fis = new FileInputStream(this.docFile); - this.doc = new XWPFDocument(fis); - } finally { - IOUtils.closeQuietly(fis); - } - } - - /** - * Called to update the embedded Excel workbook. As the format and structire - * of the workbook are known in advance, all this code attempts to do is - * write a new value into the first cell on the first row of the first - * worksheet. Prior to executing this method, that cell will contain the - * value 1. - * - * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException - * Rather - * than use the specific classes (HSSF/XSSF) to handle the embedded - * workbook this method uses those defeined in the SS stream. As - * a result, it might be the case that a SpreadsheetML file is - * opened for processing, throwing this exception if that file is - * invalid. - * @throws java.io.IOException Thrown if a problem occurs in the underlying - * file system. - */ - public void updateEmbeddedDoc() throws OpenXML4JException, IOException { - List embeddedDocs = this.doc.getAllEmbedds(); - for (PackagePart pPart : embeddedDocs) { - String ext = pPart.getPartName().getExtension(); - if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) { - // Get an InputStream from the package part and pass that - // to the create method of the WorkbookFactory class. Update - // the resulting Workbook and then stream that out again - // using an OutputStream obtained from the same PackagePart. - InputStream is = pPart.getInputStream(); - Workbook workbook = null; - OutputStream os = null; - try { - workbook = WorkbookFactory.create(is); - Sheet sheet = workbook.getSheetAt(SHEET_NUM); - Row row = sheet.getRow(ROW_NUM); - Cell cell = row.getCell(CELL_NUM); - cell.setCellValue(NEW_VALUE); - os = pPart.getOutputStream(); - workbook.write(os); - } finally { - IOUtils.closeQuietly(os); - IOUtils.closeQuietly(workbook); - IOUtils.closeQuietly(is); - } - } - } - - if (!embeddedDocs.isEmpty()) { - // Finally, write the newly modified Word document out to file. - FileOutputStream fos = new FileOutputStream(this.docFile); - this.doc.write(fos); - fos.close(); - } - } - - /** - * Called to test whether or not the embedded workbook was correctly - * updated. This method simply recovers the first cell from the first row - * of the first workbook and tests the value it contains. - *

- * Note that execution will not continue up to the assertion as the - * embedded workbook is now corrupted and causes an IllegalArgumentException - * with the following message - *

- * java.lang.IllegalArgumentException: Your InputStream was neither an - * OLE2 stream, nor an OOXML stream - *

- * to be thrown when the WorkbookFactory.createWorkbook(InputStream) method - * is executed. - * - * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException - * Rather - * than use the specific classes (HSSF/XSSF) to handle the embedded - * workbook this method uses those defeined in the SS stream. As - * a result, it might be the case that a SpreadsheetML file is - * opened for processing, throwing this exception if that file is - * invalid. - * @throws java.io.IOException Thrown if a problem occurs in the underlying - * file system. - */ - public void checkUpdatedDoc() throws OpenXML4JException, IOException { - for (PackagePart pPart : this.doc.getAllEmbedds()) { - String ext = pPart.getPartName().getExtension(); - if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) { - InputStream is = pPart.getInputStream(); - Workbook workbook = null; - try { - workbook = WorkbookFactory.create(is); - Sheet sheet = workbook.getSheetAt(SHEET_NUM); - Row row = sheet.getRow(ROW_NUM); - Cell cell = row.getCell(CELL_NUM); - assertEquals(cell.getNumericCellValue(), NEW_VALUE, 0.0001); - } finally { - IOUtils.closeQuietly(workbook); - IOUtils.closeQuietly(is); - } - } - } - } - - /** - * Code to test updating of the embedded Excel workbook. - * - * @param args - * @throws OpenXML4JException - */ - public static void main(String[] args) throws IOException, OpenXML4JException { - UpdateEmbeddedDoc ued = new UpdateEmbeddedDoc(args[0]); - ued.updateEmbeddedDoc(); - ued.checkUpdatedDoc(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xwpf.usermodel.examples; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; + +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +/** + * Tests whether it is possible to successfully update an Excel workbook that is + * embedded into a WordprocessingML document. Note that the test has currently + * only been conducted with a binary Excel workbook and NOT yet with a + * SpreadsheetML workbook embedded into the document.

+ * + * This code was successfully tested with the following file from the POI test collection: + * http://svn.apache.org/repos/asf/poi/trunk/test-data/document/EmbeddedDocument.docx + */ +public class UpdateEmbeddedDoc { + + private XWPFDocument doc = null; + private File docFile = null; + + private static final int SHEET_NUM = 0; + private static final int ROW_NUM = 0; + private static final int CELL_NUM = 0; + private static final double NEW_VALUE = 100.98D; + private static final String BINARY_EXTENSION = "xls"; + private static final String OPENXML_EXTENSION = "xlsx"; + + /** + * Create a new instance of the UpdateEmbeddedDoc class using the following + * parameters; + * + * @param filename An instance of the String class that encapsulates the name + * of and path to a WordprocessingML Word document that contains an + * embedded binary Excel workbook. + * @throws java.io.FileNotFoundException Thrown if the file cannot be found + * on the underlying file system. + * @throws java.io.IOException Thrown if a problem occurs in the underlying + * file system. + */ + public UpdateEmbeddedDoc(String filename) throws FileNotFoundException, IOException { + this.docFile = new File(filename); + FileInputStream fis = null; + if (!this.docFile.exists()) { + throw new FileNotFoundException("The Word dcoument " + filename + " does not exist."); + } + try { + // Open the Word document file and instantiate the XWPFDocument + // class. + fis = new FileInputStream(this.docFile); + this.doc = new XWPFDocument(fis); + } finally { + IOUtils.closeQuietly(fis); + } + } + + /** + * Called to update the embedded Excel workbook. As the format and structire + * of the workbook are known in advance, all this code attempts to do is + * write a new value into the first cell on the first row of the first + * worksheet. Prior to executing this method, that cell will contain the + * value 1. + * + * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException + * Rather + * than use the specific classes (HSSF/XSSF) to handle the embedded + * workbook this method uses those defeined in the SS stream. As + * a result, it might be the case that a SpreadsheetML file is + * opened for processing, throwing this exception if that file is + * invalid. + * @throws java.io.IOException Thrown if a problem occurs in the underlying + * file system. + */ + public void updateEmbeddedDoc() throws OpenXML4JException, IOException { + List embeddedDocs = this.doc.getAllEmbedds(); + for (PackagePart pPart : embeddedDocs) { + String ext = pPart.getPartName().getExtension(); + if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) { + // Get an InputStream from the package part and pass that + // to the create method of the WorkbookFactory class. Update + // the resulting Workbook and then stream that out again + // using an OutputStream obtained from the same PackagePart. + InputStream is = pPart.getInputStream(); + Workbook workbook = null; + OutputStream os = null; + try { + workbook = WorkbookFactory.create(is); + Sheet sheet = workbook.getSheetAt(SHEET_NUM); + Row row = sheet.getRow(ROW_NUM); + Cell cell = row.getCell(CELL_NUM); + cell.setCellValue(NEW_VALUE); + os = pPart.getOutputStream(); + workbook.write(os); + } finally { + IOUtils.closeQuietly(os); + IOUtils.closeQuietly(workbook); + IOUtils.closeQuietly(is); + } + } + } + + if (!embeddedDocs.isEmpty()) { + // Finally, write the newly modified Word document out to file. + FileOutputStream fos = new FileOutputStream(this.docFile); + this.doc.write(fos); + fos.close(); + } + } + + /** + * Called to test whether or not the embedded workbook was correctly + * updated. This method simply recovers the first cell from the first row + * of the first workbook and tests the value it contains. + *

+ * Note that execution will not continue up to the assertion as the + * embedded workbook is now corrupted and causes an IllegalArgumentException + * with the following message + *

+ * java.lang.IllegalArgumentException: Your InputStream was neither an + * OLE2 stream, nor an OOXML stream + *

+ * to be thrown when the WorkbookFactory.createWorkbook(InputStream) method + * is executed. + * + * @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException + * Rather + * than use the specific classes (HSSF/XSSF) to handle the embedded + * workbook this method uses those defeined in the SS stream. As + * a result, it might be the case that a SpreadsheetML file is + * opened for processing, throwing this exception if that file is + * invalid. + * @throws java.io.IOException Thrown if a problem occurs in the underlying + * file system. + */ + public void checkUpdatedDoc() throws OpenXML4JException, IOException { + for (PackagePart pPart : this.doc.getAllEmbedds()) { + String ext = pPart.getPartName().getExtension(); + if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) { + InputStream is = pPart.getInputStream(); + Workbook workbook = null; + try { + workbook = WorkbookFactory.create(is); + Sheet sheet = workbook.getSheetAt(SHEET_NUM); + Row row = sheet.getRow(ROW_NUM); + Cell cell = row.getCell(CELL_NUM); + assertEquals(cell.getNumericCellValue(), NEW_VALUE, 0.0001); + } finally { + IOUtils.closeQuietly(workbook); + IOUtils.closeQuietly(is); + } + } + } + } + + /** + * Code to test updating of the embedded Excel workbook. + * + * @param args + * @throws OpenXML4JException + */ + public static void main(String[] args) throws IOException, OpenXML4JException { + UpdateEmbeddedDoc ued = new UpdateEmbeddedDoc(args[0]); + ued.updateEmbeddedDoc(); + ued.checkUpdatedDoc(); + } +} diff --git a/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntHandlerTask.java b/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntHandlerTask.java index 35f5420f01..c6baee4f24 100644 --- a/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntHandlerTask.java +++ b/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntHandlerTask.java @@ -1,76 +1,76 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.excelant; - -import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtil; -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.Task; - -/** - * This is the class that backs the tag in the Ant task. - *

- * Its purpose is to provide a way to manipulate a workbook in the course - * of an ExcelAnt task. The idea being to model a way for test writers to - * simulate the behaviors of the workbook. - *

- * Suppose, for example, you have a workbook that has a worksheet that - * reacts to values entered or selected by the user. It's possible in - * Excel to change other cells based on this but this isn't easily possible - * in POI. In ExcelAnt we handle this using the Handler, which is a Java - * class you write to manipulate the workbook. - *

- * In order to use this tag you must write a class that implements the - * IExcelAntWorkbookHandler interface. After writing the - * class you should package it and it's dependencies into a jar file to - * add as library in your Ant build file. - * - * @author Jon Svede ( jon [at] loquatic [dot] com ) - * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov ) - * - */ -public class ExcelAntHandlerTask extends Task { - - private String className ; - - private ExcelAntWorkbookUtil wbUtil ; - - public void setClassName( String cName ) { - className = cName ; - } - - protected void setEAWorkbookUtil( ExcelAntWorkbookUtil wkbkUtil ) { - wbUtil = wkbkUtil ; - } - - @Override - public void execute() throws BuildException { - log( "handling the workbook with class " + className, Project.MSG_INFO ) ; - try { - Class clazz = Class.forName( className ) ; - Object handlerObj = clazz.newInstance() ; - if( handlerObj instanceof IExcelAntWorkbookHandler ) { - IExcelAntWorkbookHandler iHandler = (IExcelAntWorkbookHandler)handlerObj ; - iHandler.setWorkbook( wbUtil.getWorkbook() ) ; - iHandler.execute() ; - } - } catch( Exception e ) { - throw new BuildException( e.getMessage(), e ) ; - } - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.excelant; + +import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtil; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +/** + * This is the class that backs the tag in the Ant task. + *

+ * Its purpose is to provide a way to manipulate a workbook in the course + * of an ExcelAnt task. The idea being to model a way for test writers to + * simulate the behaviors of the workbook. + *

+ * Suppose, for example, you have a workbook that has a worksheet that + * reacts to values entered or selected by the user. It's possible in + * Excel to change other cells based on this but this isn't easily possible + * in POI. In ExcelAnt we handle this using the Handler, which is a Java + * class you write to manipulate the workbook. + *

+ * In order to use this tag you must write a class that implements the + * IExcelAntWorkbookHandler interface. After writing the + * class you should package it and it's dependencies into a jar file to + * add as library in your Ant build file. + * + * @author Jon Svede ( jon [at] loquatic [dot] com ) + * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov ) + * + */ +public class ExcelAntHandlerTask extends Task { + + private String className ; + + private ExcelAntWorkbookUtil wbUtil ; + + public void setClassName( String cName ) { + className = cName ; + } + + protected void setEAWorkbookUtil( ExcelAntWorkbookUtil wkbkUtil ) { + wbUtil = wkbkUtil ; + } + + @Override + public void execute() throws BuildException { + log( "handling the workbook with class " + className, Project.MSG_INFO ) ; + try { + Class clazz = Class.forName( className ) ; + Object handlerObj = clazz.newInstance() ; + if( handlerObj instanceof IExcelAntWorkbookHandler ) { + IExcelAntWorkbookHandler iHandler = (IExcelAntWorkbookHandler)handlerObj ; + iHandler.setWorkbook( wbUtil.getWorkbook() ) ; + iHandler.execute() ; + } + } catch( Exception e ) { + throw new BuildException( e.getMessage(), e ) ; + } + } + } diff --git a/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntSet.java b/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntSet.java index 974b1b9e4c..e62f0623d9 100644 --- a/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntSet.java +++ b/src/excelant/java/org/apache/poi/ss/excelant/ExcelAntSet.java @@ -1,48 +1,48 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.excelant; - -import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtil; -import org.apache.tools.ant.Task; - -/** - * - * @author Jon Svede ( jon [at] loquatic [dot] com ) - * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov ) - * - */ -public abstract class ExcelAntSet extends Task { - - protected String cellStr ; - - protected ExcelAntWorkbookUtil wbUtil ; - - public void setCell( String cellName ) { - cellStr = cellName ; - } - - public String getCell() { - return cellStr ; - } - - - public void setWorkbookUtil( ExcelAntWorkbookUtil wb ) { - wbUtil = wb ; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.excelant; + +import org.apache.poi.ss.excelant.util.ExcelAntWorkbookUtil; +import org.apache.tools.ant.Task; + +/** + * + * @author Jon Svede ( jon [at] loquatic [dot] com ) + * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov ) + * + */ +public abstract class ExcelAntSet extends Task { + + protected String cellStr ; + + protected ExcelAntWorkbookUtil wbUtil ; + + public void setCell( String cellName ) { + cellStr = cellName ; + } + + public String getCell() { + return cellStr ; + } + + + public void setWorkbookUtil( ExcelAntWorkbookUtil wb ) { + wbUtil = wb ; + } + +} diff --git a/src/excelant/java/org/apache/poi/ss/excelant/IExcelAntWorkbookHandler.java b/src/excelant/java/org/apache/poi/ss/excelant/IExcelAntWorkbookHandler.java index 139e34c0d7..c8db7008d6 100644 --- a/src/excelant/java/org/apache/poi/ss/excelant/IExcelAntWorkbookHandler.java +++ b/src/excelant/java/org/apache/poi/ss/excelant/IExcelAntWorkbookHandler.java @@ -1,42 +1,42 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.excelant; - -import org.apache.poi.ss.usermodel.Workbook; - - -/** - * In Excel there are many ways to handle manipulating a workbook based - * on some arbitrary user action (onChange, etc). You use this interface - * to create classes that will handle the workbook in whatever manner is needed - * that cannot be handled by POI. - *

- * For example, suppose that in Excel when you update a cell the workbook - * does some calculations and updates other cells based on that change. In - * ExcelAnt you would set the value of the cell then write your own handler - * then call that from your Ant task after the set task. - * - * @author Jon Svede ( jon [at] loquatic [dot] com ) - * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov ) - * - */ -public interface IExcelAntWorkbookHandler { - public void setWorkbook( Workbook workbook ) ; - - public void execute() ; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.excelant; + +import org.apache.poi.ss.usermodel.Workbook; + + +/** + * In Excel there are many ways to handle manipulating a workbook based + * on some arbitrary user action (onChange, etc). You use this interface + * to create classes that will handle the workbook in whatever manner is needed + * that cannot be handled by POI. + *

+ * For example, suppose that in Excel when you update a cell the workbook + * does some calculations and updates other cells based on that change. In + * ExcelAnt you would set the value of the cell then write your own handler + * then call that from your Ant task after the set task. + * + * @author Jon Svede ( jon [at] loquatic [dot] com ) + * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov ) + * + */ +public interface IExcelAntWorkbookHandler { + public void setWorkbook( Workbook workbook ) ; + + public void execute() ; +} diff --git a/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilFactory.java b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilFactory.java index 08e7fb3d98..683ac46368 100644 --- a/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilFactory.java +++ b/src/excelant/java/org/apache/poi/ss/excelant/util/ExcelAntWorkbookUtilFactory.java @@ -1,60 +1,60 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.excelant.util; - -import java.util.HashMap; -import java.util.Map; - - -/** - * This is a factory class maps file names to WorkbookUtil instances. This - * helps ExcelAnt be more efficient when being run many times in an Ant build. - * - * @author Jon Svede (jon [at] loquatic [dot] com) - * @author Brian Bush (brian [dot] bush [at] nrel [dot] gov) - * - */ -public final class ExcelAntWorkbookUtilFactory { - - private static Map workbookUtilMap; - - private ExcelAntWorkbookUtilFactory() { - } - - /** - * Using the fileName, check the internal map to see if an instance - * of the WorkbookUtil exists. If not, then add an instance to the map. - * - * @param fileName The filename to use as key to look for the ExcelAntWorkbookUtil. - * @return An instance of ExcelAntWorkbookUtil associated with the filename or - * a freshly instantiated one if none did exist before. - */ - public static ExcelAntWorkbookUtil getInstance(String fileName) { - if(workbookUtilMap == null) { - workbookUtilMap = new HashMap(); - } - - if(workbookUtilMap.containsKey(fileName)) { - return workbookUtilMap.get(fileName); - } - - ExcelAntWorkbookUtil wbu = new ExcelAntWorkbookUtil(fileName); - workbookUtilMap.put(fileName, wbu); - return wbu; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.excelant.util; + +import java.util.HashMap; +import java.util.Map; + + +/** + * This is a factory class maps file names to WorkbookUtil instances. This + * helps ExcelAnt be more efficient when being run many times in an Ant build. + * + * @author Jon Svede (jon [at] loquatic [dot] com) + * @author Brian Bush (brian [dot] bush [at] nrel [dot] gov) + * + */ +public final class ExcelAntWorkbookUtilFactory { + + private static Map workbookUtilMap; + + private ExcelAntWorkbookUtilFactory() { + } + + /** + * Using the fileName, check the internal map to see if an instance + * of the WorkbookUtil exists. If not, then add an instance to the map. + * + * @param fileName The filename to use as key to look for the ExcelAntWorkbookUtil. + * @return An instance of ExcelAntWorkbookUtil associated with the filename or + * a freshly instantiated one if none did exist before. + */ + public static ExcelAntWorkbookUtil getInstance(String fileName) { + if(workbookUtilMap == null) { + workbookUtilMap = new HashMap(); + } + + if(workbookUtilMap.containsKey(fileName)) { + return workbookUtilMap.get(fileName); + } + + ExcelAntWorkbookUtil wbu = new ExcelAntWorkbookUtil(fileName); + workbookUtilMap.put(fileName, wbu); + return wbu; + } +} diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/BuildFileTest.java b/src/excelant/testcases/org/apache/poi/ss/excelant/BuildFileTest.java index 55ea777871..ea2bb596cf 100644 --- a/src/excelant/testcases/org/apache/poi/ss/excelant/BuildFileTest.java +++ b/src/excelant/testcases/org/apache/poi/ss/excelant/BuildFileTest.java @@ -1,604 +1,604 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.poi.ss.excelant; - -import java.io.File; -import java.io.PrintStream; -import java.net.URL; - -import junit.framework.TestCase; - -import org.apache.poi.POIDataSamples; -import org.apache.tools.ant.BuildEvent; -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.BuildListener; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.ProjectHelper; - -/** - * A BuildFileTest is a TestCase which executes targets from an Ant buildfile - * for testing. - *

- * This class provides a number of utility methods for particular build file - * tests which extend this class. - * - * @see - * http://svn.apache.org/repos/asf/ant/core/trunk/src/tests/junit/org/apache/tools/ant/BuildFileTest.java - */ -public abstract class BuildFileTest extends TestCase { - - protected Project project; - - private StringBuffer logBuffer; - private StringBuffer fullLogBuffer; - private StringBuffer outBuffer; - private StringBuffer errBuffer; - private BuildException buildException; - - /** - * Default constructor for the BuildFileTest object. - */ - public BuildFileTest() { - super(); - } - - /** - * Constructor for the BuildFileTest object. - * - * @param name string to pass up to TestCase constructor - */ - public BuildFileTest(String name) { - super(name); - } - - /** - * Automatically calls the target called "tearDown" - * from the build file tested if it exits. - *

- * This allows to use Ant tasks directly in the build file - * to clean up after each test. Note that no "setUp" target - * is automatically called, since it's trivial to have a - * test target depend on it. - */ - @Override - protected void tearDown() throws Exception { - if (project == null) { - /* - * Maybe the BuildFileTest was subclassed and there is - * no initialized project. So we could avoid getting a - * NPE. - * If there is an initialized project getTargets() does - * not return null as it is initialized by an empty - * HashSet. - */ - return; - } - final String tearDown = "tearDown"; - if (project.getTargets().containsKey(tearDown)) { - project.executeTarget(tearDown); - } - } - - /** - * run a target, expect for any build exception - * - * @param target target to run - * @param cause information string to reader of report - */ - public void expectBuildException(String target, String cause) { - expectSpecificBuildException(target, cause, null); - } - - /** - * Assert that only the given message has been logged with a - * priority <= INFO when running the given target. - */ - public void expectLog(String target, String log) { - executeTarget(target); - String realLog = getLog(); - assertEquals(log, realLog); - } - - /** - * Assert that the given substring is in the log messages. - */ - public void assertLogContaining(String substring) { - String realLog = getLog(); - assertTrue("expecting log to contain \"" + substring + "\" log was \"" - + realLog + "\"", - realLog.indexOf(substring) >= 0); - } - - /** - * Assert that the given substring is not in the log messages. - */ - public void assertLogNotContaining(String substring) { - String realLog = getLog(); - assertFalse("didn't expect log to contain \"" + substring + "\" log was \"" - + realLog + "\"", - realLog.indexOf(substring) >= 0); - } - - /** - * Assert that the given substring is in the output messages. - * - * @since Ant1.7 - */ - public void assertOutputContaining(String substring) { - assertOutputContaining(null, substring); - } - - /** - * Assert that the given substring is in the output messages. - * - * @param message Print this message if the test fails. Defaults to - * a meaningful text if null is passed. - * @since Ant1.7 - */ - public void assertOutputContaining(String message, String substring) { - String realOutput = getOutput(); - String realMessage = (message != null) - ? message - : "expecting output to contain \"" + substring + "\" output was \"" + realOutput + "\""; - assertTrue(realMessage, realOutput.indexOf(substring) >= 0); - } - - /** - * Assert that the given substring is not in the output messages. - * - * @param message Print this message if the test fails. Defaults to - * a meaningful text if null is passed. - * @since Ant1.7 - */ - public void assertOutputNotContaining(String message, String substring) { - String realOutput = getOutput(); - String realMessage = (message != null) - ? message - : "expecting output to not contain \"" + substring + "\" output was \"" + realOutput + "\""; - assertFalse(realMessage, realOutput.indexOf(substring) >= 0); - } - - /** - * Assert that the given message has been logged with a priority <= INFO when running the - * given target. - */ - public void expectLogContaining(String target, String log) { - executeTarget(target); - assertLogContaining(log); - } - - /** - * Assert that the given message has not been logged with a - * priority <= INFO when running the given target. - */ - public void expectLogNotContaining(String target, String log) { - executeTarget(target); - assertLogNotContaining(log); - } - - /** - * Gets the log the BuildFileTest object. - * Only valid if configureProject() has been called. - * - * @return The log value - * @pre logBuffer!=null - */ - public String getLog() { - return logBuffer.toString(); - } - - /** - * Assert that the given message has been logged with a priority - * >= VERBOSE when running the given target. - */ - public void expectDebuglog(String target, String log) { - executeTarget(target); - String realLog = getFullLog(); - assertEquals(log, realLog); - } - - /** - * Assert that the given substring is in the log messages. - */ - public void assertDebuglogContaining(String substring) { - String realLog = getFullLog(); - assertTrue("expecting debug log to contain \"" + substring - + "\" log was \"" - + realLog + "\"", - realLog.indexOf(substring) >= 0); - } - - /** - * Gets the log the BuildFileTest object. - *

- * Only valid if configureProject() has been called. - * - * @return The log value - * @pre fullLogBuffer!=null - */ - public String getFullLog() { - return fullLogBuffer.toString(); - } - - /** - * execute the target, verify output matches expectations - * - * @param target target to execute - * @param output output to look for - */ - public void expectOutput(String target, String output) { - executeTarget(target); - String realOutput = getOutput(); - assertEquals(output, realOutput.trim()); - } - - /** - * Executes the target, verify output matches expectations - * and that we got the named error at the end - * - * @param target target to execute - * @param output output to look for - * @param error Description of Parameter - */ - public void expectOutputAndError(String target, String output, String error) { - executeTarget(target); - String realOutput = getOutput(); - assertEquals(output, realOutput); - String realError = getError(); - assertEquals(error, realError); - } - - public String getOutput() { - return cleanBuffer(outBuffer); - } - - public String getError() { - return cleanBuffer(errBuffer); - } - - public BuildException getBuildException() { - return buildException; - } - - private String cleanBuffer(StringBuffer buffer) { - StringBuffer cleanedBuffer = new StringBuffer(); - for (int i = 0; i < buffer.length(); i++) { - char ch = buffer.charAt(i); - if (ch != '\r') { - cleanedBuffer.append(ch); - } - } - return cleanedBuffer.toString(); - } - - /** - * Sets up to run the named project - * - * @param filename name of project file to run - */ - public void configureProject(String filename) throws BuildException { - configureProject(filename, Project.MSG_DEBUG); - } - - /** - * Sets up to run the named project - * - * @param filename name of project file to run - */ - public void configureProject(String filename, int logLevel) - throws BuildException { - logBuffer = new StringBuffer(); - fullLogBuffer = new StringBuffer(); - project = new Project(); - project.init(); - project.setNewProperty("data.dir.name", getDataDir()); - File antFile = new File(System.getProperty("root"), filename); - project.setUserProperty("ant.file", antFile.getAbsolutePath()); - project.addBuildListener(new AntTestListener(logLevel)); - ProjectHelper.configureProject(project, antFile); - } - - /** - * Executes a target we have set up - * - * @param targetName target to run - * @pre configureProject has been called - */ - public void executeTarget(String targetName) { - PrintStream sysOut = System.out; - PrintStream sysErr = System.err; - try { - sysOut.flush(); - sysErr.flush(); - outBuffer = new StringBuffer(); - PrintStream out = new PrintStream(new AntOutputStream(outBuffer)); - System.setOut(out); - errBuffer = new StringBuffer(); - PrintStream err = new PrintStream(new AntOutputStream(errBuffer)); - System.setErr(err); - logBuffer = new StringBuffer(); - fullLogBuffer = new StringBuffer(); - buildException = null; - project.executeTarget(targetName); - } finally { - System.setOut(sysOut); - System.setErr(sysErr); - } - - } - - /** - * Get the project which has been configured for a test. - * - * @return the Project instance for this test. - */ - public Project getProject() { - return project; - } - - /** - * Gets the directory of the project. - * - * @return the base dir of the project - */ - public File getProjectDir() { - return project.getBaseDir(); - } - - /** - * Runs a target, wait for a build exception. - * - * @param target target to run - * @param cause information string to reader of report - * @param msg the message value of the build exception we are waiting - * for set to null for any build exception to be valid - */ - public void expectSpecificBuildException(String target, String cause, String msg) { - try { - executeTarget(target); - } catch (org.apache.tools.ant.BuildException ex) { - buildException = ex; - if ((null != msg) && (!ex.getMessage().equals(msg))) { - fail("Should throw BuildException because '" + cause - + "' with message '" + msg - + "' (actual message '" + ex.getMessage() + "' instead)"); - } - return; - } - fail("Should throw BuildException because: " + cause); - } - - /** - * run a target, expect an exception string - * containing the substring we look for (case sensitive match) - * - * @param target target to run - * @param cause information string to reader of report - * @param contains substring of the build exception to look for - */ - public void expectBuildExceptionContaining(String target, String cause, String contains) { - try { - executeTarget(target); - } catch (org.apache.tools.ant.BuildException ex) { - buildException = ex; - if ((null != contains) && (ex.getMessage().indexOf(contains) == -1)) { - fail("Should throw BuildException because '" + cause + "' with message containing '" + contains + "' (actual message '" + ex.getMessage() + "' instead)"); - } - return; - } - fail("Should throw BuildException because: " + cause); - } - - /** - * call a target, verify property is as expected - * - * @param target build file target - * @param property property name - * @param value expected value - */ - public void expectPropertySet(String target, String property, String value) { - executeTarget(target); - assertPropertyEquals(property, value); - } - - /** - * assert that a property equals a value; comparison is case sensitive. - * - * @param property property name - * @param value expected value - */ - public void assertPropertyEquals(String property, String value) { - String result = project.getProperty(property); - assertEquals("property " + property, value, result); - } - - /** - * assert that a property equals "true". - * - * @param property property name - */ - public void assertPropertySet(String property) { - assertPropertyEquals(property, "true"); - } - - /** - * assert that a property is null. - * - * @param property property name - */ - public void assertPropertyUnset(String property) { - String result = project.getProperty(property); - if (result != null) { - fail("Expected property " + property - + " to be unset, but it is set to the value: " + result); - } - } - - /** - * call a target, verify named property is "true". - * - * @param target build file target - * @param property property name - */ - public void expectPropertySet(String target, String property) { - expectPropertySet(target, property, "true"); - } - - /** - * Call a target, verify property is null. - * - * @param target build file target - * @param property property name - */ - public void expectPropertyUnset(String target, String property) { - expectPropertySet(target, property, null); - } - - /** - * Retrieve a resource from the caller classloader to avoid - * assuming a vm working directory. The resource path must be - * relative to the package name or absolute from the root path. - * - * @param resource the resource to retrieve its url. - * @throws junit.framework.AssertionFailedError - * if the resource is not found. - */ - public URL getResource(String resource) { - URL url = getClass().getResource(resource); - assertNotNull("Could not find resource :" + resource, url); - return url; - } - - public static String getDataDir() { - String dataDirName = System.getProperty(POIDataSamples.TEST_PROPERTY); - return dataDirName == null ? "test-data" : dataDirName; - } - - /** - * an output stream which saves stuff to our buffer. - */ - protected static class AntOutputStream extends java.io.OutputStream { - private StringBuffer buffer; - - public AntOutputStream(StringBuffer buffer) { - this.buffer = buffer; - } - - @Override - public void write(int b) { - buffer.append((char) b); - } - } - - /** - * Our own personal build listener. - */ - private class AntTestListener implements BuildListener { - private int logLevel; - - /** - * Constructs a test listener which will ignore log events - * above the given level. - */ - public AntTestListener(int logLevel) { - this.logLevel = logLevel; - } - - /** - * Fired before any targets are started. - */ - @Override - public void buildStarted(BuildEvent event) { - } - - /** - * Fired after the last target has finished. This event - * will still be thrown if an error occurred during the build. - * - * @see BuildEvent#getException() - */ - @Override - public void buildFinished(BuildEvent event) { - } - - /** - * Fired when a target is started. - * - * @see BuildEvent#getTarget() - */ - @Override - public void targetStarted(BuildEvent event) { - //System.out.println("targetStarted " + event.getTarget().getName()); - } - - /** - * Fired when a target has finished. This event will - * still be thrown if an error occurred during the build. - * - * @see BuildEvent#getException() - */ - @Override - public void targetFinished(BuildEvent event) { - //System.out.println("targetFinished " + event.getTarget().getName()); - } - - /** - * Fired when a task is started. - * - * @see BuildEvent#getTask() - */ - @Override - public void taskStarted(BuildEvent event) { - //System.out.println("taskStarted " + event.getTask().getTaskName()); - } - - /** - * Fired when a task has finished. This event will still - * be throw if an error occurred during the build. - * - * @see BuildEvent#getException() - */ - @Override - public void taskFinished(BuildEvent event) { - //System.out.println("taskFinished " + event.getTask().getTaskName()); - } - - /** - * Fired whenever a message is logged. - * - * @see BuildEvent#getMessage() - * @see BuildEvent#getPriority() - */ - @Override - public void messageLogged(BuildEvent event) { - if (event.getPriority() > logLevel) { - // ignore event - return; - } - - if (event.getPriority() == Project.MSG_INFO || - event.getPriority() == Project.MSG_WARN || - event.getPriority() == Project.MSG_ERR) { - logBuffer.append(event.getMessage()); - } - fullLogBuffer.append(event.getMessage()); - } - } - -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.poi.ss.excelant; + +import java.io.File; +import java.io.PrintStream; +import java.net.URL; + +import junit.framework.TestCase; + +import org.apache.poi.POIDataSamples; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.BuildListener; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectHelper; + +/** + * A BuildFileTest is a TestCase which executes targets from an Ant buildfile + * for testing. + *

+ * This class provides a number of utility methods for particular build file + * tests which extend this class. + * + * @see + * http://svn.apache.org/repos/asf/ant/core/trunk/src/tests/junit/org/apache/tools/ant/BuildFileTest.java + */ +public abstract class BuildFileTest extends TestCase { + + protected Project project; + + private StringBuffer logBuffer; + private StringBuffer fullLogBuffer; + private StringBuffer outBuffer; + private StringBuffer errBuffer; + private BuildException buildException; + + /** + * Default constructor for the BuildFileTest object. + */ + public BuildFileTest() { + super(); + } + + /** + * Constructor for the BuildFileTest object. + * + * @param name string to pass up to TestCase constructor + */ + public BuildFileTest(String name) { + super(name); + } + + /** + * Automatically calls the target called "tearDown" + * from the build file tested if it exits. + *

+ * This allows to use Ant tasks directly in the build file + * to clean up after each test. Note that no "setUp" target + * is automatically called, since it's trivial to have a + * test target depend on it. + */ + @Override + protected void tearDown() throws Exception { + if (project == null) { + /* + * Maybe the BuildFileTest was subclassed and there is + * no initialized project. So we could avoid getting a + * NPE. + * If there is an initialized project getTargets() does + * not return null as it is initialized by an empty + * HashSet. + */ + return; + } + final String tearDown = "tearDown"; + if (project.getTargets().containsKey(tearDown)) { + project.executeTarget(tearDown); + } + } + + /** + * run a target, expect for any build exception + * + * @param target target to run + * @param cause information string to reader of report + */ + public void expectBuildException(String target, String cause) { + expectSpecificBuildException(target, cause, null); + } + + /** + * Assert that only the given message has been logged with a + * priority <= INFO when running the given target. + */ + public void expectLog(String target, String log) { + executeTarget(target); + String realLog = getLog(); + assertEquals(log, realLog); + } + + /** + * Assert that the given substring is in the log messages. + */ + public void assertLogContaining(String substring) { + String realLog = getLog(); + assertTrue("expecting log to contain \"" + substring + "\" log was \"" + + realLog + "\"", + realLog.indexOf(substring) >= 0); + } + + /** + * Assert that the given substring is not in the log messages. + */ + public void assertLogNotContaining(String substring) { + String realLog = getLog(); + assertFalse("didn't expect log to contain \"" + substring + "\" log was \"" + + realLog + "\"", + realLog.indexOf(substring) >= 0); + } + + /** + * Assert that the given substring is in the output messages. + * + * @since Ant1.7 + */ + public void assertOutputContaining(String substring) { + assertOutputContaining(null, substring); + } + + /** + * Assert that the given substring is in the output messages. + * + * @param message Print this message if the test fails. Defaults to + * a meaningful text if null is passed. + * @since Ant1.7 + */ + public void assertOutputContaining(String message, String substring) { + String realOutput = getOutput(); + String realMessage = (message != null) + ? message + : "expecting output to contain \"" + substring + "\" output was \"" + realOutput + "\""; + assertTrue(realMessage, realOutput.indexOf(substring) >= 0); + } + + /** + * Assert that the given substring is not in the output messages. + * + * @param message Print this message if the test fails. Defaults to + * a meaningful text if null is passed. + * @since Ant1.7 + */ + public void assertOutputNotContaining(String message, String substring) { + String realOutput = getOutput(); + String realMessage = (message != null) + ? message + : "expecting output to not contain \"" + substring + "\" output was \"" + realOutput + "\""; + assertFalse(realMessage, realOutput.indexOf(substring) >= 0); + } + + /** + * Assert that the given message has been logged with a priority <= INFO when running the + * given target. + */ + public void expectLogContaining(String target, String log) { + executeTarget(target); + assertLogContaining(log); + } + + /** + * Assert that the given message has not been logged with a + * priority <= INFO when running the given target. + */ + public void expectLogNotContaining(String target, String log) { + executeTarget(target); + assertLogNotContaining(log); + } + + /** + * Gets the log the BuildFileTest object. + * Only valid if configureProject() has been called. + * + * @return The log value + * @pre logBuffer!=null + */ + public String getLog() { + return logBuffer.toString(); + } + + /** + * Assert that the given message has been logged with a priority + * >= VERBOSE when running the given target. + */ + public void expectDebuglog(String target, String log) { + executeTarget(target); + String realLog = getFullLog(); + assertEquals(log, realLog); + } + + /** + * Assert that the given substring is in the log messages. + */ + public void assertDebuglogContaining(String substring) { + String realLog = getFullLog(); + assertTrue("expecting debug log to contain \"" + substring + + "\" log was \"" + + realLog + "\"", + realLog.indexOf(substring) >= 0); + } + + /** + * Gets the log the BuildFileTest object. + *

+ * Only valid if configureProject() has been called. + * + * @return The log value + * @pre fullLogBuffer!=null + */ + public String getFullLog() { + return fullLogBuffer.toString(); + } + + /** + * execute the target, verify output matches expectations + * + * @param target target to execute + * @param output output to look for + */ + public void expectOutput(String target, String output) { + executeTarget(target); + String realOutput = getOutput(); + assertEquals(output, realOutput.trim()); + } + + /** + * Executes the target, verify output matches expectations + * and that we got the named error at the end + * + * @param target target to execute + * @param output output to look for + * @param error Description of Parameter + */ + public void expectOutputAndError(String target, String output, String error) { + executeTarget(target); + String realOutput = getOutput(); + assertEquals(output, realOutput); + String realError = getError(); + assertEquals(error, realError); + } + + public String getOutput() { + return cleanBuffer(outBuffer); + } + + public String getError() { + return cleanBuffer(errBuffer); + } + + public BuildException getBuildException() { + return buildException; + } + + private String cleanBuffer(StringBuffer buffer) { + StringBuffer cleanedBuffer = new StringBuffer(); + for (int i = 0; i < buffer.length(); i++) { + char ch = buffer.charAt(i); + if (ch != '\r') { + cleanedBuffer.append(ch); + } + } + return cleanedBuffer.toString(); + } + + /** + * Sets up to run the named project + * + * @param filename name of project file to run + */ + public void configureProject(String filename) throws BuildException { + configureProject(filename, Project.MSG_DEBUG); + } + + /** + * Sets up to run the named project + * + * @param filename name of project file to run + */ + public void configureProject(String filename, int logLevel) + throws BuildException { + logBuffer = new StringBuffer(); + fullLogBuffer = new StringBuffer(); + project = new Project(); + project.init(); + project.setNewProperty("data.dir.name", getDataDir()); + File antFile = new File(System.getProperty("root"), filename); + project.setUserProperty("ant.file", antFile.getAbsolutePath()); + project.addBuildListener(new AntTestListener(logLevel)); + ProjectHelper.configureProject(project, antFile); + } + + /** + * Executes a target we have set up + * + * @param targetName target to run + * @pre configureProject has been called + */ + public void executeTarget(String targetName) { + PrintStream sysOut = System.out; + PrintStream sysErr = System.err; + try { + sysOut.flush(); + sysErr.flush(); + outBuffer = new StringBuffer(); + PrintStream out = new PrintStream(new AntOutputStream(outBuffer)); + System.setOut(out); + errBuffer = new StringBuffer(); + PrintStream err = new PrintStream(new AntOutputStream(errBuffer)); + System.setErr(err); + logBuffer = new StringBuffer(); + fullLogBuffer = new StringBuffer(); + buildException = null; + project.executeTarget(targetName); + } finally { + System.setOut(sysOut); + System.setErr(sysErr); + } + + } + + /** + * Get the project which has been configured for a test. + * + * @return the Project instance for this test. + */ + public Project getProject() { + return project; + } + + /** + * Gets the directory of the project. + * + * @return the base dir of the project + */ + public File getProjectDir() { + return project.getBaseDir(); + } + + /** + * Runs a target, wait for a build exception. + * + * @param target target to run + * @param cause information string to reader of report + * @param msg the message value of the build exception we are waiting + * for set to null for any build exception to be valid + */ + public void expectSpecificBuildException(String target, String cause, String msg) { + try { + executeTarget(target); + } catch (org.apache.tools.ant.BuildException ex) { + buildException = ex; + if ((null != msg) && (!ex.getMessage().equals(msg))) { + fail("Should throw BuildException because '" + cause + + "' with message '" + msg + + "' (actual message '" + ex.getMessage() + "' instead)"); + } + return; + } + fail("Should throw BuildException because: " + cause); + } + + /** + * run a target, expect an exception string + * containing the substring we look for (case sensitive match) + * + * @param target target to run + * @param cause information string to reader of report + * @param contains substring of the build exception to look for + */ + public void expectBuildExceptionContaining(String target, String cause, String contains) { + try { + executeTarget(target); + } catch (org.apache.tools.ant.BuildException ex) { + buildException = ex; + if ((null != contains) && (ex.getMessage().indexOf(contains) == -1)) { + fail("Should throw BuildException because '" + cause + "' with message containing '" + contains + "' (actual message '" + ex.getMessage() + "' instead)"); + } + return; + } + fail("Should throw BuildException because: " + cause); + } + + /** + * call a target, verify property is as expected + * + * @param target build file target + * @param property property name + * @param value expected value + */ + public void expectPropertySet(String target, String property, String value) { + executeTarget(target); + assertPropertyEquals(property, value); + } + + /** + * assert that a property equals a value; comparison is case sensitive. + * + * @param property property name + * @param value expected value + */ + public void assertPropertyEquals(String property, String value) { + String result = project.getProperty(property); + assertEquals("property " + property, value, result); + } + + /** + * assert that a property equals "true". + * + * @param property property name + */ + public void assertPropertySet(String property) { + assertPropertyEquals(property, "true"); + } + + /** + * assert that a property is null. + * + * @param property property name + */ + public void assertPropertyUnset(String property) { + String result = project.getProperty(property); + if (result != null) { + fail("Expected property " + property + + " to be unset, but it is set to the value: " + result); + } + } + + /** + * call a target, verify named property is "true". + * + * @param target build file target + * @param property property name + */ + public void expectPropertySet(String target, String property) { + expectPropertySet(target, property, "true"); + } + + /** + * Call a target, verify property is null. + * + * @param target build file target + * @param property property name + */ + public void expectPropertyUnset(String target, String property) { + expectPropertySet(target, property, null); + } + + /** + * Retrieve a resource from the caller classloader to avoid + * assuming a vm working directory. The resource path must be + * relative to the package name or absolute from the root path. + * + * @param resource the resource to retrieve its url. + * @throws junit.framework.AssertionFailedError + * if the resource is not found. + */ + public URL getResource(String resource) { + URL url = getClass().getResource(resource); + assertNotNull("Could not find resource :" + resource, url); + return url; + } + + public static String getDataDir() { + String dataDirName = System.getProperty(POIDataSamples.TEST_PROPERTY); + return dataDirName == null ? "test-data" : dataDirName; + } + + /** + * an output stream which saves stuff to our buffer. + */ + protected static class AntOutputStream extends java.io.OutputStream { + private StringBuffer buffer; + + public AntOutputStream(StringBuffer buffer) { + this.buffer = buffer; + } + + @Override + public void write(int b) { + buffer.append((char) b); + } + } + + /** + * Our own personal build listener. + */ + private class AntTestListener implements BuildListener { + private int logLevel; + + /** + * Constructs a test listener which will ignore log events + * above the given level. + */ + public AntTestListener(int logLevel) { + this.logLevel = logLevel; + } + + /** + * Fired before any targets are started. + */ + @Override + public void buildStarted(BuildEvent event) { + } + + /** + * Fired after the last target has finished. This event + * will still be thrown if an error occurred during the build. + * + * @see BuildEvent#getException() + */ + @Override + public void buildFinished(BuildEvent event) { + } + + /** + * Fired when a target is started. + * + * @see BuildEvent#getTarget() + */ + @Override + public void targetStarted(BuildEvent event) { + //System.out.println("targetStarted " + event.getTarget().getName()); + } + + /** + * Fired when a target has finished. This event will + * still be thrown if an error occurred during the build. + * + * @see BuildEvent#getException() + */ + @Override + public void targetFinished(BuildEvent event) { + //System.out.println("targetFinished " + event.getTarget().getName()); + } + + /** + * Fired when a task is started. + * + * @see BuildEvent#getTask() + */ + @Override + public void taskStarted(BuildEvent event) { + //System.out.println("taskStarted " + event.getTask().getTaskName()); + } + + /** + * Fired when a task has finished. This event will still + * be throw if an error occurred during the build. + * + * @see BuildEvent#getException() + */ + @Override + public void taskFinished(BuildEvent event) { + //System.out.println("taskFinished " + event.getTask().getTaskName()); + } + + /** + * Fired whenever a message is logged. + * + * @see BuildEvent#getMessage() + * @see BuildEvent#getPriority() + */ + @Override + public void messageLogged(BuildEvent event) { + if (event.getPriority() > logLevel) { + // ignore event + return; + } + + if (event.getPriority() == Project.MSG_INFO || + event.getPriority() == Project.MSG_WARN || + event.getPriority() == Project.MSG_ERR) { + logBuffer.append(event.getMessage()); + } + fullLogBuffer.append(event.getMessage()); + } + } + +} diff --git a/src/excelant/testcases/org/apache/poi/ss/excelant/TestBuildFile.java b/src/excelant/testcases/org/apache/poi/ss/excelant/TestBuildFile.java index df1993be0b..7d55c52767 100644 --- a/src/excelant/testcases/org/apache/poi/ss/excelant/TestBuildFile.java +++ b/src/excelant/testcases/org/apache/poi/ss/excelant/TestBuildFile.java @@ -1,119 +1,119 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.apache.poi.ss.excelant; - - -/** - * JUnit test for the ExcelAnt tasks. - * Leverages Ant's test framework. - * - * @see - * http://svn.apache.org/repos/asf/ant/core/trunk/src/tests/junit/org/apache/tools/ant/BuildFileTest.java - */ -public class TestBuildFile extends BuildFileTest { - - @Override - public void setUp() { - configureProject(BuildFileTest.getDataDir() + "/../src/excelant/testcases/org/apache/poi/ss/excelant/tests.xml"); - } - - public void testMissingFilename() { - expectSpecificBuildException("test-nofile", "required argument not specified", - "fileName attribute must be set!"); - } - - public void testFileNotFound() { - expectSpecificBuildException("test-filenotfound", "required argument not specified", - "Cannot load file invalid.xls. Make sure the path and file permissions are correct."); - } - - public void testEvaluate() { - executeTarget("test-evaluate"); - assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); - assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); - } - - public void testEvaluateNoDetails() { - executeTarget("test-evaluate-nodetails"); - assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); - assertLogNotContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); - } - - public void testPrecision() { - executeTarget("test-precision"); - - assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); - assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4. " + - "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-4"); - assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4. " + - "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-5"); - assertLogContaining("Failed to evaluate cell 'MortgageCalculator'!$B$4. " + - "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-10 was expected."); - assertLogContaining("2/3 tests passed"); - } - - public void testPrecisionFail() { - expectSpecificBuildException("test-precision-fails", "precision not matched", - "\tFailed to evaluate cell 'MortgageCalculator'!$B$4. It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-10 was expected."); - } - - public void testPassOnError() { - executeTarget("test-passonerror"); - } - - public void testFailOnError() { - expectBuildException("test-failonerror", "fail on error"); - assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); - assertLogNotContaining("failed because 1 of 0 evaluations failed to evaluate correctly. Failed to evaluate cell 'MortageCalculatorFunction'!$D$3"); - } - - public void testFailOnErrorNoDetails() { - expectBuildException("test-failonerror-nodetails", "fail on error"); - assertLogNotContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); - assertLogNotContaining("failed because 1 of 0 evaluations failed to evaluate correctly. Failed to evaluate cell 'MortageCalculatorFunction'!$D$3"); - } - - public void testUdf() { - executeTarget("test-udf"); - assertLogContaining("1/1 tests passed"); - } - - public void testSetText() { - executeTarget("test-settext"); - assertLogContaining("1/1 tests passed"); - } - - public void testAddHandler() { - executeTarget("test-addhandler"); - assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); - assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); - - assertNotNull("The workbook should have been passed to the handler", MockExcelAntWorkbookHandler.workbook); - assertTrue("The handler should have been executed", MockExcelAntWorkbookHandler.executed); - } - - public void testAddHandlerWrongClass() { - executeTarget("test-addhandler-wrongclass"); - assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); - assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); - } - - public void testAddHandlerFails() { - expectSpecificBuildException("test-addhandler-fails", "NullPointException", null); - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.poi.ss.excelant; + + +/** + * JUnit test for the ExcelAnt tasks. + * Leverages Ant's test framework. + * + * @see + * http://svn.apache.org/repos/asf/ant/core/trunk/src/tests/junit/org/apache/tools/ant/BuildFileTest.java + */ +public class TestBuildFile extends BuildFileTest { + + @Override + public void setUp() { + configureProject(BuildFileTest.getDataDir() + "/../src/excelant/testcases/org/apache/poi/ss/excelant/tests.xml"); + } + + public void testMissingFilename() { + expectSpecificBuildException("test-nofile", "required argument not specified", + "fileName attribute must be set!"); + } + + public void testFileNotFound() { + expectSpecificBuildException("test-filenotfound", "required argument not specified", + "Cannot load file invalid.xls. Make sure the path and file permissions are correct."); + } + + public void testEvaluate() { + executeTarget("test-evaluate"); + assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); + assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); + } + + public void testEvaluateNoDetails() { + executeTarget("test-evaluate-nodetails"); + assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); + assertLogNotContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); + } + + public void testPrecision() { + executeTarget("test-precision"); + + assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); + assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4. " + + "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-4"); + assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4. " + + "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-5"); + assertLogContaining("Failed to evaluate cell 'MortgageCalculator'!$B$4. " + + "It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-10 was expected."); + assertLogContaining("2/3 tests passed"); + } + + public void testPrecisionFail() { + expectSpecificBuildException("test-precision-fails", "precision not matched", + "\tFailed to evaluate cell 'MortgageCalculator'!$B$4. It evaluated to 2285.5761494145563 when the value of 2285.576149 with precision of 1.0E-10 was expected."); + } + + public void testPassOnError() { + executeTarget("test-passonerror"); + } + + public void testFailOnError() { + expectBuildException("test-failonerror", "fail on error"); + assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); + assertLogNotContaining("failed because 1 of 0 evaluations failed to evaluate correctly. Failed to evaluate cell 'MortageCalculatorFunction'!$D$3"); + } + + public void testFailOnErrorNoDetails() { + expectBuildException("test-failonerror-nodetails", "fail on error"); + assertLogNotContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); + assertLogNotContaining("failed because 1 of 0 evaluations failed to evaluate correctly. Failed to evaluate cell 'MortageCalculatorFunction'!$D$3"); + } + + public void testUdf() { + executeTarget("test-udf"); + assertLogContaining("1/1 tests passed"); + } + + public void testSetText() { + executeTarget("test-settext"); + assertLogContaining("1/1 tests passed"); + } + + public void testAddHandler() { + executeTarget("test-addhandler"); + assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); + assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); + + assertNotNull("The workbook should have been passed to the handler", MockExcelAntWorkbookHandler.workbook); + assertTrue("The handler should have been executed", MockExcelAntWorkbookHandler.executed); + } + + public void testAddHandlerWrongClass() { + executeTarget("test-addhandler-wrongclass"); + assertLogContaining("Using input file: " + BuildFileTest.getDataDir() + "/spreadsheet/excelant.xls"); + assertLogContaining("Succeeded when evaluating 'MortgageCalculator'!$B$4."); + } + + public void testAddHandlerFails() { + expectSpecificBuildException("test-addhandler-fails", "NullPointException", null); + } +} diff --git a/src/integrationtest/org/apache/poi/stress/AbstractFileHandler.java b/src/integrationtest/org/apache/poi/stress/AbstractFileHandler.java index 6bfeee2e71..9b49cf7718 100644 --- a/src/integrationtest/org/apache/poi/stress/AbstractFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/AbstractFileHandler.java @@ -1,142 +1,142 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.stress; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Set; - -import org.apache.poi.POIOLE2TextExtractor; -import org.apache.poi.POITextExtractor; -import org.apache.poi.extractor.ExtractorFactory; -import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.xmlbeans.XmlException; - -public abstract class AbstractFileHandler implements FileHandler { - public static final Set EXPECTED_EXTRACTOR_FAILURES = new HashSet(); - static { - // password protected files - EXPECTED_EXTRACTOR_FAILURES.add("document/bug53475-password-is-pass.docx"); - EXPECTED_EXTRACTOR_FAILURES.add("poifs/extenxls_pwd123.xlsx"); - EXPECTED_EXTRACTOR_FAILURES.add("poifs/protect.xlsx"); - EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_agile.docx"); - EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_sha512.xlsx"); - - // unsupported file-types, no supported OLE2 parts - EXPECTED_EXTRACTOR_FAILURES.add("hmef/quick-winmail.dat"); - EXPECTED_EXTRACTOR_FAILURES.add("hmef/winmail-sample1.dat"); - EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-simple.dat"); - EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-with-attachments.dat"); - EXPECTED_EXTRACTOR_FAILURES.add("hpsf/Test0313rur.adm"); - EXPECTED_EXTRACTOR_FAILURES.add("poifs/Notes.ole2"); - } - - @Override - public void handleExtracting(File file) throws Exception { - boolean before = ExtractorFactory.getThreadPrefersEventExtractors(); - try { - ExtractorFactory.setThreadPrefersEventExtractors(true); - handleExtractingInternal(file); - - ExtractorFactory.setThreadPrefersEventExtractors(false); - handleExtractingInternal(file); - } finally { - ExtractorFactory.setThreadPrefersEventExtractors(before); - } - - /* Did fail for some documents with special XML contents... - try { - OOXMLPrettyPrint.main(new String[] { file.getAbsolutePath(), - "/tmp/pretty-" + file.getName() }); - } catch (ZipException e) { - // ignore, not a Zip/OOXML file - }*/ - } - - private void handleExtractingInternal(File file) throws Exception { - long length = file.length(); - long modified = file.lastModified(); - - POITextExtractor extractor = ExtractorFactory.createExtractor(file); - try { - assertNotNull(extractor); - - assertNotNull(extractor.getText()); - - // also try metadata - @SuppressWarnings("resource") - POITextExtractor metadataExtractor = extractor.getMetadataTextExtractor(); - assertNotNull(metadataExtractor.getText()); - - assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!", - EXPECTED_EXTRACTOR_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())); - - assertEquals("File should not be modified by extractor", length, file.length()); - assertEquals("File should not be modified by extractor", modified, file.lastModified()); - - handleExtractingAsStream(file); - - if(extractor instanceof POIOLE2TextExtractor) { - HPSFPropertiesExtractor hpsfExtractor = new HPSFPropertiesExtractor((POIOLE2TextExtractor)extractor); - try { - assertNotNull(hpsfExtractor.getDocumentSummaryInformationText()); - assertNotNull(hpsfExtractor.getSummaryInformationText()); - String text = hpsfExtractor.getText(); - //System.out.println(text); - assertNotNull(text); - } finally { - hpsfExtractor.close(); - } - } - } catch (IllegalArgumentException e) { - if(!EXPECTED_EXTRACTOR_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())) { - throw e; - } - } finally { - extractor.close(); - } - } - - private void handleExtractingAsStream(File file) throws IOException, OpenXML4JException, XmlException { - InputStream stream = new FileInputStream(file); - try { - POITextExtractor streamExtractor = ExtractorFactory.createExtractor(stream); - try { - assertNotNull(streamExtractor); - - assertNotNull(streamExtractor.getText()); - } finally { - streamExtractor.close(); - } - } finally { - stream.close(); - } - } - - @Override - public void handleAdditional(File file) throws Exception { - // by default we do nothing here - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.stress; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; +import java.util.Set; + +import org.apache.poi.POIOLE2TextExtractor; +import org.apache.poi.POITextExtractor; +import org.apache.poi.extractor.ExtractorFactory; +import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.xmlbeans.XmlException; + +public abstract class AbstractFileHandler implements FileHandler { + public static final Set EXPECTED_EXTRACTOR_FAILURES = new HashSet(); + static { + // password protected files + EXPECTED_EXTRACTOR_FAILURES.add("document/bug53475-password-is-pass.docx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/extenxls_pwd123.xlsx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/protect.xlsx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_agile.docx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_sha512.xlsx"); + + // unsupported file-types, no supported OLE2 parts + EXPECTED_EXTRACTOR_FAILURES.add("hmef/quick-winmail.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hmef/winmail-sample1.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-simple.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-with-attachments.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hpsf/Test0313rur.adm"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/Notes.ole2"); + } + + @Override + public void handleExtracting(File file) throws Exception { + boolean before = ExtractorFactory.getThreadPrefersEventExtractors(); + try { + ExtractorFactory.setThreadPrefersEventExtractors(true); + handleExtractingInternal(file); + + ExtractorFactory.setThreadPrefersEventExtractors(false); + handleExtractingInternal(file); + } finally { + ExtractorFactory.setThreadPrefersEventExtractors(before); + } + + /* Did fail for some documents with special XML contents... + try { + OOXMLPrettyPrint.main(new String[] { file.getAbsolutePath(), + "/tmp/pretty-" + file.getName() }); + } catch (ZipException e) { + // ignore, not a Zip/OOXML file + }*/ + } + + private void handleExtractingInternal(File file) throws Exception { + long length = file.length(); + long modified = file.lastModified(); + + POITextExtractor extractor = ExtractorFactory.createExtractor(file); + try { + assertNotNull(extractor); + + assertNotNull(extractor.getText()); + + // also try metadata + @SuppressWarnings("resource") + POITextExtractor metadataExtractor = extractor.getMetadataTextExtractor(); + assertNotNull(metadataExtractor.getText()); + + assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!", + EXPECTED_EXTRACTOR_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())); + + assertEquals("File should not be modified by extractor", length, file.length()); + assertEquals("File should not be modified by extractor", modified, file.lastModified()); + + handleExtractingAsStream(file); + + if(extractor instanceof POIOLE2TextExtractor) { + HPSFPropertiesExtractor hpsfExtractor = new HPSFPropertiesExtractor((POIOLE2TextExtractor)extractor); + try { + assertNotNull(hpsfExtractor.getDocumentSummaryInformationText()); + assertNotNull(hpsfExtractor.getSummaryInformationText()); + String text = hpsfExtractor.getText(); + //System.out.println(text); + assertNotNull(text); + } finally { + hpsfExtractor.close(); + } + } + } catch (IllegalArgumentException e) { + if(!EXPECTED_EXTRACTOR_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())) { + throw e; + } + } finally { + extractor.close(); + } + } + + private void handleExtractingAsStream(File file) throws IOException, OpenXML4JException, XmlException { + InputStream stream = new FileInputStream(file); + try { + POITextExtractor streamExtractor = ExtractorFactory.createExtractor(stream); + try { + assertNotNull(streamExtractor); + + assertNotNull(streamExtractor.getText()); + } finally { + streamExtractor.close(); + } + } finally { + stream.close(); + } + } + + @Override + public void handleAdditional(File file) throws Exception { + // by default we do nothing here + } +} diff --git a/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java b/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java index e798b35339..d76e959b8f 100644 --- a/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java +++ b/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java @@ -1,126 +1,126 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.stress; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import org.apache.poi.sl.draw.DrawFactory; -import org.apache.poi.sl.usermodel.PictureData; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.SlideShowFactory; -import org.apache.poi.sl.usermodel.TextParagraph; -import org.apache.poi.sl.usermodel.TextRun; -import org.apache.poi.sl.usermodel.TextShape; - -public abstract class SlideShowHandler extends POIFSFileHandler { - public void handleSlideShow(SlideShow ss) throws IOException { - renderSlides(ss); - - readContent(ss); - readPictures(ss); - - // write out the file - ByteArrayOutputStream out = writeToArray(ss); - - readContent(ss); - - // read in the writen file - SlideShow read = SlideShowFactory.create(new ByteArrayInputStream(out.toByteArray())); - try { - assertNotNull(read); - readContent(read); - } finally { - read.close(); - } - } - - private ByteArrayOutputStream writeToArray(SlideShow ss) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - ss.write(stream); - } finally { - stream.close(); - } - - return stream; - } - - - private void readContent(SlideShow ss) { - for (Slide s : ss.getSlides()) { - s.getTitle(); - readText(s); - readText(s.getNotes()); - readText(s.getMasterSheet()); - } - } - - private void readText(ShapeContainer sc) { - if (sc == null) return; - for (Shape s : sc) { - if (s instanceof TextShape) { - for (TextParagraph tp : (TextShape)s) { - for (TextRun tr : tp) { - tr.getRawText(); - } - } - } - } - } - - private void readPictures(SlideShow ss) { - for (PictureData pd : ss.getPictureData()) { - Dimension dim = pd.getImageDimension(); - assertTrue(dim.getHeight() >= 0); - assertTrue(dim.getWidth() >= 0); - } - } - - private void renderSlides(SlideShow ss) { - Dimension pgsize = ss.getPageSize(); - - for (Slide s : ss.getSlides()) { - BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = img.createGraphics(); - DrawFactory.getInstance(graphics).fixFonts(graphics); - - // default rendering options - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - - // draw stuff - s.draw(graphics); - - graphics.dispose(); - img.flush(); - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.stress; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.apache.poi.sl.draw.DrawFactory; +import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.sl.usermodel.TextParagraph; +import org.apache.poi.sl.usermodel.TextRun; +import org.apache.poi.sl.usermodel.TextShape; + +public abstract class SlideShowHandler extends POIFSFileHandler { + public void handleSlideShow(SlideShow ss) throws IOException { + renderSlides(ss); + + readContent(ss); + readPictures(ss); + + // write out the file + ByteArrayOutputStream out = writeToArray(ss); + + readContent(ss); + + // read in the writen file + SlideShow read = SlideShowFactory.create(new ByteArrayInputStream(out.toByteArray())); + try { + assertNotNull(read); + readContent(read); + } finally { + read.close(); + } + } + + private ByteArrayOutputStream writeToArray(SlideShow ss) throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + ss.write(stream); + } finally { + stream.close(); + } + + return stream; + } + + + private void readContent(SlideShow ss) { + for (Slide s : ss.getSlides()) { + s.getTitle(); + readText(s); + readText(s.getNotes()); + readText(s.getMasterSheet()); + } + } + + private void readText(ShapeContainer sc) { + if (sc == null) return; + for (Shape s : sc) { + if (s instanceof TextShape) { + for (TextParagraph tp : (TextShape)s) { + for (TextRun tr : tp) { + tr.getRawText(); + } + } + } + } + } + + private void readPictures(SlideShow ss) { + for (PictureData pd : ss.getPictureData()) { + Dimension dim = pd.getImageDimension(); + assertTrue(dim.getHeight() >= 0); + assertTrue(dim.getWidth() >= 0); + } + } + + private void renderSlides(SlideShow ss) { + Dimension pgsize = ss.getPageSize(); + + for (Slide s : ss.getSlides()) { + BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = img.createGraphics(); + DrawFactory.getInstance(graphics).fixFonts(graphics); + + // default rendering options + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + // draw stuff + s.draw(graphics); + + graphics.dispose(); + img.flush(); + } + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/ddf/EscherColorRef.java b/src/java/org/apache/poi/ddf/EscherColorRef.java index 33127689e7..cbd62e17b5 100644 --- a/src/java/org/apache/poi/ddf/EscherColorRef.java +++ b/src/java/org/apache/poi/ddf/EscherColorRef.java @@ -1,296 +1,296 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ddf; - -import org.apache.poi.util.BitField; -import org.apache.poi.util.LittleEndian; - -/** - * An OfficeArtCOLORREF structure entry which also handles color extension opid data - */ -public class EscherColorRef { - @SuppressWarnings("unused") - private int opid = -1; - private int colorRef = 0; - - public enum SysIndexSource { - /** Use the fill color of the shape. */ - FILL_COLOR(0xF0), - /** If the shape contains a line, use the line color of the shape. Otherwise, use the fill color. */ - LINE_OR_FILL_COLOR(0xF1), - /** Use the line color of the shape. */ - LINE_COLOR(0xF2), - /** Use the shadow color of the shape. */ - SHADOW_COLOR(0xF3), - /** Use the current, or last-used, color. */ - CURRENT_OR_LAST_COLOR(0xF4), - /** Use the fill background color of the shape. */ - FILL_BACKGROUND_COLOR(0xF5), - /** Use the line background color of the shape. */ - LINE_BACKGROUND_COLOR(0xF6), - /** If the shape contains a fill, use the fill color of the shape. Otherwise, use the line color. */ - FILL_OR_LINE_COLOR(0xF7) - ; - private int value; - SysIndexSource(int value) { this.value = value; } - } - - /** - * The following enum specifies values that indicate special procedural properties that - * are used to modify the color components of another color. These values are combined with - * those of the {@link SysIndexSource} enum or with a user-specified color. - * The first six values are mutually exclusive. - */ - public enum SysIndexProcedure { - /** - * Darken the color by the value that is specified in the blue field. - * A blue value of 0xFF specifies that the color is to be left unchanged, - * whereas a blue value of 0x00 specifies that the color is to be completely darkened. - */ - DARKEN_COLOR(0x01), - /** - * Lighten the color by the value that is specified in the blue field. - * A blue value of 0xFF specifies that the color is to be left unchanged, - * whereas a blue value of 0x00 specifies that the color is to be completely lightened. - */ - LIGHTEN_COLOR(0x02), - /** - * Add a gray level RGB value. The blue field contains the gray level to add: - * NewColor = SourceColor + gray - */ - ADD_GRAY_LEVEL(0x03), - /** - * Subtract a gray level RGB value. The blue field contains the gray level to subtract: - * NewColor = SourceColor - gray - */ - SUB_GRAY_LEVEL(0x04), - /** - * Reverse-subtract a gray level RGB value. The blue field contains the gray level from - * which to subtract: - * NewColor = gray - SourceColor - */ - REVERSE_GRAY_LEVEL(0x05), - /** - * If the color component being modified is less than the parameter contained in the blue - * field, set it to the minimum intensity. If the color component being modified is greater - * than or equal to the parameter, set it to the maximum intensity. - */ - THRESHOLD(0x06), - /** - * After making other modifications, invert the color. - * This enum value is only for documentation and won't be directly returned. - */ - INVERT_AFTER(0x20), - /** - * After making other modifications, invert the color by toggling just the high bit of each - * color channel. - * This enum value is only for documentation and won't be directly returned. - */ - INVERT_HIGHBIT_AFTER(0x40) - ; - private BitField mask; - SysIndexProcedure(int mask) { - this.mask = new BitField(mask); - } - } - - /** - * A bit that specifies whether the system color scheme will be used to determine the color. - * A value of 0x1 specifies that green and red will be treated as an unsigned 16-bit index - * into the system color table. Values less than 0x00F0 map directly to system colors. - */ - private static final BitField FLAG_SYS_INDEX = new BitField(0x10000000); - - /** - * A bit that specifies whether the current application-defined color scheme will be used - * to determine the color. A value of 0x1 specifies that red will be treated as an index - * into the current color scheme table. If this value is 0x1, green and blue MUST be 0x00. - */ - private static final BitField FLAG_SCHEME_INDEX = new BitField(0x08000000); - - /** - * A bit that specifies whether the color is a standard RGB color. - * 0x0 : The RGB color MAY use halftone dithering to display. - * 0x1 : The color MUST be a solid color. - */ - private static final BitField FLAG_SYSTEM_RGB = new BitField(0x04000000); - - /** - * A bit that specifies whether the current palette will be used to determine the color. - * A value of 0x1 specifies that red, green, and blue contain an RGB value that will be - * matched in the current color palette. This color MUST be solid. - */ - private static final BitField FLAG_PALETTE_RGB = new BitField(0x02000000); - - /** - * A bit that specifies whether the current palette will be used to determine the color. - * A value of 0x1 specifies that green and red will be treated as an unsigned 16-bit index into - * the current color palette. This color MAY be dithered. If this value is 0x1, blue MUST be 0x00. - */ - private static final BitField FLAG_PALETTE_INDEX = new BitField(0x01000000); - - /** - * An unsigned integer that specifies the intensity of the blue color channel. A value - * of 0x00 has the minimum blue intensity. A value of 0xFF has the maximum blue intensity. - */ - private static final BitField FLAG_BLUE = new BitField(0x00FF0000); - - /** - * An unsigned integer that specifies the intensity of the green color channel. A value - * of 0x00 has the minimum green intensity. A value of 0xFF has the maximum green intensity. - */ - private static final BitField FLAG_GREEN = new BitField(0x0000FF00); - - /** - * An unsigned integer that specifies the intensity of the red color channel. A value - * of 0x00 has the minimum red intensity. A value of 0xFF has the maximum red intensity. - */ - private static final BitField FLAG_RED = new BitField(0x000000FF); - - public EscherColorRef(int colorRef) { - this.colorRef = colorRef; - } - - public EscherColorRef(byte[] source, int start, int len) { - assert(len == 4 || len == 6); - - int offset = start; - if (len == 6) { - opid = LittleEndian.getUShort(source, offset); - offset += 2; - } - colorRef = LittleEndian.getInt(source, offset); - } - - public boolean hasSysIndexFlag() { - return FLAG_SYS_INDEX.isSet(colorRef); - } - - public void setSysIndexFlag(boolean flag) { - colorRef = FLAG_SYS_INDEX.setBoolean(colorRef, flag); - } - - public boolean hasSchemeIndexFlag() { - return FLAG_SCHEME_INDEX.isSet(colorRef); - } - - public void setSchemeIndexFlag(boolean flag) { - colorRef = FLAG_SCHEME_INDEX.setBoolean(colorRef, flag); - } - - public boolean hasSystemRGBFlag() { - return FLAG_SYSTEM_RGB.isSet(colorRef); - } - - public void setSystemRGBFlag(boolean flag) { - colorRef = FLAG_SYSTEM_RGB.setBoolean(colorRef, flag); - } - - public boolean hasPaletteRGBFlag() { - return FLAG_PALETTE_RGB.isSet(colorRef); - } - - public void setPaletteRGBFlag(boolean flag) { - colorRef = FLAG_PALETTE_RGB.setBoolean(colorRef, flag); - } - - public boolean hasPaletteIndexFlag() { - return FLAG_PALETTE_INDEX.isSet(colorRef); - } - - public void setPaletteIndexFlag(boolean flag) { - colorRef = FLAG_PALETTE_INDEX.setBoolean(colorRef, flag); - } - - public int[] getRGB() { - int rgb[] = { - FLAG_RED.getValue(colorRef), - FLAG_GREEN.getValue(colorRef), - FLAG_BLUE.getValue(colorRef) - }; - return rgb; - } - - /** - * @return {@link SysIndexSource} if {@link #hasSysIndexFlag()} is {@code true}, otherwise null - */ - public SysIndexSource getSysIndexSource() { - if (!hasSysIndexFlag()) return null; - int val = FLAG_RED.getValue(colorRef); - for (SysIndexSource sis : SysIndexSource.values()) { - if (sis.value == val) return sis; - } - return null; - } - - /** - * Return the {@link SysIndexProcedure} - for invert flag use {@link #getSysIndexInvert()} - * @return {@link SysIndexProcedure} if {@link #hasSysIndexFlag()} is {@code true}, otherwise null - */ - public SysIndexProcedure getSysIndexProcedure() { - if (!hasSysIndexFlag()) return null; - int val = FLAG_GREEN.getValue(colorRef); - for (SysIndexProcedure sip : SysIndexProcedure.values()) { - if (sip == SysIndexProcedure.INVERT_AFTER || sip == SysIndexProcedure.INVERT_HIGHBIT_AFTER) continue; - if (sip.mask.isSet(val)) return sip; - } - return null; - } - - /** - * @return 0 for no invert flag, 1 for {@link SysIndexProcedure#INVERT_AFTER} and - * 2 for {@link SysIndexProcedure#INVERT_HIGHBIT_AFTER} - */ - public int getSysIndexInvert() { - if (!hasSysIndexFlag()) return 0; - int val = FLAG_GREEN.getValue(colorRef); - if ((SysIndexProcedure.INVERT_AFTER.mask.isSet(val))) return 1; - if ((SysIndexProcedure.INVERT_HIGHBIT_AFTER.mask.isSet(val))) return 2; - return 0; - } - - /** - * @return index of the scheme color or -1 if {@link #hasSchemeIndexFlag()} is {@code false} - * - * @see org.apache.poi.hslf.record.ColorSchemeAtom#getColor(int) - */ - public int getSchemeIndex() { - if (!hasSchemeIndexFlag()) return -1; - return FLAG_RED.getValue(colorRef); - } - - /** - * @return index of current palette (color) or -1 if {@link #hasPaletteIndexFlag()} is {@code false} - */ - public int getPaletteIndex() { - return (hasPaletteIndexFlag()) ? getIndex() : -1; - } - - /** - * @return index of system color table or -1 if {@link #hasSysIndexFlag()} is {@code false} - * - * @see org.apache.poi.sl.usermodel.PresetColor - */ - public int getSysIndex() { - return (hasSysIndexFlag()) ? getIndex() : -1; - } - - private int getIndex() { - return (FLAG_GREEN.getValue(colorRef) << 8) | FLAG_RED.getValue(colorRef); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ddf; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.LittleEndian; + +/** + * An OfficeArtCOLORREF structure entry which also handles color extension opid data + */ +public class EscherColorRef { + @SuppressWarnings("unused") + private int opid = -1; + private int colorRef = 0; + + public enum SysIndexSource { + /** Use the fill color of the shape. */ + FILL_COLOR(0xF0), + /** If the shape contains a line, use the line color of the shape. Otherwise, use the fill color. */ + LINE_OR_FILL_COLOR(0xF1), + /** Use the line color of the shape. */ + LINE_COLOR(0xF2), + /** Use the shadow color of the shape. */ + SHADOW_COLOR(0xF3), + /** Use the current, or last-used, color. */ + CURRENT_OR_LAST_COLOR(0xF4), + /** Use the fill background color of the shape. */ + FILL_BACKGROUND_COLOR(0xF5), + /** Use the line background color of the shape. */ + LINE_BACKGROUND_COLOR(0xF6), + /** If the shape contains a fill, use the fill color of the shape. Otherwise, use the line color. */ + FILL_OR_LINE_COLOR(0xF7) + ; + private int value; + SysIndexSource(int value) { this.value = value; } + } + + /** + * The following enum specifies values that indicate special procedural properties that + * are used to modify the color components of another color. These values are combined with + * those of the {@link SysIndexSource} enum or with a user-specified color. + * The first six values are mutually exclusive. + */ + public enum SysIndexProcedure { + /** + * Darken the color by the value that is specified in the blue field. + * A blue value of 0xFF specifies that the color is to be left unchanged, + * whereas a blue value of 0x00 specifies that the color is to be completely darkened. + */ + DARKEN_COLOR(0x01), + /** + * Lighten the color by the value that is specified in the blue field. + * A blue value of 0xFF specifies that the color is to be left unchanged, + * whereas a blue value of 0x00 specifies that the color is to be completely lightened. + */ + LIGHTEN_COLOR(0x02), + /** + * Add a gray level RGB value. The blue field contains the gray level to add: + * NewColor = SourceColor + gray + */ + ADD_GRAY_LEVEL(0x03), + /** + * Subtract a gray level RGB value. The blue field contains the gray level to subtract: + * NewColor = SourceColor - gray + */ + SUB_GRAY_LEVEL(0x04), + /** + * Reverse-subtract a gray level RGB value. The blue field contains the gray level from + * which to subtract: + * NewColor = gray - SourceColor + */ + REVERSE_GRAY_LEVEL(0x05), + /** + * If the color component being modified is less than the parameter contained in the blue + * field, set it to the minimum intensity. If the color component being modified is greater + * than or equal to the parameter, set it to the maximum intensity. + */ + THRESHOLD(0x06), + /** + * After making other modifications, invert the color. + * This enum value is only for documentation and won't be directly returned. + */ + INVERT_AFTER(0x20), + /** + * After making other modifications, invert the color by toggling just the high bit of each + * color channel. + * This enum value is only for documentation and won't be directly returned. + */ + INVERT_HIGHBIT_AFTER(0x40) + ; + private BitField mask; + SysIndexProcedure(int mask) { + this.mask = new BitField(mask); + } + } + + /** + * A bit that specifies whether the system color scheme will be used to determine the color. + * A value of 0x1 specifies that green and red will be treated as an unsigned 16-bit index + * into the system color table. Values less than 0x00F0 map directly to system colors. + */ + private static final BitField FLAG_SYS_INDEX = new BitField(0x10000000); + + /** + * A bit that specifies whether the current application-defined color scheme will be used + * to determine the color. A value of 0x1 specifies that red will be treated as an index + * into the current color scheme table. If this value is 0x1, green and blue MUST be 0x00. + */ + private static final BitField FLAG_SCHEME_INDEX = new BitField(0x08000000); + + /** + * A bit that specifies whether the color is a standard RGB color. + * 0x0 : The RGB color MAY use halftone dithering to display. + * 0x1 : The color MUST be a solid color. + */ + private static final BitField FLAG_SYSTEM_RGB = new BitField(0x04000000); + + /** + * A bit that specifies whether the current palette will be used to determine the color. + * A value of 0x1 specifies that red, green, and blue contain an RGB value that will be + * matched in the current color palette. This color MUST be solid. + */ + private static final BitField FLAG_PALETTE_RGB = new BitField(0x02000000); + + /** + * A bit that specifies whether the current palette will be used to determine the color. + * A value of 0x1 specifies that green and red will be treated as an unsigned 16-bit index into + * the current color palette. This color MAY be dithered. If this value is 0x1, blue MUST be 0x00. + */ + private static final BitField FLAG_PALETTE_INDEX = new BitField(0x01000000); + + /** + * An unsigned integer that specifies the intensity of the blue color channel. A value + * of 0x00 has the minimum blue intensity. A value of 0xFF has the maximum blue intensity. + */ + private static final BitField FLAG_BLUE = new BitField(0x00FF0000); + + /** + * An unsigned integer that specifies the intensity of the green color channel. A value + * of 0x00 has the minimum green intensity. A value of 0xFF has the maximum green intensity. + */ + private static final BitField FLAG_GREEN = new BitField(0x0000FF00); + + /** + * An unsigned integer that specifies the intensity of the red color channel. A value + * of 0x00 has the minimum red intensity. A value of 0xFF has the maximum red intensity. + */ + private static final BitField FLAG_RED = new BitField(0x000000FF); + + public EscherColorRef(int colorRef) { + this.colorRef = colorRef; + } + + public EscherColorRef(byte[] source, int start, int len) { + assert(len == 4 || len == 6); + + int offset = start; + if (len == 6) { + opid = LittleEndian.getUShort(source, offset); + offset += 2; + } + colorRef = LittleEndian.getInt(source, offset); + } + + public boolean hasSysIndexFlag() { + return FLAG_SYS_INDEX.isSet(colorRef); + } + + public void setSysIndexFlag(boolean flag) { + colorRef = FLAG_SYS_INDEX.setBoolean(colorRef, flag); + } + + public boolean hasSchemeIndexFlag() { + return FLAG_SCHEME_INDEX.isSet(colorRef); + } + + public void setSchemeIndexFlag(boolean flag) { + colorRef = FLAG_SCHEME_INDEX.setBoolean(colorRef, flag); + } + + public boolean hasSystemRGBFlag() { + return FLAG_SYSTEM_RGB.isSet(colorRef); + } + + public void setSystemRGBFlag(boolean flag) { + colorRef = FLAG_SYSTEM_RGB.setBoolean(colorRef, flag); + } + + public boolean hasPaletteRGBFlag() { + return FLAG_PALETTE_RGB.isSet(colorRef); + } + + public void setPaletteRGBFlag(boolean flag) { + colorRef = FLAG_PALETTE_RGB.setBoolean(colorRef, flag); + } + + public boolean hasPaletteIndexFlag() { + return FLAG_PALETTE_INDEX.isSet(colorRef); + } + + public void setPaletteIndexFlag(boolean flag) { + colorRef = FLAG_PALETTE_INDEX.setBoolean(colorRef, flag); + } + + public int[] getRGB() { + int rgb[] = { + FLAG_RED.getValue(colorRef), + FLAG_GREEN.getValue(colorRef), + FLAG_BLUE.getValue(colorRef) + }; + return rgb; + } + + /** + * @return {@link SysIndexSource} if {@link #hasSysIndexFlag()} is {@code true}, otherwise null + */ + public SysIndexSource getSysIndexSource() { + if (!hasSysIndexFlag()) return null; + int val = FLAG_RED.getValue(colorRef); + for (SysIndexSource sis : SysIndexSource.values()) { + if (sis.value == val) return sis; + } + return null; + } + + /** + * Return the {@link SysIndexProcedure} - for invert flag use {@link #getSysIndexInvert()} + * @return {@link SysIndexProcedure} if {@link #hasSysIndexFlag()} is {@code true}, otherwise null + */ + public SysIndexProcedure getSysIndexProcedure() { + if (!hasSysIndexFlag()) return null; + int val = FLAG_GREEN.getValue(colorRef); + for (SysIndexProcedure sip : SysIndexProcedure.values()) { + if (sip == SysIndexProcedure.INVERT_AFTER || sip == SysIndexProcedure.INVERT_HIGHBIT_AFTER) continue; + if (sip.mask.isSet(val)) return sip; + } + return null; + } + + /** + * @return 0 for no invert flag, 1 for {@link SysIndexProcedure#INVERT_AFTER} and + * 2 for {@link SysIndexProcedure#INVERT_HIGHBIT_AFTER} + */ + public int getSysIndexInvert() { + if (!hasSysIndexFlag()) return 0; + int val = FLAG_GREEN.getValue(colorRef); + if ((SysIndexProcedure.INVERT_AFTER.mask.isSet(val))) return 1; + if ((SysIndexProcedure.INVERT_HIGHBIT_AFTER.mask.isSet(val))) return 2; + return 0; + } + + /** + * @return index of the scheme color or -1 if {@link #hasSchemeIndexFlag()} is {@code false} + * + * @see org.apache.poi.hslf.record.ColorSchemeAtom#getColor(int) + */ + public int getSchemeIndex() { + if (!hasSchemeIndexFlag()) return -1; + return FLAG_RED.getValue(colorRef); + } + + /** + * @return index of current palette (color) or -1 if {@link #hasPaletteIndexFlag()} is {@code false} + */ + public int getPaletteIndex() { + return (hasPaletteIndexFlag()) ? getIndex() : -1; + } + + /** + * @return index of system color table or -1 if {@link #hasSysIndexFlag()} is {@code false} + * + * @see org.apache.poi.sl.usermodel.PresetColor + */ + public int getSysIndex() { + return (hasSysIndexFlag()) ? getIndex() : -1; + } + + private int getIndex() { + return (FLAG_GREEN.getValue(colorRef) << 8) | FLAG_RED.getValue(colorRef); + } +} diff --git a/src/java/org/apache/poi/ddf/EscherPictBlip.java b/src/java/org/apache/poi/ddf/EscherPictBlip.java index 1feaf94776..cbd5fe20a1 100644 --- a/src/java/org/apache/poi/ddf/EscherPictBlip.java +++ b/src/java/org/apache/poi/ddf/EscherPictBlip.java @@ -275,24 +275,24 @@ public final class EscherPictBlip extends EscherBlipRecord { " Size in EMU: " + getSizeEMU() + '\n' + " Compressed Size: " + HexDump.toHex( field_5_cbSave ) + '\n' + " Compression: " + HexDump.toHex( field_6_fCompression ) + '\n' + - " Filter: " + HexDump.toHex( field_7_fFilter ) + '\n' + - " Extra Data:" + '\n' + extraData; - } - - @Override - public String toXml(String tab) { - String extraData = ""; - StringBuilder builder = new StringBuilder(); - builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance()))) - .append(tab).append("\t").append("0x").append(HexDump.toHex( field_1_UID )).append("\n") - .append(tab).append("\t").append("0x").append(HexDump.toHex( field_2_cb )).append("\n") - .append(tab).append("\t").append("").append(getBounds()).append("\n") - .append(tab).append("\t").append("").append(getSizeEMU()).append("\n") - .append(tab).append("\t").append("0x").append(HexDump.toHex( field_5_cbSave )).append("\n") - .append(tab).append("\t").append("0x").append(HexDump.toHex( field_6_fCompression )).append("\n") - .append(tab).append("\t").append("0x").append(HexDump.toHex( field_7_fFilter )).append("\n") - .append(tab).append("\t").append("").append(extraData).append("\n"); - builder.append(tab).append("\n"); - return builder.toString(); - } -} + " Filter: " + HexDump.toHex( field_7_fFilter ) + '\n' + + " Extra Data:" + '\n' + extraData; + } + + @Override + public String toXml(String tab) { + String extraData = ""; + StringBuilder builder = new StringBuilder(); + builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance()))) + .append(tab).append("\t").append("0x").append(HexDump.toHex( field_1_UID )).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex( field_2_cb )).append("\n") + .append(tab).append("\t").append("").append(getBounds()).append("\n") + .append(tab).append("\t").append("").append(getSizeEMU()).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex( field_5_cbSave )).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex( field_6_fCompression )).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex( field_7_fFilter )).append("\n") + .append(tab).append("\t").append("").append(extraData).append("\n"); + builder.append(tab).append("\n"); + return builder.toString(); + } +} diff --git a/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java b/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java index 256d0230f7..9af5104430 100644 --- a/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java +++ b/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java @@ -1,164 +1,164 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.hssf.dev; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.hssf.model.InternalWorkbook; -import org.apache.poi.hssf.record.DrawingGroupRecord; -import org.apache.poi.hssf.usermodel.HSSFPatriarch; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.util.StringUtil; - -/** - * Utility for representing drawings contained in a binary Excel file as a XML tree - */ -public class BiffDrawingToXml { - private static final String SHEET_NAME_PARAM = "-sheet-name"; - private static final String SHEET_INDEXES_PARAM = "-sheet-indexes"; - private static final String EXCLUDE_WORKBOOK_RECORDS = "-exclude-workbook"; - - private static int getAttributeIndex(String attribute, String[] params) { - for (int i = 0; i < params.length; i++) { - String param = params[i]; - if (attribute.equals(param)) { - return i; - } - } - return -1; - } - - private static boolean isExcludeWorkbookRecords(String[] params) { - return -1 != getAttributeIndex(EXCLUDE_WORKBOOK_RECORDS, params); - } - - private static List getIndexesByName(String[] params, HSSFWorkbook workbook) { - List list = new ArrayList(); - int pos = getAttributeIndex(SHEET_NAME_PARAM, params); - if (-1 != pos) { - if (pos >= params.length) { - throw new IllegalArgumentException("sheet name param value was not specified"); - } - String sheetName = params[pos + 1]; - int sheetPos = workbook.getSheetIndex(sheetName); - if (-1 == sheetPos){ - throw new IllegalArgumentException("specified sheet name has not been found in xls file"); - } - list.add(sheetPos); - } - return list; - } - - private static List getIndexesByIdArray(String[] params) { - List list = new ArrayList(); - int pos = getAttributeIndex(SHEET_INDEXES_PARAM, params); - if (-1 != pos) { - if (pos >= params.length) { - throw new IllegalArgumentException("sheet list value was not specified"); - } - String sheetParam = params[pos + 1]; - String[] sheets = sheetParam.split(","); - for (String sheet : sheets) { - list.add(Integer.parseInt(sheet)); - } - } - return list; - } - - private static List getSheetsIndexes(String[] params, HSSFWorkbook workbook) { - List list = new ArrayList(); - list.addAll(getIndexesByIdArray(params)); - list.addAll(getIndexesByName(params, workbook)); - if (0 == list.size()) { - int size = workbook.getNumberOfSheets(); - for (int i = 0; i < size; i++) { - list.add(i); - } - } - return list; - } - - private static String getInputFileName(String[] params) { - return params[params.length - 1]; - } - - private static String getOutputFileName(String input) { - if (input.contains("xls")) { - return input.replace(".xls", ".xml"); - } - return input + ".xml"; - } - - public static void main(String[] params) throws IOException { - if (0 == params.length) { - System.out.println("Usage: BiffDrawingToXml [options] inputWorkbook"); - System.out.println("Options:"); - System.out.println(" -exclude-workbook exclude workbook-level records"); - System.out.println(" -sheet-indexes output sheets with specified indexes"); - System.out.println(" -sheet-namek output sheets with specified name"); - return; - } - String input = getInputFileName(params); - FileInputStream inp = new FileInputStream(input); - String output = getOutputFileName(input); - FileOutputStream outputStream = new FileOutputStream(output); - writeToFile(outputStream, inp, isExcludeWorkbookRecords(params), params); - inp.close(); - outputStream.close(); - } - - public static void writeToFile(OutputStream fos, InputStream xlsWorkbook, boolean excludeWorkbookRecords, String[] params) throws IOException { - HSSFWorkbook workbook = new HSSFWorkbook(xlsWorkbook); - InternalWorkbook internalWorkbook = workbook.getInternalWorkbook(); - DrawingGroupRecord r = (DrawingGroupRecord) internalWorkbook.findFirstRecordBySid(DrawingGroupRecord.sid); - - StringBuilder builder = new StringBuilder(); - builder.append("\n"); - String tab = "\t"; - if (!excludeWorkbookRecords && r != null) { - r.decode(); - List escherRecords = r.getEscherRecords(); - for (EscherRecord record : escherRecords) { - builder.append(record.toXml(tab)); - } - } - List sheets = getSheetsIndexes(params, workbook); - for (Integer i : sheets) { - HSSFPatriarch p = workbook.getSheetAt(i).getDrawingPatriarch(); - if(p != null ) { - builder.append(tab).append("\n"); - builder.append(p.getBoundAggregate().toXml(tab + "\t")); - builder.append(tab).append("\n"); - } - } - builder.append("\n"); - fos.write(builder.toString().getBytes(StringUtil.UTF8)); - fos.close(); - workbook.close(); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.hssf.dev; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.hssf.model.InternalWorkbook; +import org.apache.poi.hssf.record.DrawingGroupRecord; +import org.apache.poi.hssf.usermodel.HSSFPatriarch; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.util.StringUtil; + +/** + * Utility for representing drawings contained in a binary Excel file as a XML tree + */ +public class BiffDrawingToXml { + private static final String SHEET_NAME_PARAM = "-sheet-name"; + private static final String SHEET_INDEXES_PARAM = "-sheet-indexes"; + private static final String EXCLUDE_WORKBOOK_RECORDS = "-exclude-workbook"; + + private static int getAttributeIndex(String attribute, String[] params) { + for (int i = 0; i < params.length; i++) { + String param = params[i]; + if (attribute.equals(param)) { + return i; + } + } + return -1; + } + + private static boolean isExcludeWorkbookRecords(String[] params) { + return -1 != getAttributeIndex(EXCLUDE_WORKBOOK_RECORDS, params); + } + + private static List getIndexesByName(String[] params, HSSFWorkbook workbook) { + List list = new ArrayList(); + int pos = getAttributeIndex(SHEET_NAME_PARAM, params); + if (-1 != pos) { + if (pos >= params.length) { + throw new IllegalArgumentException("sheet name param value was not specified"); + } + String sheetName = params[pos + 1]; + int sheetPos = workbook.getSheetIndex(sheetName); + if (-1 == sheetPos){ + throw new IllegalArgumentException("specified sheet name has not been found in xls file"); + } + list.add(sheetPos); + } + return list; + } + + private static List getIndexesByIdArray(String[] params) { + List list = new ArrayList(); + int pos = getAttributeIndex(SHEET_INDEXES_PARAM, params); + if (-1 != pos) { + if (pos >= params.length) { + throw new IllegalArgumentException("sheet list value was not specified"); + } + String sheetParam = params[pos + 1]; + String[] sheets = sheetParam.split(","); + for (String sheet : sheets) { + list.add(Integer.parseInt(sheet)); + } + } + return list; + } + + private static List getSheetsIndexes(String[] params, HSSFWorkbook workbook) { + List list = new ArrayList(); + list.addAll(getIndexesByIdArray(params)); + list.addAll(getIndexesByName(params, workbook)); + if (0 == list.size()) { + int size = workbook.getNumberOfSheets(); + for (int i = 0; i < size; i++) { + list.add(i); + } + } + return list; + } + + private static String getInputFileName(String[] params) { + return params[params.length - 1]; + } + + private static String getOutputFileName(String input) { + if (input.contains("xls")) { + return input.replace(".xls", ".xml"); + } + return input + ".xml"; + } + + public static void main(String[] params) throws IOException { + if (0 == params.length) { + System.out.println("Usage: BiffDrawingToXml [options] inputWorkbook"); + System.out.println("Options:"); + System.out.println(" -exclude-workbook exclude workbook-level records"); + System.out.println(" -sheet-indexes output sheets with specified indexes"); + System.out.println(" -sheet-namek output sheets with specified name"); + return; + } + String input = getInputFileName(params); + FileInputStream inp = new FileInputStream(input); + String output = getOutputFileName(input); + FileOutputStream outputStream = new FileOutputStream(output); + writeToFile(outputStream, inp, isExcludeWorkbookRecords(params), params); + inp.close(); + outputStream.close(); + } + + public static void writeToFile(OutputStream fos, InputStream xlsWorkbook, boolean excludeWorkbookRecords, String[] params) throws IOException { + HSSFWorkbook workbook = new HSSFWorkbook(xlsWorkbook); + InternalWorkbook internalWorkbook = workbook.getInternalWorkbook(); + DrawingGroupRecord r = (DrawingGroupRecord) internalWorkbook.findFirstRecordBySid(DrawingGroupRecord.sid); + + StringBuilder builder = new StringBuilder(); + builder.append("\n"); + String tab = "\t"; + if (!excludeWorkbookRecords && r != null) { + r.decode(); + List escherRecords = r.getEscherRecords(); + for (EscherRecord record : escherRecords) { + builder.append(record.toXml(tab)); + } + } + List sheets = getSheetsIndexes(params, workbook); + for (Integer i : sheets) { + HSSFPatriarch p = workbook.getSheetAt(i).getDrawingPatriarch(); + if(p != null ) { + builder.append(tab).append("\n"); + builder.append(p.getBoundAggregate().toXml(tab + "\t")); + builder.append(tab).append("\n"); + } + } + builder.append("\n"); + fos.write(builder.toString().getBytes(StringUtil.UTF8)); + fos.close(); + workbook.close(); + } + +} diff --git a/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java b/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java index 2e98cba55e..c5fa4bae99 100644 --- a/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java +++ b/src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java @@ -1,420 +1,420 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hssf.record; - -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.util.HexDump; -import org.apache.poi.util.LittleEndianInput; -import org.apache.poi.util.LittleEndianOutput; -import org.apache.poi.util.StringUtil; - -/** - * This structure specifies the properties of a list or drop-down list embedded object in a sheet. - */ -public class LbsDataSubRecord extends SubRecord { - - public static final int sid = 0x0013; - - /** - * From [MS-XLS].pdf 2.5.147 FtLbsData: - * - * An unsigned integer that indirectly specifies whether - * some of the data in this structure appear in a subsequent Continue record. - * If _cbFContinued is 0x00, all of the fields in this structure except sid and _cbFContinued - * MUST NOT exist. If this entire structure is contained within the same record, - * then _cbFContinued MUST be greater than or equal to the size, in bytes, - * of this structure, not including the four bytes for the ft and _cbFContinued fields - */ - private int _cbFContinued; - - /** - * a formula that specifies the range of cell values that are the items in this list. - */ - private int _unknownPreFormulaInt; - private Ptg _linkPtg; - private Byte _unknownPostFormulaByte; - - /** - * An unsigned integer that specifies the number of items in the list. - */ - private int _cLines; - - /** - * An unsigned integer that specifies the one-based index of the first selected item in this list. - * A value of 0x00 specifies there is no currently selected item. - */ - private int _iSel; - - /** - * flags that tell what data follows - */ - private int _flags; - - /** - * An ObjId that specifies the edit box associated with this list. - * A value of 0x00 specifies that there is no edit box associated with this list. - */ - private int _idEdit; - - /** - * An optional LbsDropData that specifies properties for this dropdown control. - * This field MUST exist if and only if the containing Obj?s cmo.ot is equal to 0x14. - */ - private LbsDropData _dropData; - - /** - * An optional array of strings where each string specifies an item in the list. - * The number of elements in this array, if it exists, MUST be {@link #_cLines} - */ - private String[] _rgLines; - - /** - * An optional array of booleans that specifies - * which items in the list are part of a multiple selection - */ - private boolean[] _bsels; - - /** - * @param in the stream to read data from - * @param cbFContinued the seconf short in the record header - * @param cmoOt the containing Obj's {@link CommonObjectDataSubRecord#field_1_objectType} - */ - public LbsDataSubRecord(LittleEndianInput in, int cbFContinued, int cmoOt) { - _cbFContinued = cbFContinued; - - int encodedTokenLen = in.readUShort(); - if (encodedTokenLen > 0) { - int formulaSize = in.readUShort(); - _unknownPreFormulaInt = in.readInt(); - - Ptg[] ptgs = Ptg.readTokens(formulaSize, in); - if (ptgs.length != 1) { - throw new RecordFormatException("Read " + ptgs.length - + " tokens but expected exactly 1"); - } - _linkPtg = ptgs[0]; - switch (encodedTokenLen - formulaSize - 6) { - case 1: - _unknownPostFormulaByte = in.readByte(); - break; - case 0: - _unknownPostFormulaByte = null; - break; - default: - throw new RecordFormatException("Unexpected leftover bytes"); - } - } - - _cLines = in.readUShort(); - _iSel = in.readUShort(); - _flags = in.readUShort(); - _idEdit = in.readUShort(); - - // From [MS-XLS].pdf 2.5.147 FtLbsData: - // This field MUST exist if and only if the containing Obj?s cmo.ot is equal to 0x14. - if(cmoOt == 0x14) { - _dropData = new LbsDropData(in); - } - - // From [MS-XLS].pdf 2.5.147 FtLbsData: - // This array MUST exist if and only if the fValidPlex flag (0x2) is set - if((_flags & 0x2) != 0) { - _rgLines = new String[_cLines]; - for(int i=0; i < _cLines; i++) { - _rgLines[i] = StringUtil.readUnicodeString(in); - } - } - - // bits 5-6 in the _flags specify the type - // of selection behavior this list control is expected to support - - // From [MS-XLS].pdf 2.5.147 FtLbsData: - // This array MUST exist if and only if the wListType field is not equal to 0. - if(((_flags >> 4) & 0x2) != 0) { - _bsels = new boolean[_cLines]; - for(int i=0; i < _cLines; i++) { - _bsels[i] = in.readByte() == 1; - } - } - - } - - LbsDataSubRecord(){ - - } - - /** - * - * @return a new instance of LbsDataSubRecord to construct auto-filters - * @see org.apache.poi.hssf.usermodel.HSSFCombobox - */ - public static LbsDataSubRecord newAutoFilterInstance(){ - LbsDataSubRecord lbs = new LbsDataSubRecord(); - lbs._cbFContinued = 0x1FEE; //autofilters seem to alway have this magic number - lbs._iSel = 0x000; - - lbs._flags = 0x0301; - lbs._dropData = new LbsDropData(); - lbs._dropData._wStyle = LbsDropData.STYLE_COMBO_SIMPLE_DROPDOWN; - - // the number of lines to be displayed in the dropdown - lbs._dropData._cLine = 8; - return lbs; - } - - /** - * @return true as LbsDataSubRecord is always the last sub-record - */ - @Override - public boolean isTerminating(){ - return true; - } - - @Override - protected int getDataSize() { - int result = 2; // 2 initial shorts - - // optional link formula - if (_linkPtg != null) { - result += 2; // encoded Ptg size - result += 4; // unknown int - result += _linkPtg.getSize(); - if (_unknownPostFormulaByte != null) { - result += 1; - } - } - - result += 4 * 2; // 4 shorts - if(_dropData != null) { - result += _dropData.getDataSize(); - } - if(_rgLines != null) { - for(String str : _rgLines){ - result += StringUtil.getEncodedSize(str); - } - } - if(_bsels != null) { - result += _bsels.length; - } - return result; - } - - @Override - public void serialize(LittleEndianOutput out) { - out.writeShort(sid); - out.writeShort(_cbFContinued); - - if (_linkPtg == null) { - out.writeShort(0); - } else { - int formulaSize = _linkPtg.getSize(); - int linkSize = formulaSize + 6; - if (_unknownPostFormulaByte != null) { - linkSize++; - } - out.writeShort(linkSize); - out.writeShort(formulaSize); - out.writeInt(_unknownPreFormulaInt); - _linkPtg.write(out); - if (_unknownPostFormulaByte != null) { - out.writeByte(_unknownPostFormulaByte.intValue()); - } - } - - out.writeShort(_cLines); - out.writeShort(_iSel); - out.writeShort(_flags); - out.writeShort(_idEdit); - - if(_dropData != null) { - _dropData.serialize(out); - } - - if(_rgLines != null) { - for(String str : _rgLines){ - StringUtil.writeUnicodeString(out, str); - } - } - - if(_bsels != null) { - for(boolean val : _bsels){ - out.writeByte(val ? 1 : 0); - } - } - } - - @Override - public LbsDataSubRecord clone() { - // TODO: is immutable ??? - return this; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(256); - - sb.append("[ftLbsData]\n"); - sb.append(" .unknownShort1 =").append(HexDump.shortToHex(_cbFContinued)).append("\n"); - sb.append(" .formula = ").append('\n'); - if(_linkPtg != null) { - sb.append(_linkPtg.toString()).append(_linkPtg.getRVAType()).append('\n'); - } - sb.append(" .nEntryCount =").append(HexDump.shortToHex(_cLines)).append("\n"); - sb.append(" .selEntryIx =").append(HexDump.shortToHex(_iSel)).append("\n"); - sb.append(" .style =").append(HexDump.shortToHex(_flags)).append("\n"); - sb.append(" .unknownShort10=").append(HexDump.shortToHex(_idEdit)).append("\n"); - if(_dropData != null) { - sb.append('\n').append(_dropData.toString()); - } - sb.append("[/ftLbsData]\n"); - return sb.toString(); - } - - /** - * - * @return the formula that specifies the range of cell values that are the items in this list. - */ - public Ptg getFormula(){ - return _linkPtg; - } - - /** - * @return the number of items in the list - */ - public int getNumberOfItems(){ - return _cLines; - } - - /** - * This structure specifies properties of the dropdown list control - */ - public static class LbsDropData { - /** - * Combo dropdown control - */ - public static final int STYLE_COMBO_DROPDOWN = 0; - /** - * Combo Edit dropdown control - */ - public static final int STYLE_COMBO_EDIT_DROPDOWN = 1; - /** - * Simple dropdown control (just the dropdown button) - */ - public static final int STYLE_COMBO_SIMPLE_DROPDOWN = 2; - - /** - * An unsigned integer that specifies the style of this dropdown. - */ - private int _wStyle; - - /** - * An unsigned integer that specifies the number of lines to be displayed in the dropdown. - */ - private int _cLine; - - /** - * An unsigned integer that specifies the smallest width in pixels allowed for the dropdown window - */ - private int _dxMin; - - /** - * a string that specifies the current string value in the dropdown - */ - private final String _str; - - /** - * Optional, undefined and MUST be ignored. - * This field MUST exist if and only if the size of str in bytes is an odd number - */ - private Byte _unused; - - public LbsDropData(){ - _str = ""; - _unused = 0; - } - - public LbsDropData(LittleEndianInput in){ - _wStyle = in.readUShort(); - _cLine = in.readUShort(); - _dxMin = in.readUShort(); - _str = StringUtil.readUnicodeString(in); - if(StringUtil.getEncodedSize(_str) % 2 != 0){ - _unused = in.readByte(); - } - } - - /** - * Set the style of this dropdown.

- * - * Possible values: - *

    - *
  • 0: Combo dropdown control
  • - *
  • 1: Combo Edit dropdown control
  • - *
  • 2: Simple dropdown control (just the dropdown button)
  • - *
- * - * @param style the style - see possible values - */ - public void setStyle(int style){ - _wStyle = style; - } - - /** - * Set the number of lines to be displayed in the dropdown. - * - * @param num the number of lines to be displayed in the dropdown - */ - public void setNumLines(int num){ - _cLine = num; - } - - public void serialize(LittleEndianOutput out) { - out.writeShort(_wStyle); - out.writeShort(_cLine); - out.writeShort(_dxMin); - StringUtil.writeUnicodeString(out, _str); - if(_unused != null) { - out.writeByte(_unused); - } - } - - public int getDataSize() { - int size = 6; - size += StringUtil.getEncodedSize(_str); - if(_unused != null) { - size++; - } - return size; - } - - @Override - public String toString(){ - StringBuffer sb = new StringBuffer(); - sb.append("[LbsDropData]\n"); - sb.append(" ._wStyle: ").append(_wStyle).append('\n'); - sb.append(" ._cLine: ").append(_cLine).append('\n'); - sb.append(" ._dxMin: ").append(_dxMin).append('\n'); - sb.append(" ._str: ").append(_str).append('\n'); - if(_unused != null) { - sb.append(" ._unused: ").append(_unused).append('\n'); - } - sb.append("[/LbsDropData]\n"); - - return sb.toString(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hssf.record; + +import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.StringUtil; + +/** + * This structure specifies the properties of a list or drop-down list embedded object in a sheet. + */ +public class LbsDataSubRecord extends SubRecord { + + public static final int sid = 0x0013; + + /** + * From [MS-XLS].pdf 2.5.147 FtLbsData: + * + * An unsigned integer that indirectly specifies whether + * some of the data in this structure appear in a subsequent Continue record. + * If _cbFContinued is 0x00, all of the fields in this structure except sid and _cbFContinued + * MUST NOT exist. If this entire structure is contained within the same record, + * then _cbFContinued MUST be greater than or equal to the size, in bytes, + * of this structure, not including the four bytes for the ft and _cbFContinued fields + */ + private int _cbFContinued; + + /** + * a formula that specifies the range of cell values that are the items in this list. + */ + private int _unknownPreFormulaInt; + private Ptg _linkPtg; + private Byte _unknownPostFormulaByte; + + /** + * An unsigned integer that specifies the number of items in the list. + */ + private int _cLines; + + /** + * An unsigned integer that specifies the one-based index of the first selected item in this list. + * A value of 0x00 specifies there is no currently selected item. + */ + private int _iSel; + + /** + * flags that tell what data follows + */ + private int _flags; + + /** + * An ObjId that specifies the edit box associated with this list. + * A value of 0x00 specifies that there is no edit box associated with this list. + */ + private int _idEdit; + + /** + * An optional LbsDropData that specifies properties for this dropdown control. + * This field MUST exist if and only if the containing Obj?s cmo.ot is equal to 0x14. + */ + private LbsDropData _dropData; + + /** + * An optional array of strings where each string specifies an item in the list. + * The number of elements in this array, if it exists, MUST be {@link #_cLines} + */ + private String[] _rgLines; + + /** + * An optional array of booleans that specifies + * which items in the list are part of a multiple selection + */ + private boolean[] _bsels; + + /** + * @param in the stream to read data from + * @param cbFContinued the seconf short in the record header + * @param cmoOt the containing Obj's {@link CommonObjectDataSubRecord#field_1_objectType} + */ + public LbsDataSubRecord(LittleEndianInput in, int cbFContinued, int cmoOt) { + _cbFContinued = cbFContinued; + + int encodedTokenLen = in.readUShort(); + if (encodedTokenLen > 0) { + int formulaSize = in.readUShort(); + _unknownPreFormulaInt = in.readInt(); + + Ptg[] ptgs = Ptg.readTokens(formulaSize, in); + if (ptgs.length != 1) { + throw new RecordFormatException("Read " + ptgs.length + + " tokens but expected exactly 1"); + } + _linkPtg = ptgs[0]; + switch (encodedTokenLen - formulaSize - 6) { + case 1: + _unknownPostFormulaByte = in.readByte(); + break; + case 0: + _unknownPostFormulaByte = null; + break; + default: + throw new RecordFormatException("Unexpected leftover bytes"); + } + } + + _cLines = in.readUShort(); + _iSel = in.readUShort(); + _flags = in.readUShort(); + _idEdit = in.readUShort(); + + // From [MS-XLS].pdf 2.5.147 FtLbsData: + // This field MUST exist if and only if the containing Obj?s cmo.ot is equal to 0x14. + if(cmoOt == 0x14) { + _dropData = new LbsDropData(in); + } + + // From [MS-XLS].pdf 2.5.147 FtLbsData: + // This array MUST exist if and only if the fValidPlex flag (0x2) is set + if((_flags & 0x2) != 0) { + _rgLines = new String[_cLines]; + for(int i=0; i < _cLines; i++) { + _rgLines[i] = StringUtil.readUnicodeString(in); + } + } + + // bits 5-6 in the _flags specify the type + // of selection behavior this list control is expected to support + + // From [MS-XLS].pdf 2.5.147 FtLbsData: + // This array MUST exist if and only if the wListType field is not equal to 0. + if(((_flags >> 4) & 0x2) != 0) { + _bsels = new boolean[_cLines]; + for(int i=0; i < _cLines; i++) { + _bsels[i] = in.readByte() == 1; + } + } + + } + + LbsDataSubRecord(){ + + } + + /** + * + * @return a new instance of LbsDataSubRecord to construct auto-filters + * @see org.apache.poi.hssf.usermodel.HSSFCombobox + */ + public static LbsDataSubRecord newAutoFilterInstance(){ + LbsDataSubRecord lbs = new LbsDataSubRecord(); + lbs._cbFContinued = 0x1FEE; //autofilters seem to alway have this magic number + lbs._iSel = 0x000; + + lbs._flags = 0x0301; + lbs._dropData = new LbsDropData(); + lbs._dropData._wStyle = LbsDropData.STYLE_COMBO_SIMPLE_DROPDOWN; + + // the number of lines to be displayed in the dropdown + lbs._dropData._cLine = 8; + return lbs; + } + + /** + * @return true as LbsDataSubRecord is always the last sub-record + */ + @Override + public boolean isTerminating(){ + return true; + } + + @Override + protected int getDataSize() { + int result = 2; // 2 initial shorts + + // optional link formula + if (_linkPtg != null) { + result += 2; // encoded Ptg size + result += 4; // unknown int + result += _linkPtg.getSize(); + if (_unknownPostFormulaByte != null) { + result += 1; + } + } + + result += 4 * 2; // 4 shorts + if(_dropData != null) { + result += _dropData.getDataSize(); + } + if(_rgLines != null) { + for(String str : _rgLines){ + result += StringUtil.getEncodedSize(str); + } + } + if(_bsels != null) { + result += _bsels.length; + } + return result; + } + + @Override + public void serialize(LittleEndianOutput out) { + out.writeShort(sid); + out.writeShort(_cbFContinued); + + if (_linkPtg == null) { + out.writeShort(0); + } else { + int formulaSize = _linkPtg.getSize(); + int linkSize = formulaSize + 6; + if (_unknownPostFormulaByte != null) { + linkSize++; + } + out.writeShort(linkSize); + out.writeShort(formulaSize); + out.writeInt(_unknownPreFormulaInt); + _linkPtg.write(out); + if (_unknownPostFormulaByte != null) { + out.writeByte(_unknownPostFormulaByte.intValue()); + } + } + + out.writeShort(_cLines); + out.writeShort(_iSel); + out.writeShort(_flags); + out.writeShort(_idEdit); + + if(_dropData != null) { + _dropData.serialize(out); + } + + if(_rgLines != null) { + for(String str : _rgLines){ + StringUtil.writeUnicodeString(out, str); + } + } + + if(_bsels != null) { + for(boolean val : _bsels){ + out.writeByte(val ? 1 : 0); + } + } + } + + @Override + public LbsDataSubRecord clone() { + // TODO: is immutable ??? + return this; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(256); + + sb.append("[ftLbsData]\n"); + sb.append(" .unknownShort1 =").append(HexDump.shortToHex(_cbFContinued)).append("\n"); + sb.append(" .formula = ").append('\n'); + if(_linkPtg != null) { + sb.append(_linkPtg.toString()).append(_linkPtg.getRVAType()).append('\n'); + } + sb.append(" .nEntryCount =").append(HexDump.shortToHex(_cLines)).append("\n"); + sb.append(" .selEntryIx =").append(HexDump.shortToHex(_iSel)).append("\n"); + sb.append(" .style =").append(HexDump.shortToHex(_flags)).append("\n"); + sb.append(" .unknownShort10=").append(HexDump.shortToHex(_idEdit)).append("\n"); + if(_dropData != null) { + sb.append('\n').append(_dropData.toString()); + } + sb.append("[/ftLbsData]\n"); + return sb.toString(); + } + + /** + * + * @return the formula that specifies the range of cell values that are the items in this list. + */ + public Ptg getFormula(){ + return _linkPtg; + } + + /** + * @return the number of items in the list + */ + public int getNumberOfItems(){ + return _cLines; + } + + /** + * This structure specifies properties of the dropdown list control + */ + public static class LbsDropData { + /** + * Combo dropdown control + */ + public static final int STYLE_COMBO_DROPDOWN = 0; + /** + * Combo Edit dropdown control + */ + public static final int STYLE_COMBO_EDIT_DROPDOWN = 1; + /** + * Simple dropdown control (just the dropdown button) + */ + public static final int STYLE_COMBO_SIMPLE_DROPDOWN = 2; + + /** + * An unsigned integer that specifies the style of this dropdown. + */ + private int _wStyle; + + /** + * An unsigned integer that specifies the number of lines to be displayed in the dropdown. + */ + private int _cLine; + + /** + * An unsigned integer that specifies the smallest width in pixels allowed for the dropdown window + */ + private int _dxMin; + + /** + * a string that specifies the current string value in the dropdown + */ + private final String _str; + + /** + * Optional, undefined and MUST be ignored. + * This field MUST exist if and only if the size of str in bytes is an odd number + */ + private Byte _unused; + + public LbsDropData(){ + _str = ""; + _unused = 0; + } + + public LbsDropData(LittleEndianInput in){ + _wStyle = in.readUShort(); + _cLine = in.readUShort(); + _dxMin = in.readUShort(); + _str = StringUtil.readUnicodeString(in); + if(StringUtil.getEncodedSize(_str) % 2 != 0){ + _unused = in.readByte(); + } + } + + /** + * Set the style of this dropdown.

+ * + * Possible values: + *

    + *
  • 0: Combo dropdown control
  • + *
  • 1: Combo Edit dropdown control
  • + *
  • 2: Simple dropdown control (just the dropdown button)
  • + *
+ * + * @param style the style - see possible values + */ + public void setStyle(int style){ + _wStyle = style; + } + + /** + * Set the number of lines to be displayed in the dropdown. + * + * @param num the number of lines to be displayed in the dropdown + */ + public void setNumLines(int num){ + _cLine = num; + } + + public void serialize(LittleEndianOutput out) { + out.writeShort(_wStyle); + out.writeShort(_cLine); + out.writeShort(_dxMin); + StringUtil.writeUnicodeString(out, _str); + if(_unused != null) { + out.writeByte(_unused); + } + } + + public int getDataSize() { + int size = 6; + size += StringUtil.getEncodedSize(_str); + if(_unused != null) { + size++; + } + return size; + } + + @Override + public String toString(){ + StringBuffer sb = new StringBuffer(); + sb.append("[LbsDropData]\n"); + sb.append(" ._wStyle: ").append(_wStyle).append('\n'); + sb.append(" ._cLine: ").append(_cLine).append('\n'); + sb.append(" ._dxMin: ").append(_dxMin).append('\n'); + sb.append(" ._str: ").append(_str).append('\n'); + if(_unused != null) { + sb.append(" ._unused: ").append(_unused).append('\n'); + } + sb.append("[/LbsDropData]\n"); + + return sb.toString(); + } + } +} diff --git a/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java b/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java index 2c5ba94c09..e5f11e83e2 100644 --- a/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java +++ b/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java @@ -341,14 +341,14 @@ public final class RecordFactoryInputStream { } if (_lastRecord instanceof DrawingGroupRecord) { ((DrawingGroupRecord) _lastRecord).processContinueRecord(contRec.getData()); - return null; - } - if (_lastRecord instanceof DrawingRecord) { -// ((DrawingRecord) _lastRecord).appendContinueRecord(contRec.getData()); - return contRec; - } - if (_lastRecord instanceof UnknownRecord) { - //Gracefully handle records that we don't know about, + return null; + } + if (_lastRecord instanceof DrawingRecord) { +// ((DrawingRecord) _lastRecord).appendContinueRecord(contRec.getData()); + return contRec; + } + if (_lastRecord instanceof UnknownRecord) { + //Gracefully handle records that we don't know about, //that happen to be continued return record; } diff --git a/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordInput.java b/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordInput.java index ecd8d4b595..b301d54442 100644 --- a/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordInput.java +++ b/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordInput.java @@ -1,132 +1,132 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.hssf.record.cont; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.hssf.record.ContinueRecord; -import org.apache.poi.util.LittleEndianInput; - -/** - * A decorated {@link RecordInputStream} that can read primitive data types - * (short, int, long, etc.) spanned across a {@link ContinueRecord } boundary. - * - *

- * Most records construct themselves from {@link RecordInputStream}. - * This class assumes that a {@link ContinueRecord} record break always occurs at the type boundary, - * however, it is not always so. - *

- * Two attachments to Bugzilla 50779 - * demonstrate that a CONTINUE break can appear right in between two bytes of a unicode character - * or between two bytes of a short. The problematic portion of the data is - * in a Asian Phonetic Settings Block (ExtRst) of a UnicodeString. - *

- * {@link RecordInputStream} greedily requests the bytes to be read and stumbles on such files with a - * "Not enough data (1) to read requested (2) bytes" exception. The ContinuableRecordInput - * class circumvents this "type boundary" rule and reads data byte-by-byte rolling over CONTINUE if necessary. - *

- * - *

- * YK: For now (March 2011) this class is only used to read - * @link org.apache.poi.hssf.record.common.UnicodeString.ExtRst} blocks of a UnicodeString. - * - *

- */ -public class ContinuableRecordInput implements LittleEndianInput { - private final RecordInputStream _in; - - public ContinuableRecordInput(RecordInputStream in){ - _in = in; - } - @Override - public int available(){ - return _in.available(); - } - - @Override - public byte readByte(){ - return _in.readByte(); - } - - @Override - public int readUByte(){ - return _in.readUByte(); - } - - @Override - public short readShort(){ - return _in.readShort(); - } - - @Override - public int readUShort(){ - int ch1 = readUByte(); - int ch2 = readUByte(); - return (ch2 << 8) + (ch1 << 0); - } - - @Override - public int readInt(){ - int ch1 = _in.readUByte(); - int ch2 = _in.readUByte(); - int ch3 = _in.readUByte(); - int ch4 = _in.readUByte(); - return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0); - } - - @Override - public long readLong(){ - int b0 = _in.readUByte(); - int b1 = _in.readUByte(); - int b2 = _in.readUByte(); - int b3 = _in.readUByte(); - int b4 = _in.readUByte(); - int b5 = _in.readUByte(); - int b6 = _in.readUByte(); - int b7 = _in.readUByte(); - return (((long)b7 << 56) + - ((long)b6 << 48) + - ((long)b5 << 40) + - ((long)b4 << 32) + - ((long)b3 << 24) + - (b2 << 16) + - (b1 << 8) + - (b0 << 0)); - } - - @Override - public double readDouble(){ - return _in.readDouble(); - } - - @Override - public void readFully(byte[] buf){ - _in.readFully(buf); - } - - @Override - public void readFully(byte[] buf, int off, int len){ - _in.readFully(buf, off, len); - } - - @Override - public void readPlain(byte[] buf, int off, int len) { - readFully(buf, off, len); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.hssf.record.cont; + +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.hssf.record.ContinueRecord; +import org.apache.poi.util.LittleEndianInput; + +/** + * A decorated {@link RecordInputStream} that can read primitive data types + * (short, int, long, etc.) spanned across a {@link ContinueRecord } boundary. + * + *

+ * Most records construct themselves from {@link RecordInputStream}. + * This class assumes that a {@link ContinueRecord} record break always occurs at the type boundary, + * however, it is not always so. + *

+ * Two attachments to Bugzilla 50779 + * demonstrate that a CONTINUE break can appear right in between two bytes of a unicode character + * or between two bytes of a short. The problematic portion of the data is + * in a Asian Phonetic Settings Block (ExtRst) of a UnicodeString. + *

+ * {@link RecordInputStream} greedily requests the bytes to be read and stumbles on such files with a + * "Not enough data (1) to read requested (2) bytes" exception. The ContinuableRecordInput + * class circumvents this "type boundary" rule and reads data byte-by-byte rolling over CONTINUE if necessary. + *

+ * + *

+ * YK: For now (March 2011) this class is only used to read + * @link org.apache.poi.hssf.record.common.UnicodeString.ExtRst} blocks of a UnicodeString. + * + *

+ */ +public class ContinuableRecordInput implements LittleEndianInput { + private final RecordInputStream _in; + + public ContinuableRecordInput(RecordInputStream in){ + _in = in; + } + @Override + public int available(){ + return _in.available(); + } + + @Override + public byte readByte(){ + return _in.readByte(); + } + + @Override + public int readUByte(){ + return _in.readUByte(); + } + + @Override + public short readShort(){ + return _in.readShort(); + } + + @Override + public int readUShort(){ + int ch1 = readUByte(); + int ch2 = readUByte(); + return (ch2 << 8) + (ch1 << 0); + } + + @Override + public int readInt(){ + int ch1 = _in.readUByte(); + int ch2 = _in.readUByte(); + int ch3 = _in.readUByte(); + int ch4 = _in.readUByte(); + return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0); + } + + @Override + public long readLong(){ + int b0 = _in.readUByte(); + int b1 = _in.readUByte(); + int b2 = _in.readUByte(); + int b3 = _in.readUByte(); + int b4 = _in.readUByte(); + int b5 = _in.readUByte(); + int b6 = _in.readUByte(); + int b7 = _in.readUByte(); + return (((long)b7 << 56) + + ((long)b6 << 48) + + ((long)b5 << 40) + + ((long)b4 << 32) + + ((long)b3 << 24) + + (b2 << 16) + + (b1 << 8) + + (b0 << 0)); + } + + @Override + public double readDouble(){ + return _in.readDouble(); + } + + @Override + public void readFully(byte[] buf){ + _in.readFully(buf); + } + + @Override + public void readFully(byte[] buf, int off, int len){ + _in.readFully(buf, off, len); + } + + @Override + public void readPlain(byte[] buf, int off, int len) { + readFully(buf, off, len); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java b/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java index 31cd919ed6..093d2083a8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java +++ b/src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java @@ -1,832 +1,832 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - - -package org.apache.poi.hssf.usermodel; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.Image; -import java.awt.Paint; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ImageObserver; -import java.awt.image.RenderedImage; -import java.awt.image.renderable.RenderableImage; -import java.io.PrintStream; -import java.text.AttributedCharacterIterator; -import java.util.Arrays; -import java.util.Map; - -import org.apache.poi.util.Internal; - -public class DummyGraphics2d extends Graphics2D { - private BufferedImage bufimg; - private final Graphics2D g2D; - private final PrintStream log; - - public DummyGraphics2d() { - this(System.out); - } - - public DummyGraphics2d(PrintStream log) { - bufimg = new BufferedImage(1000, 1000, 2); - g2D = (Graphics2D)bufimg.getGraphics(); - this.log = log; - } - - public DummyGraphics2d(PrintStream log, Graphics2D g2D) { - this.g2D = g2D; - this.log = log; - } - - public void addRenderingHints(Map hints) { - String l = - "addRenderingHinds(Map):" + - "\n hints = " + hints; - log.println( l ); - g2D.addRenderingHints( hints ); - } - - public void clip(Shape s) { - String l = - "clip(Shape):" + - "\n s = " + s; - log.println( l ); - g2D.clip( s ); - } - - public void draw(Shape s) { - String l = - "draw(Shape):" + - "\n s = " + s; - log.println( l ); - g2D.draw( s ); - } - - public void drawGlyphVector(GlyphVector g, float x, float y) { - String l = - "drawGlyphVector(GlyphVector, float, float):" + - "\n g = " + g + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawGlyphVector( g, x, y ); - } - - public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { - String l = - "drawImage(BufferedImage, BufferedImageOp, x, y):" + - "\n img = " + img + - "\n op = " + op + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawImage( img, op, x, y ); - } - - public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { - String l = - "drawImage(Image,AfflineTransform,ImageObserver):" + - "\n img = " + img + - "\n xform = " + xform + - "\n obs = " + obs; - log.println( l ); - return g2D.drawImage( img, xform, obs ); - } - - public void drawRenderableImage(RenderableImage img, AffineTransform xform) { - String l = - "drawRenderableImage(RenderableImage, AfflineTransform):" + - "\n img = " + img + - "\n xform = " + xform; - log.println( l ); - g2D.drawRenderableImage( img, xform ); - } - - public void drawRenderedImage(RenderedImage img, AffineTransform xform) { - String l = - "drawRenderedImage(RenderedImage, AffineTransform):" + - "\n img = " + img + - "\n xform = " + xform; - log.println( l ); - g2D.drawRenderedImage( img, xform ); - } - - public void drawString(AttributedCharacterIterator iterator, float x, float y) { - String l = - "drawString(AttributedCharacterIterator):" + - "\n iterator = " + iterator + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawString( iterator, x, y ); - } - - public void drawString(String s, float x, float y) { - String l = - "drawString(s,x,y):" + - "\n s = " + s + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawString( s, x, y ); - } - - public void fill(Shape s) { - String l = - "fill(Shape):" + - "\n s = " + s; - log.println( l ); - g2D.fill( s ); - } - - public Color getBackground() { - log.println( "getBackground():" ); - return g2D.getBackground(); - } - - public Composite getComposite() { - log.println( "getComposite():" ); - return g2D.getComposite(); - } - - public GraphicsConfiguration getDeviceConfiguration() { - log.println( "getDeviceConfiguration():" ); - return g2D.getDeviceConfiguration(); - } - - public FontRenderContext getFontRenderContext() { - log.println( "getFontRenderContext():" ); - return g2D.getFontRenderContext(); - } - - public Paint getPaint() { - log.println( "getPaint():" ); - return g2D.getPaint(); - } - - public Object getRenderingHint(RenderingHints.Key hintKey) { - String l = - "getRenderingHint(RenderingHints.Key):" + - "\n hintKey = " + hintKey; - log.println( l ); - return g2D.getRenderingHint( hintKey ); - } - - public RenderingHints getRenderingHints() { - log.println( "getRenderingHints():" ); - return g2D.getRenderingHints(); - } - - public Stroke getStroke() { - log.println( "getStroke():" ); - return g2D.getStroke(); - } - - public AffineTransform getTransform() { - log.println( "getTransform():" ); - return g2D.getTransform(); - } - - public boolean hit(Rectangle rect, Shape s, boolean onStroke) { - String l = - "hit(Rectangle, Shape, onStroke):" + - "\n rect = " + rect + - "\n s = " + s + - "\n onStroke = " + onStroke; - log.println( l ); - return g2D.hit( rect, s, onStroke ); - } - - public void rotate(double theta) { - String l = - "rotate(theta):" + - "\n theta = " + theta; - log.println( l ); - g2D.rotate( theta ); - } - - public void rotate(double theta, double x, double y) { - String l = - "rotate(double,double,double):" + - "\n theta = " + theta + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.rotate( theta, x, y ); - } - - public void scale(double sx, double sy) { - String l = - "scale(double,double):" + - "\n sx = " + sx + - "\n sy"; - log.println( l ); - g2D.scale( sx, sy ); - } - - public void setBackground(Color color) { - String l = - "setBackground(Color):" + - "\n color = " + color; - log.println( l ); - g2D.setBackground( color ); - } - - public void setComposite(Composite comp) { - String l = - "setComposite(Composite):" + - "\n comp = " + comp; - log.println( l ); - g2D.setComposite( comp ); - } - - public void setPaint( Paint paint ) { - String l = - "setPaint(Paint):" + - "\n paint = " + paint; - log.println( l ); - g2D.setPaint( paint ); - } - - public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) { - String l = - "setRenderingHint(RenderingHints.Key, Object):" + - "\n hintKey = " + hintKey + - "\n hintValue = " + hintValue; - log.println( l ); - g2D.setRenderingHint( hintKey, hintValue ); - } - - public void setRenderingHints(Map hints) { - String l = - "setRenderingHints(Map):" + - "\n hints = " + hints; - log.println( l ); - g2D.setRenderingHints( hints ); - } - - public void setStroke(Stroke s) { - String l; - if (s instanceof BasicStroke) { - BasicStroke bs = (BasicStroke)s; - l = "setStroke(Stoke):" + - "\n s = BasicStroke(" + - "\n dash[]: "+Arrays.toString(bs.getDashArray()) + - "\n dashPhase: "+bs.getDashPhase() + - "\n endCap: "+bs.getEndCap() + - "\n lineJoin: "+bs.getLineJoin() + - "\n width: "+bs.getLineWidth() + - "\n miterLimit: "+bs.getMiterLimit() + - "\n )"; - } else { - l = "setStroke(Stoke):" + - "\n s = " + s; - } - log.println( l ); - g2D.setStroke( s ); - } - - public void setTransform(AffineTransform Tx) { - String l = - "setTransform():" + - "\n Tx = " + Tx; - log.println( l ); - g2D.setTransform( Tx ); - } - - public void shear(double shx, double shy) { - String l = - "shear(shx, dhy):" + - "\n shx = " + shx + - "\n shy = " + shy; - log.println( l ); - g2D.shear( shx, shy ); - } - - public void transform(AffineTransform Tx) { - String l = - "transform(AffineTransform):" + - "\n Tx = " + Tx; - log.println( l ); - g2D.transform( Tx ); - } - - public void translate(double tx, double ty) { - String l = - "translate(double, double):" + - "\n tx = " + tx + - "\n ty = " + ty; - log.println( l ); - g2D.translate( tx, ty ); - } - - public void clearRect(int x, int y, int width, int height) { - String l = - "clearRect(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.clearRect( x, y, width, height ); - } - - public void clipRect(int x, int y, int width, int height) { - String l = - "clipRect(int, int, int, int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "height = " + height; - log.println( l ); - g2D.clipRect( x, y, width, height ); - } - - public void copyArea(int x, int y, int width, int height, int dx, int dy) { - String l = - "copyArea(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.copyArea( x, y, width, height, dx, dy ); - } - - public Graphics create() { - log.println( "create():" ); - return g2D.create(); - } - - public Graphics create(int x, int y, int width, int height) { - String l = - "create(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - return g2D.create( x, y, width, height ); - } - - public void dispose() { - log.println( "dispose():" ); - g2D.dispose(); - } - - public void draw3DRect(int x, int y, int width, int height, boolean raised) { - String l = - "draw3DRect(int,int,int,int,boolean):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height + - "\n raised = " + raised; - log.println( l ); - g2D.draw3DRect( x, y, width, height, raised ); - } - - public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { - String l = - "drawArc(int,int,int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height + - "\n startAngle = " + startAngle + - "\n arcAngle = " + arcAngle; - log.println( l ); - g2D.drawArc( x, y, width, height, startAngle, arcAngle ); - } - - public void drawBytes(byte data[], int offset, int length, int x, int y) { - String l = - "drawBytes(byte[],int,int,int,int):" + - "\n data = " + Arrays.toString(data) + - "\n offset = " + offset + - "\n length = " + length + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawBytes( data, offset, length, x, y ); - } - - public void drawChars(char data[], int offset, int length, int x, int y) { - String l = - "drawChars(data,int,int,int,int):" + - "\n data = " + Arrays.toString(data) + - "\n offset = " + offset + - "\n length = " + length + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawChars( data, offset, length, x, y ); - } - - public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { - String l = - "drawImage(Image,int,int,int,int,int,int,int,int,ImageObserver):" + - "\n img = " + img + - "\n dx1 = " + dx1 + - "\n dy1 = " + dy1 + - "\n dx2 = " + dx2 + - "\n dy2 = " + dy2 + - "\n sx1 = " + sx1 + - "\n sy1 = " + sy1 + - "\n sx2 = " + sx2 + - "\n sy2 = " + sy2 + - "\n observer = " + observer; - log.println( l ); - return g2D.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer ); - } - - public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { - String l = - "drawImage(Image,int,int,int,int,int,int,int,int,Color,ImageObserver):" + - "\n img = " + img + - "\n dx1 = " + dx1 + - "\n dy1 = " + dy1 + - "\n dx2 = " + dx2 + - "\n dy2 = " + dy2 + - "\n sx1 = " + sx1 + - "\n sy1 = " + sy1 + - "\n sx2 = " + sx2 + - "\n sy2 = " + sy2 + - "\n bgcolor = " + bgcolor + - "\n observer = " + observer; - log.println( l ); - return g2D.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer ); - } - - public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { - String l = - "drawImage(Image,int,int,Color,ImageObserver):" + - "\n img = " + img + - "\n x = " + x + - "\n y = " + y + - "\n bgcolor = " + bgcolor + - "\n observer = " + observer; - log.println( l ); - return g2D.drawImage( img, x, y, bgcolor, observer ); - } - - public boolean drawImage(Image img, int x, int y, ImageObserver observer) { - String l = - "drawImage(Image,int,int,observer):" + - "\n img = " + img + - "\n x = " + x + - "\n y = " + y + - "\n observer = " + observer; - log.println( l ); - return g2D.drawImage( img, x, y, observer ); - } - - public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { - String l = - "drawImage(Image,int,int,int,int,Color,ImageObserver):" + - "\n img = " + img + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height + - "\n bgcolor = " + bgcolor + - "\n observer = " + observer; - log.println( l ); - return g2D.drawImage( img, x, y, width, height, bgcolor, observer ); - } - - public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { - String l = - "drawImage(Image,int,int,width,height,observer):" + - "\n img = " + img + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height + - "\n observer = " + observer; - log.println( l ); - return g2D.drawImage( img, x, y, width, height, observer ); - } - - public void drawLine(int x1, int y1, int x2, int y2) { - String l = - "drawLine(int,int,int,int):" + - "\n x1 = " + x1 + - "\n y1 = " + y1 + - "\n x2 = " + x2 + - "\n y2 = " + y2; - log.println( l ); - g2D.drawLine( x1, y1, x2, y2 ); - } - - public void drawOval(int x, int y, int width, int height) { - String l = - "drawOval(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.drawOval( x, y, width, height ); - } - - public void drawPolygon(Polygon p) { - String l = - "drawPolygon(Polygon):" + - "\n p = " + p; - log.println( l ); - g2D.drawPolygon( p ); - } - - public void drawPolygon(int xPoints[], int yPoints[], int nPoints) { - String l = - "drawPolygon(int[],int[],int):" + - "\n xPoints = " + Arrays.toString(xPoints) + - "\n yPoints = " + Arrays.toString(yPoints) + - "\n nPoints = " + nPoints; - log.println( l ); - g2D.drawPolygon( xPoints, yPoints, nPoints ); - } - - public void drawPolyline(int xPoints[], int yPoints[], int nPoints) { - String l = - "drawPolyline(int[],int[],int):" + - "\n xPoints = " + Arrays.toString(xPoints) + - "\n yPoints = " + Arrays.toString(yPoints) + - "\n nPoints = " + nPoints; - log.println( l ); - g2D.drawPolyline( xPoints, yPoints, nPoints ); - } - - public void drawRect(int x, int y, int width, int height) { - String l = - "drawRect(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.drawRect( x, y, width, height ); - } - - public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { - String l = - "drawRoundRect(int,int,int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height + - "\n arcWidth = " + arcWidth + - "\n arcHeight = " + arcHeight; - log.println( l ); - g2D.drawRoundRect( x, y, width, height, arcWidth, arcHeight ); - } - - public void drawString(AttributedCharacterIterator iterator, int x, int y) { - String l = - "drawString(AttributedCharacterIterator,int,int):" + - "\n iterator = " + iterator + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawString( iterator, x, y ); - } - - public void drawString(String str, int x, int y) { - String l = - "drawString(str,int,int):" + - "\n str = " + str + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.drawString( str, x, y ); - } - - public void fill3DRect(int x, int y, int width, int height, boolean raised) { - String l = - "fill3DRect(int,int,int,int,boolean):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height + - "\n raised = " + raised; - log.println( l ); - g2D.fill3DRect( x, y, width, height, raised ); - } - - public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { - String l = - "fillArc(int,int,int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height + - "\n startAngle = " + startAngle + - "\n arcAngle = " + arcAngle; - log.println( l ); - g2D.fillArc( x, y, width, height, startAngle, arcAngle ); - } - - public void fillOval(int x, int y, int width, int height) { - String l = - "fillOval(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.fillOval( x, y, width, height ); - } - - public void fillPolygon(Polygon p) { - String l = - "fillPolygon(Polygon):" + - "\n p = " + p; - log.println( l ); - g2D.fillPolygon( p ); - } - - public void fillPolygon(int xPoints[], int yPoints[], int nPoints) { - String l = - "fillPolygon(int[],int[],int):" + - "\n xPoints = " + Arrays.toString(xPoints) + - "\n yPoints = " + Arrays.toString(yPoints) + - "\n nPoints = " + nPoints; - log.println( l ); - g2D.fillPolygon( xPoints, yPoints, nPoints ); - } - - public void fillRect(int x, int y, int width, int height) { - String l = - "fillRect(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.fillRect( x, y, width, height ); - } - - public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { - String l = - "fillRoundRect(int,int,int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.fillRoundRect( x, y, width, height, arcWidth, arcHeight ); - } - - // FIXME: should be protected - // FindBugs, category MALICIOUS_CODE, FI_PUBLIC_SHOULD_BE_PROTECTED - // A class's finalize() method should have protected access, not public - @Internal - @Override - public final void finalize() { - log.println( "finalize():" ); - g2D.finalize(); // NOSOLAR - super.finalize(); - } - - public Shape getClip() { - log.println( "getClip():" ); - return g2D.getClip(); - } - - public Rectangle getClipBounds() { - log.println( "getClipBounds():" ); - return g2D.getClipBounds(); - } - - public Rectangle getClipBounds(Rectangle r) { - String l = - "getClipBounds(Rectangle):" + - "\n r = " + r; - log.println( l ); - return g2D.getClipBounds( r ); - } - - public Color getColor() { - log.println( "getColor():" ); - return g2D.getColor(); - } - - public Font getFont() { - log.println( "getFont():" ); - return g2D.getFont(); - } - - public FontMetrics getFontMetrics() { - log.println( "getFontMetrics():" ); - return g2D.getFontMetrics(); - } - - public FontMetrics getFontMetrics(Font f) { - log.println( "getFontMetrics():" ); - return g2D.getFontMetrics( f ); - } - - public boolean hitClip(int x, int y, int width, int height) { - String l = - "hitClip(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - return g2D.hitClip( x, y, width, height ); - } - - public void setClip(Shape clip) { - String l = - "setClip(Shape):" + - "\n clip = " + clip; - log.println( l ); - g2D.setClip( clip ); - } - - public void setClip(int x, int y, int width, int height) { - String l = - "setClip(int,int,int,int):" + - "\n x = " + x + - "\n y = " + y + - "\n width = " + width + - "\n height = " + height; - log.println( l ); - g2D.setClip( x, y, width, height ); - } - - public void setColor(Color c) { - String l = - "setColor():" + - "\n c = " + c; - log.println( l ); - g2D.setColor( c ); - } - - public void setFont(Font font) { - String l = - "setFont(Font):" + - "\n font = " + font; - log.println( l ); - g2D.setFont( font ); - } - - public void setPaintMode() { - log.println( "setPaintMode():" ); - g2D.setPaintMode(); - } - - public void setXORMode(Color c1) { - String l = - "setXORMode(Color):" + - "\n c1 = " + c1; - log.println( l ); - g2D.setXORMode( c1 ); - } - - public String toString() { - log.println( "toString():" ); - return g2D.toString(); - } - - public void translate(int x, int y) { - String l = - "translate(int,int):" + - "\n x = " + x + - "\n y = " + y; - log.println( l ); - g2D.translate( x, y ); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.hssf.usermodel; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.io.PrintStream; +import java.text.AttributedCharacterIterator; +import java.util.Arrays; +import java.util.Map; + +import org.apache.poi.util.Internal; + +public class DummyGraphics2d extends Graphics2D { + private BufferedImage bufimg; + private final Graphics2D g2D; + private final PrintStream log; + + public DummyGraphics2d() { + this(System.out); + } + + public DummyGraphics2d(PrintStream log) { + bufimg = new BufferedImage(1000, 1000, 2); + g2D = (Graphics2D)bufimg.getGraphics(); + this.log = log; + } + + public DummyGraphics2d(PrintStream log, Graphics2D g2D) { + this.g2D = g2D; + this.log = log; + } + + public void addRenderingHints(Map hints) { + String l = + "addRenderingHinds(Map):" + + "\n hints = " + hints; + log.println( l ); + g2D.addRenderingHints( hints ); + } + + public void clip(Shape s) { + String l = + "clip(Shape):" + + "\n s = " + s; + log.println( l ); + g2D.clip( s ); + } + + public void draw(Shape s) { + String l = + "draw(Shape):" + + "\n s = " + s; + log.println( l ); + g2D.draw( s ); + } + + public void drawGlyphVector(GlyphVector g, float x, float y) { + String l = + "drawGlyphVector(GlyphVector, float, float):" + + "\n g = " + g + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawGlyphVector( g, x, y ); + } + + public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { + String l = + "drawImage(BufferedImage, BufferedImageOp, x, y):" + + "\n img = " + img + + "\n op = " + op + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawImage( img, op, x, y ); + } + + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { + String l = + "drawImage(Image,AfflineTransform,ImageObserver):" + + "\n img = " + img + + "\n xform = " + xform + + "\n obs = " + obs; + log.println( l ); + return g2D.drawImage( img, xform, obs ); + } + + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + String l = + "drawRenderableImage(RenderableImage, AfflineTransform):" + + "\n img = " + img + + "\n xform = " + xform; + log.println( l ); + g2D.drawRenderableImage( img, xform ); + } + + public void drawRenderedImage(RenderedImage img, AffineTransform xform) { + String l = + "drawRenderedImage(RenderedImage, AffineTransform):" + + "\n img = " + img + + "\n xform = " + xform; + log.println( l ); + g2D.drawRenderedImage( img, xform ); + } + + public void drawString(AttributedCharacterIterator iterator, float x, float y) { + String l = + "drawString(AttributedCharacterIterator):" + + "\n iterator = " + iterator + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawString( iterator, x, y ); + } + + public void drawString(String s, float x, float y) { + String l = + "drawString(s,x,y):" + + "\n s = " + s + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawString( s, x, y ); + } + + public void fill(Shape s) { + String l = + "fill(Shape):" + + "\n s = " + s; + log.println( l ); + g2D.fill( s ); + } + + public Color getBackground() { + log.println( "getBackground():" ); + return g2D.getBackground(); + } + + public Composite getComposite() { + log.println( "getComposite():" ); + return g2D.getComposite(); + } + + public GraphicsConfiguration getDeviceConfiguration() { + log.println( "getDeviceConfiguration():" ); + return g2D.getDeviceConfiguration(); + } + + public FontRenderContext getFontRenderContext() { + log.println( "getFontRenderContext():" ); + return g2D.getFontRenderContext(); + } + + public Paint getPaint() { + log.println( "getPaint():" ); + return g2D.getPaint(); + } + + public Object getRenderingHint(RenderingHints.Key hintKey) { + String l = + "getRenderingHint(RenderingHints.Key):" + + "\n hintKey = " + hintKey; + log.println( l ); + return g2D.getRenderingHint( hintKey ); + } + + public RenderingHints getRenderingHints() { + log.println( "getRenderingHints():" ); + return g2D.getRenderingHints(); + } + + public Stroke getStroke() { + log.println( "getStroke():" ); + return g2D.getStroke(); + } + + public AffineTransform getTransform() { + log.println( "getTransform():" ); + return g2D.getTransform(); + } + + public boolean hit(Rectangle rect, Shape s, boolean onStroke) { + String l = + "hit(Rectangle, Shape, onStroke):" + + "\n rect = " + rect + + "\n s = " + s + + "\n onStroke = " + onStroke; + log.println( l ); + return g2D.hit( rect, s, onStroke ); + } + + public void rotate(double theta) { + String l = + "rotate(theta):" + + "\n theta = " + theta; + log.println( l ); + g2D.rotate( theta ); + } + + public void rotate(double theta, double x, double y) { + String l = + "rotate(double,double,double):" + + "\n theta = " + theta + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.rotate( theta, x, y ); + } + + public void scale(double sx, double sy) { + String l = + "scale(double,double):" + + "\n sx = " + sx + + "\n sy"; + log.println( l ); + g2D.scale( sx, sy ); + } + + public void setBackground(Color color) { + String l = + "setBackground(Color):" + + "\n color = " + color; + log.println( l ); + g2D.setBackground( color ); + } + + public void setComposite(Composite comp) { + String l = + "setComposite(Composite):" + + "\n comp = " + comp; + log.println( l ); + g2D.setComposite( comp ); + } + + public void setPaint( Paint paint ) { + String l = + "setPaint(Paint):" + + "\n paint = " + paint; + log.println( l ); + g2D.setPaint( paint ); + } + + public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) { + String l = + "setRenderingHint(RenderingHints.Key, Object):" + + "\n hintKey = " + hintKey + + "\n hintValue = " + hintValue; + log.println( l ); + g2D.setRenderingHint( hintKey, hintValue ); + } + + public void setRenderingHints(Map hints) { + String l = + "setRenderingHints(Map):" + + "\n hints = " + hints; + log.println( l ); + g2D.setRenderingHints( hints ); + } + + public void setStroke(Stroke s) { + String l; + if (s instanceof BasicStroke) { + BasicStroke bs = (BasicStroke)s; + l = "setStroke(Stoke):" + + "\n s = BasicStroke(" + + "\n dash[]: "+Arrays.toString(bs.getDashArray()) + + "\n dashPhase: "+bs.getDashPhase() + + "\n endCap: "+bs.getEndCap() + + "\n lineJoin: "+bs.getLineJoin() + + "\n width: "+bs.getLineWidth() + + "\n miterLimit: "+bs.getMiterLimit() + + "\n )"; + } else { + l = "setStroke(Stoke):" + + "\n s = " + s; + } + log.println( l ); + g2D.setStroke( s ); + } + + public void setTransform(AffineTransform Tx) { + String l = + "setTransform():" + + "\n Tx = " + Tx; + log.println( l ); + g2D.setTransform( Tx ); + } + + public void shear(double shx, double shy) { + String l = + "shear(shx, dhy):" + + "\n shx = " + shx + + "\n shy = " + shy; + log.println( l ); + g2D.shear( shx, shy ); + } + + public void transform(AffineTransform Tx) { + String l = + "transform(AffineTransform):" + + "\n Tx = " + Tx; + log.println( l ); + g2D.transform( Tx ); + } + + public void translate(double tx, double ty) { + String l = + "translate(double, double):" + + "\n tx = " + tx + + "\n ty = " + ty; + log.println( l ); + g2D.translate( tx, ty ); + } + + public void clearRect(int x, int y, int width, int height) { + String l = + "clearRect(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.clearRect( x, y, width, height ); + } + + public void clipRect(int x, int y, int width, int height) { + String l = + "clipRect(int, int, int, int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "height = " + height; + log.println( l ); + g2D.clipRect( x, y, width, height ); + } + + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + String l = + "copyArea(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.copyArea( x, y, width, height, dx, dy ); + } + + public Graphics create() { + log.println( "create():" ); + return g2D.create(); + } + + public Graphics create(int x, int y, int width, int height) { + String l = + "create(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + return g2D.create( x, y, width, height ); + } + + public void dispose() { + log.println( "dispose():" ); + g2D.dispose(); + } + + public void draw3DRect(int x, int y, int width, int height, boolean raised) { + String l = + "draw3DRect(int,int,int,int,boolean):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height + + "\n raised = " + raised; + log.println( l ); + g2D.draw3DRect( x, y, width, height, raised ); + } + + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + String l = + "drawArc(int,int,int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height + + "\n startAngle = " + startAngle + + "\n arcAngle = " + arcAngle; + log.println( l ); + g2D.drawArc( x, y, width, height, startAngle, arcAngle ); + } + + public void drawBytes(byte data[], int offset, int length, int x, int y) { + String l = + "drawBytes(byte[],int,int,int,int):" + + "\n data = " + Arrays.toString(data) + + "\n offset = " + offset + + "\n length = " + length + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawBytes( data, offset, length, x, y ); + } + + public void drawChars(char data[], int offset, int length, int x, int y) { + String l = + "drawChars(data,int,int,int,int):" + + "\n data = " + Arrays.toString(data) + + "\n offset = " + offset + + "\n length = " + length + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawChars( data, offset, length, x, y ); + } + + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { + String l = + "drawImage(Image,int,int,int,int,int,int,int,int,ImageObserver):" + + "\n img = " + img + + "\n dx1 = " + dx1 + + "\n dy1 = " + dy1 + + "\n dx2 = " + dx2 + + "\n dy2 = " + dy2 + + "\n sx1 = " + sx1 + + "\n sy1 = " + sy1 + + "\n sx2 = " + sx2 + + "\n sy2 = " + sy2 + + "\n observer = " + observer; + log.println( l ); + return g2D.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer ); + } + + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { + String l = + "drawImage(Image,int,int,int,int,int,int,int,int,Color,ImageObserver):" + + "\n img = " + img + + "\n dx1 = " + dx1 + + "\n dy1 = " + dy1 + + "\n dx2 = " + dx2 + + "\n dy2 = " + dy2 + + "\n sx1 = " + sx1 + + "\n sy1 = " + sy1 + + "\n sx2 = " + sx2 + + "\n sy2 = " + sy2 + + "\n bgcolor = " + bgcolor + + "\n observer = " + observer; + log.println( l ); + return g2D.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer ); + } + + public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { + String l = + "drawImage(Image,int,int,Color,ImageObserver):" + + "\n img = " + img + + "\n x = " + x + + "\n y = " + y + + "\n bgcolor = " + bgcolor + + "\n observer = " + observer; + log.println( l ); + return g2D.drawImage( img, x, y, bgcolor, observer ); + } + + public boolean drawImage(Image img, int x, int y, ImageObserver observer) { + String l = + "drawImage(Image,int,int,observer):" + + "\n img = " + img + + "\n x = " + x + + "\n y = " + y + + "\n observer = " + observer; + log.println( l ); + return g2D.drawImage( img, x, y, observer ); + } + + public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { + String l = + "drawImage(Image,int,int,int,int,Color,ImageObserver):" + + "\n img = " + img + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height + + "\n bgcolor = " + bgcolor + + "\n observer = " + observer; + log.println( l ); + return g2D.drawImage( img, x, y, width, height, bgcolor, observer ); + } + + public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { + String l = + "drawImage(Image,int,int,width,height,observer):" + + "\n img = " + img + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height + + "\n observer = " + observer; + log.println( l ); + return g2D.drawImage( img, x, y, width, height, observer ); + } + + public void drawLine(int x1, int y1, int x2, int y2) { + String l = + "drawLine(int,int,int,int):" + + "\n x1 = " + x1 + + "\n y1 = " + y1 + + "\n x2 = " + x2 + + "\n y2 = " + y2; + log.println( l ); + g2D.drawLine( x1, y1, x2, y2 ); + } + + public void drawOval(int x, int y, int width, int height) { + String l = + "drawOval(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.drawOval( x, y, width, height ); + } + + public void drawPolygon(Polygon p) { + String l = + "drawPolygon(Polygon):" + + "\n p = " + p; + log.println( l ); + g2D.drawPolygon( p ); + } + + public void drawPolygon(int xPoints[], int yPoints[], int nPoints) { + String l = + "drawPolygon(int[],int[],int):" + + "\n xPoints = " + Arrays.toString(xPoints) + + "\n yPoints = " + Arrays.toString(yPoints) + + "\n nPoints = " + nPoints; + log.println( l ); + g2D.drawPolygon( xPoints, yPoints, nPoints ); + } + + public void drawPolyline(int xPoints[], int yPoints[], int nPoints) { + String l = + "drawPolyline(int[],int[],int):" + + "\n xPoints = " + Arrays.toString(xPoints) + + "\n yPoints = " + Arrays.toString(yPoints) + + "\n nPoints = " + nPoints; + log.println( l ); + g2D.drawPolyline( xPoints, yPoints, nPoints ); + } + + public void drawRect(int x, int y, int width, int height) { + String l = + "drawRect(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.drawRect( x, y, width, height ); + } + + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + String l = + "drawRoundRect(int,int,int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height + + "\n arcWidth = " + arcWidth + + "\n arcHeight = " + arcHeight; + log.println( l ); + g2D.drawRoundRect( x, y, width, height, arcWidth, arcHeight ); + } + + public void drawString(AttributedCharacterIterator iterator, int x, int y) { + String l = + "drawString(AttributedCharacterIterator,int,int):" + + "\n iterator = " + iterator + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawString( iterator, x, y ); + } + + public void drawString(String str, int x, int y) { + String l = + "drawString(str,int,int):" + + "\n str = " + str + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.drawString( str, x, y ); + } + + public void fill3DRect(int x, int y, int width, int height, boolean raised) { + String l = + "fill3DRect(int,int,int,int,boolean):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height + + "\n raised = " + raised; + log.println( l ); + g2D.fill3DRect( x, y, width, height, raised ); + } + + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + String l = + "fillArc(int,int,int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height + + "\n startAngle = " + startAngle + + "\n arcAngle = " + arcAngle; + log.println( l ); + g2D.fillArc( x, y, width, height, startAngle, arcAngle ); + } + + public void fillOval(int x, int y, int width, int height) { + String l = + "fillOval(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.fillOval( x, y, width, height ); + } + + public void fillPolygon(Polygon p) { + String l = + "fillPolygon(Polygon):" + + "\n p = " + p; + log.println( l ); + g2D.fillPolygon( p ); + } + + public void fillPolygon(int xPoints[], int yPoints[], int nPoints) { + String l = + "fillPolygon(int[],int[],int):" + + "\n xPoints = " + Arrays.toString(xPoints) + + "\n yPoints = " + Arrays.toString(yPoints) + + "\n nPoints = " + nPoints; + log.println( l ); + g2D.fillPolygon( xPoints, yPoints, nPoints ); + } + + public void fillRect(int x, int y, int width, int height) { + String l = + "fillRect(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.fillRect( x, y, width, height ); + } + + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + String l = + "fillRoundRect(int,int,int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.fillRoundRect( x, y, width, height, arcWidth, arcHeight ); + } + + // FIXME: should be protected + // FindBugs, category MALICIOUS_CODE, FI_PUBLIC_SHOULD_BE_PROTECTED + // A class's finalize() method should have protected access, not public + @Internal + @Override + public final void finalize() { + log.println( "finalize():" ); + g2D.finalize(); // NOSOLAR + super.finalize(); + } + + public Shape getClip() { + log.println( "getClip():" ); + return g2D.getClip(); + } + + public Rectangle getClipBounds() { + log.println( "getClipBounds():" ); + return g2D.getClipBounds(); + } + + public Rectangle getClipBounds(Rectangle r) { + String l = + "getClipBounds(Rectangle):" + + "\n r = " + r; + log.println( l ); + return g2D.getClipBounds( r ); + } + + public Color getColor() { + log.println( "getColor():" ); + return g2D.getColor(); + } + + public Font getFont() { + log.println( "getFont():" ); + return g2D.getFont(); + } + + public FontMetrics getFontMetrics() { + log.println( "getFontMetrics():" ); + return g2D.getFontMetrics(); + } + + public FontMetrics getFontMetrics(Font f) { + log.println( "getFontMetrics():" ); + return g2D.getFontMetrics( f ); + } + + public boolean hitClip(int x, int y, int width, int height) { + String l = + "hitClip(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + return g2D.hitClip( x, y, width, height ); + } + + public void setClip(Shape clip) { + String l = + "setClip(Shape):" + + "\n clip = " + clip; + log.println( l ); + g2D.setClip( clip ); + } + + public void setClip(int x, int y, int width, int height) { + String l = + "setClip(int,int,int,int):" + + "\n x = " + x + + "\n y = " + y + + "\n width = " + width + + "\n height = " + height; + log.println( l ); + g2D.setClip( x, y, width, height ); + } + + public void setColor(Color c) { + String l = + "setColor():" + + "\n c = " + c; + log.println( l ); + g2D.setColor( c ); + } + + public void setFont(Font font) { + String l = + "setFont(Font):" + + "\n font = " + font; + log.println( l ); + g2D.setFont( font ); + } + + public void setPaintMode() { + log.println( "setPaintMode():" ); + g2D.setPaintMode(); + } + + public void setXORMode(Color c1) { + String l = + "setXORMode(Color):" + + "\n c1 = " + c1; + log.println( l ); + g2D.setXORMode( c1 ); + } + + public String toString() { + log.println( "toString():" ); + return g2D.toString(); + } + + public void translate(int x, int y) { + String l = + "translate(int,int):" + + "\n x = " + x + + "\n y = " + y; + log.println( l ); + g2D.translate( x, y ); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java index 6ebca2f4c9..5116f07620 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java @@ -1,101 +1,101 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.usermodel; - -import org.apache.poi.ddf.*; -import org.apache.poi.hssf.record.*; -import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; - -/** - * - */ -public class HSSFCombobox extends HSSFSimpleShape { - - public HSSFCombobox(EscherContainerRecord spContainer, ObjRecord objRecord) { - super(spContainer, objRecord); - } - - public HSSFCombobox(HSSFShape parent, HSSFAnchor anchor) { - super(parent, anchor); - super.setShapeType(OBJECT_TYPE_COMBO_BOX); - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); - cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX); - } - - @Override - protected TextObjectRecord createTextObjRecord() { - return null; - } - - @Override - protected EscherContainerRecord createSpContainer() { - EscherContainerRecord spContainer = new EscherContainerRecord(); - EscherSpRecord sp = new EscherSpRecord(); - EscherOptRecord opt = new EscherOptRecord(); - EscherClientDataRecord clientData = new EscherClientDataRecord(); - - spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); - spContainer.setOptions((short) 0x000F); - sp.setRecordId(EscherSpRecord.RECORD_ID); - sp.setOptions((short) ((EscherAggregate.ST_HOSTCONTROL << 4) | 0x2)); - - sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); - opt.setRecordId(EscherOptRecord.RECORD_ID); - opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 17039620)); - opt.addEscherProperty(new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x00080008)); - opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000)); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00020000)); - - HSSFClientAnchor userAnchor = (HSSFClientAnchor) getAnchor(); - userAnchor.setAnchorType(AnchorType.DONT_MOVE_DO_RESIZE); - EscherRecord anchor = userAnchor.getEscherAnchor(); - clientData.setRecordId(EscherClientDataRecord.RECORD_ID); - clientData.setOptions((short) 0x0000); - - spContainer.addChildRecord(sp); - spContainer.addChildRecord(opt); - spContainer.addChildRecord(anchor); - spContainer.addChildRecord(clientData); - - return spContainer; - } - - @Override - protected ObjRecord createObjRecord() { - ObjRecord obj = new ObjRecord(); - CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); - c.setObjectType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX); - c.setLocked(true); - c.setPrintable(false); - c.setAutofill(true); - c.setAutoline(false); - FtCblsSubRecord f = new FtCblsSubRecord(); - LbsDataSubRecord l = LbsDataSubRecord.newAutoFilterInstance(); - EndSubRecord e = new EndSubRecord(); - obj.addSubRecord(c); - obj.addSubRecord(f); - obj.addSubRecord(l); - obj.addSubRecord(e); - return obj; - } - - @Override - public void setShapeType(int shapeType) { - throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.*; +import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; + +/** + * + */ +public class HSSFCombobox extends HSSFSimpleShape { + + public HSSFCombobox(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); + } + + public HSSFCombobox(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); + super.setShapeType(OBJECT_TYPE_COMBO_BOX); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); + cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX); + } + + @Override + protected TextObjectRecord createTextObjRecord() { + return null; + } + + @Override + protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spContainer = new EscherContainerRecord(); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherClientDataRecord clientData = new EscherClientDataRecord(); + + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) ((EscherAggregate.ST_HOSTCONTROL << 4) | 0x2)); + + sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 17039620)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x00080008)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00020000)); + + HSSFClientAnchor userAnchor = (HSSFClientAnchor) getAnchor(); + userAnchor.setAnchorType(AnchorType.DONT_MOVE_DO_RESIZE); + EscherRecord anchor = userAnchor.getEscherAnchor(); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); + + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); + + return spContainer; + } + + @Override + protected ObjRecord createObjRecord() { + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setObjectType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX); + c.setLocked(true); + c.setPrintable(false); + c.setAutofill(true); + c.setAutoline(false); + FtCblsSubRecord f = new FtCblsSubRecord(); + LbsDataSubRecord l = LbsDataSubRecord.newAutoFilterInstance(); + EndSubRecord e = new EndSubRecord(); + obj.addSubRecord(c); + obj.addSubRecord(f); + obj.addSubRecord(l); + obj.addSubRecord(e); + return obj; + } + + @Override + public void setShapeType(int shapeType) { + throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java index 084a6bfe04..237ac657cc 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java @@ -29,12 +29,12 @@ public class HSSFHyperlink implements Hyperlink { /** * Low-level record object that stores the actual hyperlink data */ - final protected HyperlinkRecord record; - - /** - * If we create a new hyperlink remember its type - */ - final protected HyperlinkType link_type; + final protected HyperlinkRecord record; + + /** + * If we create a new hyperlink remember its type + */ + final protected HyperlinkType link_type; /** * Construct a new hyperlink @@ -50,7 +50,7 @@ public class HSSFHyperlink implements Hyperlink { { this(HyperlinkType.forInt(type)); } - + /** * Construct a new hyperlink * @@ -203,14 +203,14 @@ public class HSSFHyperlink implements Hyperlink { @Override public void setLastColumn(int col){ record.setLastColumn((short)col); - } - - /** - * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file, etc. - * - * @return the address of this hyperlink + } + + /** + * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file, etc. + * + * @return the address of this hyperlink */ - @Override + @Override public String getAddress(){ return record.getAddress(); } @@ -218,32 +218,32 @@ public class HSSFHyperlink implements Hyperlink { return record.getTextMark(); } - /** - * Convenience method equivalent to {@link #setAddress(String)} - * - * @param textMark the place in worksheet this hyperlink refers to, e.g. 'Target Sheet'!A1' - */ - public void setTextMark(String textMark) { - record.setTextMark(textMark); + /** + * Convenience method equivalent to {@link #setAddress(String)} + * + * @param textMark the place in worksheet this hyperlink refers to, e.g. 'Target Sheet'!A1' + */ + public void setTextMark(String textMark) { + record.setTextMark(textMark); } public String getShortFilename(){ return record.getShortFilename(); } - /** - * Convenience method equivalent to {@link #setAddress(String)} - * - * @param shortFilename the path to a file this hyperlink points to, e.g. 'readme.txt' - */ - public void setShortFilename(String shortFilename) { - record.setShortFilename(shortFilename); - } - - /** - * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file, etc. - * - * @param address the address of this hyperlink + /** + * Convenience method equivalent to {@link #setAddress(String)} + * + * @param shortFilename the path to a file this hyperlink points to, e.g. 'readme.txt' + */ + public void setShortFilename(String shortFilename) { + record.setShortFilename(shortFilename); + } + + /** + * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file, etc. + * + * @param address the address of this hyperlink */ - @Override + @Override public void setAddress(String address){ record.setAddress(address); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 5135078c00..5659545745 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -1,142 +1,142 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.poi.hssf.usermodel; - -import java.util.List; -import java.util.Map; - -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherProperty; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherTextboxRecord; -import org.apache.poi.hssf.record.CommonObjectDataSubRecord; -import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.SubRecord; -import org.apache.poi.hssf.record.TextObjectRecord; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.util.RecordFormatException; - -/** - * Factory class for producing Excel Shapes from Escher records - */ -public class HSSFShapeFactory { - /** - * build shape tree from escher container - * @param container root escher container from which escher records must be taken - * @param agg - EscherAggregate - * @param out - shape container to which shapes must be added - * @param root - node to create HSSFObjectData shapes - */ - public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { - if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - ObjRecord obj = null; - EscherClientDataRecord clientData = ((EscherContainerRecord) container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID); - if (null != clientData) { - obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData); - } - HSSFShapeGroup group = new HSSFShapeGroup(container, obj); - List children = container.getChildContainers(); - // skip the first child record, it is group descriptor - for (int i = 0; i < children.size(); i++) { - EscherContainerRecord spContainer = children.get(i); - if (i != 0) { - createShapeTree(spContainer, agg, group, root); - } - } - out.addShape(group); - } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) { - Map shapeToObj = agg.getShapeToObjMapping(); - ObjRecord objRecord = null; - TextObjectRecord txtRecord = null; - - for (EscherRecord record : container) { - switch (record.getRecordId()) { - case EscherClientDataRecord.RECORD_ID: - objRecord = (ObjRecord) shapeToObj.get(record); - break; - case EscherTextboxRecord.RECORD_ID: - txtRecord = (TextObjectRecord) shapeToObj.get(record); - break; - default: - break; - } - } - if (objRecord == null) { - throw new RecordFormatException("EscherClientDataRecord can't be found."); - } - if (isEmbeddedObject(objRecord)) { - HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root); - out.addShape(objectData); - return; - } - CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); - final HSSFShape shape; - switch (cmo.getObjectType()) { - case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE: - shape = new HSSFPicture(container, objRecord); - break; - case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: - shape = new HSSFSimpleShape(container, objRecord, txtRecord); - break; - case CommonObjectDataSubRecord.OBJECT_TYPE_LINE: - shape = new HSSFSimpleShape(container, objRecord); - break; - case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX: - shape = new HSSFCombobox(container, objRecord); - break; - case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: - EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); - if(optRecord == null) { - shape = new HSSFSimpleShape(container, objRecord, txtRecord); - } else { - EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); - if (null != property) { - shape = new HSSFPolygon(container, objRecord, txtRecord); - } else { - shape = new HSSFSimpleShape(container, objRecord, txtRecord); - } - } - break; - case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: - shape = new HSSFTextbox(container, objRecord, txtRecord); - break; - case CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT: - shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord)); - break; - default: - shape = new HSSFSimpleShape(container, objRecord, txtRecord); - } - out.addShape(shape); - } - } - - private static boolean isEmbeddedObject(ObjRecord obj) { - for (SubRecord sub : obj.getSubRecords()) { - if (sub instanceof EmbeddedObjectRefSubRecord) { - return true; - } - } - return false; - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.poi.hssf.usermodel; + +import java.util.List; +import java.util.Map; + +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherProperty; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.SubRecord; +import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.util.RecordFormatException; + +/** + * Factory class for producing Excel Shapes from Escher records + */ +public class HSSFShapeFactory { + /** + * build shape tree from escher container + * @param container root escher container from which escher records must be taken + * @param agg - EscherAggregate + * @param out - shape container to which shapes must be added + * @param root - node to create HSSFObjectData shapes + */ + public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { + if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { + ObjRecord obj = null; + EscherClientDataRecord clientData = ((EscherContainerRecord) container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID); + if (null != clientData) { + obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData); + } + HSSFShapeGroup group = new HSSFShapeGroup(container, obj); + List children = container.getChildContainers(); + // skip the first child record, it is group descriptor + for (int i = 0; i < children.size(); i++) { + EscherContainerRecord spContainer = children.get(i); + if (i != 0) { + createShapeTree(spContainer, agg, group, root); + } + } + out.addShape(group); + } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) { + Map shapeToObj = agg.getShapeToObjMapping(); + ObjRecord objRecord = null; + TextObjectRecord txtRecord = null; + + for (EscherRecord record : container) { + switch (record.getRecordId()) { + case EscherClientDataRecord.RECORD_ID: + objRecord = (ObjRecord) shapeToObj.get(record); + break; + case EscherTextboxRecord.RECORD_ID: + txtRecord = (TextObjectRecord) shapeToObj.get(record); + break; + default: + break; + } + } + if (objRecord == null) { + throw new RecordFormatException("EscherClientDataRecord can't be found."); + } + if (isEmbeddedObject(objRecord)) { + HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root); + out.addShape(objectData); + return; + } + CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); + final HSSFShape shape; + switch (cmo.getObjectType()) { + case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE: + shape = new HSSFPicture(container, objRecord); + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: + shape = new HSSFSimpleShape(container, objRecord, txtRecord); + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_LINE: + shape = new HSSFSimpleShape(container, objRecord); + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX: + shape = new HSSFCombobox(container, objRecord); + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: + EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); + if(optRecord == null) { + shape = new HSSFSimpleShape(container, objRecord, txtRecord); + } else { + EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + if (null != property) { + shape = new HSSFPolygon(container, objRecord, txtRecord); + } else { + shape = new HSSFSimpleShape(container, objRecord, txtRecord); + } + } + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: + shape = new HSSFTextbox(container, objRecord, txtRecord); + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT: + shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord)); + break; + default: + shape = new HSSFSimpleShape(container, objRecord, txtRecord); + } + out.addShape(shape); + } + } + + private static boolean isEmbeddedObject(ObjRecord obj) { + for (SubRecord sub : obj.getSubRecords()) { + if (sub instanceof EmbeddedObjectRefSubRecord) { + return true; + } + } + return false; + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/ChainingMode.java b/src/java/org/apache/poi/poifs/crypt/ChainingMode.java index 7fccccfb25..88c2c8493c 100644 --- a/src/java/org/apache/poi/poifs/crypt/ChainingMode.java +++ b/src/java/org/apache/poi/poifs/crypt/ChainingMode.java @@ -1,33 +1,33 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -public enum ChainingMode { - // ecb - only for standard encryption - ecb("ECB", 1), - cbc("CBC", 2), - /* Cipher feedback chaining (CFB), with an 8-bit window */ - cfb("CFB8", 3); - - public final String jceId; - public final int ecmaId; - ChainingMode(String jceId, int ecmaId) { - this.jceId = jceId; - this.ecmaId = ecmaId; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +public enum ChainingMode { + // ecb - only for standard encryption + ecb("ECB", 1), + cbc("CBC", 2), + /* Cipher feedback chaining (CFB), with an 8-bit window */ + cfb("CFB8", 3); + + public final String jceId; + public final int ecmaId; + ChainingMode(String jceId, int ecmaId) { + this.jceId = jceId; + this.ecmaId = ecmaId; + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java index df27d58484..ffc4e600f9 100644 --- a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java +++ b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java @@ -1,280 +1,280 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.ShortBufferException; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndianInputStream; - -@Internal -public abstract class ChunkedCipherInputStream extends LittleEndianInputStream { - private final int chunkSize; - private final int chunkBits; - - private final long size; - private final byte[] chunk, plain; - private final Cipher cipher; - - private int lastIndex; - private long pos; - private boolean chunkIsValid = false; - - public ChunkedCipherInputStream(InputStream stream, long size, int chunkSize) - throws GeneralSecurityException { - this(stream, size, chunkSize, 0); - } - - public ChunkedCipherInputStream(InputStream stream, long size, int chunkSize, int initialPos) - throws GeneralSecurityException { - super(stream); - this.size = size; - this.pos = initialPos; - this.chunkSize = chunkSize; - int cs = chunkSize == -1 ? 4096 : chunkSize; - this.chunk = new byte[cs]; - this.plain = new byte[cs]; - this.chunkBits = Integer.bitCount(chunk.length-1); - this.lastIndex = (int)(pos >> chunkBits); - this.cipher = initCipherForBlock(null, lastIndex); - } - - public final Cipher initCipherForBlock(int block) throws IOException, GeneralSecurityException { - if (chunkSize != -1) { - throw new GeneralSecurityException("the cipher block can only be set for streaming encryption, e.g. CryptoAPI..."); - } - - chunkIsValid = false; - return initCipherForBlock(cipher, block); - } - - protected abstract Cipher initCipherForBlock(Cipher existing, int block) - throws GeneralSecurityException; - - @Override - public int read() throws IOException { - byte[] b = new byte[1]; - if (read(b) == 1) { - return b[0]; - } - return -1; - } - - // do not implement! -> recursion - // public int read(byte[] b) throws IOException; - - @Override - public int read(byte[] b, int off, int len) throws IOException { - return read(b, off, len, false); - } - - private int read(byte[] b, int off, int len, boolean readPlain) throws IOException { - int total = 0; - - if (available() <= 0) { - return -1; - } - - final int chunkMask = getChunkMask(); - while (len > 0) { - if (!chunkIsValid) { - try { - nextChunk(); - chunkIsValid = true; - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException(e.getMessage(), e); - } - } - int count = (int)(chunk.length - (pos & chunkMask)); - int avail = available(); - if (avail == 0) { - return total; - } - count = Math.min(avail, Math.min(count, len)); - - System.arraycopy(readPlain ? plain : chunk, (int)(pos & chunkMask), b, off, count); - - off += count; - len -= count; - pos += count; - if ((pos & chunkMask) == 0) { - chunkIsValid = false; - } - total += count; - } - - return total; - } - - @Override - public long skip(final long n) throws IOException { - long start = pos; - long skip = Math.min(remainingBytes(), n); - - if ((((pos + skip) ^ start) & ~getChunkMask()) != 0) { - chunkIsValid = false; - } - pos += skip; - return skip; - } - - @Override - public int available() { - return remainingBytes(); - } - - /** - * Helper method for forbidden available call - we know the size beforehand, so it's ok ... - * - * @return the remaining byte until EOF - */ - private int remainingBytes() { - return (int)(size - pos); - } - - @Override - public boolean markSupported() { - return false; - } - - @Override - public synchronized void mark(int readlimit) { - throw new UnsupportedOperationException(); - } - - @Override - public synchronized void reset() throws IOException { - throw new UnsupportedOperationException(); - } - - protected int getChunkMask() { - return chunk.length-1; - } - - private void nextChunk() throws GeneralSecurityException, IOException { - if (chunkSize != -1) { - int index = (int)(pos >> chunkBits); - initCipherForBlock(cipher, index); - - if (lastIndex != index) { - long skipN = (index - lastIndex) << chunkBits; - if (super.skip(skipN) < skipN) { - throw new EOFException("buffer underrun"); - }; - } - - lastIndex = index + 1; - } - - final int todo = (int)Math.min(size, chunk.length); - int readBytes = 0, totalBytes = 0; - do { - readBytes = super.read(plain, totalBytes, todo-totalBytes); - totalBytes += Math.max(0, readBytes); - } while (readBytes != -1 && totalBytes < todo); - - if (readBytes == -1 && pos+totalBytes < size && size < Integer.MAX_VALUE) { - throw new EOFException("buffer underrun"); - } - - System.arraycopy(plain, 0, chunk, 0, totalBytes); - - invokeCipher(totalBytes, totalBytes == chunkSize); - } - - /** - * Helper function for overriding the cipher invocation, i.e. XOR doesn't use a cipher - * and uses it's own implementation - * - * @throws BadPaddingException - * @throws IllegalBlockSizeException - * @throws ShortBufferException - */ - protected int invokeCipher(int totalBytes, boolean doFinal) throws GeneralSecurityException { - if (doFinal) { - return cipher.doFinal(chunk, 0, totalBytes, chunk); - } else { - return cipher.update(chunk, 0, totalBytes, chunk); - } - } - - /** - * Used when BIFF header fields (sid, size) are being read. The internal - * {@link Cipher} instance must step even when unencrypted bytes are read - * - */ - @Override - public void readPlain(byte b[], int off, int len) { - if (len <= 0) { - return; - } - - try { - int readBytes, total = 0; - do { - readBytes = read(b, off, len, true); - total += Math.max(0, readBytes); - } while (readBytes > -1 && total < len); - - if (total < len) { - throw new EOFException("buffer underrun"); - } - } catch (IOException e) { - // need to wrap checked exception, because of LittleEndianInput interface :( - throw new RuntimeException(e); - } - } - - /** - * Some ciphers (actually just XOR) are based on the record size, - * which needs to be set before decryption - * - * @param recordSize the size of the next record - */ - public void setNextRecordSize(int recordSize) { - } - - /** - * @return the chunk bytes - */ - protected byte[] getChunk() { - return chunk; - } - - /** - * @return the plain bytes - */ - protected byte[] getPlain() { - return plain; - } - - /** - * @return the absolute position in the stream - */ - public long getPos() { - return pos; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndianInputStream; + +@Internal +public abstract class ChunkedCipherInputStream extends LittleEndianInputStream { + private final int chunkSize; + private final int chunkBits; + + private final long size; + private final byte[] chunk, plain; + private final Cipher cipher; + + private int lastIndex; + private long pos; + private boolean chunkIsValid = false; + + public ChunkedCipherInputStream(InputStream stream, long size, int chunkSize) + throws GeneralSecurityException { + this(stream, size, chunkSize, 0); + } + + public ChunkedCipherInputStream(InputStream stream, long size, int chunkSize, int initialPos) + throws GeneralSecurityException { + super(stream); + this.size = size; + this.pos = initialPos; + this.chunkSize = chunkSize; + int cs = chunkSize == -1 ? 4096 : chunkSize; + this.chunk = new byte[cs]; + this.plain = new byte[cs]; + this.chunkBits = Integer.bitCount(chunk.length-1); + this.lastIndex = (int)(pos >> chunkBits); + this.cipher = initCipherForBlock(null, lastIndex); + } + + public final Cipher initCipherForBlock(int block) throws IOException, GeneralSecurityException { + if (chunkSize != -1) { + throw new GeneralSecurityException("the cipher block can only be set for streaming encryption, e.g. CryptoAPI..."); + } + + chunkIsValid = false; + return initCipherForBlock(cipher, block); + } + + protected abstract Cipher initCipherForBlock(Cipher existing, int block) + throws GeneralSecurityException; + + @Override + public int read() throws IOException { + byte[] b = new byte[1]; + if (read(b) == 1) { + return b[0]; + } + return -1; + } + + // do not implement! -> recursion + // public int read(byte[] b) throws IOException; + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return read(b, off, len, false); + } + + private int read(byte[] b, int off, int len, boolean readPlain) throws IOException { + int total = 0; + + if (available() <= 0) { + return -1; + } + + final int chunkMask = getChunkMask(); + while (len > 0) { + if (!chunkIsValid) { + try { + nextChunk(); + chunkIsValid = true; + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException(e.getMessage(), e); + } + } + int count = (int)(chunk.length - (pos & chunkMask)); + int avail = available(); + if (avail == 0) { + return total; + } + count = Math.min(avail, Math.min(count, len)); + + System.arraycopy(readPlain ? plain : chunk, (int)(pos & chunkMask), b, off, count); + + off += count; + len -= count; + pos += count; + if ((pos & chunkMask) == 0) { + chunkIsValid = false; + } + total += count; + } + + return total; + } + + @Override + public long skip(final long n) throws IOException { + long start = pos; + long skip = Math.min(remainingBytes(), n); + + if ((((pos + skip) ^ start) & ~getChunkMask()) != 0) { + chunkIsValid = false; + } + pos += skip; + return skip; + } + + @Override + public int available() { + return remainingBytes(); + } + + /** + * Helper method for forbidden available call - we know the size beforehand, so it's ok ... + * + * @return the remaining byte until EOF + */ + private int remainingBytes() { + return (int)(size - pos); + } + + @Override + public boolean markSupported() { + return false; + } + + @Override + public synchronized void mark(int readlimit) { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void reset() throws IOException { + throw new UnsupportedOperationException(); + } + + protected int getChunkMask() { + return chunk.length-1; + } + + private void nextChunk() throws GeneralSecurityException, IOException { + if (chunkSize != -1) { + int index = (int)(pos >> chunkBits); + initCipherForBlock(cipher, index); + + if (lastIndex != index) { + long skipN = (index - lastIndex) << chunkBits; + if (super.skip(skipN) < skipN) { + throw new EOFException("buffer underrun"); + }; + } + + lastIndex = index + 1; + } + + final int todo = (int)Math.min(size, chunk.length); + int readBytes = 0, totalBytes = 0; + do { + readBytes = super.read(plain, totalBytes, todo-totalBytes); + totalBytes += Math.max(0, readBytes); + } while (readBytes != -1 && totalBytes < todo); + + if (readBytes == -1 && pos+totalBytes < size && size < Integer.MAX_VALUE) { + throw new EOFException("buffer underrun"); + } + + System.arraycopy(plain, 0, chunk, 0, totalBytes); + + invokeCipher(totalBytes, totalBytes == chunkSize); + } + + /** + * Helper function for overriding the cipher invocation, i.e. XOR doesn't use a cipher + * and uses it's own implementation + * + * @throws BadPaddingException + * @throws IllegalBlockSizeException + * @throws ShortBufferException + */ + protected int invokeCipher(int totalBytes, boolean doFinal) throws GeneralSecurityException { + if (doFinal) { + return cipher.doFinal(chunk, 0, totalBytes, chunk); + } else { + return cipher.update(chunk, 0, totalBytes, chunk); + } + } + + /** + * Used when BIFF header fields (sid, size) are being read. The internal + * {@link Cipher} instance must step even when unencrypted bytes are read + * + */ + @Override + public void readPlain(byte b[], int off, int len) { + if (len <= 0) { + return; + } + + try { + int readBytes, total = 0; + do { + readBytes = read(b, off, len, true); + total += Math.max(0, readBytes); + } while (readBytes > -1 && total < len); + + if (total < len) { + throw new EOFException("buffer underrun"); + } + } catch (IOException e) { + // need to wrap checked exception, because of LittleEndianInput interface :( + throw new RuntimeException(e); + } + } + + /** + * Some ciphers (actually just XOR) are based on the record size, + * which needs to be set before decryption + * + * @param recordSize the size of the next record + */ + public void setNextRecordSize(int recordSize) { + } + + /** + * @return the chunk bytes + */ + protected byte[] getChunk() { + return chunk; + } + + /** + * @return the plain bytes + */ + protected byte[] getPlain() { + return plain; + } + + /** + * @return the absolute position in the stream + */ + public long getPos() { + return pos; + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java index 6b18f0d9f2..dbbc8a5d53 100644 --- a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java +++ b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java @@ -1,300 +1,300 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import static org.apache.poi.poifs.crypt.Decryptor.DEFAULT_POIFS_ENTRY; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.util.BitSet; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.ShortBufferException; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.POIFSWriterEvent; -import org.apache.poi.poifs.filesystem.POIFSWriterListener; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.TempFile; - -@Internal -public abstract class ChunkedCipherOutputStream extends FilterOutputStream { - private static final POILogger LOG = POILogFactory.getLogger(ChunkedCipherOutputStream.class); - private static final int STREAMING = -1; - - private final int chunkSize; - private final int chunkBits; - - private final byte[] chunk; - private final BitSet plainByteFlags; - private final File fileOut; - private final DirectoryNode dir; - - private long pos; - private long totalPos; - private long written; - - // the cipher can't be final, because for the last chunk we change the padding - // and therefore need to change the cipher too - private Cipher cipher; - - public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException { - super(null); - this.chunkSize = chunkSize; - int cs = chunkSize == STREAMING ? 4096 : chunkSize; - this.chunk = new byte[cs]; - this.plainByteFlags = new BitSet(cs); - this.chunkBits = Integer.bitCount(cs-1); - this.fileOut = TempFile.createTempFile("encrypted_package", "crypt"); - this.fileOut.deleteOnExit(); - this.out = new FileOutputStream(fileOut); - this.dir = dir; - this.cipher = initCipherForBlock(null, 0, false); - } - - public ChunkedCipherOutputStream(OutputStream stream, int chunkSize) throws IOException, GeneralSecurityException { - super(stream); - this.chunkSize = chunkSize; - int cs = chunkSize == STREAMING ? 4096 : chunkSize; - this.chunk = new byte[cs]; - this.plainByteFlags = new BitSet(cs); - this.chunkBits = Integer.bitCount(cs-1); - this.fileOut = null; - this.dir = null; - this.cipher = initCipherForBlock(null, 0, false); - } - - public final Cipher initCipherForBlock(int block, boolean lastChunk) throws IOException, GeneralSecurityException { - return initCipherForBlock(cipher, block, lastChunk); - } - - protected abstract Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk) - throws IOException, GeneralSecurityException; - - protected abstract void calculateChecksum(File fileOut, int oleStreamSize) - throws GeneralSecurityException, IOException; - - protected abstract void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) - throws IOException, GeneralSecurityException; - - @Override - public void write(int b) throws IOException { - write(new byte[]{(byte)b}); - } - - @Override - public void write(byte[] b) throws IOException { - write(b, 0, b.length); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - write(b, off, len, false); - } - - public void writePlain(byte[] b, int off, int len) throws IOException { - write(b, off, len, true); - } - - protected void write(byte[] b, int off, int len, boolean writePlain) throws IOException { - if (len == 0) { - return; - } - - if (len < 0 || b.length < off+len) { - throw new IOException("not enough bytes in your input buffer"); - } - - final int chunkMask = getChunkMask(); - while (len > 0) { - int posInChunk = (int)(pos & chunkMask); - int nextLen = Math.min(chunk.length-posInChunk, len); - System.arraycopy(b, off, chunk, posInChunk, nextLen); - if (writePlain) { - plainByteFlags.set(posInChunk, posInChunk+nextLen); - } - pos += nextLen; - totalPos += nextLen; - off += nextLen; - len -= nextLen; - if ((pos & chunkMask) == 0) { - writeChunk(len > 0); - } - } - } - - protected int getChunkMask() { - return chunk.length-1; - } - - protected void writeChunk(boolean continued) throws IOException { - if (pos == 0 || totalPos == written) { - return; - } - - int posInChunk = (int)(pos & getChunkMask()); - - // normally posInChunk is 0, i.e. on the next chunk (-> index-1) - // but if called on close(), posInChunk is somewhere within the chunk data - int index = (int)(pos >> chunkBits); - boolean lastChunk; - if (posInChunk==0) { - index--; - posInChunk = chunk.length; - lastChunk = false; - } else { - // pad the last chunk - lastChunk = true; - } - - int ciLen; - try { - boolean doFinal = true; - long oldPos = pos; - // reset stream (not only) in case we were interrupted by plain stream parts - // this also needs to be set to prevent an endless loop - pos = 0; - if (chunkSize == STREAMING) { - if (continued) { - doFinal = false; - } - } else { - cipher = initCipherForBlock(cipher, index, lastChunk); - // restore pos - only streaming chunks will be reset - pos = oldPos; - } - ciLen = invokeCipher(posInChunk, doFinal); - } catch (GeneralSecurityException e) { - throw new IOException("can't re-/initialize cipher", e); - } - - out.write(chunk, 0, ciLen); - plainByteFlags.clear(); - written += ciLen; - } - - /** - * Helper function for overriding the cipher invocation, i.e. XOR doesn't use a cipher - * and uses it's own implementation - * - * @throws BadPaddingException - * @throws IllegalBlockSizeException - * @throws ShortBufferException - */ - protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException { - byte plain[] = (plainByteFlags.isEmpty()) ? null : chunk.clone(); - - int ciLen = (doFinal) - ? cipher.doFinal(chunk, 0, posInChunk, chunk) - : cipher.update(chunk, 0, posInChunk, chunk); - - for (int i = plainByteFlags.nextSetBit(0); i >= 0 && i < posInChunk; i = plainByteFlags.nextSetBit(i+1)) { - chunk[i] = plain[i]; - } - - return ciLen; - } - - @Override - public void close() throws IOException { - try { - writeChunk(false); - - super.close(); - - if (fileOut != null) { - int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE); - calculateChecksum(fileOut, (int)pos); - dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter()); - createEncryptionInfoEntry(dir, fileOut); - } - } catch (GeneralSecurityException e) { - throw new IOException(e); - } - } - - protected byte[] getChunk() { - return chunk; - } - - protected BitSet getPlainByteFlags() { - return plainByteFlags; - } - - protected long getPos() { - return pos; - } - - protected long getTotalPos() { - return totalPos; - } - - /** - * Some ciphers (actually just XOR) are based on the record size, - * which needs to be set before encryption - * - * @param recordSize the size of the next record - * @param isPlain {@code true} if the record is unencrypted - */ - public void setNextRecordSize(int recordSize, boolean isPlain) { - } - - private class EncryptedPackageWriter implements POIFSWriterListener { - @Override - public void processPOIFSWriterEvent(POIFSWriterEvent event) { - try { - OutputStream os = event.getStream(); - - // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data - // encrypted within the EncryptedData field, not including the size of the StreamSize field. - // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this - // value, depending on the block size of the chosen encryption algorithm - byte buf[] = new byte[LittleEndianConsts.LONG_SIZE]; - LittleEndian.putLong(buf, 0, pos); - os.write(buf); - - FileInputStream fis = new FileInputStream(fileOut); - try { - IOUtils.copy(fis, os); - } finally { - fis.close(); - } - - os.close(); - - if (!fileOut.delete()) { - LOG.log(POILogger.ERROR, "Can't delete temporary encryption file: "+fileOut); - } - } catch (IOException e) { - throw new EncryptedDocumentException(e); - } - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import static org.apache.poi.poifs.crypt.Decryptor.DEFAULT_POIFS_ENTRY; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.util.BitSet; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.POIFSWriterEvent; +import org.apache.poi.poifs.filesystem.POIFSWriterListener; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.TempFile; + +@Internal +public abstract class ChunkedCipherOutputStream extends FilterOutputStream { + private static final POILogger LOG = POILogFactory.getLogger(ChunkedCipherOutputStream.class); + private static final int STREAMING = -1; + + private final int chunkSize; + private final int chunkBits; + + private final byte[] chunk; + private final BitSet plainByteFlags; + private final File fileOut; + private final DirectoryNode dir; + + private long pos; + private long totalPos; + private long written; + + // the cipher can't be final, because for the last chunk we change the padding + // and therefore need to change the cipher too + private Cipher cipher; + + public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException { + super(null); + this.chunkSize = chunkSize; + int cs = chunkSize == STREAMING ? 4096 : chunkSize; + this.chunk = new byte[cs]; + this.plainByteFlags = new BitSet(cs); + this.chunkBits = Integer.bitCount(cs-1); + this.fileOut = TempFile.createTempFile("encrypted_package", "crypt"); + this.fileOut.deleteOnExit(); + this.out = new FileOutputStream(fileOut); + this.dir = dir; + this.cipher = initCipherForBlock(null, 0, false); + } + + public ChunkedCipherOutputStream(OutputStream stream, int chunkSize) throws IOException, GeneralSecurityException { + super(stream); + this.chunkSize = chunkSize; + int cs = chunkSize == STREAMING ? 4096 : chunkSize; + this.chunk = new byte[cs]; + this.plainByteFlags = new BitSet(cs); + this.chunkBits = Integer.bitCount(cs-1); + this.fileOut = null; + this.dir = null; + this.cipher = initCipherForBlock(null, 0, false); + } + + public final Cipher initCipherForBlock(int block, boolean lastChunk) throws IOException, GeneralSecurityException { + return initCipherForBlock(cipher, block, lastChunk); + } + + protected abstract Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk) + throws IOException, GeneralSecurityException; + + protected abstract void calculateChecksum(File fileOut, int oleStreamSize) + throws GeneralSecurityException, IOException; + + protected abstract void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) + throws IOException, GeneralSecurityException; + + @Override + public void write(int b) throws IOException { + write(new byte[]{(byte)b}); + } + + @Override + public void write(byte[] b) throws IOException { + write(b, 0, b.length); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + write(b, off, len, false); + } + + public void writePlain(byte[] b, int off, int len) throws IOException { + write(b, off, len, true); + } + + protected void write(byte[] b, int off, int len, boolean writePlain) throws IOException { + if (len == 0) { + return; + } + + if (len < 0 || b.length < off+len) { + throw new IOException("not enough bytes in your input buffer"); + } + + final int chunkMask = getChunkMask(); + while (len > 0) { + int posInChunk = (int)(pos & chunkMask); + int nextLen = Math.min(chunk.length-posInChunk, len); + System.arraycopy(b, off, chunk, posInChunk, nextLen); + if (writePlain) { + plainByteFlags.set(posInChunk, posInChunk+nextLen); + } + pos += nextLen; + totalPos += nextLen; + off += nextLen; + len -= nextLen; + if ((pos & chunkMask) == 0) { + writeChunk(len > 0); + } + } + } + + protected int getChunkMask() { + return chunk.length-1; + } + + protected void writeChunk(boolean continued) throws IOException { + if (pos == 0 || totalPos == written) { + return; + } + + int posInChunk = (int)(pos & getChunkMask()); + + // normally posInChunk is 0, i.e. on the next chunk (-> index-1) + // but if called on close(), posInChunk is somewhere within the chunk data + int index = (int)(pos >> chunkBits); + boolean lastChunk; + if (posInChunk==0) { + index--; + posInChunk = chunk.length; + lastChunk = false; + } else { + // pad the last chunk + lastChunk = true; + } + + int ciLen; + try { + boolean doFinal = true; + long oldPos = pos; + // reset stream (not only) in case we were interrupted by plain stream parts + // this also needs to be set to prevent an endless loop + pos = 0; + if (chunkSize == STREAMING) { + if (continued) { + doFinal = false; + } + } else { + cipher = initCipherForBlock(cipher, index, lastChunk); + // restore pos - only streaming chunks will be reset + pos = oldPos; + } + ciLen = invokeCipher(posInChunk, doFinal); + } catch (GeneralSecurityException e) { + throw new IOException("can't re-/initialize cipher", e); + } + + out.write(chunk, 0, ciLen); + plainByteFlags.clear(); + written += ciLen; + } + + /** + * Helper function for overriding the cipher invocation, i.e. XOR doesn't use a cipher + * and uses it's own implementation + * + * @throws BadPaddingException + * @throws IllegalBlockSizeException + * @throws ShortBufferException + */ + protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException { + byte plain[] = (plainByteFlags.isEmpty()) ? null : chunk.clone(); + + int ciLen = (doFinal) + ? cipher.doFinal(chunk, 0, posInChunk, chunk) + : cipher.update(chunk, 0, posInChunk, chunk); + + for (int i = plainByteFlags.nextSetBit(0); i >= 0 && i < posInChunk; i = plainByteFlags.nextSetBit(i+1)) { + chunk[i] = plain[i]; + } + + return ciLen; + } + + @Override + public void close() throws IOException { + try { + writeChunk(false); + + super.close(); + + if (fileOut != null) { + int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE); + calculateChecksum(fileOut, (int)pos); + dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter()); + createEncryptionInfoEntry(dir, fileOut); + } + } catch (GeneralSecurityException e) { + throw new IOException(e); + } + } + + protected byte[] getChunk() { + return chunk; + } + + protected BitSet getPlainByteFlags() { + return plainByteFlags; + } + + protected long getPos() { + return pos; + } + + protected long getTotalPos() { + return totalPos; + } + + /** + * Some ciphers (actually just XOR) are based on the record size, + * which needs to be set before encryption + * + * @param recordSize the size of the next record + * @param isPlain {@code true} if the record is unencrypted + */ + public void setNextRecordSize(int recordSize, boolean isPlain) { + } + + private class EncryptedPackageWriter implements POIFSWriterListener { + @Override + public void processPOIFSWriterEvent(POIFSWriterEvent event) { + try { + OutputStream os = event.getStream(); + + // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data + // encrypted within the EncryptedData field, not including the size of the StreamSize field. + // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this + // value, depending on the block size of the chosen encryption algorithm + byte buf[] = new byte[LittleEndianConsts.LONG_SIZE]; + LittleEndian.putLong(buf, 0, pos); + os.write(buf); + + FileInputStream fis = new FileInputStream(fileOut); + try { + IOUtils.copy(fis, os); + } finally { + fis.close(); + } + + os.close(); + + if (!fileOut.delete()) { + LOG.log(POILogger.ERROR, "Can't delete temporary encryption file: "+fileOut); + } + } catch (IOException e) { + throw new EncryptedDocumentException(e); + } + } + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/CipherAlgorithm.java b/src/java/org/apache/poi/poifs/crypt/CipherAlgorithm.java index c5887354db..6da96d8524 100644 --- a/src/java/org/apache/poi/poifs/crypt/CipherAlgorithm.java +++ b/src/java/org/apache/poi/poifs/crypt/CipherAlgorithm.java @@ -1,78 +1,78 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -import org.apache.poi.EncryptedDocumentException; - -public enum CipherAlgorithm { - // key size for rc4: 0x00000028 - 0x00000080 (inclusive) with 8-bit increments - // no block size, because its a streaming cipher - rc4(CipherProvider.rc4, "RC4", 0x6801, 0x40, new int[]{0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80}, -1, 20, "RC4", false), - // aes has always a block size of 128 - only its keysize may vary - aes128(CipherProvider.aes, "AES", 0x660E, 128, new int[]{128}, 16, 32, "AES", false), - aes192(CipherProvider.aes, "AES", 0x660F, 192, new int[]{192}, 16, 32, "AES", false), - aes256(CipherProvider.aes, "AES", 0x6610, 256, new int[]{256}, 16, 32, "AES", false), - rc2(null, "RC2", -1, 0x80, new int[]{0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80}, 8, 20, "RC2", false), - des(null, "DES", -1, 64, new int[]{64}, 8/*for 56-bit*/, 32, "DES", false), - // desx is not supported. Not sure, if it can be simulated by des3 somehow - des3(null, "DESede", -1, 192, new int[]{192}, 8, 32, "3DES", false), - // need bouncycastle provider for this one ... - // see http://stackoverflow.com/questions/4436397/3des-des-encryption-using-the-jce-generating-an-acceptable-key - des3_112(null, "DESede", -1, 128, new int[]{128}, 8, 32, "3DES_112", true), - // only for digital signatures - rsa(null, "RSA", -1, 1024, new int[]{1024, 2048, 3072, 4096}, -1, -1, "", false); - - public final CipherProvider provider; - public final String jceId; - public final int ecmaId; - public final int defaultKeySize; - public final int allowedKeySize[]; - public final int blockSize; - public final int encryptedVerifierHashLength; - public final String xmlId; - public final boolean needsBouncyCastle; - - CipherAlgorithm(CipherProvider provider, String jceId, int ecmaId, int defaultKeySize, int allowedKeySize[], int blockSize, int encryptedVerifierHashLength, String xmlId, boolean needsBouncyCastle) { - this.provider = provider; - this.jceId = jceId; - this.ecmaId = ecmaId; - this.defaultKeySize = defaultKeySize; - this.allowedKeySize = allowedKeySize.clone(); - this.blockSize = blockSize; - this.encryptedVerifierHashLength = encryptedVerifierHashLength; - this.xmlId = xmlId; - this.needsBouncyCastle = needsBouncyCastle; - } - - public static CipherAlgorithm fromEcmaId(int ecmaId) { - for (CipherAlgorithm ca : CipherAlgorithm.values()) { - if (ca.ecmaId == ecmaId) return ca; - } - throw new EncryptedDocumentException("cipher algorithm " + ecmaId + " not found"); - } - - public static CipherAlgorithm fromXmlId(String xmlId, int keySize) { - for (CipherAlgorithm ca : CipherAlgorithm.values()) { - if (!ca.xmlId.equals(xmlId)) continue; - for (int ks : ca.allowedKeySize) { - if (ks == keySize) return ca; - } - } - throw new EncryptedDocumentException("cipher algorithm " + xmlId + "/" + keySize + " not found"); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +import org.apache.poi.EncryptedDocumentException; + +public enum CipherAlgorithm { + // key size for rc4: 0x00000028 - 0x00000080 (inclusive) with 8-bit increments + // no block size, because its a streaming cipher + rc4(CipherProvider.rc4, "RC4", 0x6801, 0x40, new int[]{0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80}, -1, 20, "RC4", false), + // aes has always a block size of 128 - only its keysize may vary + aes128(CipherProvider.aes, "AES", 0x660E, 128, new int[]{128}, 16, 32, "AES", false), + aes192(CipherProvider.aes, "AES", 0x660F, 192, new int[]{192}, 16, 32, "AES", false), + aes256(CipherProvider.aes, "AES", 0x6610, 256, new int[]{256}, 16, 32, "AES", false), + rc2(null, "RC2", -1, 0x80, new int[]{0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80}, 8, 20, "RC2", false), + des(null, "DES", -1, 64, new int[]{64}, 8/*for 56-bit*/, 32, "DES", false), + // desx is not supported. Not sure, if it can be simulated by des3 somehow + des3(null, "DESede", -1, 192, new int[]{192}, 8, 32, "3DES", false), + // need bouncycastle provider for this one ... + // see http://stackoverflow.com/questions/4436397/3des-des-encryption-using-the-jce-generating-an-acceptable-key + des3_112(null, "DESede", -1, 128, new int[]{128}, 8, 32, "3DES_112", true), + // only for digital signatures + rsa(null, "RSA", -1, 1024, new int[]{1024, 2048, 3072, 4096}, -1, -1, "", false); + + public final CipherProvider provider; + public final String jceId; + public final int ecmaId; + public final int defaultKeySize; + public final int allowedKeySize[]; + public final int blockSize; + public final int encryptedVerifierHashLength; + public final String xmlId; + public final boolean needsBouncyCastle; + + CipherAlgorithm(CipherProvider provider, String jceId, int ecmaId, int defaultKeySize, int allowedKeySize[], int blockSize, int encryptedVerifierHashLength, String xmlId, boolean needsBouncyCastle) { + this.provider = provider; + this.jceId = jceId; + this.ecmaId = ecmaId; + this.defaultKeySize = defaultKeySize; + this.allowedKeySize = allowedKeySize.clone(); + this.blockSize = blockSize; + this.encryptedVerifierHashLength = encryptedVerifierHashLength; + this.xmlId = xmlId; + this.needsBouncyCastle = needsBouncyCastle; + } + + public static CipherAlgorithm fromEcmaId(int ecmaId) { + for (CipherAlgorithm ca : CipherAlgorithm.values()) { + if (ca.ecmaId == ecmaId) return ca; + } + throw new EncryptedDocumentException("cipher algorithm " + ecmaId + " not found"); + } + + public static CipherAlgorithm fromXmlId(String xmlId, int keySize) { + for (CipherAlgorithm ca : CipherAlgorithm.values()) { + if (!ca.xmlId.equals(xmlId)) continue; + for (int ks : ca.allowedKeySize) { + if (ks == keySize) return ca; + } + } + throw new EncryptedDocumentException("cipher algorithm " + xmlId + "/" + keySize + " not found"); + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/poifs/crypt/CipherProvider.java b/src/java/org/apache/poi/poifs/crypt/CipherProvider.java index 5ffe1d33ae..ac2dbafd0a 100644 --- a/src/java/org/apache/poi/poifs/crypt/CipherProvider.java +++ b/src/java/org/apache/poi/poifs/crypt/CipherProvider.java @@ -1,41 +1,41 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -import org.apache.poi.EncryptedDocumentException; - -public enum CipherProvider { - rc4("RC4", 1, "Microsoft Base Cryptographic Provider v1.0"), - aes("AES", 0x18, "Microsoft Enhanced RSA and AES Cryptographic Provider"); - - public static CipherProvider fromEcmaId(int ecmaId) { - for (CipherProvider cp : CipherProvider.values()) { - if (cp.ecmaId == ecmaId) return cp; - } - throw new EncryptedDocumentException("cipher provider not found"); - } - - public final String jceId; - public final int ecmaId; - public final String cipherProviderName; - CipherProvider(String jceId, int ecmaId, String cipherProviderName) { - this.jceId = jceId; - this.ecmaId = ecmaId; - this.cipherProviderName = cipherProviderName; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +import org.apache.poi.EncryptedDocumentException; + +public enum CipherProvider { + rc4("RC4", 1, "Microsoft Base Cryptographic Provider v1.0"), + aes("AES", 0x18, "Microsoft Enhanced RSA and AES Cryptographic Provider"); + + public static CipherProvider fromEcmaId(int ecmaId) { + for (CipherProvider cp : CipherProvider.values()) { + if (cp.ecmaId == ecmaId) return cp; + } + throw new EncryptedDocumentException("cipher provider not found"); + } + + public final String jceId; + public final int ecmaId; + public final String cipherProviderName; + CipherProvider(String jceId, int ecmaId, String cipherProviderName) { + this.jceId = jceId; + this.ecmaId = ecmaId; + this.cipherProviderName = cipherProviderName; + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java b/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java index b35d2c59cd..f7265d1ed3 100644 --- a/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java +++ b/src/java/org/apache/poi/poifs/crypt/CryptoFunctions.java @@ -1,576 +1,576 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import java.nio.charset.Charset; -import java.security.DigestException; -import java.security.GeneralSecurityException; -import java.security.Key; -import java.security.MessageDigest; -import java.security.Provider; -import java.security.Security; -import java.security.spec.AlgorithmParameterSpec; -import java.util.Arrays; -import java.util.Locale; - -import javax.crypto.Cipher; -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.RC2ParameterSpec; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.StringUtil; - -/** - * Helper functions used for standard and agile encryption - */ -@Internal -public class CryptoFunctions { - /** - *

2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)
- * 2.3.4.11 Encryption Key Generation (Agile Encryption)

- * - *

The encryption key for ECMA-376 document encryption [ECMA-376] using agile - * encryption MUST be generated by using the following method, which is derived from PKCS #5: - * Password-Based Cryptography Version 2.0 [RFC2898].

- * - *

Let H() be a hashing algorithm as determined by the PasswordKeyEncryptor.hashAlgorithm - * element, H_n be the hash data of the n-th iteration, and a plus sign (+) represent concatenation. - * The password MUST be provided as an array of Unicode characters. Limitations on the length of the - * password and the characters used by the password are implementation-dependent. - * The initial password hash is generated as follows:

- * - * - *
H_0 = H(salt + password)
- * - *

The salt used MUST be generated randomly. The salt MUST be stored in the - * PasswordKeyEncryptor.saltValue element contained within the \EncryptionInfo stream as - * specified in section 2.3.4.10. The hash is then iterated by using the following approach:

- * - *
H_n = H(iterator + H_n-1)
- * - *

where iterator is an unsigned 32-bit value that is initially set to 0x00000000 and then incremented - * monotonically on each iteration until PasswordKey.spinCount iterations have been performed. - * The value of iterator on the last iteration MUST be one less than PasswordKey.spinCount.

- * - *

For POI, H_final will be calculated by {@link #generateKey(byte[],HashAlgorithm,byte[],int)}

- * - * @param password - * @param hashAlgorithm - * @param salt - * @param spinCount - * @return the hashed password - */ - public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte salt[], int spinCount) { - return hashPassword(password, hashAlgorithm, salt, spinCount, true); - } - - /** - * Generalized method for read and write protection hash generation. - * The difference is, read protection uses the order iterator then hash in the hash loop, whereas write protection - * uses first the last hash value and then the current iterator value - * - * @param password - * @param hashAlgorithm - * @param salt - * @param spinCount - * @param iteratorFirst if true, the iterator is hashed before the n-1 hash value, - * if false the n-1 hash value is applied first - * @return the hashed password - */ - public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte salt[], int spinCount, boolean iteratorFirst) { - // If no password was given, use the default - if (password == null) { - password = Decryptor.DEFAULT_PASSWORD; - } - - MessageDigest hashAlg = getMessageDigest(hashAlgorithm); - - hashAlg.update(salt); - byte[] hash = hashAlg.digest(StringUtil.getToUnicodeLE(password)); - byte[] iterator = new byte[LittleEndianConsts.INT_SIZE]; - - byte[] first = (iteratorFirst ? iterator : hash); - byte[] second = (iteratorFirst ? hash : iterator); - - try { - for (int i = 0; i < spinCount; i++) { - LittleEndian.putInt(iterator, 0, i); - hashAlg.reset(); - hashAlg.update(first); - hashAlg.update(second); - hashAlg.digest(hash, 0, hash.length); // don't create hash buffer everytime new - } - } catch (DigestException e) { - throw new EncryptedDocumentException("error in password hashing"); - } - - return hash; - } - - /** - *

2.3.4.12 Initialization Vector Generation (Agile Encryption)

- * - *

Initialization vectors are used in all cases for agile encryption. An initialization vector MUST be - * generated by using the following method, where H() is a hash function that MUST be the same as - * specified in section 2.3.4.11 and a plus sign (+) represents concatenation:

- *
    - *
  • If a blockKey is provided, let IV be a hash of the KeySalt and the following value:
    - * {@code blockKey: IV = H(KeySalt + blockKey)}
  • - *
  • If a blockKey is not provided, let IV be equal to the following value:
    - * {@code KeySalt:IV = KeySalt}
  • - *
  • If the number of bytes in the value of IV is less than the the value of the blockSize attribute - * corresponding to the cipherAlgorithm attribute, pad the array of bytes by appending 0x36 until - * the array is blockSize bytes. If the array of bytes is larger than blockSize bytes, truncate the - * array to blockSize bytes.
  • - *
- **/ - public static byte[] generateIv(HashAlgorithm hashAlgorithm, byte[] salt, byte[] blockKey, int blockSize) { - byte iv[] = salt; - if (blockKey != null) { - MessageDigest hashAlgo = getMessageDigest(hashAlgorithm); - hashAlgo.update(salt); - iv = hashAlgo.digest(blockKey); - } - return getBlock36(iv, blockSize); - } - - /** - *

2.3.4.11 Encryption Key Generation (Agile Encryption)

- * - *

The final hash data that is used for an encryption key is then generated by using the following - * method:

- * - *
H_final = H(H_n + blockKey)
- * - *

where blockKey represents an array of bytes used to prevent two different blocks from encrypting - * to the same cipher text.

- * - *

If the size of the resulting H_final is smaller than that of PasswordKeyEncryptor.keyBits, the key - * MUST be padded by appending bytes with a value of 0x36. If the hash value is larger in size than - * PasswordKeyEncryptor.keyBits, the key is obtained by truncating the hash value.

- * - * @param passwordHash - * @param hashAlgorithm - * @param blockKey - * @param keySize - * @return intermediate key - */ - public static byte[] generateKey(byte[] passwordHash, HashAlgorithm hashAlgorithm, byte[] blockKey, int keySize) { - MessageDigest hashAlgo = getMessageDigest(hashAlgorithm); - hashAlgo.update(passwordHash); - byte[] key = hashAlgo.digest(blockKey); - return getBlock36(key, keySize); - } - - /** - * Initialize a new cipher object with the given cipher properties and no padding - * If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle - * provider. - * - * @param key the secrect key - * @param cipherAlgorithm the cipher algorithm - * @param chain the chaining mode - * @param vec the initialization vector (IV), can be null - * @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE - * @return the requested cipher - * @throws GeneralSecurityException - * @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified, - * which depends on a missing bouncy castle provider - */ - public static Cipher getCipher(SecretKey key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode) { - return getCipher(key, cipherAlgorithm, chain, vec, cipherMode, null); - } - - /** - * Initialize a new cipher object with the given cipher properties - * If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle - * provider. - * - * @param key the secrect key - * @param cipherAlgorithm the cipher algorithm - * @param chain the chaining mode - * @param vec the initialization vector (IV), can be null - * @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE - * @param padding the padding (null = NOPADDING, ANSIX923Padding, PKCS5Padding, PKCS7Padding, ISO10126Padding, ...) - * @return the requested cipher - * @throws GeneralSecurityException - * @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified, - * which depends on a missing bouncy castle provider - */ - public static Cipher getCipher(Key key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode, String padding) { - int keySizeInBytes = key.getEncoded().length; - if (padding == null) padding = "NoPadding"; - - try { - // Ensure the JCE policies files allow for this sized key - if (Cipher.getMaxAllowedKeyLength(cipherAlgorithm.jceId) < keySizeInBytes*8) { - throw new EncryptedDocumentException("Export Restrictions in place - please install JCE Unlimited Strength Jurisdiction Policy files"); - } - - Cipher cipher; - if (cipherAlgorithm == CipherAlgorithm.rc4) { - cipher = Cipher.getInstance(cipherAlgorithm.jceId); - } else if (cipherAlgorithm.needsBouncyCastle) { - registerBouncyCastle(); - cipher = Cipher.getInstance(cipherAlgorithm.jceId + "/" + chain.jceId + "/" + padding, "BC"); - } else { - cipher = Cipher.getInstance(cipherAlgorithm.jceId + "/" + chain.jceId + "/" + padding); - } - - if (vec == null) { - cipher.init(cipherMode, key); - } else { - AlgorithmParameterSpec aps; - if (cipherAlgorithm == CipherAlgorithm.rc2) { - aps = new RC2ParameterSpec(key.getEncoded().length*8, vec); - } else { - aps = new IvParameterSpec(vec); - } - cipher.init(cipherMode, key, aps); - } - return cipher; - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException(e); - } - } - - /** - * Returns a new byte array with a truncated to the given size. - * If the hash has less then size bytes, it will be filled with 0x36-bytes - * - * @param hash the to be truncated/filled hash byte array - * @param size the size of the returned byte array - * @return the padded hash - */ - private static byte[] getBlock36(byte[] hash, int size) { - return getBlockX(hash, size, (byte)0x36); - } - - /** - * Returns a new byte array with a truncated to the given size. - * If the hash has less then size bytes, it will be filled with 0-bytes - * - * @param hash the to be truncated/filled hash byte array - * @param size the size of the returned byte array - * @return the padded hash - */ - public static byte[] getBlock0(byte[] hash, int size) { - return getBlockX(hash, size, (byte)0); - } - - private static byte[] getBlockX(byte[] hash, int size, byte fill) { - if (hash.length == size) return hash; - - byte[] result = new byte[size]; - Arrays.fill(result, fill); - System.arraycopy(hash, 0, result, 0, Math.min(result.length, hash.length)); - return result; - } - - public static MessageDigest getMessageDigest(HashAlgorithm hashAlgorithm) { - try { - if (hashAlgorithm.needsBouncyCastle) { - registerBouncyCastle(); - return MessageDigest.getInstance(hashAlgorithm.jceId, "BC"); - } else { - return MessageDigest.getInstance(hashAlgorithm.jceId); - } - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException("hash algo not supported", e); - } - } - - public static Mac getMac(HashAlgorithm hashAlgorithm) { - try { - if (hashAlgorithm.needsBouncyCastle) { - registerBouncyCastle(); - return Mac.getInstance(hashAlgorithm.jceHmacId, "BC"); - } else { - return Mac.getInstance(hashAlgorithm.jceHmacId); - } - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException("hmac algo not supported", e); - } - } - - @SuppressWarnings("unchecked") - public static void registerBouncyCastle() { - if (Security.getProvider("BC") != null) { - return; - } - - try { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - String bcProviderName = "org.bouncycastle.jce.provider.BouncyCastleProvider"; - Class clazz = (Class)cl.loadClass(bcProviderName); - Security.addProvider(clazz.newInstance()); - } catch (Exception e) { - throw new EncryptedDocumentException("Only the BouncyCastle provider supports your encryption settings - please add it to the classpath.", e); - } - } - - private static final int INITIAL_CODE_ARRAY[] = { - 0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, - 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, - 0x4EC3 - }; - - private static final byte PAD_ARRAY[] = { - (byte)0xBB, (byte)0xFF, (byte)0xFF, (byte)0xBA, (byte)0xFF, - (byte)0xFF, (byte)0xB9, (byte)0x80, (byte)0x00, (byte)0xBE, - (byte)0x0F, (byte)0x00, (byte)0xBF, (byte)0x0F, (byte)0x00 - }; - - private static final int ENCRYPTION_MATRIX[][] = { - /* char 1 */ {0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09}, - /* char 2 */ {0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF}, - /* char 3 */ {0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0}, - /* char 4 */ {0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40}, - /* char 5 */ {0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5}, - /* char 6 */ {0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A}, - /* char 7 */ {0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9}, - /* char 8 */ {0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0}, - /* char 9 */ {0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC}, - /* char 10 */ {0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10}, - /* char 11 */ {0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168}, - /* char 12 */ {0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C}, - /* char 13 */ {0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD}, - /* char 14 */ {0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC}, - /* char 15 */ {0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4} - }; - - /** - * Create the verifier for xor obfuscation (method 1) - * - * @see 2.3.7.1 Binary Document Password Verifier Derivation Method 1 - * @see 2.3.7.4 Binary Document Password Verifier Derivation Method 2 - * @see Part 4 - Markup Language Reference - Ecma International - 3.2.12 fileSharing - * - * @param password the password - * @return the verifier (actually a short value) - */ - public static int createXorVerifier1(String password) { - byte[] arrByteChars = toAnsiPassword(password); - - // SET Verifier TO 0x0000 - short verifier = 0; - - if (!"".equals(password)) { - // FOR EACH PasswordByte IN PasswordArray IN REVERSE ORDER - for (int i = arrByteChars.length-1; i >= 0; i--) { - // SET Verifier TO Intermediate3 BITWISE XOR PasswordByte - verifier = rotateLeftBase15Bit(verifier); - verifier ^= arrByteChars[i]; - } - - // as we haven't prepended the password length into the input array - // we need to do it now separately ... - verifier = rotateLeftBase15Bit(verifier); - verifier ^= arrByteChars.length; - - // RETURN Verifier BITWISE XOR 0xCE4B - verifier ^= 0xCE4B; // (0x8000 | ('N' << 8) | 'K') - } - - return verifier & 0xFFFF; - } - - /** - * This method generates the xor verifier for word documents < 2007 (method 2). - * Its output will be used as password input for the newer word generations which - * utilize a real hashing algorithm like sha1. - * - * @param password the password - * @return the hashed password - * - * @see 2.3.7.4 Binary Document Password Verifier Derivation Method 2 - * @see How to set the editing restrictions in Word using Open XML SDK 2.0 - * @see Funny: How the new powerful cryptography implemented in Word 2007 turns it into a perfect tool for document password removal. - */ - public static int createXorVerifier2(String password) { - //Array to hold Key Values - byte[] generatedKey = new byte[4]; - - //Maximum length of the password is 15 chars. - final int maxPasswordLength = 15; - - if (!"".equals(password)) { - // Truncate the password to 15 characters - password = password.substring(0, Math.min(password.length(), maxPasswordLength)); - - byte[] arrByteChars = toAnsiPassword(password); - - // Compute the high-order word of the new key: - - // --> Initialize from the initial code array (see below), depending on the passwords length. - int highOrderWord = INITIAL_CODE_ARRAY[arrByteChars.length - 1]; - - // --> For each character in the password: - // --> For every bit in the character, starting with the least significant and progressing to (but excluding) - // the most significant, if the bit is set, XOR the keys high-order word with the corresponding word from - // the Encryption Matrix - for (int i = 0; i < arrByteChars.length; i++) { - int tmp = maxPasswordLength - arrByteChars.length + i; - for (int intBit = 0; intBit < 7; intBit++) { - if ((arrByteChars[i] & (0x0001 << intBit)) != 0) { - highOrderWord ^= ENCRYPTION_MATRIX[tmp][intBit]; - } - } - } - - // Compute the low-order word of the new key: - int verifier = createXorVerifier1(password); - - // The byte order of the result shall be reversed [password "Example": 0x64CEED7E becomes 7EEDCE64], - // and that value shall be hashed as defined by the attribute values. - - LittleEndian.putShort(generatedKey, 0, (short)verifier); - LittleEndian.putShort(generatedKey, 2, (short)highOrderWord); - } - - return LittleEndian.getInt(generatedKey); - } - - /** - * This method generates the xored-hashed password for word documents < 2007. - */ - public static String xorHashPassword(String password) { - int hashedPassword = createXorVerifier2(password); - return String.format(Locale.ROOT, "%1$08X", hashedPassword); - } - - /** - * Convenience function which returns the reversed xored-hashed password for further - * processing in word documents 2007 and newer, which utilize a real hashing algorithm like sha1. - */ - public static String xorHashPasswordReversed(String password) { - int hashedPassword = createXorVerifier2(password); - - return String.format(Locale.ROOT, "%1$02X%2$02X%3$02X%4$02X" - , ( hashedPassword >>> 0 ) & 0xFF - , ( hashedPassword >>> 8 ) & 0xFF - , ( hashedPassword >>> 16 ) & 0xFF - , ( hashedPassword >>> 24 ) & 0xFF - ); - } - - /** - * Create the xor key for xor obfuscation, which is used to create the xor array (method 1) - * - * @see 2.3.7.2 Binary Document XOR Array Initialization Method 1 - * @see 2.3.7.4 Binary Document Password Verifier Derivation Method 2 - * - * @param password the password - * @return the xor key - */ - public static int createXorKey1(String password) { - // the xor key for method 1 is part of the verifier for method 2 - // so we simply chop it from there - return createXorVerifier2(password) >>> 16; - } - - /** - * Creates an byte array for xor obfuscation (method 1) - * - * @see 2.3.7.2 Binary Document XOR Array Initialization Method 1 - * @see Libre Office implementation - * - * @param password the password - * @return the byte array for xor obfuscation - */ - public static byte[] createXorArray1(String password) { - if (password.length() > 15) { - password = password.substring(0, 15); - } - byte passBytes[] = password.getBytes(Charset.forName("ASCII")); - - // this code is based on the libre office implementation. - // The MS-OFFCRYPTO misses some infos about the various rotation sizes - byte obfuscationArray[] = new byte[16]; - System.arraycopy(passBytes, 0, obfuscationArray, 0, passBytes.length); - System.arraycopy(PAD_ARRAY, 0, obfuscationArray, passBytes.length, PAD_ARRAY.length-passBytes.length+1); - - int xorKey = createXorKey1(password); - - // rotation of key values is application dependent - Excel = 2 / Word = 7 - int nRotateSize = 2; - - byte baseKeyLE[] = { (byte)(xorKey & 0xFF), (byte)((xorKey >>> 8) & 0xFF) }; - for (int i=0; iPart 4 - Markup Language Reference - Ecma International - section 3.2.29 (workbookProtection) - */ - private static byte[] toAnsiPassword(String password) { - // TODO: charset conversion (see ecma spec) - - // Get the single-byte values by iterating through the Unicode characters. - // For each character, if the low byte is not equal to 0, take it. - // Otherwise, take the high byte. - byte[] arrByteChars = new byte[password.length()]; - - for (int i = 0; i < password.length(); i++) { - int intTemp = password.charAt(i); - byte lowByte = (byte)(intTemp & 0xFF); - byte highByte = (byte)((intTemp >>> 8) & 0xFF); - arrByteChars[i] = (lowByte != 0 ? lowByte : highByte); - } - - return arrByteChars; - } - - private static byte rotateLeft(byte bits, int shift) { - return (byte)(((bits & 0xff) << shift) | ((bits & 0xff) >>> (8 - shift))); - } - - private static short rotateLeftBase15Bit(short verifier) { - /* - * IF (Verifier BITWISE AND 0x4000) is 0x0000 - * SET Intermediate1 TO 0 - * ELSE - * SET Intermediate1 TO 1 - * ENDIF - */ - short intermediate1 = (short)(((verifier & 0x4000) == 0) ? 0 : 1); - /* - * SET Intermediate2 TO Verifier MULTIPLED BY 2 - * SET most significant bit of Intermediate2 TO 0 - */ - short intermediate2 = (short)((verifier<<1) & 0x7FFF); - /* - * SET Intermediate3 TO Intermediate1 BITWISE OR Intermediate2 - */ - short intermediate3 = (short)(intermediate1 | intermediate2); - return intermediate3; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import java.nio.charset.Charset; +import java.security.DigestException; +import java.security.GeneralSecurityException; +import java.security.Key; +import java.security.MessageDigest; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import java.util.Locale; + +import javax.crypto.Cipher; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.RC2ParameterSpec; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.StringUtil; + +/** + * Helper functions used for standard and agile encryption + */ +@Internal +public class CryptoFunctions { + /** + *

2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)
+ * 2.3.4.11 Encryption Key Generation (Agile Encryption)

+ * + *

The encryption key for ECMA-376 document encryption [ECMA-376] using agile + * encryption MUST be generated by using the following method, which is derived from PKCS #5: + * Password-Based Cryptography Version 2.0 [RFC2898].

+ * + *

Let H() be a hashing algorithm as determined by the PasswordKeyEncryptor.hashAlgorithm + * element, H_n be the hash data of the n-th iteration, and a plus sign (+) represent concatenation. + * The password MUST be provided as an array of Unicode characters. Limitations on the length of the + * password and the characters used by the password are implementation-dependent. + * The initial password hash is generated as follows:

+ * + * + *
H_0 = H(salt + password)
+ * + *

The salt used MUST be generated randomly. The salt MUST be stored in the + * PasswordKeyEncryptor.saltValue element contained within the \EncryptionInfo stream as + * specified in section 2.3.4.10. The hash is then iterated by using the following approach:

+ * + *
H_n = H(iterator + H_n-1)
+ * + *

where iterator is an unsigned 32-bit value that is initially set to 0x00000000 and then incremented + * monotonically on each iteration until PasswordKey.spinCount iterations have been performed. + * The value of iterator on the last iteration MUST be one less than PasswordKey.spinCount.

+ * + *

For POI, H_final will be calculated by {@link #generateKey(byte[],HashAlgorithm,byte[],int)}

+ * + * @param password + * @param hashAlgorithm + * @param salt + * @param spinCount + * @return the hashed password + */ + public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte salt[], int spinCount) { + return hashPassword(password, hashAlgorithm, salt, spinCount, true); + } + + /** + * Generalized method for read and write protection hash generation. + * The difference is, read protection uses the order iterator then hash in the hash loop, whereas write protection + * uses first the last hash value and then the current iterator value + * + * @param password + * @param hashAlgorithm + * @param salt + * @param spinCount + * @param iteratorFirst if true, the iterator is hashed before the n-1 hash value, + * if false the n-1 hash value is applied first + * @return the hashed password + */ + public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte salt[], int spinCount, boolean iteratorFirst) { + // If no password was given, use the default + if (password == null) { + password = Decryptor.DEFAULT_PASSWORD; + } + + MessageDigest hashAlg = getMessageDigest(hashAlgorithm); + + hashAlg.update(salt); + byte[] hash = hashAlg.digest(StringUtil.getToUnicodeLE(password)); + byte[] iterator = new byte[LittleEndianConsts.INT_SIZE]; + + byte[] first = (iteratorFirst ? iterator : hash); + byte[] second = (iteratorFirst ? hash : iterator); + + try { + for (int i = 0; i < spinCount; i++) { + LittleEndian.putInt(iterator, 0, i); + hashAlg.reset(); + hashAlg.update(first); + hashAlg.update(second); + hashAlg.digest(hash, 0, hash.length); // don't create hash buffer everytime new + } + } catch (DigestException e) { + throw new EncryptedDocumentException("error in password hashing"); + } + + return hash; + } + + /** + *

2.3.4.12 Initialization Vector Generation (Agile Encryption)

+ * + *

Initialization vectors are used in all cases for agile encryption. An initialization vector MUST be + * generated by using the following method, where H() is a hash function that MUST be the same as + * specified in section 2.3.4.11 and a plus sign (+) represents concatenation:

+ *
    + *
  • If a blockKey is provided, let IV be a hash of the KeySalt and the following value:
    + * {@code blockKey: IV = H(KeySalt + blockKey)}
  • + *
  • If a blockKey is not provided, let IV be equal to the following value:
    + * {@code KeySalt:IV = KeySalt}
  • + *
  • If the number of bytes in the value of IV is less than the the value of the blockSize attribute + * corresponding to the cipherAlgorithm attribute, pad the array of bytes by appending 0x36 until + * the array is blockSize bytes. If the array of bytes is larger than blockSize bytes, truncate the + * array to blockSize bytes.
  • + *
+ **/ + public static byte[] generateIv(HashAlgorithm hashAlgorithm, byte[] salt, byte[] blockKey, int blockSize) { + byte iv[] = salt; + if (blockKey != null) { + MessageDigest hashAlgo = getMessageDigest(hashAlgorithm); + hashAlgo.update(salt); + iv = hashAlgo.digest(blockKey); + } + return getBlock36(iv, blockSize); + } + + /** + *

2.3.4.11 Encryption Key Generation (Agile Encryption)

+ * + *

The final hash data that is used for an encryption key is then generated by using the following + * method:

+ * + *
H_final = H(H_n + blockKey)
+ * + *

where blockKey represents an array of bytes used to prevent two different blocks from encrypting + * to the same cipher text.

+ * + *

If the size of the resulting H_final is smaller than that of PasswordKeyEncryptor.keyBits, the key + * MUST be padded by appending bytes with a value of 0x36. If the hash value is larger in size than + * PasswordKeyEncryptor.keyBits, the key is obtained by truncating the hash value.

+ * + * @param passwordHash + * @param hashAlgorithm + * @param blockKey + * @param keySize + * @return intermediate key + */ + public static byte[] generateKey(byte[] passwordHash, HashAlgorithm hashAlgorithm, byte[] blockKey, int keySize) { + MessageDigest hashAlgo = getMessageDigest(hashAlgorithm); + hashAlgo.update(passwordHash); + byte[] key = hashAlgo.digest(blockKey); + return getBlock36(key, keySize); + } + + /** + * Initialize a new cipher object with the given cipher properties and no padding + * If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle + * provider. + * + * @param key the secrect key + * @param cipherAlgorithm the cipher algorithm + * @param chain the chaining mode + * @param vec the initialization vector (IV), can be null + * @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE + * @return the requested cipher + * @throws GeneralSecurityException + * @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified, + * which depends on a missing bouncy castle provider + */ + public static Cipher getCipher(SecretKey key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode) { + return getCipher(key, cipherAlgorithm, chain, vec, cipherMode, null); + } + + /** + * Initialize a new cipher object with the given cipher properties + * If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle + * provider. + * + * @param key the secrect key + * @param cipherAlgorithm the cipher algorithm + * @param chain the chaining mode + * @param vec the initialization vector (IV), can be null + * @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE + * @param padding the padding (null = NOPADDING, ANSIX923Padding, PKCS5Padding, PKCS7Padding, ISO10126Padding, ...) + * @return the requested cipher + * @throws GeneralSecurityException + * @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified, + * which depends on a missing bouncy castle provider + */ + public static Cipher getCipher(Key key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode, String padding) { + int keySizeInBytes = key.getEncoded().length; + if (padding == null) padding = "NoPadding"; + + try { + // Ensure the JCE policies files allow for this sized key + if (Cipher.getMaxAllowedKeyLength(cipherAlgorithm.jceId) < keySizeInBytes*8) { + throw new EncryptedDocumentException("Export Restrictions in place - please install JCE Unlimited Strength Jurisdiction Policy files"); + } + + Cipher cipher; + if (cipherAlgorithm == CipherAlgorithm.rc4) { + cipher = Cipher.getInstance(cipherAlgorithm.jceId); + } else if (cipherAlgorithm.needsBouncyCastle) { + registerBouncyCastle(); + cipher = Cipher.getInstance(cipherAlgorithm.jceId + "/" + chain.jceId + "/" + padding, "BC"); + } else { + cipher = Cipher.getInstance(cipherAlgorithm.jceId + "/" + chain.jceId + "/" + padding); + } + + if (vec == null) { + cipher.init(cipherMode, key); + } else { + AlgorithmParameterSpec aps; + if (cipherAlgorithm == CipherAlgorithm.rc2) { + aps = new RC2ParameterSpec(key.getEncoded().length*8, vec); + } else { + aps = new IvParameterSpec(vec); + } + cipher.init(cipherMode, key, aps); + } + return cipher; + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException(e); + } + } + + /** + * Returns a new byte array with a truncated to the given size. + * If the hash has less then size bytes, it will be filled with 0x36-bytes + * + * @param hash the to be truncated/filled hash byte array + * @param size the size of the returned byte array + * @return the padded hash + */ + private static byte[] getBlock36(byte[] hash, int size) { + return getBlockX(hash, size, (byte)0x36); + } + + /** + * Returns a new byte array with a truncated to the given size. + * If the hash has less then size bytes, it will be filled with 0-bytes + * + * @param hash the to be truncated/filled hash byte array + * @param size the size of the returned byte array + * @return the padded hash + */ + public static byte[] getBlock0(byte[] hash, int size) { + return getBlockX(hash, size, (byte)0); + } + + private static byte[] getBlockX(byte[] hash, int size, byte fill) { + if (hash.length == size) return hash; + + byte[] result = new byte[size]; + Arrays.fill(result, fill); + System.arraycopy(hash, 0, result, 0, Math.min(result.length, hash.length)); + return result; + } + + public static MessageDigest getMessageDigest(HashAlgorithm hashAlgorithm) { + try { + if (hashAlgorithm.needsBouncyCastle) { + registerBouncyCastle(); + return MessageDigest.getInstance(hashAlgorithm.jceId, "BC"); + } else { + return MessageDigest.getInstance(hashAlgorithm.jceId); + } + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException("hash algo not supported", e); + } + } + + public static Mac getMac(HashAlgorithm hashAlgorithm) { + try { + if (hashAlgorithm.needsBouncyCastle) { + registerBouncyCastle(); + return Mac.getInstance(hashAlgorithm.jceHmacId, "BC"); + } else { + return Mac.getInstance(hashAlgorithm.jceHmacId); + } + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException("hmac algo not supported", e); + } + } + + @SuppressWarnings("unchecked") + public static void registerBouncyCastle() { + if (Security.getProvider("BC") != null) { + return; + } + + try { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + String bcProviderName = "org.bouncycastle.jce.provider.BouncyCastleProvider"; + Class clazz = (Class)cl.loadClass(bcProviderName); + Security.addProvider(clazz.newInstance()); + } catch (Exception e) { + throw new EncryptedDocumentException("Only the BouncyCastle provider supports your encryption settings - please add it to the classpath.", e); + } + } + + private static final int INITIAL_CODE_ARRAY[] = { + 0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, + 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, + 0x4EC3 + }; + + private static final byte PAD_ARRAY[] = { + (byte)0xBB, (byte)0xFF, (byte)0xFF, (byte)0xBA, (byte)0xFF, + (byte)0xFF, (byte)0xB9, (byte)0x80, (byte)0x00, (byte)0xBE, + (byte)0x0F, (byte)0x00, (byte)0xBF, (byte)0x0F, (byte)0x00 + }; + + private static final int ENCRYPTION_MATRIX[][] = { + /* char 1 */ {0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09}, + /* char 2 */ {0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF}, + /* char 3 */ {0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0}, + /* char 4 */ {0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40}, + /* char 5 */ {0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5}, + /* char 6 */ {0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A}, + /* char 7 */ {0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9}, + /* char 8 */ {0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0}, + /* char 9 */ {0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC}, + /* char 10 */ {0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10}, + /* char 11 */ {0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168}, + /* char 12 */ {0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C}, + /* char 13 */ {0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD}, + /* char 14 */ {0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC}, + /* char 15 */ {0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4} + }; + + /** + * Create the verifier for xor obfuscation (method 1) + * + * @see 2.3.7.1 Binary Document Password Verifier Derivation Method 1 + * @see 2.3.7.4 Binary Document Password Verifier Derivation Method 2 + * @see Part 4 - Markup Language Reference - Ecma International - 3.2.12 fileSharing + * + * @param password the password + * @return the verifier (actually a short value) + */ + public static int createXorVerifier1(String password) { + byte[] arrByteChars = toAnsiPassword(password); + + // SET Verifier TO 0x0000 + short verifier = 0; + + if (!"".equals(password)) { + // FOR EACH PasswordByte IN PasswordArray IN REVERSE ORDER + for (int i = arrByteChars.length-1; i >= 0; i--) { + // SET Verifier TO Intermediate3 BITWISE XOR PasswordByte + verifier = rotateLeftBase15Bit(verifier); + verifier ^= arrByteChars[i]; + } + + // as we haven't prepended the password length into the input array + // we need to do it now separately ... + verifier = rotateLeftBase15Bit(verifier); + verifier ^= arrByteChars.length; + + // RETURN Verifier BITWISE XOR 0xCE4B + verifier ^= 0xCE4B; // (0x8000 | ('N' << 8) | 'K') + } + + return verifier & 0xFFFF; + } + + /** + * This method generates the xor verifier for word documents < 2007 (method 2). + * Its output will be used as password input for the newer word generations which + * utilize a real hashing algorithm like sha1. + * + * @param password the password + * @return the hashed password + * + * @see 2.3.7.4 Binary Document Password Verifier Derivation Method 2 + * @see How to set the editing restrictions in Word using Open XML SDK 2.0 + * @see Funny: How the new powerful cryptography implemented in Word 2007 turns it into a perfect tool for document password removal. + */ + public static int createXorVerifier2(String password) { + //Array to hold Key Values + byte[] generatedKey = new byte[4]; + + //Maximum length of the password is 15 chars. + final int maxPasswordLength = 15; + + if (!"".equals(password)) { + // Truncate the password to 15 characters + password = password.substring(0, Math.min(password.length(), maxPasswordLength)); + + byte[] arrByteChars = toAnsiPassword(password); + + // Compute the high-order word of the new key: + + // --> Initialize from the initial code array (see below), depending on the passwords length. + int highOrderWord = INITIAL_CODE_ARRAY[arrByteChars.length - 1]; + + // --> For each character in the password: + // --> For every bit in the character, starting with the least significant and progressing to (but excluding) + // the most significant, if the bit is set, XOR the keys high-order word with the corresponding word from + // the Encryption Matrix + for (int i = 0; i < arrByteChars.length; i++) { + int tmp = maxPasswordLength - arrByteChars.length + i; + for (int intBit = 0; intBit < 7; intBit++) { + if ((arrByteChars[i] & (0x0001 << intBit)) != 0) { + highOrderWord ^= ENCRYPTION_MATRIX[tmp][intBit]; + } + } + } + + // Compute the low-order word of the new key: + int verifier = createXorVerifier1(password); + + // The byte order of the result shall be reversed [password "Example": 0x64CEED7E becomes 7EEDCE64], + // and that value shall be hashed as defined by the attribute values. + + LittleEndian.putShort(generatedKey, 0, (short)verifier); + LittleEndian.putShort(generatedKey, 2, (short)highOrderWord); + } + + return LittleEndian.getInt(generatedKey); + } + + /** + * This method generates the xored-hashed password for word documents < 2007. + */ + public static String xorHashPassword(String password) { + int hashedPassword = createXorVerifier2(password); + return String.format(Locale.ROOT, "%1$08X", hashedPassword); + } + + /** + * Convenience function which returns the reversed xored-hashed password for further + * processing in word documents 2007 and newer, which utilize a real hashing algorithm like sha1. + */ + public static String xorHashPasswordReversed(String password) { + int hashedPassword = createXorVerifier2(password); + + return String.format(Locale.ROOT, "%1$02X%2$02X%3$02X%4$02X" + , ( hashedPassword >>> 0 ) & 0xFF + , ( hashedPassword >>> 8 ) & 0xFF + , ( hashedPassword >>> 16 ) & 0xFF + , ( hashedPassword >>> 24 ) & 0xFF + ); + } + + /** + * Create the xor key for xor obfuscation, which is used to create the xor array (method 1) + * + * @see 2.3.7.2 Binary Document XOR Array Initialization Method 1 + * @see 2.3.7.4 Binary Document Password Verifier Derivation Method 2 + * + * @param password the password + * @return the xor key + */ + public static int createXorKey1(String password) { + // the xor key for method 1 is part of the verifier for method 2 + // so we simply chop it from there + return createXorVerifier2(password) >>> 16; + } + + /** + * Creates an byte array for xor obfuscation (method 1) + * + * @see 2.3.7.2 Binary Document XOR Array Initialization Method 1 + * @see Libre Office implementation + * + * @param password the password + * @return the byte array for xor obfuscation + */ + public static byte[] createXorArray1(String password) { + if (password.length() > 15) { + password = password.substring(0, 15); + } + byte passBytes[] = password.getBytes(Charset.forName("ASCII")); + + // this code is based on the libre office implementation. + // The MS-OFFCRYPTO misses some infos about the various rotation sizes + byte obfuscationArray[] = new byte[16]; + System.arraycopy(passBytes, 0, obfuscationArray, 0, passBytes.length); + System.arraycopy(PAD_ARRAY, 0, obfuscationArray, passBytes.length, PAD_ARRAY.length-passBytes.length+1); + + int xorKey = createXorKey1(password); + + // rotation of key values is application dependent - Excel = 2 / Word = 7 + int nRotateSize = 2; + + byte baseKeyLE[] = { (byte)(xorKey & 0xFF), (byte)((xorKey >>> 8) & 0xFF) }; + for (int i=0; iPart 4 - Markup Language Reference - Ecma International - section 3.2.29 (workbookProtection) + */ + private static byte[] toAnsiPassword(String password) { + // TODO: charset conversion (see ecma spec) + + // Get the single-byte values by iterating through the Unicode characters. + // For each character, if the low byte is not equal to 0, take it. + // Otherwise, take the high byte. + byte[] arrByteChars = new byte[password.length()]; + + for (int i = 0; i < password.length(); i++) { + int intTemp = password.charAt(i); + byte lowByte = (byte)(intTemp & 0xFF); + byte highByte = (byte)((intTemp >>> 8) & 0xFF); + arrByteChars[i] = (lowByte != 0 ? lowByte : highByte); + } + + return arrByteChars; + } + + private static byte rotateLeft(byte bits, int shift) { + return (byte)(((bits & 0xff) << shift) | ((bits & 0xff) >>> (8 - shift))); + } + + private static short rotateLeftBase15Bit(short verifier) { + /* + * IF (Verifier BITWISE AND 0x4000) is 0x0000 + * SET Intermediate1 TO 0 + * ELSE + * SET Intermediate1 TO 1 + * ENDIF + */ + short intermediate1 = (short)(((verifier & 0x4000) == 0) ? 0 : 1); + /* + * SET Intermediate2 TO Verifier MULTIPLED BY 2 + * SET most significant bit of Intermediate2 TO 0 + */ + short intermediate2 = (short)((verifier<<1) & 0x7FFF); + /* + * SET Intermediate3 TO Intermediate1 BITWISE OR Intermediate2 + */ + short intermediate3 = (short)(intermediate1 | intermediate2); + return intermediate3; + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java index 923d7075ff..9c377fa2d7 100644 --- a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java +++ b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java @@ -1,370 +1,370 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -import java.io.IOException; -import java.nio.charset.Charset; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.standard.EncryptionRecord; -import org.apache.poi.poifs.filesystem.DirectoryEntry; -import org.apache.poi.poifs.filesystem.DocumentEntry; -import org.apache.poi.poifs.filesystem.POIFSWriterEvent; -import org.apache.poi.poifs.filesystem.POIFSWriterListener; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInput; -import org.apache.poi.util.LittleEndianOutput; -import org.apache.poi.util.StringUtil; - -public class DataSpaceMapUtils { - public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException { - DataSpaceMapEntry dsme = new DataSpaceMapEntry( - new int[]{ 0 } - , new String[]{ Decryptor.DEFAULT_POIFS_ENTRY } - , "StrongEncryptionDataSpace" - ); - DataSpaceMap dsm = new DataSpaceMap(new DataSpaceMapEntry[]{dsme}); - createEncryptionEntry(dir, "\u0006DataSpaces/DataSpaceMap", dsm); - - DataSpaceDefinition dsd = new DataSpaceDefinition(new String[]{ "StrongEncryptionTransform" }); - createEncryptionEntry(dir, "\u0006DataSpaces/DataSpaceInfo/StrongEncryptionDataSpace", dsd); - - TransformInfoHeader tih = new TransformInfoHeader( - 1 - , "{FF9A3F03-56EF-4613-BDD5-5A41C1D07246}" - , "Microsoft.Container.EncryptionTransform" - , 1, 0, 1, 0, 1, 0 - ); - IRMDSTransformInfo irm = new IRMDSTransformInfo(tih, 0, null); - createEncryptionEntry(dir, "\u0006DataSpaces/TransformInfo/StrongEncryptionTransform/\u0006Primary", irm); - - DataSpaceVersionInfo dsvi = new DataSpaceVersionInfo("Microsoft.Container.DataSpaces", 1, 0, 1, 0, 1, 0); - createEncryptionEntry(dir, "\u0006DataSpaces/Version", dsvi); - } - - public static DocumentEntry createEncryptionEntry(DirectoryEntry dir, String path, EncryptionRecord out) throws IOException { - String parts[] = path.split("/"); - for (int i=0; i 0) { - for (int i=0; i<(4-scratchedBytes); i++) { - is.readByte(); - } - } - - return new String(data, 0, data.length, Charset.forName("UTF-8")); - } - - public static void writeUtf8LPP4(LittleEndianOutput os, String str) { - if (str == null || "".equals(str)) { - os.writeInt(str == null ? 0 : 4); - os.writeInt(0); - } else { - byte buf[] = str.getBytes(Charset.forName("UTF-8")); - os.writeInt(buf.length); - os.write(buf); - int scratchBytes = buf.length%4; - if (scratchBytes > 0) { - for (int i=0; i<(4-scratchBytes); i++) { - os.writeByte(0); - } - } - } - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +import java.io.IOException; +import java.nio.charset.Charset; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.standard.EncryptionRecord; +import org.apache.poi.poifs.filesystem.DirectoryEntry; +import org.apache.poi.poifs.filesystem.DocumentEntry; +import org.apache.poi.poifs.filesystem.POIFSWriterEvent; +import org.apache.poi.poifs.filesystem.POIFSWriterListener; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.StringUtil; + +public class DataSpaceMapUtils { + public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException { + DataSpaceMapEntry dsme = new DataSpaceMapEntry( + new int[]{ 0 } + , new String[]{ Decryptor.DEFAULT_POIFS_ENTRY } + , "StrongEncryptionDataSpace" + ); + DataSpaceMap dsm = new DataSpaceMap(new DataSpaceMapEntry[]{dsme}); + createEncryptionEntry(dir, "\u0006DataSpaces/DataSpaceMap", dsm); + + DataSpaceDefinition dsd = new DataSpaceDefinition(new String[]{ "StrongEncryptionTransform" }); + createEncryptionEntry(dir, "\u0006DataSpaces/DataSpaceInfo/StrongEncryptionDataSpace", dsd); + + TransformInfoHeader tih = new TransformInfoHeader( + 1 + , "{FF9A3F03-56EF-4613-BDD5-5A41C1D07246}" + , "Microsoft.Container.EncryptionTransform" + , 1, 0, 1, 0, 1, 0 + ); + IRMDSTransformInfo irm = new IRMDSTransformInfo(tih, 0, null); + createEncryptionEntry(dir, "\u0006DataSpaces/TransformInfo/StrongEncryptionTransform/\u0006Primary", irm); + + DataSpaceVersionInfo dsvi = new DataSpaceVersionInfo("Microsoft.Container.DataSpaces", 1, 0, 1, 0, 1, 0); + createEncryptionEntry(dir, "\u0006DataSpaces/Version", dsvi); + } + + public static DocumentEntry createEncryptionEntry(DirectoryEntry dir, String path, EncryptionRecord out) throws IOException { + String parts[] = path.split("/"); + for (int i=0; i 0) { + for (int i=0; i<(4-scratchedBytes); i++) { + is.readByte(); + } + } + + return new String(data, 0, data.length, Charset.forName("UTF-8")); + } + + public static void writeUtf8LPP4(LittleEndianOutput os, String str) { + if (str == null || "".equals(str)) { + os.writeInt(str == null ? 0 : 4); + os.writeInt(0); + } else { + byte buf[] = str.getBytes(Charset.forName("UTF-8")); + os.writeInt(buf.length); + os.write(buf); + int scratchBytes = buf.length%4; + if (scratchBytes > 0) { + for (int i=0; i<(4-scratchBytes); i++) { + os.writeByte(0); + } + } + } + } + +} diff --git a/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java b/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java index 24371dfdd6..c32b069116 100644 --- a/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java +++ b/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java @@ -1,33 +1,33 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import java.io.IOException; - -import org.apache.poi.util.LittleEndianInput; - -public interface EncryptionInfoBuilder { - /** - * initialize the builder from a stream - */ - void initialize(EncryptionInfo ei, LittleEndianInput dis) throws IOException; - - /** - * initialize the builder from scratch - */ - void initialize(EncryptionInfo ei, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import java.io.IOException; + +import org.apache.poi.util.LittleEndianInput; + +public interface EncryptionInfoBuilder { + /** + * initialize the builder from a stream + */ + void initialize(EncryptionInfo ei, LittleEndianInput dis) throws IOException; + + /** + * initialize the builder from scratch + */ + void initialize(EncryptionInfo ei, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode); +} diff --git a/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java b/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java index 50064b5a6b..2f89557996 100644 --- a/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java +++ b/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java @@ -1,52 +1,52 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; - -/** - * Office supports various encryption modes. - * The encryption is either based on the whole container ({@link #agile}, {@link #standard} or {@link #binaryRC4}) - * or record based ({@link #cryptoAPI}). The record based encryption can't be accessed directly, but will be - * invoked by using the {@link Biff8EncryptionKey#setCurrentUserPassword(String)} before saving the document. - */ -public enum EncryptionMode { - /* @see 2.3.6 Office Binary Document RC4 Encryption */ - binaryRC4("org.apache.poi.poifs.crypt.binaryrc4.BinaryRC4EncryptionInfoBuilder", 1, 1, 0x0), - /* @see 2.3.5 Office Binary Document RC4 CryptoAPI Encryption */ - cryptoAPI("org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionInfoBuilder", 4, 2, 0x04), - /* @see 2.3.4.5 \EncryptionInfo Stream (Standard Encryption) */ - standard("org.apache.poi.poifs.crypt.standard.StandardEncryptionInfoBuilder", 4, 2, 0x24), - /* @see 2.3.4.10 \EncryptionInfo Stream (Agile Encryption) */ - agile("org.apache.poi.poifs.crypt.agile.AgileEncryptionInfoBuilder", 4, 4, 0x40), - /* @see XOR Obfuscation */ - xor("org.apache.poi.poifs.crypt.xor.XOREncryptionInfoBuilder", 0, 0, 0) - ; - - public final String builder; - public final int versionMajor; - public final int versionMinor; - public final int encryptionFlags; - - EncryptionMode(String builder, int versionMajor, int versionMinor, int encryptionFlags) { - this.builder = builder; - this.versionMajor = versionMajor; - this.versionMinor = versionMinor; - this.encryptionFlags = encryptionFlags; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; + +/** + * Office supports various encryption modes. + * The encryption is either based on the whole container ({@link #agile}, {@link #standard} or {@link #binaryRC4}) + * or record based ({@link #cryptoAPI}). The record based encryption can't be accessed directly, but will be + * invoked by using the {@link Biff8EncryptionKey#setCurrentUserPassword(String)} before saving the document. + */ +public enum EncryptionMode { + /* @see 2.3.6 Office Binary Document RC4 Encryption */ + binaryRC4("org.apache.poi.poifs.crypt.binaryrc4.BinaryRC4EncryptionInfoBuilder", 1, 1, 0x0), + /* @see 2.3.5 Office Binary Document RC4 CryptoAPI Encryption */ + cryptoAPI("org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionInfoBuilder", 4, 2, 0x04), + /* @see 2.3.4.5 \EncryptionInfo Stream (Standard Encryption) */ + standard("org.apache.poi.poifs.crypt.standard.StandardEncryptionInfoBuilder", 4, 2, 0x24), + /* @see 2.3.4.10 \EncryptionInfo Stream (Agile Encryption) */ + agile("org.apache.poi.poifs.crypt.agile.AgileEncryptionInfoBuilder", 4, 4, 0x40), + /* @see XOR Obfuscation */ + xor("org.apache.poi.poifs.crypt.xor.XOREncryptionInfoBuilder", 0, 0, 0) + ; + + public final String builder; + public final int versionMajor; + public final int versionMinor; + public final int encryptionFlags; + + EncryptionMode(String builder, int versionMajor, int versionMinor, int encryptionFlags) { + this.builder = builder; + this.versionMajor = versionMajor; + this.versionMinor = versionMinor; + this.encryptionFlags = encryptionFlags; + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/Encryptor.java b/src/java/org/apache/poi/poifs/crypt/Encryptor.java index f4c0c1639f..ff954ab6b1 100644 --- a/src/java/org/apache/poi/poifs/crypt/Encryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/Encryptor.java @@ -1,104 +1,104 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import java.io.IOException; -import java.io.OutputStream; -import java.security.GeneralSecurityException; - -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; - -public abstract class Encryptor implements Cloneable { - protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY; - private EncryptionInfo encryptionInfo; - private SecretKey secretKey; - - /** - * Return a output stream for encrypted data. - * - * @param dir the node to write to - * @return encrypted stream - */ - public abstract OutputStream getDataStream(DirectoryNode dir) - throws IOException, GeneralSecurityException; - - // for tests - public abstract void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]); - - public abstract void confirmPassword(String password); - - public static Encryptor getInstance(EncryptionInfo info) { - return info.getEncryptor(); - } - - public OutputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException { - return getDataStream(fs.getRoot()); - } - public OutputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException { - return getDataStream(fs.getRoot()); - } - public OutputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException { - return getDataStream(fs.getRoot()); - } - - public ChunkedCipherOutputStream getDataStream(OutputStream stream, int initialOffset) - throws IOException, GeneralSecurityException { - throw new EncryptedDocumentException("this decryptor doesn't support writing directly to a stream"); - } - - public SecretKey getSecretKey() { - return secretKey; - } - - public void setSecretKey(SecretKey secretKey) { - this.secretKey = secretKey; - } - - public EncryptionInfo getEncryptionInfo() { - return encryptionInfo; - } - - public void setEncryptionInfo(EncryptionInfo encryptionInfo) { - this.encryptionInfo = encryptionInfo; - } - - /** - * Sets the chunk size of the data stream. - * Needs to be set before the data stream is requested. - * When not set, the implementation uses method specific default values - * - * @param chunkSize the chunk size, i.e. the block size with the same encryption key - */ - public void setChunkSize(int chunkSize) { - throw new EncryptedDocumentException("this decryptor doesn't support changing the chunk size"); - } - - @Override - public Encryptor clone() throws CloneNotSupportedException { - Encryptor other = (Encryptor)super.clone(); - other.secretKey = new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm()); - // encryptionInfo is set from outside - return other; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import java.io.IOException; +import java.io.OutputStream; +import java.security.GeneralSecurityException; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +public abstract class Encryptor implements Cloneable { + protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY; + private EncryptionInfo encryptionInfo; + private SecretKey secretKey; + + /** + * Return a output stream for encrypted data. + * + * @param dir the node to write to + * @return encrypted stream + */ + public abstract OutputStream getDataStream(DirectoryNode dir) + throws IOException, GeneralSecurityException; + + // for tests + public abstract void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]); + + public abstract void confirmPassword(String password); + + public static Encryptor getInstance(EncryptionInfo info) { + return info.getEncryptor(); + } + + public OutputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException { + return getDataStream(fs.getRoot()); + } + public OutputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException { + return getDataStream(fs.getRoot()); + } + public OutputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException { + return getDataStream(fs.getRoot()); + } + + public ChunkedCipherOutputStream getDataStream(OutputStream stream, int initialOffset) + throws IOException, GeneralSecurityException { + throw new EncryptedDocumentException("this decryptor doesn't support writing directly to a stream"); + } + + public SecretKey getSecretKey() { + return secretKey; + } + + public void setSecretKey(SecretKey secretKey) { + this.secretKey = secretKey; + } + + public EncryptionInfo getEncryptionInfo() { + return encryptionInfo; + } + + public void setEncryptionInfo(EncryptionInfo encryptionInfo) { + this.encryptionInfo = encryptionInfo; + } + + /** + * Sets the chunk size of the data stream. + * Needs to be set before the data stream is requested. + * When not set, the implementation uses method specific default values + * + * @param chunkSize the chunk size, i.e. the block size with the same encryption key + */ + public void setChunkSize(int chunkSize) { + throw new EncryptedDocumentException("this decryptor doesn't support changing the chunk size"); + } + + @Override + public Encryptor clone() throws CloneNotSupportedException { + Encryptor other = (Encryptor)super.clone(); + other.secretKey = new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm()); + // encryptionInfo is set from outside + return other; + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java b/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java index 24c43325d9..0440c78c04 100644 --- a/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java +++ b/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java @@ -1,75 +1,75 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -import org.apache.poi.EncryptedDocumentException; - -public enum HashAlgorithm { - none ( "", 0x0000, "", 0, "", false), - sha1 ( "SHA-1", 0x8004, "SHA1", 20, "HmacSHA1", false), - sha256 ( "SHA-256", 0x800C, "SHA256", 32, "HmacSHA256", false), - sha384 ( "SHA-384", 0x800D, "SHA384", 48, "HmacSHA384", false), - sha512 ( "SHA-512", 0x800E, "SHA512", 64, "HmacSHA512", false), - /* only for agile encryption */ - md5 ( "MD5", -1, "MD5", 16, "HmacMD5", false), - // although sunjc2 supports md2, hmac-md2 is only supported by bouncycastle - md2 ( "MD2", -1, "MD2", 16, "Hmac-MD2", true), - md4 ( "MD4", -1, "MD4", 16, "Hmac-MD4", true), - ripemd128("RipeMD128", -1, "RIPEMD-128", 16, "HMac-RipeMD128", true), - ripemd160("RipeMD160", -1, "RIPEMD-160", 20, "HMac-RipeMD160", true), - whirlpool("Whirlpool", -1, "WHIRLPOOL", 64, "HMac-Whirlpool", true), - // only for xml signing - sha224 ( "SHA-224", -1, "SHA224", 28, "HmacSHA224", true); - - public final String jceId; - public final int ecmaId; - public final String ecmaString; - public final int hashSize; - public final String jceHmacId; - public final boolean needsBouncyCastle; - - HashAlgorithm(String jceId, int ecmaId, String ecmaString, int hashSize, String jceHmacId, boolean needsBouncyCastle) { - this.jceId = jceId; - this.ecmaId = ecmaId; - this.ecmaString = ecmaString; - this.hashSize = hashSize; - this.jceHmacId = jceHmacId; - this.needsBouncyCastle = needsBouncyCastle; - } - - public static HashAlgorithm fromEcmaId(int ecmaId) { - for (HashAlgorithm ha : values()) { - if (ha.ecmaId == ecmaId) return ha; - } - throw new EncryptedDocumentException("hash algorithm not found"); - } - - public static HashAlgorithm fromEcmaId(String ecmaString) { - for (HashAlgorithm ha : values()) { - if (ha.ecmaString.equals(ecmaString)) return ha; - } - throw new EncryptedDocumentException("hash algorithm not found"); - } - - public static HashAlgorithm fromString(String string) { - for (HashAlgorithm ha : values()) { - if (ha.ecmaString.equalsIgnoreCase(string) || ha.jceId.equalsIgnoreCase(string)) return ha; - } - throw new EncryptedDocumentException("hash algorithm not found"); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +import org.apache.poi.EncryptedDocumentException; + +public enum HashAlgorithm { + none ( "", 0x0000, "", 0, "", false), + sha1 ( "SHA-1", 0x8004, "SHA1", 20, "HmacSHA1", false), + sha256 ( "SHA-256", 0x800C, "SHA256", 32, "HmacSHA256", false), + sha384 ( "SHA-384", 0x800D, "SHA384", 48, "HmacSHA384", false), + sha512 ( "SHA-512", 0x800E, "SHA512", 64, "HmacSHA512", false), + /* only for agile encryption */ + md5 ( "MD5", -1, "MD5", 16, "HmacMD5", false), + // although sunjc2 supports md2, hmac-md2 is only supported by bouncycastle + md2 ( "MD2", -1, "MD2", 16, "Hmac-MD2", true), + md4 ( "MD4", -1, "MD4", 16, "Hmac-MD4", true), + ripemd128("RipeMD128", -1, "RIPEMD-128", 16, "HMac-RipeMD128", true), + ripemd160("RipeMD160", -1, "RIPEMD-160", 20, "HMac-RipeMD160", true), + whirlpool("Whirlpool", -1, "WHIRLPOOL", 64, "HMac-Whirlpool", true), + // only for xml signing + sha224 ( "SHA-224", -1, "SHA224", 28, "HmacSHA224", true); + + public final String jceId; + public final int ecmaId; + public final String ecmaString; + public final int hashSize; + public final String jceHmacId; + public final boolean needsBouncyCastle; + + HashAlgorithm(String jceId, int ecmaId, String ecmaString, int hashSize, String jceHmacId, boolean needsBouncyCastle) { + this.jceId = jceId; + this.ecmaId = ecmaId; + this.ecmaString = ecmaString; + this.hashSize = hashSize; + this.jceHmacId = jceHmacId; + this.needsBouncyCastle = needsBouncyCastle; + } + + public static HashAlgorithm fromEcmaId(int ecmaId) { + for (HashAlgorithm ha : values()) { + if (ha.ecmaId == ecmaId) return ha; + } + throw new EncryptedDocumentException("hash algorithm not found"); + } + + public static HashAlgorithm fromEcmaId(String ecmaString) { + for (HashAlgorithm ha : values()) { + if (ha.ecmaString.equals(ecmaString)) return ha; + } + throw new EncryptedDocumentException("hash algorithm not found"); + } + + public static HashAlgorithm fromString(String string) { + for (HashAlgorithm ha : values()) { + if (ha.ecmaString.equalsIgnoreCase(string) || ha.jceId.equalsIgnoreCase(string)) return ha; + } + throw new EncryptedDocumentException("hash algorithm not found"); + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java index e02273407c..1cc6b1b2f4 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java @@ -1,166 +1,166 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.binaryrc4; - -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.util.Arrays; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.*; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.StringUtil; - -public class BinaryRC4Decryptor extends Decryptor implements Cloneable { - private long length = -1L; - private int chunkSize = 512; - - private class BinaryRC4CipherInputStream extends ChunkedCipherInputStream { - - @Override - protected Cipher initCipherForBlock(Cipher existing, int block) - throws GeneralSecurityException { - return BinaryRC4Decryptor.this.initCipherForBlock(existing, block); - } - - public BinaryRC4CipherInputStream(DocumentInputStream stream, long size) - throws GeneralSecurityException { - super(stream, size, chunkSize); - } - - public BinaryRC4CipherInputStream(InputStream stream) - throws GeneralSecurityException { - super(stream, Integer.MAX_VALUE, chunkSize); - } - } - - protected BinaryRC4Decryptor() { - } - - @Override - public boolean verifyPassword(String password) { - EncryptionVerifier ver = getEncryptionInfo().getVerifier(); - SecretKey skey = generateSecretKey(password, ver); - try { - Cipher cipher = initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.DECRYPT_MODE); - byte encryptedVerifier[] = ver.getEncryptedVerifier(); - byte verifier[] = new byte[encryptedVerifier.length]; - cipher.update(encryptedVerifier, 0, encryptedVerifier.length, verifier); - setVerifier(verifier); - byte encryptedVerifierHash[] = ver.getEncryptedVerifierHash(); - byte verifierHash[] = cipher.doFinal(encryptedVerifierHash); - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); - byte calcVerifierHash[] = hashAlg.digest(verifier); - if (Arrays.equals(calcVerifierHash, verifierHash)) { - setSecretKey(skey); - return true; - } - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException(e); - } - return false; - } - - @Override - public Cipher initCipherForBlock(Cipher cipher, int block) - throws GeneralSecurityException { - return initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE); - } - - protected static Cipher initCipherForBlock(Cipher cipher, int block, - EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode) - throws GeneralSecurityException { - EncryptionVerifier ver = encryptionInfo.getVerifier(); - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - byte blockKey[] = new byte[4]; - LittleEndian.putUInt(blockKey, 0, block); - byte encKey[] = CryptoFunctions.generateKey(skey.getEncoded(), hashAlgo, blockKey, 16); - SecretKey key = new SecretKeySpec(encKey, skey.getAlgorithm()); - if (cipher == null) { - EncryptionHeader em = encryptionInfo.getHeader(); - cipher = CryptoFunctions.getCipher(key, em.getCipherAlgorithm(), null, null, encryptMode); - } else { - cipher.init(encryptMode, key); - } - return cipher; - } - - protected static SecretKey generateSecretKey(String password, EncryptionVerifier ver) { - if (password.length() > 255) { - password = password.substring(0, 255); - } - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); - byte hash[] = hashAlg.digest(StringUtil.getToUnicodeLE(password)); - byte salt[] = ver.getSalt(); - hashAlg.reset(); - for (int i = 0; i < 16; i++) { - hashAlg.update(hash, 0, 5); - hashAlg.update(salt); - } - - hash = new byte[5]; - System.arraycopy(hashAlg.digest(), 0, hash, 0, 5); - SecretKey skey = new SecretKeySpec(hash, ver.getCipherAlgorithm().jceId); - return skey; - } - - @Override - @SuppressWarnings("resource") - public ChunkedCipherInputStream getDataStream(DirectoryNode dir) throws IOException, - GeneralSecurityException { - DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY); - length = dis.readLong(); - return new BinaryRC4CipherInputStream(dis, length); - } - - @Override - public InputStream getDataStream(InputStream stream, int size, int initialPos) - throws IOException, GeneralSecurityException { - return new BinaryRC4CipherInputStream(stream); - } - - - @Override - public long getLength() { - if (length == -1L) { - throw new IllegalStateException("Decryptor.getDataStream() was not called"); - } - - return length; - } - - @Override - public void setChunkSize(int chunkSize) { - this.chunkSize = chunkSize; - } - - @Override - public BinaryRC4Decryptor clone() throws CloneNotSupportedException { - return (BinaryRC4Decryptor)super.clone(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.binaryrc4; + +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.util.Arrays; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.*; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.StringUtil; + +public class BinaryRC4Decryptor extends Decryptor implements Cloneable { + private long length = -1L; + private int chunkSize = 512; + + private class BinaryRC4CipherInputStream extends ChunkedCipherInputStream { + + @Override + protected Cipher initCipherForBlock(Cipher existing, int block) + throws GeneralSecurityException { + return BinaryRC4Decryptor.this.initCipherForBlock(existing, block); + } + + public BinaryRC4CipherInputStream(DocumentInputStream stream, long size) + throws GeneralSecurityException { + super(stream, size, chunkSize); + } + + public BinaryRC4CipherInputStream(InputStream stream) + throws GeneralSecurityException { + super(stream, Integer.MAX_VALUE, chunkSize); + } + } + + protected BinaryRC4Decryptor() { + } + + @Override + public boolean verifyPassword(String password) { + EncryptionVerifier ver = getEncryptionInfo().getVerifier(); + SecretKey skey = generateSecretKey(password, ver); + try { + Cipher cipher = initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.DECRYPT_MODE); + byte encryptedVerifier[] = ver.getEncryptedVerifier(); + byte verifier[] = new byte[encryptedVerifier.length]; + cipher.update(encryptedVerifier, 0, encryptedVerifier.length, verifier); + setVerifier(verifier); + byte encryptedVerifierHash[] = ver.getEncryptedVerifierHash(); + byte verifierHash[] = cipher.doFinal(encryptedVerifierHash); + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); + byte calcVerifierHash[] = hashAlg.digest(verifier); + if (Arrays.equals(calcVerifierHash, verifierHash)) { + setSecretKey(skey); + return true; + } + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException(e); + } + return false; + } + + @Override + public Cipher initCipherForBlock(Cipher cipher, int block) + throws GeneralSecurityException { + return initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE); + } + + protected static Cipher initCipherForBlock(Cipher cipher, int block, + EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode) + throws GeneralSecurityException { + EncryptionVerifier ver = encryptionInfo.getVerifier(); + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + byte blockKey[] = new byte[4]; + LittleEndian.putUInt(blockKey, 0, block); + byte encKey[] = CryptoFunctions.generateKey(skey.getEncoded(), hashAlgo, blockKey, 16); + SecretKey key = new SecretKeySpec(encKey, skey.getAlgorithm()); + if (cipher == null) { + EncryptionHeader em = encryptionInfo.getHeader(); + cipher = CryptoFunctions.getCipher(key, em.getCipherAlgorithm(), null, null, encryptMode); + } else { + cipher.init(encryptMode, key); + } + return cipher; + } + + protected static SecretKey generateSecretKey(String password, EncryptionVerifier ver) { + if (password.length() > 255) { + password = password.substring(0, 255); + } + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); + byte hash[] = hashAlg.digest(StringUtil.getToUnicodeLE(password)); + byte salt[] = ver.getSalt(); + hashAlg.reset(); + for (int i = 0; i < 16; i++) { + hashAlg.update(hash, 0, 5); + hashAlg.update(salt); + } + + hash = new byte[5]; + System.arraycopy(hashAlg.digest(), 0, hash, 0, 5); + SecretKey skey = new SecretKeySpec(hash, ver.getCipherAlgorithm().jceId); + return skey; + } + + @Override + @SuppressWarnings("resource") + public ChunkedCipherInputStream getDataStream(DirectoryNode dir) throws IOException, + GeneralSecurityException { + DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY); + length = dis.readLong(); + return new BinaryRC4CipherInputStream(dis, length); + } + + @Override + public InputStream getDataStream(InputStream stream, int size, int initialPos) + throws IOException, GeneralSecurityException { + return new BinaryRC4CipherInputStream(stream); + } + + + @Override + public long getLength() { + if (length == -1L) { + throw new IllegalStateException("Decryptor.getDataStream() was not called"); + } + + return length; + } + + @Override + public void setChunkSize(int chunkSize) { + this.chunkSize = chunkSize; + } + + @Override + public BinaryRC4Decryptor clone() throws CloneNotSupportedException { + return (BinaryRC4Decryptor)super.clone(); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java index b9022017b9..549d0f85f9 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java @@ -1,51 +1,51 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.binaryrc4; - -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.CipherProvider; -import org.apache.poi.poifs.crypt.EncryptionHeader; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.standard.EncryptionRecord; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; - -public class BinaryRC4EncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable { - - protected BinaryRC4EncryptionHeader() { - setCipherAlgorithm(CipherAlgorithm.rc4); - setKeySize(40); - setBlockSize(-1); - setCipherProvider(CipherProvider.rc4); - setHashAlgorithm(HashAlgorithm.md5); - setSizeExtra(0); - setFlags(0); - setCspName(""); - setChainingMode(null); - } - - @Override - public void write(LittleEndianByteArrayOutputStream littleendianbytearrayoutputstream) { - } - - @Override - public BinaryRC4EncryptionHeader clone() throws CloneNotSupportedException { - return (BinaryRC4EncryptionHeader)super.clone(); - } - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.binaryrc4; + +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.CipherProvider; +import org.apache.poi.poifs.crypt.EncryptionHeader; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.standard.EncryptionRecord; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; + +public class BinaryRC4EncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable { + + protected BinaryRC4EncryptionHeader() { + setCipherAlgorithm(CipherAlgorithm.rc4); + setKeySize(40); + setBlockSize(-1); + setCipherProvider(CipherProvider.rc4); + setHashAlgorithm(HashAlgorithm.md5); + setSizeExtra(0); + setFlags(0); + setCspName(""); + setChainingMode(null); + } + + @Override + public void write(LittleEndianByteArrayOutputStream littleendianbytearrayoutputstream) { + } + + @Override + public BinaryRC4EncryptionHeader clone() throws CloneNotSupportedException { + return (BinaryRC4EncryptionHeader)super.clone(); + } + + +} diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java index 94ddde72ab..d8b8573597 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java @@ -1,59 +1,59 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.binaryrc4; - -import java.io.IOException; -import org.apache.poi.poifs.crypt.*; -import org.apache.poi.util.LittleEndianInput; - -public class BinaryRC4EncryptionInfoBuilder implements EncryptionInfoBuilder { - - public BinaryRC4EncryptionInfoBuilder() { - } - - @Override - public void initialize(EncryptionInfo info, LittleEndianInput dis) - throws IOException { - int vMajor = info.getVersionMajor(); - int vMinor = info.getVersionMinor(); - assert (vMajor == 1 && vMinor == 1); - - info.setHeader(new BinaryRC4EncryptionHeader()); - info.setVerifier(new BinaryRC4EncryptionVerifier(dis)); - Decryptor dec = new BinaryRC4Decryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - Encryptor enc = new BinaryRC4Encryptor(); - enc.setEncryptionInfo(info); - info.setEncryptor(enc); - } - - @Override - public void initialize(EncryptionInfo info, - CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, - int keyBits, int blockSize, ChainingMode chainingMode) { - info.setHeader(new BinaryRC4EncryptionHeader()); - info.setVerifier(new BinaryRC4EncryptionVerifier()); - Decryptor dec = new BinaryRC4Decryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - Encryptor enc = new BinaryRC4Encryptor(); - enc.setEncryptionInfo(info); - info.setEncryptor(enc); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.binaryrc4; + +import java.io.IOException; +import org.apache.poi.poifs.crypt.*; +import org.apache.poi.util.LittleEndianInput; + +public class BinaryRC4EncryptionInfoBuilder implements EncryptionInfoBuilder { + + public BinaryRC4EncryptionInfoBuilder() { + } + + @Override + public void initialize(EncryptionInfo info, LittleEndianInput dis) + throws IOException { + int vMajor = info.getVersionMajor(); + int vMinor = info.getVersionMinor(); + assert (vMajor == 1 && vMinor == 1); + + info.setHeader(new BinaryRC4EncryptionHeader()); + info.setVerifier(new BinaryRC4EncryptionVerifier(dis)); + Decryptor dec = new BinaryRC4Decryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + Encryptor enc = new BinaryRC4Encryptor(); + enc.setEncryptionInfo(info); + info.setEncryptor(enc); + } + + @Override + public void initialize(EncryptionInfo info, + CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, + int keyBits, int blockSize, ChainingMode chainingMode) { + info.setHeader(new BinaryRC4EncryptionHeader()); + info.setVerifier(new BinaryRC4EncryptionVerifier()); + Decryptor dec = new BinaryRC4Decryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + Encryptor enc = new BinaryRC4Encryptor(); + enc.setEncryptionInfo(info); + info.setEncryptor(enc); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java index 654b64a3e5..b20ed0ce76 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java @@ -1,89 +1,89 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.binaryrc4; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.*; -import org.apache.poi.poifs.crypt.standard.EncryptionRecord; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; -import org.apache.poi.util.LittleEndianInput; - -public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements EncryptionRecord, Cloneable { - - protected BinaryRC4EncryptionVerifier() { - setSpinCount(-1); - setCipherAlgorithm(CipherAlgorithm.rc4); - setChainingMode(null); - setEncryptedKey(null); - setHashAlgorithm(HashAlgorithm.md5); - } - - protected BinaryRC4EncryptionVerifier(LittleEndianInput is) { - byte salt[] = new byte[16]; - is.readFully(salt); - setSalt(salt); - byte encryptedVerifier[] = new byte[16]; - is.readFully(encryptedVerifier); - setEncryptedVerifier(encryptedVerifier); - byte encryptedVerifierHash[] = new byte[16]; - is.readFully(encryptedVerifierHash); - setEncryptedVerifierHash(encryptedVerifierHash); - setSpinCount(-1); - setCipherAlgorithm(CipherAlgorithm.rc4); - setChainingMode(null); - setEncryptedKey(null); - setHashAlgorithm(HashAlgorithm.md5); - } - - @Override - protected void setSalt(byte salt[]) { - if (salt == null || salt.length != 16) { - throw new EncryptedDocumentException("invalid verifier salt"); - } - - super.setSalt(salt); - } - - @Override - protected void setEncryptedVerifier(byte encryptedVerifier[]) { - super.setEncryptedVerifier(encryptedVerifier); - } - - @Override - protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) { - super.setEncryptedVerifierHash(encryptedVerifierHash); - } - - @Override - public void write(LittleEndianByteArrayOutputStream bos) { - byte salt[] = getSalt(); - assert (salt.length == 16); - bos.write(salt); - byte encryptedVerifier[] = getEncryptedVerifier(); - assert (encryptedVerifier.length == 16); - bos.write(encryptedVerifier); - byte encryptedVerifierHash[] = getEncryptedVerifierHash(); - assert (encryptedVerifierHash.length == 16); - bos.write(encryptedVerifierHash); - } - - @Override - public BinaryRC4EncryptionVerifier clone() throws CloneNotSupportedException { - return (BinaryRC4EncryptionVerifier)super.clone(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.binaryrc4; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.*; +import org.apache.poi.poifs.crypt.standard.EncryptionRecord; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; +import org.apache.poi.util.LittleEndianInput; + +public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements EncryptionRecord, Cloneable { + + protected BinaryRC4EncryptionVerifier() { + setSpinCount(-1); + setCipherAlgorithm(CipherAlgorithm.rc4); + setChainingMode(null); + setEncryptedKey(null); + setHashAlgorithm(HashAlgorithm.md5); + } + + protected BinaryRC4EncryptionVerifier(LittleEndianInput is) { + byte salt[] = new byte[16]; + is.readFully(salt); + setSalt(salt); + byte encryptedVerifier[] = new byte[16]; + is.readFully(encryptedVerifier); + setEncryptedVerifier(encryptedVerifier); + byte encryptedVerifierHash[] = new byte[16]; + is.readFully(encryptedVerifierHash); + setEncryptedVerifierHash(encryptedVerifierHash); + setSpinCount(-1); + setCipherAlgorithm(CipherAlgorithm.rc4); + setChainingMode(null); + setEncryptedKey(null); + setHashAlgorithm(HashAlgorithm.md5); + } + + @Override + protected void setSalt(byte salt[]) { + if (salt == null || salt.length != 16) { + throw new EncryptedDocumentException("invalid verifier salt"); + } + + super.setSalt(salt); + } + + @Override + protected void setEncryptedVerifier(byte encryptedVerifier[]) { + super.setEncryptedVerifier(encryptedVerifier); + } + + @Override + protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) { + super.setEncryptedVerifierHash(encryptedVerifierHash); + } + + @Override + public void write(LittleEndianByteArrayOutputStream bos) { + byte salt[] = getSalt(); + assert (salt.length == 16); + bos.write(salt); + byte encryptedVerifier[] = getEncryptedVerifier(); + assert (encryptedVerifier.length == 16); + bos.write(encryptedVerifier); + byte encryptedVerifierHash[] = getEncryptedVerifierHash(); + assert (encryptedVerifierHash.length == 16); + bos.write(encryptedVerifierHash); + } + + @Override + public BinaryRC4EncryptionVerifier clone() throws CloneNotSupportedException { + return (BinaryRC4EncryptionVerifier)super.clone(); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java index 15bb476ea9..743fedb38f 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java @@ -1,160 +1,160 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.binaryrc4; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.SecureRandom; -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.DataSpaceMapUtils; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.Encryptor; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.standard.EncryptionRecord; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; - -public class BinaryRC4Encryptor extends Encryptor implements Cloneable { - - private int chunkSize = 512; - - protected BinaryRC4Encryptor() { - } - - @Override - public void confirmPassword(String password) { - Random r = new SecureRandom(); - byte salt[] = new byte[16]; - byte verifier[] = new byte[16]; - r.nextBytes(salt); - r.nextBytes(verifier); - confirmPassword(password, null, null, verifier, salt, null); - } - - @Override - public void confirmPassword(String password, byte keySpec[], - byte keySalt[], byte verifier[], byte verifierSalt[], - byte integritySalt[]) { - BinaryRC4EncryptionVerifier ver = (BinaryRC4EncryptionVerifier)getEncryptionInfo().getVerifier(); - ver.setSalt(verifierSalt); - SecretKey skey = BinaryRC4Decryptor.generateSecretKey(password, ver); - setSecretKey(skey); - try { - Cipher cipher = BinaryRC4Decryptor.initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.ENCRYPT_MODE); - byte encryptedVerifier[] = new byte[16]; - cipher.update(verifier, 0, 16, encryptedVerifier); - ver.setEncryptedVerifier(encryptedVerifier); - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); - byte calcVerifierHash[] = hashAlg.digest(verifier); - byte encryptedVerifierHash[] = cipher.doFinal(calcVerifierHash); - ver.setEncryptedVerifierHash(encryptedVerifierHash); - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException("Password confirmation failed", e); - } - } - - @Override - public OutputStream getDataStream(DirectoryNode dir) - throws IOException, GeneralSecurityException { - OutputStream countStream = new BinaryRC4CipherOutputStream(dir); - return countStream; - } - - @Override - public BinaryRC4CipherOutputStream getDataStream(OutputStream stream, int initialOffset) - throws IOException, GeneralSecurityException { - return new BinaryRC4CipherOutputStream(stream); - } - - protected int getKeySizeInBytes() { - return getEncryptionInfo().getHeader().getKeySize() / 8; - } - - protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException { - DataSpaceMapUtils.addDefaultDataSpace(dir); - final EncryptionInfo info = getEncryptionInfo(); - final BinaryRC4EncryptionHeader header = (BinaryRC4EncryptionHeader)info.getHeader(); - final BinaryRC4EncryptionVerifier verifier = (BinaryRC4EncryptionVerifier)info.getVerifier(); - EncryptionRecord er = new EncryptionRecord() { - @Override - public void write(LittleEndianByteArrayOutputStream bos) { - bos.writeShort(info.getVersionMajor()); - bos.writeShort(info.getVersionMinor()); - header.write(bos); - verifier.write(bos); - } - }; - DataSpaceMapUtils.createEncryptionEntry(dir, "EncryptionInfo", er); - } - - @Override - public void setChunkSize(int chunkSize) { - this.chunkSize = chunkSize; - } - - @Override - public BinaryRC4Encryptor clone() throws CloneNotSupportedException { - return (BinaryRC4Encryptor)super.clone(); - } - - protected class BinaryRC4CipherOutputStream extends ChunkedCipherOutputStream { - - public BinaryRC4CipherOutputStream(OutputStream stream) - throws IOException, GeneralSecurityException { - super(stream, BinaryRC4Encryptor.this.chunkSize); - } - - public BinaryRC4CipherOutputStream(DirectoryNode dir) - throws IOException, GeneralSecurityException { - super(dir, BinaryRC4Encryptor.this.chunkSize); - } - - @Override - protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk) - throws GeneralSecurityException { - return BinaryRC4Decryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); - } - - @Override - protected void calculateChecksum(File file, int i) { - } - - @Override - protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) - throws IOException, GeneralSecurityException { - BinaryRC4Encryptor.this.createEncryptionInfoEntry(dir); - } - - @Override - public void flush() throws IOException { - writeChunk(false); - super.flush(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.binaryrc4; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.Random; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.DataSpaceMapUtils; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.standard.EncryptionRecord; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; + +public class BinaryRC4Encryptor extends Encryptor implements Cloneable { + + private int chunkSize = 512; + + protected BinaryRC4Encryptor() { + } + + @Override + public void confirmPassword(String password) { + Random r = new SecureRandom(); + byte salt[] = new byte[16]; + byte verifier[] = new byte[16]; + r.nextBytes(salt); + r.nextBytes(verifier); + confirmPassword(password, null, null, verifier, salt, null); + } + + @Override + public void confirmPassword(String password, byte keySpec[], + byte keySalt[], byte verifier[], byte verifierSalt[], + byte integritySalt[]) { + BinaryRC4EncryptionVerifier ver = (BinaryRC4EncryptionVerifier)getEncryptionInfo().getVerifier(); + ver.setSalt(verifierSalt); + SecretKey skey = BinaryRC4Decryptor.generateSecretKey(password, ver); + setSecretKey(skey); + try { + Cipher cipher = BinaryRC4Decryptor.initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.ENCRYPT_MODE); + byte encryptedVerifier[] = new byte[16]; + cipher.update(verifier, 0, 16, encryptedVerifier); + ver.setEncryptedVerifier(encryptedVerifier); + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); + byte calcVerifierHash[] = hashAlg.digest(verifier); + byte encryptedVerifierHash[] = cipher.doFinal(calcVerifierHash); + ver.setEncryptedVerifierHash(encryptedVerifierHash); + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException("Password confirmation failed", e); + } + } + + @Override + public OutputStream getDataStream(DirectoryNode dir) + throws IOException, GeneralSecurityException { + OutputStream countStream = new BinaryRC4CipherOutputStream(dir); + return countStream; + } + + @Override + public BinaryRC4CipherOutputStream getDataStream(OutputStream stream, int initialOffset) + throws IOException, GeneralSecurityException { + return new BinaryRC4CipherOutputStream(stream); + } + + protected int getKeySizeInBytes() { + return getEncryptionInfo().getHeader().getKeySize() / 8; + } + + protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException { + DataSpaceMapUtils.addDefaultDataSpace(dir); + final EncryptionInfo info = getEncryptionInfo(); + final BinaryRC4EncryptionHeader header = (BinaryRC4EncryptionHeader)info.getHeader(); + final BinaryRC4EncryptionVerifier verifier = (BinaryRC4EncryptionVerifier)info.getVerifier(); + EncryptionRecord er = new EncryptionRecord() { + @Override + public void write(LittleEndianByteArrayOutputStream bos) { + bos.writeShort(info.getVersionMajor()); + bos.writeShort(info.getVersionMinor()); + header.write(bos); + verifier.write(bos); + } + }; + DataSpaceMapUtils.createEncryptionEntry(dir, "EncryptionInfo", er); + } + + @Override + public void setChunkSize(int chunkSize) { + this.chunkSize = chunkSize; + } + + @Override + public BinaryRC4Encryptor clone() throws CloneNotSupportedException { + return (BinaryRC4Encryptor)super.clone(); + } + + protected class BinaryRC4CipherOutputStream extends ChunkedCipherOutputStream { + + public BinaryRC4CipherOutputStream(OutputStream stream) + throws IOException, GeneralSecurityException { + super(stream, BinaryRC4Encryptor.this.chunkSize); + } + + public BinaryRC4CipherOutputStream(DirectoryNode dir) + throws IOException, GeneralSecurityException { + super(dir, BinaryRC4Encryptor.this.chunkSize); + } + + @Override + protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk) + throws GeneralSecurityException { + return BinaryRC4Decryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); + } + + @Override + protected void calculateChecksum(File file, int i) { + } + + @Override + protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) + throws IOException, GeneralSecurityException { + BinaryRC4Encryptor.this.createEncryptionInfoEntry(dir); + } + + @Override + public void flush() throws IOException { + writeChunk(false); + super.flush(); + } + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java index 669931f9e9..222b425178 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java @@ -1,255 +1,255 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.cryptoapi; - -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.util.Arrays; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.ChunkedCipherInputStream; -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.Decryptor; -import org.apache.poi.poifs.crypt.EncryptionHeader; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.EncryptionVerifier; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.poifs.filesystem.DocumentNode; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.BitField; -import org.apache.poi.util.BitFieldFactory; -import org.apache.poi.util.BoundedInputStream; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianInputStream; -import org.apache.poi.util.StringUtil; - -public class CryptoAPIDecryptor extends Decryptor implements Cloneable { - - private long length = -1L; - private int chunkSize = -1; - - static class StreamDescriptorEntry { - static BitField flagStream = BitFieldFactory.getInstance(1); - - int streamOffset; - int streamSize; - int block; - int flags; - int reserved2; - String streamName; - } - - protected CryptoAPIDecryptor() { - } - - @Override - public boolean verifyPassword(String password) { - EncryptionVerifier ver = getEncryptionInfo().getVerifier(); - SecretKey skey = generateSecretKey(password, ver); - try { - Cipher cipher = initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.DECRYPT_MODE); - byte encryptedVerifier[] = ver.getEncryptedVerifier(); - byte verifier[] = new byte[encryptedVerifier.length]; - cipher.update(encryptedVerifier, 0, encryptedVerifier.length, verifier); - setVerifier(verifier); - byte encryptedVerifierHash[] = ver.getEncryptedVerifierHash(); - byte verifierHash[] = cipher.doFinal(encryptedVerifierHash); - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); - byte calcVerifierHash[] = hashAlg.digest(verifier); - if (Arrays.equals(calcVerifierHash, verifierHash)) { - setSecretKey(skey); - return true; - } - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException(e); - } - return false; - } - - @Override - public Cipher initCipherForBlock(Cipher cipher, int block) - throws GeneralSecurityException { - EncryptionInfo ei = getEncryptionInfo(); - SecretKey sk = getSecretKey(); - return initCipherForBlock(cipher, block, ei, sk, Cipher.DECRYPT_MODE); - } - - protected static Cipher initCipherForBlock(Cipher cipher, int block, - EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode) - throws GeneralSecurityException { - EncryptionVerifier ver = encryptionInfo.getVerifier(); - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - byte blockKey[] = new byte[4]; - LittleEndian.putUInt(blockKey, 0, block); - MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); - hashAlg.update(skey.getEncoded()); - byte encKey[] = hashAlg.digest(blockKey); - EncryptionHeader header = encryptionInfo.getHeader(); - int keyBits = header.getKeySize(); - encKey = CryptoFunctions.getBlock0(encKey, keyBits / 8); - if (keyBits == 40) { - encKey = CryptoFunctions.getBlock0(encKey, 16); - } - SecretKey key = new SecretKeySpec(encKey, skey.getAlgorithm()); - if (cipher == null) { - cipher = CryptoFunctions.getCipher(key, header.getCipherAlgorithm(), null, null, encryptMode); - } else { - cipher.init(encryptMode, key); - } - return cipher; - } - - protected static SecretKey generateSecretKey(String password, EncryptionVerifier ver) { - if (password.length() > 255) { - password = password.substring(0, 255); - } - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); - hashAlg.update(ver.getSalt()); - byte hash[] = hashAlg.digest(StringUtil.getToUnicodeLE(password)); - SecretKey skey = new SecretKeySpec(hash, ver.getCipherAlgorithm().jceId); - return skey; - } - - @Override - public ChunkedCipherInputStream getDataStream(DirectoryNode dir) - throws IOException, GeneralSecurityException { - throw new IOException("not supported"); - } - - @Override - public ChunkedCipherInputStream getDataStream(InputStream stream, int size, int initialPos) - throws IOException, GeneralSecurityException { - return new CryptoAPICipherInputStream(stream, size, initialPos); - } - - /** - * Decrypt the Document-/SummaryInformation and other optionally streams. - * Opposed to other crypto modes, cryptoapi is record based and can't be used - * to stream-decrypt a whole file - * - * @see 2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream - */ - public POIFSFileSystem getSummaryEntries(DirectoryNode root, String encryptedStream) - throws IOException, GeneralSecurityException { - // HSLF: encryptedStream - // HSSF: encryption - DocumentNode es = (DocumentNode) root.getEntry(encryptedStream); - DocumentInputStream dis = root.createDocumentInputStream(es); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - IOUtils.copy(dis, bos); - dis.close(); - CryptoAPIDocumentInputStream sbis = new CryptoAPIDocumentInputStream(this, bos.toByteArray()); - LittleEndianInputStream leis = new LittleEndianInputStream(sbis); - POIFSFileSystem fsOut = null; - try { - int streamDescriptorArrayOffset = (int) leis.readUInt(); - /* int streamDescriptorArraySize = (int) */ leis.readUInt(); - long skipN = streamDescriptorArrayOffset - 8L; - if (sbis.skip(skipN) < skipN) { - throw new EOFException("buffer underrun"); - } - sbis.setBlock(0); - int encryptedStreamDescriptorCount = (int) leis.readUInt(); - StreamDescriptorEntry entries[] = new StreamDescriptorEntry[encryptedStreamDescriptorCount]; - for (int i = 0; i < encryptedStreamDescriptorCount; i++) { - StreamDescriptorEntry entry = new StreamDescriptorEntry(); - entries[i] = entry; - entry.streamOffset = (int) leis.readUInt(); - entry.streamSize = (int) leis.readUInt(); - entry.block = leis.readUShort(); - int nameSize = leis.readUByte(); - entry.flags = leis.readUByte(); - // boolean isStream = StreamDescriptorEntry.flagStream.isSet(entry.flags); - entry.reserved2 = leis.readInt(); - entry.streamName = StringUtil.readUnicodeLE(leis, nameSize); - leis.readShort(); - assert(entry.streamName.length() == nameSize); - } - - fsOut = new POIFSFileSystem(); // NOSONAR - for (StreamDescriptorEntry entry : entries) { - sbis.seek(entry.streamOffset); - sbis.setBlock(entry.block); - InputStream is = new BoundedInputStream(sbis, entry.streamSize); - fsOut.createDocument(is, entry.streamName); - is.close(); - } - } catch (Exception e) { - IOUtils.closeQuietly(fsOut); - if (e instanceof GeneralSecurityException) { - throw (GeneralSecurityException)e; - } else if (e instanceof IOException) { - throw (IOException)e; - } else { - throw new IOException("summary entries can't be read", e); - } - } finally { - IOUtils.closeQuietly(leis); - IOUtils.closeQuietly(sbis); - } - return fsOut; - } - - /** - * @return the length of the stream returned by {@link #getDataStream(DirectoryNode)} - */ - @Override - public long getLength() { - if (length == -1L) { - throw new IllegalStateException("Decryptor.getDataStream() was not called"); - } - return length; - } - - @Override - public void setChunkSize(int chunkSize) { - this.chunkSize = chunkSize; - } - - @Override - public CryptoAPIDecryptor clone() throws CloneNotSupportedException { - return (CryptoAPIDecryptor)super.clone(); - } - - private class CryptoAPICipherInputStream extends ChunkedCipherInputStream { - - @Override - protected Cipher initCipherForBlock(Cipher existing, int block) - throws GeneralSecurityException { - return CryptoAPIDecryptor.this.initCipherForBlock(existing, block); - } - - public CryptoAPICipherInputStream(InputStream stream, long size, int initialPos) - throws GeneralSecurityException { - super(stream, size, chunkSize, initialPos); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.cryptoapi; + +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.util.Arrays; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.ChunkedCipherInputStream; +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.crypt.EncryptionHeader; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionVerifier; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.DocumentNode; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.BitField; +import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.BoundedInputStream; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianInputStream; +import org.apache.poi.util.StringUtil; + +public class CryptoAPIDecryptor extends Decryptor implements Cloneable { + + private long length = -1L; + private int chunkSize = -1; + + static class StreamDescriptorEntry { + static BitField flagStream = BitFieldFactory.getInstance(1); + + int streamOffset; + int streamSize; + int block; + int flags; + int reserved2; + String streamName; + } + + protected CryptoAPIDecryptor() { + } + + @Override + public boolean verifyPassword(String password) { + EncryptionVerifier ver = getEncryptionInfo().getVerifier(); + SecretKey skey = generateSecretKey(password, ver); + try { + Cipher cipher = initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.DECRYPT_MODE); + byte encryptedVerifier[] = ver.getEncryptedVerifier(); + byte verifier[] = new byte[encryptedVerifier.length]; + cipher.update(encryptedVerifier, 0, encryptedVerifier.length, verifier); + setVerifier(verifier); + byte encryptedVerifierHash[] = ver.getEncryptedVerifierHash(); + byte verifierHash[] = cipher.doFinal(encryptedVerifierHash); + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); + byte calcVerifierHash[] = hashAlg.digest(verifier); + if (Arrays.equals(calcVerifierHash, verifierHash)) { + setSecretKey(skey); + return true; + } + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException(e); + } + return false; + } + + @Override + public Cipher initCipherForBlock(Cipher cipher, int block) + throws GeneralSecurityException { + EncryptionInfo ei = getEncryptionInfo(); + SecretKey sk = getSecretKey(); + return initCipherForBlock(cipher, block, ei, sk, Cipher.DECRYPT_MODE); + } + + protected static Cipher initCipherForBlock(Cipher cipher, int block, + EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode) + throws GeneralSecurityException { + EncryptionVerifier ver = encryptionInfo.getVerifier(); + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + byte blockKey[] = new byte[4]; + LittleEndian.putUInt(blockKey, 0, block); + MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); + hashAlg.update(skey.getEncoded()); + byte encKey[] = hashAlg.digest(blockKey); + EncryptionHeader header = encryptionInfo.getHeader(); + int keyBits = header.getKeySize(); + encKey = CryptoFunctions.getBlock0(encKey, keyBits / 8); + if (keyBits == 40) { + encKey = CryptoFunctions.getBlock0(encKey, 16); + } + SecretKey key = new SecretKeySpec(encKey, skey.getAlgorithm()); + if (cipher == null) { + cipher = CryptoFunctions.getCipher(key, header.getCipherAlgorithm(), null, null, encryptMode); + } else { + cipher.init(encryptMode, key); + } + return cipher; + } + + protected static SecretKey generateSecretKey(String password, EncryptionVerifier ver) { + if (password.length() > 255) { + password = password.substring(0, 255); + } + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); + hashAlg.update(ver.getSalt()); + byte hash[] = hashAlg.digest(StringUtil.getToUnicodeLE(password)); + SecretKey skey = new SecretKeySpec(hash, ver.getCipherAlgorithm().jceId); + return skey; + } + + @Override + public ChunkedCipherInputStream getDataStream(DirectoryNode dir) + throws IOException, GeneralSecurityException { + throw new IOException("not supported"); + } + + @Override + public ChunkedCipherInputStream getDataStream(InputStream stream, int size, int initialPos) + throws IOException, GeneralSecurityException { + return new CryptoAPICipherInputStream(stream, size, initialPos); + } + + /** + * Decrypt the Document-/SummaryInformation and other optionally streams. + * Opposed to other crypto modes, cryptoapi is record based and can't be used + * to stream-decrypt a whole file + * + * @see 2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream + */ + public POIFSFileSystem getSummaryEntries(DirectoryNode root, String encryptedStream) + throws IOException, GeneralSecurityException { + // HSLF: encryptedStream + // HSSF: encryption + DocumentNode es = (DocumentNode) root.getEntry(encryptedStream); + DocumentInputStream dis = root.createDocumentInputStream(es); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + IOUtils.copy(dis, bos); + dis.close(); + CryptoAPIDocumentInputStream sbis = new CryptoAPIDocumentInputStream(this, bos.toByteArray()); + LittleEndianInputStream leis = new LittleEndianInputStream(sbis); + POIFSFileSystem fsOut = null; + try { + int streamDescriptorArrayOffset = (int) leis.readUInt(); + /* int streamDescriptorArraySize = (int) */ leis.readUInt(); + long skipN = streamDescriptorArrayOffset - 8L; + if (sbis.skip(skipN) < skipN) { + throw new EOFException("buffer underrun"); + } + sbis.setBlock(0); + int encryptedStreamDescriptorCount = (int) leis.readUInt(); + StreamDescriptorEntry entries[] = new StreamDescriptorEntry[encryptedStreamDescriptorCount]; + for (int i = 0; i < encryptedStreamDescriptorCount; i++) { + StreamDescriptorEntry entry = new StreamDescriptorEntry(); + entries[i] = entry; + entry.streamOffset = (int) leis.readUInt(); + entry.streamSize = (int) leis.readUInt(); + entry.block = leis.readUShort(); + int nameSize = leis.readUByte(); + entry.flags = leis.readUByte(); + // boolean isStream = StreamDescriptorEntry.flagStream.isSet(entry.flags); + entry.reserved2 = leis.readInt(); + entry.streamName = StringUtil.readUnicodeLE(leis, nameSize); + leis.readShort(); + assert(entry.streamName.length() == nameSize); + } + + fsOut = new POIFSFileSystem(); // NOSONAR + for (StreamDescriptorEntry entry : entries) { + sbis.seek(entry.streamOffset); + sbis.setBlock(entry.block); + InputStream is = new BoundedInputStream(sbis, entry.streamSize); + fsOut.createDocument(is, entry.streamName); + is.close(); + } + } catch (Exception e) { + IOUtils.closeQuietly(fsOut); + if (e instanceof GeneralSecurityException) { + throw (GeneralSecurityException)e; + } else if (e instanceof IOException) { + throw (IOException)e; + } else { + throw new IOException("summary entries can't be read", e); + } + } finally { + IOUtils.closeQuietly(leis); + IOUtils.closeQuietly(sbis); + } + return fsOut; + } + + /** + * @return the length of the stream returned by {@link #getDataStream(DirectoryNode)} + */ + @Override + public long getLength() { + if (length == -1L) { + throw new IllegalStateException("Decryptor.getDataStream() was not called"); + } + return length; + } + + @Override + public void setChunkSize(int chunkSize) { + this.chunkSize = chunkSize; + } + + @Override + public CryptoAPIDecryptor clone() throws CloneNotSupportedException { + return (CryptoAPIDecryptor)super.clone(); + } + + private class CryptoAPICipherInputStream extends ChunkedCipherInputStream { + + @Override + protected Cipher initCipherForBlock(Cipher existing, int block) + throws GeneralSecurityException { + return CryptoAPIDecryptor.this.initCipherForBlock(existing, block); + } + + public CryptoAPICipherInputStream(InputStream stream, long size, int initialPos) + throws GeneralSecurityException { + super(stream, size, chunkSize, initialPos); + } + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java index b54dc2f0d5..2e838f7ddf 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java @@ -1,68 +1,68 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.cryptoapi; - -import java.io.IOException; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.ChainingMode; -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.CipherProvider; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.standard.StandardEncryptionHeader; -import org.apache.poi.util.LittleEndianInput; - -public class CryptoAPIEncryptionHeader extends StandardEncryptionHeader implements Cloneable { - - public CryptoAPIEncryptionHeader(LittleEndianInput is) throws IOException { - super(is); - } - - protected CryptoAPIEncryptionHeader(CipherAlgorithm cipherAlgorithm, - HashAlgorithm hashAlgorithm, int keyBits, int blockSize, - ChainingMode chainingMode) { - super(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode); - } - - @Override - public void setKeySize(int keyBits) { - // Microsoft Base Cryptographic Provider is limited up to 40 bits - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375599(v=vs.85).aspx - boolean found = false; - for (int size : getCipherAlgorithm().allowedKeySize) { - if (size == keyBits) { - found = true; - break; - } - } - if (!found) { - throw new EncryptedDocumentException("invalid keysize "+keyBits+" for cipher algorithm "+getCipherAlgorithm()); - } - super.setKeySize(keyBits); - if (keyBits > 40) { - setCspName("Microsoft Enhanced Cryptographic Provider v1.0"); - } else { - setCspName(CipherProvider.rc4.cipherProviderName); - } - } - - @Override - public CryptoAPIEncryptionHeader clone() throws CloneNotSupportedException { - return (CryptoAPIEncryptionHeader)super.clone(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.cryptoapi; + +import java.io.IOException; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.ChainingMode; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.CipherProvider; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.standard.StandardEncryptionHeader; +import org.apache.poi.util.LittleEndianInput; + +public class CryptoAPIEncryptionHeader extends StandardEncryptionHeader implements Cloneable { + + public CryptoAPIEncryptionHeader(LittleEndianInput is) throws IOException { + super(is); + } + + protected CryptoAPIEncryptionHeader(CipherAlgorithm cipherAlgorithm, + HashAlgorithm hashAlgorithm, int keyBits, int blockSize, + ChainingMode chainingMode) { + super(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode); + } + + @Override + public void setKeySize(int keyBits) { + // Microsoft Base Cryptographic Provider is limited up to 40 bits + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375599(v=vs.85).aspx + boolean found = false; + for (int size : getCipherAlgorithm().allowedKeySize) { + if (size == keyBits) { + found = true; + break; + } + } + if (!found) { + throw new EncryptedDocumentException("invalid keysize "+keyBits+" for cipher algorithm "+getCipherAlgorithm()); + } + super.setKeySize(keyBits); + if (keyBits > 40) { + setCspName("Microsoft Enhanced Cryptographic Provider v1.0"); + } else { + setCspName(CipherProvider.rc4.cipherProviderName); + } + } + + @Override + public CryptoAPIEncryptionHeader clone() throws CloneNotSupportedException { + return (CryptoAPIEncryptionHeader)super.clone(); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java index fef4dde168..c1484d691b 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java @@ -1,74 +1,74 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.cryptoapi; - -import java.io.IOException; - -import org.apache.poi.poifs.crypt.*; -import org.apache.poi.util.LittleEndianInput; - -public class CryptoAPIEncryptionInfoBuilder implements EncryptionInfoBuilder { - public CryptoAPIEncryptionInfoBuilder() { - } - - /** - * initialize the builder from a stream - */ - @Override - public void initialize(EncryptionInfo info, LittleEndianInput dis) - throws IOException { - /* int hSize = */ dis.readInt(); - CryptoAPIEncryptionHeader header = new CryptoAPIEncryptionHeader(dis); - info.setHeader(header); - info.setVerifier(new CryptoAPIEncryptionVerifier(dis, header)); - CryptoAPIDecryptor dec = new CryptoAPIDecryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - CryptoAPIEncryptor enc = new CryptoAPIEncryptor(); - enc.setEncryptionInfo(info); - info.setEncryptor(enc); - } - - /** - * initialize the builder from scratch - */ - @Override - public void initialize(EncryptionInfo info, - CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, - int keyBits, int blockSize, ChainingMode chainingMode) { - if (cipherAlgorithm == null) { - cipherAlgorithm = CipherAlgorithm.rc4; - } - if (hashAlgorithm == null) { - hashAlgorithm = HashAlgorithm.sha1; - } - if (keyBits == -1) { - keyBits = 0x28; - } - assert(cipherAlgorithm == CipherAlgorithm.rc4 && hashAlgorithm == HashAlgorithm.sha1); - - info.setHeader(new CryptoAPIEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); - info.setVerifier(new CryptoAPIEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); - CryptoAPIDecryptor dec = new CryptoAPIDecryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - CryptoAPIEncryptor enc = new CryptoAPIEncryptor(); - enc.setEncryptionInfo(info); - info.setEncryptor(enc); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.cryptoapi; + +import java.io.IOException; + +import org.apache.poi.poifs.crypt.*; +import org.apache.poi.util.LittleEndianInput; + +public class CryptoAPIEncryptionInfoBuilder implements EncryptionInfoBuilder { + public CryptoAPIEncryptionInfoBuilder() { + } + + /** + * initialize the builder from a stream + */ + @Override + public void initialize(EncryptionInfo info, LittleEndianInput dis) + throws IOException { + /* int hSize = */ dis.readInt(); + CryptoAPIEncryptionHeader header = new CryptoAPIEncryptionHeader(dis); + info.setHeader(header); + info.setVerifier(new CryptoAPIEncryptionVerifier(dis, header)); + CryptoAPIDecryptor dec = new CryptoAPIDecryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + CryptoAPIEncryptor enc = new CryptoAPIEncryptor(); + enc.setEncryptionInfo(info); + info.setEncryptor(enc); + } + + /** + * initialize the builder from scratch + */ + @Override + public void initialize(EncryptionInfo info, + CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, + int keyBits, int blockSize, ChainingMode chainingMode) { + if (cipherAlgorithm == null) { + cipherAlgorithm = CipherAlgorithm.rc4; + } + if (hashAlgorithm == null) { + hashAlgorithm = HashAlgorithm.sha1; + } + if (keyBits == -1) { + keyBits = 0x28; + } + assert(cipherAlgorithm == CipherAlgorithm.rc4 && hashAlgorithm == HashAlgorithm.sha1); + + info.setHeader(new CryptoAPIEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); + info.setVerifier(new CryptoAPIEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); + CryptoAPIDecryptor dec = new CryptoAPIDecryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + CryptoAPIEncryptor enc = new CryptoAPIEncryptor(); + enc.setEncryptionInfo(info); + info.setEncryptor(enc); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java index d2c87b7ab9..f5482c58e7 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java @@ -1,58 +1,58 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.cryptoapi; - -import org.apache.poi.poifs.crypt.ChainingMode; -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.standard.StandardEncryptionVerifier; -import org.apache.poi.util.LittleEndianInput; - -public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier implements Cloneable { - - protected CryptoAPIEncryptionVerifier(LittleEndianInput is, - CryptoAPIEncryptionHeader header) { - super(is, header); - } - - protected CryptoAPIEncryptionVerifier(CipherAlgorithm cipherAlgorithm, - HashAlgorithm hashAlgorithm, int keyBits, int blockSize, - ChainingMode chainingMode) { - super(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode); - } - - @Override - protected void setSalt(byte salt[]) { - super.setSalt(salt); - } - - @Override - protected void setEncryptedVerifier(byte encryptedVerifier[]) { - super.setEncryptedVerifier(encryptedVerifier); - } - - @Override - protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) { - super.setEncryptedVerifierHash(encryptedVerifierHash); - } - - @Override - public CryptoAPIEncryptionVerifier clone() throws CloneNotSupportedException { - return (CryptoAPIEncryptionVerifier)super.clone(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.cryptoapi; + +import org.apache.poi.poifs.crypt.ChainingMode; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.standard.StandardEncryptionVerifier; +import org.apache.poi.util.LittleEndianInput; + +public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier implements Cloneable { + + protected CryptoAPIEncryptionVerifier(LittleEndianInput is, + CryptoAPIEncryptionHeader header) { + super(is, header); + } + + protected CryptoAPIEncryptionVerifier(CipherAlgorithm cipherAlgorithm, + HashAlgorithm hashAlgorithm, int keyBits, int blockSize, + ChainingMode chainingMode) { + super(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode); + } + + @Override + protected void setSalt(byte salt[]) { + super.setSalt(salt); + } + + @Override + protected void setEncryptedVerifier(byte encryptedVerifier[]) { + super.setEncryptedVerifier(encryptedVerifier); + } + + @Override + protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) { + super.setEncryptedVerifierHash(encryptedVerifierHash); + } + + @Override + public CryptoAPIEncryptionVerifier clone() throws CloneNotSupportedException { + return (CryptoAPIEncryptionVerifier)super.clone(); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java index 5740380d0f..2a47922883 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java @@ -1,277 +1,277 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.cryptoapi; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.hpsf.DocumentSummaryInformation; -import org.apache.poi.hpsf.PropertySetFactory; -import org.apache.poi.hpsf.SummaryInformation; -import org.apache.poi.hpsf.WritingNotSupportedException; -import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.DataSpaceMapUtils; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.Encryptor; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor.StreamDescriptorEntry; -import org.apache.poi.poifs.crypt.standard.EncryptionRecord; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; -import org.apache.poi.util.StringUtil; - -public class CryptoAPIEncryptor extends Encryptor implements Cloneable { - - private int chunkSize = 512; - - protected CryptoAPIEncryptor() { - } - - @Override - public void confirmPassword(String password) { - Random r = new SecureRandom(); - byte salt[] = new byte[16]; - byte verifier[] = new byte[16]; - r.nextBytes(salt); - r.nextBytes(verifier); - confirmPassword(password, null, null, verifier, salt, null); - } - - @Override - public void confirmPassword(String password, byte keySpec[], - byte keySalt[], byte verifier[], byte verifierSalt[], - byte integritySalt[]) { - assert(verifier != null && verifierSalt != null); - CryptoAPIEncryptionVerifier ver = (CryptoAPIEncryptionVerifier)getEncryptionInfo().getVerifier(); - ver.setSalt(verifierSalt); - SecretKey skey = CryptoAPIDecryptor.generateSecretKey(password, ver); - setSecretKey(skey); - try { - Cipher cipher = initCipherForBlock(null, 0); - byte encryptedVerifier[] = new byte[verifier.length]; - cipher.update(verifier, 0, verifier.length, encryptedVerifier); - ver.setEncryptedVerifier(encryptedVerifier); - HashAlgorithm hashAlgo = ver.getHashAlgorithm(); - MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); - byte calcVerifierHash[] = hashAlg.digest(verifier); - byte encryptedVerifierHash[] = cipher.doFinal(calcVerifierHash); - ver.setEncryptedVerifierHash(encryptedVerifierHash); - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException("Password confirmation failed", e); - } - } - - /** - * Initializes a cipher object for a given block index for encryption - * - * @param cipher may be null, otherwise the given instance is reset to the new block index - * @param block the block index, e.g. the persist/slide id (hslf) - * @return a new cipher object, if cipher was null, otherwise the reinitialized cipher - * @throws GeneralSecurityException - */ - public Cipher initCipherForBlock(Cipher cipher, int block) - throws GeneralSecurityException { - return CryptoAPIDecryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); - } - - @Override - public ChunkedCipherOutputStream getDataStream(DirectoryNode dir) - throws IOException, GeneralSecurityException { - throw new IOException("not supported"); - } - - @Override - public CryptoAPICipherOutputStream getDataStream(OutputStream stream, int initialOffset) - throws IOException, GeneralSecurityException { - return new CryptoAPICipherOutputStream(stream); - } - - /** - * Encrypt the Document-/SummaryInformation and other optionally streams. - * Opposed to other crypto modes, cryptoapi is record based and can't be used - * to stream-encrypt a whole file - * - * @see 2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream - */ - public OutputStream getSummaryEntries(DirectoryNode dir) - throws IOException, GeneralSecurityException { - CryptoAPIDocumentOutputStream bos = new CryptoAPIDocumentOutputStream(this); // NOSONAR - byte buf[] = new byte[8]; - - bos.write(buf, 0, 8); // skip header - String entryNames[] = { - SummaryInformation.DEFAULT_STREAM_NAME, - DocumentSummaryInformation.DEFAULT_STREAM_NAME - }; - - List descList = new ArrayList(); - - int block = 0; - for (String entryName : entryNames) { - if (!dir.hasEntry(entryName)) { - continue; - } - StreamDescriptorEntry descEntry = new StreamDescriptorEntry(); - descEntry.block = block; - descEntry.streamOffset = bos.size(); - descEntry.streamName = entryName; - descEntry.flags = StreamDescriptorEntry.flagStream.setValue(0, 1); - descEntry.reserved2 = 0; - - bos.setBlock(block); - DocumentInputStream dis = dir.createDocumentInputStream(entryName); - IOUtils.copy(dis, bos); - dis.close(); - - descEntry.streamSize = bos.size() - descEntry.streamOffset; - descList.add(descEntry); - - dir.getEntry(entryName).delete(); - - block++; - } - - int streamDescriptorArrayOffset = bos.size(); - - bos.setBlock(0); - LittleEndian.putUInt(buf, 0, descList.size()); - bos.write(buf, 0, 4); - - for (StreamDescriptorEntry sde : descList) { - LittleEndian.putUInt(buf, 0, sde.streamOffset); - bos.write(buf, 0, 4); - LittleEndian.putUInt(buf, 0, sde.streamSize); - bos.write(buf, 0, 4); - LittleEndian.putUShort(buf, 0, sde.block); - bos.write(buf, 0, 2); - LittleEndian.putUByte(buf, 0, (short)sde.streamName.length()); - bos.write(buf, 0, 1); - LittleEndian.putUByte(buf, 0, (short)sde.flags); - bos.write(buf, 0, 1); - LittleEndian.putUInt(buf, 0, sde.reserved2); - bos.write(buf, 0, 4); - byte nameBytes[] = StringUtil.getToUnicodeLE(sde.streamName); - bos.write(nameBytes, 0, nameBytes.length); - LittleEndian.putShort(buf, 0, (short)0); // null-termination - bos.write(buf, 0, 2); - } - - int savedSize = bos.size(); - int streamDescriptorArraySize = savedSize - streamDescriptorArrayOffset; - LittleEndian.putUInt(buf, 0, streamDescriptorArrayOffset); - LittleEndian.putUInt(buf, 4, streamDescriptorArraySize); - - bos.reset(); - bos.setBlock(0); - bos.write(buf, 0, 8); - bos.setSize(savedSize); - - dir.createDocument("EncryptedSummary", new ByteArrayInputStream(bos.getBuf(), 0, savedSize)); - DocumentSummaryInformation dsi = PropertySetFactory.newDocumentSummaryInformation(); - - try { - dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME); - } catch (WritingNotSupportedException e) { - throw new IOException(e); - } - - return bos; - } - - protected int getKeySizeInBytes() { - return getEncryptionInfo().getHeader().getKeySize() / 8; - } - - @Override - public void setChunkSize(int chunkSize) { - this.chunkSize = chunkSize; - } - - protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException { - DataSpaceMapUtils.addDefaultDataSpace(dir); - final EncryptionInfo info = getEncryptionInfo(); - final CryptoAPIEncryptionHeader header = (CryptoAPIEncryptionHeader)getEncryptionInfo().getHeader(); - final CryptoAPIEncryptionVerifier verifier = (CryptoAPIEncryptionVerifier)getEncryptionInfo().getVerifier(); - EncryptionRecord er = new EncryptionRecord() { - @Override - public void write(LittleEndianByteArrayOutputStream bos) { - bos.writeShort(info.getVersionMajor()); - bos.writeShort(info.getVersionMinor()); - header.write(bos); - verifier.write(bos); - } - }; - DataSpaceMapUtils.createEncryptionEntry(dir, "EncryptionInfo", er); - } - - - @Override - public CryptoAPIEncryptor clone() throws CloneNotSupportedException { - return (CryptoAPIEncryptor)super.clone(); - } - - protected class CryptoAPICipherOutputStream extends ChunkedCipherOutputStream { - - @Override - protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk) - throws IOException, GeneralSecurityException { - flush(); - EncryptionInfo ei = getEncryptionInfo(); - SecretKey sk = getSecretKey(); - return CryptoAPIDecryptor.initCipherForBlock(cipher, block, ei, sk, Cipher.ENCRYPT_MODE); - } - - @Override - protected void calculateChecksum(File file, int i) { - } - - @Override - protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) - throws IOException, GeneralSecurityException { - throw new EncryptedDocumentException("createEncryptionInfoEntry not supported"); - } - - public CryptoAPICipherOutputStream(OutputStream stream) - throws IOException, GeneralSecurityException { - super(stream, CryptoAPIEncryptor.this.chunkSize); - } - - @Override - public void flush() throws IOException { - writeChunk(false); - super.flush(); - } - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.cryptoapi; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.hpsf.DocumentSummaryInformation; +import org.apache.poi.hpsf.PropertySetFactory; +import org.apache.poi.hpsf.SummaryInformation; +import org.apache.poi.hpsf.WritingNotSupportedException; +import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.DataSpaceMapUtils; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor.StreamDescriptorEntry; +import org.apache.poi.poifs.crypt.standard.EncryptionRecord; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; +import org.apache.poi.util.StringUtil; + +public class CryptoAPIEncryptor extends Encryptor implements Cloneable { + + private int chunkSize = 512; + + protected CryptoAPIEncryptor() { + } + + @Override + public void confirmPassword(String password) { + Random r = new SecureRandom(); + byte salt[] = new byte[16]; + byte verifier[] = new byte[16]; + r.nextBytes(salt); + r.nextBytes(verifier); + confirmPassword(password, null, null, verifier, salt, null); + } + + @Override + public void confirmPassword(String password, byte keySpec[], + byte keySalt[], byte verifier[], byte verifierSalt[], + byte integritySalt[]) { + assert(verifier != null && verifierSalt != null); + CryptoAPIEncryptionVerifier ver = (CryptoAPIEncryptionVerifier)getEncryptionInfo().getVerifier(); + ver.setSalt(verifierSalt); + SecretKey skey = CryptoAPIDecryptor.generateSecretKey(password, ver); + setSecretKey(skey); + try { + Cipher cipher = initCipherForBlock(null, 0); + byte encryptedVerifier[] = new byte[verifier.length]; + cipher.update(verifier, 0, verifier.length, encryptedVerifier); + ver.setEncryptedVerifier(encryptedVerifier); + HashAlgorithm hashAlgo = ver.getHashAlgorithm(); + MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); + byte calcVerifierHash[] = hashAlg.digest(verifier); + byte encryptedVerifierHash[] = cipher.doFinal(calcVerifierHash); + ver.setEncryptedVerifierHash(encryptedVerifierHash); + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException("Password confirmation failed", e); + } + } + + /** + * Initializes a cipher object for a given block index for encryption + * + * @param cipher may be null, otherwise the given instance is reset to the new block index + * @param block the block index, e.g. the persist/slide id (hslf) + * @return a new cipher object, if cipher was null, otherwise the reinitialized cipher + * @throws GeneralSecurityException + */ + public Cipher initCipherForBlock(Cipher cipher, int block) + throws GeneralSecurityException { + return CryptoAPIDecryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); + } + + @Override + public ChunkedCipherOutputStream getDataStream(DirectoryNode dir) + throws IOException, GeneralSecurityException { + throw new IOException("not supported"); + } + + @Override + public CryptoAPICipherOutputStream getDataStream(OutputStream stream, int initialOffset) + throws IOException, GeneralSecurityException { + return new CryptoAPICipherOutputStream(stream); + } + + /** + * Encrypt the Document-/SummaryInformation and other optionally streams. + * Opposed to other crypto modes, cryptoapi is record based and can't be used + * to stream-encrypt a whole file + * + * @see 2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream + */ + public OutputStream getSummaryEntries(DirectoryNode dir) + throws IOException, GeneralSecurityException { + CryptoAPIDocumentOutputStream bos = new CryptoAPIDocumentOutputStream(this); // NOSONAR + byte buf[] = new byte[8]; + + bos.write(buf, 0, 8); // skip header + String entryNames[] = { + SummaryInformation.DEFAULT_STREAM_NAME, + DocumentSummaryInformation.DEFAULT_STREAM_NAME + }; + + List descList = new ArrayList(); + + int block = 0; + for (String entryName : entryNames) { + if (!dir.hasEntry(entryName)) { + continue; + } + StreamDescriptorEntry descEntry = new StreamDescriptorEntry(); + descEntry.block = block; + descEntry.streamOffset = bos.size(); + descEntry.streamName = entryName; + descEntry.flags = StreamDescriptorEntry.flagStream.setValue(0, 1); + descEntry.reserved2 = 0; + + bos.setBlock(block); + DocumentInputStream dis = dir.createDocumentInputStream(entryName); + IOUtils.copy(dis, bos); + dis.close(); + + descEntry.streamSize = bos.size() - descEntry.streamOffset; + descList.add(descEntry); + + dir.getEntry(entryName).delete(); + + block++; + } + + int streamDescriptorArrayOffset = bos.size(); + + bos.setBlock(0); + LittleEndian.putUInt(buf, 0, descList.size()); + bos.write(buf, 0, 4); + + for (StreamDescriptorEntry sde : descList) { + LittleEndian.putUInt(buf, 0, sde.streamOffset); + bos.write(buf, 0, 4); + LittleEndian.putUInt(buf, 0, sde.streamSize); + bos.write(buf, 0, 4); + LittleEndian.putUShort(buf, 0, sde.block); + bos.write(buf, 0, 2); + LittleEndian.putUByte(buf, 0, (short)sde.streamName.length()); + bos.write(buf, 0, 1); + LittleEndian.putUByte(buf, 0, (short)sde.flags); + bos.write(buf, 0, 1); + LittleEndian.putUInt(buf, 0, sde.reserved2); + bos.write(buf, 0, 4); + byte nameBytes[] = StringUtil.getToUnicodeLE(sde.streamName); + bos.write(nameBytes, 0, nameBytes.length); + LittleEndian.putShort(buf, 0, (short)0); // null-termination + bos.write(buf, 0, 2); + } + + int savedSize = bos.size(); + int streamDescriptorArraySize = savedSize - streamDescriptorArrayOffset; + LittleEndian.putUInt(buf, 0, streamDescriptorArrayOffset); + LittleEndian.putUInt(buf, 4, streamDescriptorArraySize); + + bos.reset(); + bos.setBlock(0); + bos.write(buf, 0, 8); + bos.setSize(savedSize); + + dir.createDocument("EncryptedSummary", new ByteArrayInputStream(bos.getBuf(), 0, savedSize)); + DocumentSummaryInformation dsi = PropertySetFactory.newDocumentSummaryInformation(); + + try { + dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME); + } catch (WritingNotSupportedException e) { + throw new IOException(e); + } + + return bos; + } + + protected int getKeySizeInBytes() { + return getEncryptionInfo().getHeader().getKeySize() / 8; + } + + @Override + public void setChunkSize(int chunkSize) { + this.chunkSize = chunkSize; + } + + protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException { + DataSpaceMapUtils.addDefaultDataSpace(dir); + final EncryptionInfo info = getEncryptionInfo(); + final CryptoAPIEncryptionHeader header = (CryptoAPIEncryptionHeader)getEncryptionInfo().getHeader(); + final CryptoAPIEncryptionVerifier verifier = (CryptoAPIEncryptionVerifier)getEncryptionInfo().getVerifier(); + EncryptionRecord er = new EncryptionRecord() { + @Override + public void write(LittleEndianByteArrayOutputStream bos) { + bos.writeShort(info.getVersionMajor()); + bos.writeShort(info.getVersionMinor()); + header.write(bos); + verifier.write(bos); + } + }; + DataSpaceMapUtils.createEncryptionEntry(dir, "EncryptionInfo", er); + } + + + @Override + public CryptoAPIEncryptor clone() throws CloneNotSupportedException { + return (CryptoAPIEncryptor)super.clone(); + } + + protected class CryptoAPICipherOutputStream extends ChunkedCipherOutputStream { + + @Override + protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk) + throws IOException, GeneralSecurityException { + flush(); + EncryptionInfo ei = getEncryptionInfo(); + SecretKey sk = getSecretKey(); + return CryptoAPIDecryptor.initCipherForBlock(cipher, block, ei, sk, Cipher.ENCRYPT_MODE); + } + + @Override + protected void calculateChecksum(File file, int i) { + } + + @Override + protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) + throws IOException, GeneralSecurityException { + throw new EncryptedDocumentException("createEncryptionInfoEntry not supported"); + } + + public CryptoAPICipherOutputStream(OutputStream stream) + throws IOException, GeneralSecurityException { + super(stream, CryptoAPIEncryptor.this.chunkSize); + } + + @Override + public void flush() throws IOException { + writeChunk(false); + super.flush(); + } + } + +} diff --git a/src/java/org/apache/poi/poifs/crypt/standard/EncryptionRecord.java b/src/java/org/apache/poi/poifs/crypt/standard/EncryptionRecord.java index bf65fbe796..3b45190497 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/EncryptionRecord.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/EncryptionRecord.java @@ -1,23 +1,23 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt.standard; - -import org.apache.poi.util.LittleEndianByteArrayOutputStream; - -public interface EncryptionRecord { - void write(LittleEndianByteArrayOutputStream os); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt.standard; + +import org.apache.poi.util.LittleEndianByteArrayOutputStream; + +public interface EncryptionRecord { + void write(LittleEndianByteArrayOutputStream os); +} diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java index a04f74d400..2c42c60f8e 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java @@ -1,130 +1,130 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt.standard; - -import static org.apache.poi.poifs.crypt.EncryptionInfo.flagAES; -import static org.apache.poi.poifs.crypt.EncryptionInfo.flagCryptoAPI; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.poifs.crypt.ChainingMode; -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.CipherProvider; -import org.apache.poi.poifs.crypt.EncryptionHeader; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInput; -import org.apache.poi.util.LittleEndianOutput; -import org.apache.poi.util.StringUtil; - -public class StandardEncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable { - - protected StandardEncryptionHeader(LittleEndianInput is) throws IOException { - setFlags(is.readInt()); - setSizeExtra(is.readInt()); - setCipherAlgorithm(CipherAlgorithm.fromEcmaId(is.readInt())); - setHashAlgorithm(HashAlgorithm.fromEcmaId(is.readInt())); - int keySize = is.readInt(); - if (keySize == 0) { - // for the sake of inheritance of the cryptoAPI classes - // see 2.3.5.1 RC4 CryptoAPI Encryption Header - // If set to 0x00000000, it MUST be interpreted as 0x00000028 bits. - keySize = 0x28; - } - setKeySize(keySize); - setBlockSize(getKeySize()); - setCipherProvider(CipherProvider.fromEcmaId(is.readInt())); - - is.readLong(); // skip reserved - - // CSPName may not always be specified - // In some cases, the salt value of the EncryptionVerifier is the next chunk of data - if (is instanceof RecordInputStream) { - ((RecordInputStream)is).mark(LittleEndianConsts.INT_SIZE+1); - } else { - ((InputStream)is).mark(LittleEndianConsts.INT_SIZE+1); - } - int checkForSalt = is.readInt(); - if (is instanceof RecordInputStream) { - ((RecordInputStream)is).reset(); - } else { - ((InputStream)is).reset(); - } - - if (checkForSalt == 16) { - setCspName(""); - } else { - StringBuilder builder = new StringBuilder(); - while (true) { - char c = (char) is.readShort(); - if (c == 0) { - break; - } - builder.append(c); - } - setCspName(builder.toString()); - } - - setChainingMode(ChainingMode.ecb); - setKeySalt(null); - } - - protected StandardEncryptionHeader(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { - setCipherAlgorithm(cipherAlgorithm); - setHashAlgorithm(hashAlgorithm); - setKeySize(keyBits); - setBlockSize(blockSize); - setCipherProvider(cipherAlgorithm.provider); - setFlags(flagCryptoAPI.setBoolean(0, true) - | flagAES.setBoolean(0, cipherAlgorithm.provider == CipherProvider.aes)); - // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb931357(v=vs.85).aspx for a full list - // setCspName("Microsoft Enhanced RSA and AES Cryptographic Provider"); - } - - /** - * serializes the header - */ - @Override - public void write(LittleEndianByteArrayOutputStream bos) { - int startIdx = bos.getWriteIndex(); - LittleEndianOutput sizeOutput = bos.createDelayedOutput(LittleEndianConsts.INT_SIZE); - bos.writeInt(getFlags()); - bos.writeInt(0); // size extra - bos.writeInt(getCipherAlgorithm().ecmaId); - bos.writeInt(getHashAlgorithm().ecmaId); - bos.writeInt(getKeySize()); - bos.writeInt(getCipherProvider().ecmaId); - bos.writeInt(0); // reserved1 - bos.writeInt(0); // reserved2 - String cspName = getCspName(); - if (cspName == null) { - cspName = getCipherProvider().cipherProviderName; - } - bos.write(StringUtil.getToUnicodeLE(cspName)); - bos.writeShort(0); - int headerSize = bos.getWriteIndex()-startIdx-LittleEndianConsts.INT_SIZE; - sizeOutput.writeInt(headerSize); - } - - @Override - public StandardEncryptionHeader clone() throws CloneNotSupportedException { - return (StandardEncryptionHeader)super.clone(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt.standard; + +import static org.apache.poi.poifs.crypt.EncryptionInfo.flagAES; +import static org.apache.poi.poifs.crypt.EncryptionInfo.flagCryptoAPI; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.poifs.crypt.ChainingMode; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.CipherProvider; +import org.apache.poi.poifs.crypt.EncryptionHeader; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.StringUtil; + +public class StandardEncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable { + + protected StandardEncryptionHeader(LittleEndianInput is) throws IOException { + setFlags(is.readInt()); + setSizeExtra(is.readInt()); + setCipherAlgorithm(CipherAlgorithm.fromEcmaId(is.readInt())); + setHashAlgorithm(HashAlgorithm.fromEcmaId(is.readInt())); + int keySize = is.readInt(); + if (keySize == 0) { + // for the sake of inheritance of the cryptoAPI classes + // see 2.3.5.1 RC4 CryptoAPI Encryption Header + // If set to 0x00000000, it MUST be interpreted as 0x00000028 bits. + keySize = 0x28; + } + setKeySize(keySize); + setBlockSize(getKeySize()); + setCipherProvider(CipherProvider.fromEcmaId(is.readInt())); + + is.readLong(); // skip reserved + + // CSPName may not always be specified + // In some cases, the salt value of the EncryptionVerifier is the next chunk of data + if (is instanceof RecordInputStream) { + ((RecordInputStream)is).mark(LittleEndianConsts.INT_SIZE+1); + } else { + ((InputStream)is).mark(LittleEndianConsts.INT_SIZE+1); + } + int checkForSalt = is.readInt(); + if (is instanceof RecordInputStream) { + ((RecordInputStream)is).reset(); + } else { + ((InputStream)is).reset(); + } + + if (checkForSalt == 16) { + setCspName(""); + } else { + StringBuilder builder = new StringBuilder(); + while (true) { + char c = (char) is.readShort(); + if (c == 0) { + break; + } + builder.append(c); + } + setCspName(builder.toString()); + } + + setChainingMode(ChainingMode.ecb); + setKeySalt(null); + } + + protected StandardEncryptionHeader(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { + setCipherAlgorithm(cipherAlgorithm); + setHashAlgorithm(hashAlgorithm); + setKeySize(keyBits); + setBlockSize(blockSize); + setCipherProvider(cipherAlgorithm.provider); + setFlags(flagCryptoAPI.setBoolean(0, true) + | flagAES.setBoolean(0, cipherAlgorithm.provider == CipherProvider.aes)); + // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb931357(v=vs.85).aspx for a full list + // setCspName("Microsoft Enhanced RSA and AES Cryptographic Provider"); + } + + /** + * serializes the header + */ + @Override + public void write(LittleEndianByteArrayOutputStream bos) { + int startIdx = bos.getWriteIndex(); + LittleEndianOutput sizeOutput = bos.createDelayedOutput(LittleEndianConsts.INT_SIZE); + bos.writeInt(getFlags()); + bos.writeInt(0); // size extra + bos.writeInt(getCipherAlgorithm().ecmaId); + bos.writeInt(getHashAlgorithm().ecmaId); + bos.writeInt(getKeySize()); + bos.writeInt(getCipherProvider().ecmaId); + bos.writeInt(0); // reserved1 + bos.writeInt(0); // reserved2 + String cspName = getCspName(); + if (cspName == null) { + cspName = getCipherProvider().cipherProviderName; + } + bos.write(StringUtil.getToUnicodeLE(cspName)); + bos.writeShort(0); + int headerSize = bos.getWriteIndex()-startIdx-LittleEndianConsts.INT_SIZE; + sizeOutput.writeInt(headerSize); + } + + @Override + public StandardEncryptionHeader clone() throws CloneNotSupportedException { + return (StandardEncryptionHeader)super.clone(); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java index c2bffdd05a..771a6895be 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java @@ -1,96 +1,96 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt.standard; - -import java.io.IOException; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.ChainingMode; -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.EncryptionInfoBuilder; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.util.LittleEndianInput; - -public class StandardEncryptionInfoBuilder implements EncryptionInfoBuilder { - - /** - * initialize the builder from a stream - */ - @Override - public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException { - /* int hSize = */ dis.readInt(); - StandardEncryptionHeader header = new StandardEncryptionHeader(dis); - info.setHeader(header); - info.setVerifier(new StandardEncryptionVerifier(dis, header)); - - if (info.getVersionMinor() == 2 && (info.getVersionMajor() == 3 || info.getVersionMajor() == 4)) { - StandardDecryptor dec = new StandardDecryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - } - } - - /** - * initialize the builder from scratch - */ - @Override - public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { - if (cipherAlgorithm == null) { - cipherAlgorithm = CipherAlgorithm.aes128; - } - if (cipherAlgorithm != CipherAlgorithm.aes128 && - cipherAlgorithm != CipherAlgorithm.aes192 && - cipherAlgorithm != CipherAlgorithm.aes256) { - throw new EncryptedDocumentException("Standard encryption only supports AES128/192/256."); - } - - if (hashAlgorithm == null) { - hashAlgorithm = HashAlgorithm.sha1; - } - if (hashAlgorithm != HashAlgorithm.sha1) { - throw new EncryptedDocumentException("Standard encryption only supports SHA-1."); - } - if (chainingMode == null) { - chainingMode = ChainingMode.ecb; - } - if (chainingMode != ChainingMode.ecb) { - throw new EncryptedDocumentException("Standard encryption only supports ECB chaining."); - } - if (keyBits == -1) { - keyBits = cipherAlgorithm.defaultKeySize; - } - if (blockSize == -1) { - blockSize = cipherAlgorithm.blockSize; - } - boolean found = false; - for (int ks : cipherAlgorithm.allowedKeySize) { - found |= (ks == keyBits); - } - if (!found) { - throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+cipherAlgorithm.toString()); - } - info.setHeader(new StandardEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); - info.setVerifier(new StandardEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); - StandardDecryptor dec = new StandardDecryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - StandardEncryptor enc = new StandardEncryptor(); - enc.setEncryptionInfo(info); - info.setEncryptor(enc); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt.standard; + +import java.io.IOException; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.ChainingMode; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionInfoBuilder; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.util.LittleEndianInput; + +public class StandardEncryptionInfoBuilder implements EncryptionInfoBuilder { + + /** + * initialize the builder from a stream + */ + @Override + public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException { + /* int hSize = */ dis.readInt(); + StandardEncryptionHeader header = new StandardEncryptionHeader(dis); + info.setHeader(header); + info.setVerifier(new StandardEncryptionVerifier(dis, header)); + + if (info.getVersionMinor() == 2 && (info.getVersionMajor() == 3 || info.getVersionMajor() == 4)) { + StandardDecryptor dec = new StandardDecryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + } + } + + /** + * initialize the builder from scratch + */ + @Override + public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { + if (cipherAlgorithm == null) { + cipherAlgorithm = CipherAlgorithm.aes128; + } + if (cipherAlgorithm != CipherAlgorithm.aes128 && + cipherAlgorithm != CipherAlgorithm.aes192 && + cipherAlgorithm != CipherAlgorithm.aes256) { + throw new EncryptedDocumentException("Standard encryption only supports AES128/192/256."); + } + + if (hashAlgorithm == null) { + hashAlgorithm = HashAlgorithm.sha1; + } + if (hashAlgorithm != HashAlgorithm.sha1) { + throw new EncryptedDocumentException("Standard encryption only supports SHA-1."); + } + if (chainingMode == null) { + chainingMode = ChainingMode.ecb; + } + if (chainingMode != ChainingMode.ecb) { + throw new EncryptedDocumentException("Standard encryption only supports ECB chaining."); + } + if (keyBits == -1) { + keyBits = cipherAlgorithm.defaultKeySize; + } + if (blockSize == -1) { + blockSize = cipherAlgorithm.blockSize; + } + boolean found = false; + for (int ks : cipherAlgorithm.allowedKeySize) { + found |= (ks == keyBits); + } + if (!found) { + throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+cipherAlgorithm.toString()); + } + info.setHeader(new StandardEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); + info.setVerifier(new StandardEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); + StandardDecryptor dec = new StandardDecryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + StandardEncryptor enc = new StandardEncryptor(); + enc.setEncryptionInfo(info); + info.setEncryptor(enc); + } +} diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java index 2fcd912a95..274a778cca 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java @@ -1,235 +1,235 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.standard; - -import static org.apache.poi.poifs.crypt.DataSpaceMapUtils.createEncryptionEntry; -import static org.apache.poi.poifs.crypt.standard.StandardDecryptor.generateSecretKey; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.CipherOutputStream; -import javax.crypto.SecretKey; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.DataSpaceMapUtils; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.EncryptionVerifier; -import org.apache.poi.poifs.crypt.Encryptor; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.POIFSWriterEvent; -import org.apache.poi.poifs.filesystem.POIFSWriterListener; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianOutputStream; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.TempFile; - -public class StandardEncryptor extends Encryptor implements Cloneable { - private static final POILogger logger = POILogFactory.getLogger(StandardEncryptor.class); - - protected StandardEncryptor() { - } - - @Override - public void confirmPassword(String password) { - // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier - Random r = new SecureRandom(); - byte[] salt = new byte[16], verifier = new byte[16]; - r.nextBytes(salt); - r.nextBytes(verifier); - - confirmPassword(password, null, null, salt, verifier, null); - } - - - /** - * Fills the fields of verifier and header with the calculated hashes based - * on the password and a random salt - * - * see [MS-OFFCRYPTO] - 2.3.4.7 ECMA-376 Document Encryption Key Generation - */ - @Override - public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) { - StandardEncryptionVerifier ver = (StandardEncryptionVerifier)getEncryptionInfo().getVerifier(); - - ver.setSalt(verifierSalt); - SecretKey secretKey = generateSecretKey(password, ver, getKeySizeInBytes()); - setSecretKey(secretKey); - Cipher cipher = getCipher(secretKey, null); - - try { - byte encryptedVerifier[] = cipher.doFinal(verifier); - MessageDigest hashAlgo = CryptoFunctions.getMessageDigest(ver.getHashAlgorithm()); - byte calcVerifierHash[] = hashAlgo.digest(verifier); - - // 2.3.3 EncryptionVerifier ... - // An array of bytes that contains the encrypted form of the - // hash of the randomly generated Verifier value. The length of the array MUST be the size of - // the encryption block size multiplied by the number of blocks needed to encrypt the hash of the - // Verifier. If the encryption algorithm is RC4, the length MUST be 20 bytes. If the encryption - // algorithm is AES, the length MUST be 32 bytes. After decrypting the EncryptedVerifierHash - // field, only the first VerifierHashSize bytes MUST be used. - int encVerHashSize = ver.getCipherAlgorithm().encryptedVerifierHashLength; - byte encryptedVerifierHash[] = cipher.doFinal(Arrays.copyOf(calcVerifierHash, encVerHashSize)); - - ver.setEncryptedVerifier(encryptedVerifier); - ver.setEncryptedVerifierHash(encryptedVerifierHash); - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException("Password confirmation failed", e); - } - - } - - private Cipher getCipher(SecretKey key, String padding) { - EncryptionVerifier ver = getEncryptionInfo().getVerifier(); - return CryptoFunctions.getCipher(key, ver.getCipherAlgorithm(), ver.getChainingMode(), null, Cipher.ENCRYPT_MODE, padding); - } - - @Override - public OutputStream getDataStream(final DirectoryNode dir) - throws IOException, GeneralSecurityException { - createEncryptionInfoEntry(dir); - DataSpaceMapUtils.addDefaultDataSpace(dir); - return new StandardCipherOutputStream(dir); - } - - protected class StandardCipherOutputStream extends FilterOutputStream implements POIFSWriterListener { - protected long countBytes; - protected final File fileOut; - protected final DirectoryNode dir; - - @SuppressWarnings("resource") - private StandardCipherOutputStream(DirectoryNode dir, File fileOut) throws IOException { - // although not documented, we need the same padding as with agile encryption - // and instead of calculating the missing bytes for the block size ourselves - // we leave it up to the CipherOutputStream, which generates/saves them on close() - // ... we can't use "NoPadding" here - // - // see also [MS-OFFCRYPT] - 2.3.4.15 - // The final data block MUST be padded to the next integral multiple of the - // KeyData.blockSize value. Any padding bytes can be used. Note that the StreamSize - // field of the EncryptedPackage field specifies the number of bytes of - // unencrypted data as specified in section 2.3.4.4. - super( - new CipherOutputStream(new FileOutputStream(fileOut), getCipher(getSecretKey(), "PKCS5Padding")) - ); - this.fileOut = fileOut; - this.dir = dir; - } - - protected StandardCipherOutputStream(DirectoryNode dir) throws IOException { - this(dir, TempFile.createTempFile("encrypted_package", "crypt")); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - out.write(b, off, len); - countBytes += len; - } - - @Override - public void write(int b) throws IOException { - out.write(b); - countBytes++; - } - - @Override - public void close() throws IOException { - // the CipherOutputStream adds the padding bytes on close() - super.close(); - writeToPOIFS(); - } - - void writeToPOIFS() throws IOException { - int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE); - dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, this); - // TODO: any properties??? - } - - @Override - public void processPOIFSWriterEvent(POIFSWriterEvent event) { - try { - LittleEndianOutputStream leos = new LittleEndianOutputStream(event.getStream()); - - // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data - // encrypted within the EncryptedData field, not including the size of the StreamSize field. - // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this - // value, depending on the block size of the chosen encryption algorithm - leos.writeLong(countBytes); - - FileInputStream fis = new FileInputStream(fileOut); - try { - IOUtils.copy(fis, leos); - } finally { - fis.close(); - } - if (!fileOut.delete()) { - logger.log(POILogger.ERROR, "Can't delete temporary encryption file: "+fileOut); - } - - leos.close(); - } catch (IOException e) { - throw new EncryptedDocumentException(e); - } - } - } - - protected int getKeySizeInBytes() { - return getEncryptionInfo().getHeader().getKeySize()/8; - } - - protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException { - final EncryptionInfo info = getEncryptionInfo(); - final StandardEncryptionHeader header = (StandardEncryptionHeader)info.getHeader(); - final StandardEncryptionVerifier verifier = (StandardEncryptionVerifier)info.getVerifier(); - - EncryptionRecord er = new EncryptionRecord(){ - @Override - public void write(LittleEndianByteArrayOutputStream bos) { - bos.writeShort(info.getVersionMajor()); - bos.writeShort(info.getVersionMinor()); - bos.writeInt(info.getEncryptionFlags()); - header.write(bos); - verifier.write(bos); - } - }; - - createEncryptionEntry(dir, "EncryptionInfo", er); - - // TODO: any properties??? - } - - @Override - public StandardEncryptor clone() throws CloneNotSupportedException { - return (StandardEncryptor)super.clone(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.standard; + +import static org.apache.poi.poifs.crypt.DataSpaceMapUtils.createEncryptionEntry; +import static org.apache.poi.poifs.crypt.standard.StandardDecryptor.generateSecretKey; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.Random; + +import javax.crypto.Cipher; +import javax.crypto.CipherOutputStream; +import javax.crypto.SecretKey; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.DataSpaceMapUtils; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionVerifier; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.POIFSWriterEvent; +import org.apache.poi.poifs.filesystem.POIFSWriterListener; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianOutputStream; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.TempFile; + +public class StandardEncryptor extends Encryptor implements Cloneable { + private static final POILogger logger = POILogFactory.getLogger(StandardEncryptor.class); + + protected StandardEncryptor() { + } + + @Override + public void confirmPassword(String password) { + // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier + Random r = new SecureRandom(); + byte[] salt = new byte[16], verifier = new byte[16]; + r.nextBytes(salt); + r.nextBytes(verifier); + + confirmPassword(password, null, null, salt, verifier, null); + } + + + /** + * Fills the fields of verifier and header with the calculated hashes based + * on the password and a random salt + * + * see [MS-OFFCRYPTO] - 2.3.4.7 ECMA-376 Document Encryption Key Generation + */ + @Override + public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) { + StandardEncryptionVerifier ver = (StandardEncryptionVerifier)getEncryptionInfo().getVerifier(); + + ver.setSalt(verifierSalt); + SecretKey secretKey = generateSecretKey(password, ver, getKeySizeInBytes()); + setSecretKey(secretKey); + Cipher cipher = getCipher(secretKey, null); + + try { + byte encryptedVerifier[] = cipher.doFinal(verifier); + MessageDigest hashAlgo = CryptoFunctions.getMessageDigest(ver.getHashAlgorithm()); + byte calcVerifierHash[] = hashAlgo.digest(verifier); + + // 2.3.3 EncryptionVerifier ... + // An array of bytes that contains the encrypted form of the + // hash of the randomly generated Verifier value. The length of the array MUST be the size of + // the encryption block size multiplied by the number of blocks needed to encrypt the hash of the + // Verifier. If the encryption algorithm is RC4, the length MUST be 20 bytes. If the encryption + // algorithm is AES, the length MUST be 32 bytes. After decrypting the EncryptedVerifierHash + // field, only the first VerifierHashSize bytes MUST be used. + int encVerHashSize = ver.getCipherAlgorithm().encryptedVerifierHashLength; + byte encryptedVerifierHash[] = cipher.doFinal(Arrays.copyOf(calcVerifierHash, encVerHashSize)); + + ver.setEncryptedVerifier(encryptedVerifier); + ver.setEncryptedVerifierHash(encryptedVerifierHash); + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException("Password confirmation failed", e); + } + + } + + private Cipher getCipher(SecretKey key, String padding) { + EncryptionVerifier ver = getEncryptionInfo().getVerifier(); + return CryptoFunctions.getCipher(key, ver.getCipherAlgorithm(), ver.getChainingMode(), null, Cipher.ENCRYPT_MODE, padding); + } + + @Override + public OutputStream getDataStream(final DirectoryNode dir) + throws IOException, GeneralSecurityException { + createEncryptionInfoEntry(dir); + DataSpaceMapUtils.addDefaultDataSpace(dir); + return new StandardCipherOutputStream(dir); + } + + protected class StandardCipherOutputStream extends FilterOutputStream implements POIFSWriterListener { + protected long countBytes; + protected final File fileOut; + protected final DirectoryNode dir; + + @SuppressWarnings("resource") + private StandardCipherOutputStream(DirectoryNode dir, File fileOut) throws IOException { + // although not documented, we need the same padding as with agile encryption + // and instead of calculating the missing bytes for the block size ourselves + // we leave it up to the CipherOutputStream, which generates/saves them on close() + // ... we can't use "NoPadding" here + // + // see also [MS-OFFCRYPT] - 2.3.4.15 + // The final data block MUST be padded to the next integral multiple of the + // KeyData.blockSize value. Any padding bytes can be used. Note that the StreamSize + // field of the EncryptedPackage field specifies the number of bytes of + // unencrypted data as specified in section 2.3.4.4. + super( + new CipherOutputStream(new FileOutputStream(fileOut), getCipher(getSecretKey(), "PKCS5Padding")) + ); + this.fileOut = fileOut; + this.dir = dir; + } + + protected StandardCipherOutputStream(DirectoryNode dir) throws IOException { + this(dir, TempFile.createTempFile("encrypted_package", "crypt")); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + countBytes += len; + } + + @Override + public void write(int b) throws IOException { + out.write(b); + countBytes++; + } + + @Override + public void close() throws IOException { + // the CipherOutputStream adds the padding bytes on close() + super.close(); + writeToPOIFS(); + } + + void writeToPOIFS() throws IOException { + int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE); + dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, this); + // TODO: any properties??? + } + + @Override + public void processPOIFSWriterEvent(POIFSWriterEvent event) { + try { + LittleEndianOutputStream leos = new LittleEndianOutputStream(event.getStream()); + + // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data + // encrypted within the EncryptedData field, not including the size of the StreamSize field. + // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this + // value, depending on the block size of the chosen encryption algorithm + leos.writeLong(countBytes); + + FileInputStream fis = new FileInputStream(fileOut); + try { + IOUtils.copy(fis, leos); + } finally { + fis.close(); + } + if (!fileOut.delete()) { + logger.log(POILogger.ERROR, "Can't delete temporary encryption file: "+fileOut); + } + + leos.close(); + } catch (IOException e) { + throw new EncryptedDocumentException(e); + } + } + } + + protected int getKeySizeInBytes() { + return getEncryptionInfo().getHeader().getKeySize()/8; + } + + protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException { + final EncryptionInfo info = getEncryptionInfo(); + final StandardEncryptionHeader header = (StandardEncryptionHeader)info.getHeader(); + final StandardEncryptionVerifier verifier = (StandardEncryptionVerifier)info.getVerifier(); + + EncryptionRecord er = new EncryptionRecord(){ + @Override + public void write(LittleEndianByteArrayOutputStream bos) { + bos.writeShort(info.getVersionMajor()); + bos.writeShort(info.getVersionMinor()); + bos.writeInt(info.getEncryptionFlags()); + header.write(bos); + verifier.write(bos); + } + }; + + createEncryptionEntry(dir, "EncryptionInfo", er); + + // TODO: any properties??? + } + + @Override + public StandardEncryptor clone() throws CloneNotSupportedException { + return (StandardEncryptor)super.clone(); + } +} diff --git a/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java b/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java index d11841dd59..7ccdf5ed2f 100644 --- a/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java +++ b/src/java/org/apache/poi/poifs/filesystem/Ole10Native.java @@ -1,401 +1,401 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.filesystem; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianOutputStream; -import org.apache.poi.util.StringUtil; - -/** - * Represents an Ole10Native record which is wrapped around certain binary - * files being embedded in OLE2 documents. - * - * @author Rainer Schwarze - */ -public class Ole10Native { - - public static final String OLE10_NATIVE = "\u0001Ole10Native"; - protected static final String ISO1 = "ISO-8859-1"; - - // (the fields as they appear in the raw record:) - private int totalSize; // 4 bytes, total size of record not including this field - private short flags1 = 2; // 2 bytes, unknown, mostly [02 00] - private String label; // ASCIIZ, stored in this field without the terminating zero - private String fileName; // ASCIIZ, stored in this field without the terminating zero - private short flags2 = 0; // 2 bytes, unknown, mostly [00 00] - private short unknown1 = 3; // see below - private String command; // ASCIIZ, stored in this field without the terminating zero - private byte[] dataBuffer; // varying size, the actual native data - private short flags3 = 0; // some final flags? or zero terminators?, sometimes not there - - /** - * the field encoding mode - merely a try-and-error guess ... - **/ - private enum EncodingMode { - /** - * the data is stored in parsed format - including label, command, etc. - */ - parsed, - /** - * the data is stored raw after the length field - */ - unparsed, - /** - * the data is stored raw after the length field and the flags1 field - */ - compact - } - - private EncodingMode mode; - - - - /** - * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected - * to include a stream "{01}Ole10Native" which contains the actual - * data relevant for this class. - * - * @param poifs POI Filesystem object - * @return Returns an instance of this class - * @throws IOException on IO error - * @throws Ole10NativeException on invalid or unexcepted data format - */ - public static Ole10Native createFromEmbeddedOleObject(POIFSFileSystem poifs) throws IOException, Ole10NativeException { - return createFromEmbeddedOleObject(poifs.getRoot()); - } - - /** - * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected - * to include a stream "{01}Ole10Native" which contains the actual - * data relevant for this class. - * - * @param directory POI Filesystem object - * @return Returns an instance of this class - * @throws IOException on IO error - * @throws Ole10NativeException on invalid or unexcepted data format - */ - public static Ole10Native createFromEmbeddedOleObject(DirectoryNode directory) throws IOException, Ole10NativeException { - DocumentEntry nativeEntry = - (DocumentEntry)directory.getEntry(OLE10_NATIVE); - byte[] data = new byte[nativeEntry.getSize()]; - int readBytes = directory.createDocumentInputStream(nativeEntry).read(data); - assert(readBytes == data.length); - - return new Ole10Native(data, 0); - } - - /** - * Creates an instance and fills the fields based on ... the fields - */ - public Ole10Native(String label, String filename, String command, byte[] data) { - setLabel(label); - setFileName(filename); - setCommand(command); - setDataBuffer(data); - mode = EncodingMode.parsed; - } - - /** - * Creates an instance and fills the fields based on the data in the given buffer. - * - * @param data The buffer containing the Ole10Native record - * @param offset The start offset of the record in the buffer - * @throws Ole10NativeException on invalid or unexcepted data format - */ - public Ole10Native(byte[] data, int offset) throws Ole10NativeException { - int ofs = offset; // current offset, initialized to start - - if (data.length < offset + 2) { - throw new Ole10NativeException("data is too small"); - } - - totalSize = LittleEndian.getInt(data, ofs); - ofs += LittleEndianConsts.INT_SIZE; - - mode = EncodingMode.unparsed; - if (LittleEndian.getShort(data, ofs) == 2) { - // some files like equations don't have a valid filename, - // but somehow encode the formula right away in the ole10 header - if (Character.isISOControl(data[ofs+LittleEndianConsts.SHORT_SIZE])) { - mode = EncodingMode.compact; - } else { - mode = EncodingMode.parsed; - } - } - - int dataSize; - switch (mode) { - case parsed: { - flags1 = LittleEndian.getShort(data, ofs); - - // structured format - ofs += LittleEndianConsts.SHORT_SIZE; - - int len = getStringLength(data, ofs); - label = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); - ofs += len; - - len = getStringLength(data, ofs); - fileName = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); - ofs += len; - - flags2 = LittleEndian.getShort(data, ofs); - ofs += LittleEndianConsts.SHORT_SIZE; - - unknown1 = LittleEndian.getShort(data, ofs); - ofs += LittleEndianConsts.SHORT_SIZE; - - len = LittleEndian.getInt(data, ofs); - ofs += LittleEndianConsts.INT_SIZE; - command = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); - ofs += len; - - if (totalSize < ofs) { - throw new Ole10NativeException("Invalid Ole10Native"); - } - - dataSize = LittleEndian.getInt(data, ofs); - ofs += LittleEndianConsts.INT_SIZE; - - if (dataSize < 0 || totalSize - (ofs - LittleEndianConsts.INT_SIZE) < dataSize) { - throw new Ole10NativeException("Invalid Ole10Native"); - } - break; - } - case compact: - flags1 = LittleEndian.getShort(data, ofs); - ofs += LittleEndianConsts.SHORT_SIZE; - dataSize = totalSize - LittleEndianConsts.SHORT_SIZE; - break; - default: - case unparsed: - dataSize = totalSize; - break; - } - - if ((long)dataSize + (long)ofs > (long)data.length) { //cast to avoid overflow - throw new Ole10NativeException("Invalid Ole10Native: declared data length > available data"); - } - dataBuffer = new byte[dataSize]; - System.arraycopy(data, ofs, dataBuffer, 0, dataSize); - ofs += dataSize; - } - - /* - * Helper - determine length of zero terminated string (ASCIIZ). - */ - private static int getStringLength(byte[] data, int ofs) { - int len = 0; - while (len + ofs < data.length && data[ofs + len] != 0) { - len++; - } - len++; - return len; - } - - /** - * Returns the value of the totalSize field - the total length of the - * structure is totalSize + 4 (value of this field + size of this field). - * - * @return the totalSize - */ - public int getTotalSize() { - return totalSize; - } - - /** - * Returns flags1 - currently unknown - usually 0x0002. - * - * @return the flags1 - */ - public short getFlags1() { - return flags1; - } - - /** - * Returns the label field - usually the name of the file (without - * directory) but probably may be any name specified during - * packaging/embedding the data. - * - * @return the label - */ - public String getLabel() { - return label; - } - - /** - * Returns the fileName field - usually the name of the file being embedded - * including the full path. - * - * @return the fileName - */ - public String getFileName() { - return fileName; - } - - /** - * Returns flags2 - currently unknown - mostly 0x0000. - * - * @return the flags2 - */ - public short getFlags2() { - return flags2; - } - - /** - * Returns unknown1 field - currently unknown. - * - * @return the unknown1 - */ - public short getUnknown1() { - return unknown1; - } - - /** - * Returns the command field - usually the name of the file being embedded - * including the full path, may be a command specified during embedding the - * file. - * - * @return the command - */ - public String getCommand() { - return command; - } - - /** - * Returns the size of the embedded file. If the size is 0 (zero), no data - * has been embedded. To be sure, that no data has been embedded, check - * whether {@link #getDataBuffer()} returns null. - * - * @return the dataSize - */ - public int getDataSize() { - return dataBuffer.length; - } - - /** - * Returns the buffer containing the embedded file's data, or - * null if no data was embedded. Note that an embedding may - * provide information about the data, but the actual data is not included. - * (So label, filename etc. are available, but this method returns - * null.) - * - * @return the dataBuffer - */ - public byte[] getDataBuffer() { - return dataBuffer; - } - - /** - * Returns the flags3 - currently unknown. - * - * @return the flags3 - */ - public short getFlags3() { - return flags3; - } - - /** - * Have the contents printer out into an OutputStream, used when writing a - * file back out to disk (Normally, atom classes will keep their bytes - * around, but non atom classes will just request the bytes from their - * children, then chuck on their header and return) - */ - public void writeOut(OutputStream out) throws IOException { - // byte intbuf[] = new byte[LittleEndianConsts.INT_SIZE]; - // byte shortbuf[] = new byte[LittleEndianConsts.SHORT_SIZE]; - - @SuppressWarnings("resource") - LittleEndianOutputStream leosOut = new LittleEndianOutputStream(out); - - switch (mode) { - case parsed: { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - LittleEndianOutputStream leos = new LittleEndianOutputStream(bos); - // total size, will be determined later .. - - leos.writeShort(getFlags1()); - leos.write(getLabel().getBytes(ISO1)); - leos.write(0); - leos.write(getFileName().getBytes(ISO1)); - leos.write(0); - leos.writeShort(getFlags2()); - leos.writeShort(getUnknown1()); - leos.writeInt(getCommand().length() + 1); - leos.write(getCommand().getBytes(ISO1)); - leos.write(0); - leos.writeInt(getDataSize()); - leos.write(getDataBuffer()); - leos.writeShort(getFlags3()); - leos.close(); // satisfy compiler ... - - leosOut.writeInt(bos.size()); // total size - bos.writeTo(out); - break; - } - case compact: - leosOut.writeInt(getDataSize()+LittleEndianConsts.SHORT_SIZE); - leosOut.writeShort(getFlags1()); - out.write(getDataBuffer()); - break; - default: - case unparsed: - leosOut.writeInt(getDataSize()); - out.write(getDataBuffer()); - break; - } - - } - - public void setFlags1(short flags1) { - this.flags1 = flags1; - } - - public void setFlags2(short flags2) { - this.flags2 = flags2; - } - - public void setFlags3(short flags3) { - this.flags3 = flags3; - } - - public void setLabel(String label) { - this.label = label; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public void setCommand(String command) { - this.command = command; - } - - public void setUnknown1(short unknown1) { - this.unknown1 = unknown1; - } - - public void setDataBuffer(byte dataBuffer[]) { - this.dataBuffer = dataBuffer.clone(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.filesystem; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianOutputStream; +import org.apache.poi.util.StringUtil; + +/** + * Represents an Ole10Native record which is wrapped around certain binary + * files being embedded in OLE2 documents. + * + * @author Rainer Schwarze + */ +public class Ole10Native { + + public static final String OLE10_NATIVE = "\u0001Ole10Native"; + protected static final String ISO1 = "ISO-8859-1"; + + // (the fields as they appear in the raw record:) + private int totalSize; // 4 bytes, total size of record not including this field + private short flags1 = 2; // 2 bytes, unknown, mostly [02 00] + private String label; // ASCIIZ, stored in this field without the terminating zero + private String fileName; // ASCIIZ, stored in this field without the terminating zero + private short flags2 = 0; // 2 bytes, unknown, mostly [00 00] + private short unknown1 = 3; // see below + private String command; // ASCIIZ, stored in this field without the terminating zero + private byte[] dataBuffer; // varying size, the actual native data + private short flags3 = 0; // some final flags? or zero terminators?, sometimes not there + + /** + * the field encoding mode - merely a try-and-error guess ... + **/ + private enum EncodingMode { + /** + * the data is stored in parsed format - including label, command, etc. + */ + parsed, + /** + * the data is stored raw after the length field + */ + unparsed, + /** + * the data is stored raw after the length field and the flags1 field + */ + compact + } + + private EncodingMode mode; + + + + /** + * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected + * to include a stream "{01}Ole10Native" which contains the actual + * data relevant for this class. + * + * @param poifs POI Filesystem object + * @return Returns an instance of this class + * @throws IOException on IO error + * @throws Ole10NativeException on invalid or unexcepted data format + */ + public static Ole10Native createFromEmbeddedOleObject(POIFSFileSystem poifs) throws IOException, Ole10NativeException { + return createFromEmbeddedOleObject(poifs.getRoot()); + } + + /** + * Creates an instance of this class from an embedded OLE Object. The OLE Object is expected + * to include a stream "{01}Ole10Native" which contains the actual + * data relevant for this class. + * + * @param directory POI Filesystem object + * @return Returns an instance of this class + * @throws IOException on IO error + * @throws Ole10NativeException on invalid or unexcepted data format + */ + public static Ole10Native createFromEmbeddedOleObject(DirectoryNode directory) throws IOException, Ole10NativeException { + DocumentEntry nativeEntry = + (DocumentEntry)directory.getEntry(OLE10_NATIVE); + byte[] data = new byte[nativeEntry.getSize()]; + int readBytes = directory.createDocumentInputStream(nativeEntry).read(data); + assert(readBytes == data.length); + + return new Ole10Native(data, 0); + } + + /** + * Creates an instance and fills the fields based on ... the fields + */ + public Ole10Native(String label, String filename, String command, byte[] data) { + setLabel(label); + setFileName(filename); + setCommand(command); + setDataBuffer(data); + mode = EncodingMode.parsed; + } + + /** + * Creates an instance and fills the fields based on the data in the given buffer. + * + * @param data The buffer containing the Ole10Native record + * @param offset The start offset of the record in the buffer + * @throws Ole10NativeException on invalid or unexcepted data format + */ + public Ole10Native(byte[] data, int offset) throws Ole10NativeException { + int ofs = offset; // current offset, initialized to start + + if (data.length < offset + 2) { + throw new Ole10NativeException("data is too small"); + } + + totalSize = LittleEndian.getInt(data, ofs); + ofs += LittleEndianConsts.INT_SIZE; + + mode = EncodingMode.unparsed; + if (LittleEndian.getShort(data, ofs) == 2) { + // some files like equations don't have a valid filename, + // but somehow encode the formula right away in the ole10 header + if (Character.isISOControl(data[ofs+LittleEndianConsts.SHORT_SIZE])) { + mode = EncodingMode.compact; + } else { + mode = EncodingMode.parsed; + } + } + + int dataSize; + switch (mode) { + case parsed: { + flags1 = LittleEndian.getShort(data, ofs); + + // structured format + ofs += LittleEndianConsts.SHORT_SIZE; + + int len = getStringLength(data, ofs); + label = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); + ofs += len; + + len = getStringLength(data, ofs); + fileName = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); + ofs += len; + + flags2 = LittleEndian.getShort(data, ofs); + ofs += LittleEndianConsts.SHORT_SIZE; + + unknown1 = LittleEndian.getShort(data, ofs); + ofs += LittleEndianConsts.SHORT_SIZE; + + len = LittleEndian.getInt(data, ofs); + ofs += LittleEndianConsts.INT_SIZE; + command = StringUtil.getFromCompressedUnicode(data, ofs, len - 1); + ofs += len; + + if (totalSize < ofs) { + throw new Ole10NativeException("Invalid Ole10Native"); + } + + dataSize = LittleEndian.getInt(data, ofs); + ofs += LittleEndianConsts.INT_SIZE; + + if (dataSize < 0 || totalSize - (ofs - LittleEndianConsts.INT_SIZE) < dataSize) { + throw new Ole10NativeException("Invalid Ole10Native"); + } + break; + } + case compact: + flags1 = LittleEndian.getShort(data, ofs); + ofs += LittleEndianConsts.SHORT_SIZE; + dataSize = totalSize - LittleEndianConsts.SHORT_SIZE; + break; + default: + case unparsed: + dataSize = totalSize; + break; + } + + if ((long)dataSize + (long)ofs > (long)data.length) { //cast to avoid overflow + throw new Ole10NativeException("Invalid Ole10Native: declared data length > available data"); + } + dataBuffer = new byte[dataSize]; + System.arraycopy(data, ofs, dataBuffer, 0, dataSize); + ofs += dataSize; + } + + /* + * Helper - determine length of zero terminated string (ASCIIZ). + */ + private static int getStringLength(byte[] data, int ofs) { + int len = 0; + while (len + ofs < data.length && data[ofs + len] != 0) { + len++; + } + len++; + return len; + } + + /** + * Returns the value of the totalSize field - the total length of the + * structure is totalSize + 4 (value of this field + size of this field). + * + * @return the totalSize + */ + public int getTotalSize() { + return totalSize; + } + + /** + * Returns flags1 - currently unknown - usually 0x0002. + * + * @return the flags1 + */ + public short getFlags1() { + return flags1; + } + + /** + * Returns the label field - usually the name of the file (without + * directory) but probably may be any name specified during + * packaging/embedding the data. + * + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * Returns the fileName field - usually the name of the file being embedded + * including the full path. + * + * @return the fileName + */ + public String getFileName() { + return fileName; + } + + /** + * Returns flags2 - currently unknown - mostly 0x0000. + * + * @return the flags2 + */ + public short getFlags2() { + return flags2; + } + + /** + * Returns unknown1 field - currently unknown. + * + * @return the unknown1 + */ + public short getUnknown1() { + return unknown1; + } + + /** + * Returns the command field - usually the name of the file being embedded + * including the full path, may be a command specified during embedding the + * file. + * + * @return the command + */ + public String getCommand() { + return command; + } + + /** + * Returns the size of the embedded file. If the size is 0 (zero), no data + * has been embedded. To be sure, that no data has been embedded, check + * whether {@link #getDataBuffer()} returns null. + * + * @return the dataSize + */ + public int getDataSize() { + return dataBuffer.length; + } + + /** + * Returns the buffer containing the embedded file's data, or + * null if no data was embedded. Note that an embedding may + * provide information about the data, but the actual data is not included. + * (So label, filename etc. are available, but this method returns + * null.) + * + * @return the dataBuffer + */ + public byte[] getDataBuffer() { + return dataBuffer; + } + + /** + * Returns the flags3 - currently unknown. + * + * @return the flags3 + */ + public short getFlags3() { + return flags3; + } + + /** + * Have the contents printer out into an OutputStream, used when writing a + * file back out to disk (Normally, atom classes will keep their bytes + * around, but non atom classes will just request the bytes from their + * children, then chuck on their header and return) + */ + public void writeOut(OutputStream out) throws IOException { + // byte intbuf[] = new byte[LittleEndianConsts.INT_SIZE]; + // byte shortbuf[] = new byte[LittleEndianConsts.SHORT_SIZE]; + + @SuppressWarnings("resource") + LittleEndianOutputStream leosOut = new LittleEndianOutputStream(out); + + switch (mode) { + case parsed: { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + LittleEndianOutputStream leos = new LittleEndianOutputStream(bos); + // total size, will be determined later .. + + leos.writeShort(getFlags1()); + leos.write(getLabel().getBytes(ISO1)); + leos.write(0); + leos.write(getFileName().getBytes(ISO1)); + leos.write(0); + leos.writeShort(getFlags2()); + leos.writeShort(getUnknown1()); + leos.writeInt(getCommand().length() + 1); + leos.write(getCommand().getBytes(ISO1)); + leos.write(0); + leos.writeInt(getDataSize()); + leos.write(getDataBuffer()); + leos.writeShort(getFlags3()); + leos.close(); // satisfy compiler ... + + leosOut.writeInt(bos.size()); // total size + bos.writeTo(out); + break; + } + case compact: + leosOut.writeInt(getDataSize()+LittleEndianConsts.SHORT_SIZE); + leosOut.writeShort(getFlags1()); + out.write(getDataBuffer()); + break; + default: + case unparsed: + leosOut.writeInt(getDataSize()); + out.write(getDataBuffer()); + break; + } + + } + + public void setFlags1(short flags1) { + this.flags1 = flags1; + } + + public void setFlags2(short flags2) { + this.flags2 = flags2; + } + + public void setFlags3(short flags3) { + this.flags3 = flags3; + } + + public void setLabel(String label) { + this.label = label; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public void setCommand(String command) { + this.command = command; + } + + public void setUnknown1(short unknown1) { + this.unknown1 = unknown1; + } + + public void setDataBuffer(byte dataBuffer[]) { + this.dataBuffer = dataBuffer.clone(); + } +} diff --git a/src/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java b/src/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java index c5c84aff9d..665ccf5bdc 100644 --- a/src/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java +++ b/src/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java @@ -1,58 +1,58 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.macros; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.macros; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.Map; -import java.util.Map.Entry; - -import org.apache.poi.util.StringUtil; - -/** - * This tool extracts out the source of all VBA Modules of an office file, +import java.util.Map.Entry; + +import org.apache.poi.util.StringUtil; + +/** + * This tool extracts out the source of all VBA Modules of an office file, * both OOXML (eg XLSM) and OLE2/POIFS (eg DOC), to STDOUT or a directory. * - * @since 3.15-beta2 - */ -public class VBAMacroExtractor { - public static void main(String args[]) throws IOException { - if (args.length == 0) { - System.err.println("Use:"); - System.err.println(" VBAMacroExtractor [output]"); - System.err.println(""); - System.err.println("If an output directory is given, macros are written there"); - System.err.println("Otherwise they are output to the screen"); - System.exit(1); - } - - File input = new File(args[0]); - File output = null; - if (args.length > 1) { - output = new File(args[1]); - } - - VBAMacroExtractor extractor = new VBAMacroExtractor(); - extractor.extract(input, output); - } + * @since 3.15-beta2 + */ +public class VBAMacroExtractor { + public static void main(String args[]) throws IOException { + if (args.length == 0) { + System.err.println("Use:"); + System.err.println(" VBAMacroExtractor [output]"); + System.err.println(""); + System.err.println("If an output directory is given, macros are written there"); + System.err.println("Otherwise they are output to the screen"); + System.exit(1); + } + + File input = new File(args[0]); + File output = null; + if (args.length > 1) { + output = new File(args[1]); + } + + VBAMacroExtractor extractor = new VBAMacroExtractor(); + extractor.extract(input, output); + } /** * Extracts the VBA modules from a macro-enabled office file and writes them @@ -66,45 +66,45 @@ public class VBAMacroExtractor { * @param outputDir the directory to write the extracted VBA modules to. * @param extension file extension of the extracted VBA modules * @since 3.15-beta2 - */ - public void extract(File input, File outputDir, String extension) throws IOException { - if (! input.exists()) throw new FileNotFoundException(input.toString()); - System.err.print("Extracting VBA Macros from " + input + " to "); - if (outputDir != null) { + */ + public void extract(File input, File outputDir, String extension) throws IOException { + if (! input.exists()) throw new FileNotFoundException(input.toString()); + System.err.print("Extracting VBA Macros from " + input + " to "); + if (outputDir != null) { if (!outputDir.exists() && !outputDir.mkdirs()) { throw new IOException("Output directory " + outputDir + " could not be created"); - } - System.err.println(outputDir); - } else { - System.err.println("STDOUT"); - } - - VBAMacroReader reader = new VBAMacroReader(input); - Map macros = reader.readMacros(); - reader.close(); - - final String divider = "---------------------------------------"; + } + System.err.println(outputDir); + } else { + System.err.println("STDOUT"); + } + + VBAMacroReader reader = new VBAMacroReader(input); + Map macros = reader.readMacros(); + reader.close(); + + final String divider = "---------------------------------------"; for (Entry entry : macros.entrySet()) { String moduleName = entry.getKey(); - String moduleCode = entry.getValue(); - if (outputDir == null) { - System.out.println(divider); - System.out.println(moduleName); - System.out.println(""); - System.out.println(moduleCode); - } else { - File out = new File(outputDir, moduleName + extension); - FileOutputStream fout = new FileOutputStream(out); - OutputStreamWriter fwriter = new OutputStreamWriter(fout, StringUtil.UTF8); - fwriter.write(moduleCode); - fwriter.close(); - fout.close(); - System.out.println("Extracted " + out); - } - } - if (outputDir == null) { - System.out.println(divider); - } + String moduleCode = entry.getValue(); + if (outputDir == null) { + System.out.println(divider); + System.out.println(moduleName); + System.out.println(""); + System.out.println(moduleCode); + } else { + File out = new File(outputDir, moduleName + extension); + FileOutputStream fout = new FileOutputStream(out); + OutputStreamWriter fwriter = new OutputStreamWriter(fout, StringUtil.UTF8); + fwriter.write(moduleCode); + fwriter.close(); + fout.close(); + System.out.println("Extracted " + out); + } + } + if (outputDir == null) { + System.out.println(divider); + } } /** @@ -118,8 +118,8 @@ public class VBAMacroExtractor { * @param input the macro-enabled office file. * @param outputDir the directory to write the extracted VBA modules to. * @since 3.15-beta2 - */ + */ public void extract(File input, File outputDir) throws IOException { extract(input, outputDir, ".vba"); - } -} + } +} diff --git a/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java b/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java index 818b10b10d..43818cb5d6 100644 --- a/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java +++ b/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java @@ -1,306 +1,306 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.AlphaComposite; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.awt.image.RescaleOp; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; - -import javax.imageio.ImageIO; -import javax.imageio.ImageReadParam; -import javax.imageio.ImageReader; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.stream.ImageInputStream; -import javax.imageio.stream.MemoryCacheImageInputStream; - -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * For now this class renders only images supported by the javax.imageio.ImageIO framework. - **/ -public class BitmapImageRenderer implements ImageRenderer { - private final static POILogger LOG = POILogFactory.getLogger(ImageRenderer.class); - - protected BufferedImage img; - - @Override - public void loadImage(InputStream data, String contentType) throws IOException { - img = readImage(data, contentType); - } - - @Override - public void loadImage(byte data[], String contentType) throws IOException { - img = readImage(new ByteArrayInputStream(data), contentType); - } - - /** - * Read the image data via ImageIO and optionally try to workaround metadata errors. - * The resulting image is of image type {@link BufferedImage#TYPE_INT_ARGB} - * - * @param data the data stream - * @param contentType the content type - * @return the bufferedImage or null, if there was no image reader for this content type - * @throws IOException thrown if there was an error while processing the image - */ - private static BufferedImage readImage(InputStream data, String contentType) throws IOException { - IOException lastException = null; - BufferedImage img = null; - if (data.markSupported()) { - data.mark(data.available()); - } - - // currently don't use FileCacheImageInputStream, - // because of the risk of filling the file handles (see #59166) - ImageInputStream iis = new MemoryCacheImageInputStream(data); - try { - iis = new MemoryCacheImageInputStream(data); - iis.mark(); - - Iterator iter = ImageIO.getImageReaders(iis); - while (img==null && iter.hasNext()) { - ImageReader reader = iter.next(); - ImageReadParam param = reader.getDefaultReadParam(); - // 0:default mode, 1:fallback mode - for (int mode=0; img==null && mode<3; mode++) { - lastException = null; - try { - iis.reset(); - } catch (IOException e) { - if (data.markSupported()) { - data.reset(); - data.mark(data.available()); - iis.close(); - iis = new MemoryCacheImageInputStream(data); - } else { - // can't restore the input stream, so we need to stop processing here - lastException = e; - break; - } - } - iis.mark(); - - try { - - switch (mode) { - case 0: - reader.setInput(iis, false, true); - img = reader.read(0, param); - break; - case 1: { - // try to load picture in gray scale mode - // fallback mode for invalid image band metadata - // see http://stackoverflow.com/questions/10416378 - Iterator imageTypes = reader.getImageTypes(0); - while (imageTypes.hasNext()) { - ImageTypeSpecifier imageTypeSpecifier = imageTypes.next(); - int bufferedImageType = imageTypeSpecifier.getBufferedImageType(); - if (bufferedImageType == BufferedImage.TYPE_BYTE_GRAY) { - param.setDestinationType(imageTypeSpecifier); - break; - } - } - reader.setInput(iis, false, true); - img = reader.read(0, param); - break; - } - case 2: { - // try to load truncated pictures by supplying a BufferedImage - // and use the processed data up till the point of error - reader.setInput(iis, false, true); - int height = reader.getHeight(0); - int width = reader.getWidth(0); - - Iterator imageTypes = reader.getImageTypes(0); - if (imageTypes.hasNext()) { - ImageTypeSpecifier imageTypeSpecifier = imageTypes.next(); - img = imageTypeSpecifier.createBufferedImage(width, height); - param.setDestination(img); - } else { - lastException = new IOException("unable to load even a truncated version of the image."); - break; - } - - try { - reader.read(0, param); - } finally { - if (img.getType() != BufferedImage.TYPE_INT_ARGB) { - int y = findTruncatedBlackBox(img, width, height); - if (y < height) { - BufferedImage argbImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = argbImg.createGraphics(); - g.clipRect(0, 0, width, y); - g.drawImage(img, 0, 0, null); - g.dispose(); - img.flush(); - img = argbImg; - } - } - } - break; - } - } - - } catch (IOException e) { - if (mode < 2) { - lastException = e; - } - } catch (RuntimeException e) { - if (mode < 2) { - lastException = new IOException("ImageIO runtime exception - "+(mode==0 ? "normal" : "fallback"), e); - } - } - } - reader.dispose(); - } - } finally { - iis.close(); - } - - // If you don't have an image at the end of all readers - if (img == null) { - if (lastException != null) { - // rethrow exception - be aware that the exception source can be in - // multiple locations above ... - throw lastException; - } - LOG.log(POILogger.WARN, "Content-type: "+contentType+" is not support. Image ignored."); - return null; - } - - // add alpha channel - if (img.getType() != BufferedImage.TYPE_INT_ARGB) { - BufferedImage argbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics g = argbImg.getGraphics(); - g.drawImage(img, 0, 0, null); - g.dispose(); - return argbImg; - } - - return img; - } - - private static int findTruncatedBlackBox(BufferedImage img, int width, int height) { - // scan through the image to find the black box after the truncated data - int h = height-1; - for (; h > 0; h--) { - for (int w = width-1; w > 0; w-=width/10) { - int p = img.getRGB(w, h); - if (p != 0xff000000) { - return h+1; - } - } - } - return 0; - } - - - @Override - public BufferedImage getImage() { - return img; - } - - @Override - public BufferedImage getImage(Dimension dim) { - double w_old = img.getWidth(); - double h_old = img.getHeight(); - BufferedImage scaled = new BufferedImage((int)w_old, (int)h_old, BufferedImage.TYPE_INT_ARGB); - double w_new = dim.getWidth(); - double h_new = dim.getHeight(); - AffineTransform at = new AffineTransform(); - at.scale(w_new/w_old, h_new/h_old); - AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); - scaleOp.filter(img, scaled); - return scaled; - } - - @Override - public Dimension getDimension() { - return (img == null) - ? new Dimension(0,0) - : new Dimension(img.getWidth(),img.getHeight()); - } - - @Override - public void setAlpha(double alpha) { - if (img == null) return; - - Dimension dim = getDimension(); - BufferedImage newImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics2D g = newImg.createGraphics(); - RescaleOp op = new RescaleOp(new float[]{1.0f, 1.0f, 1.0f, (float)alpha}, new float[]{0,0,0,0}, null); - g.drawImage(img, op, 0, 0); - g.dispose(); - - img = newImg; - } - - - @Override - public boolean drawImage( - Graphics2D graphics, - Rectangle2D anchor) { - return drawImage(graphics, anchor, null); - } - - @Override - public boolean drawImage( - Graphics2D graphics, - Rectangle2D anchor, - Insets clip) { - if (img == null) return false; - - boolean isClipped = true; - if (clip == null) { - isClipped = false; - clip = new Insets(0,0,0,0); - } - - int iw = img.getWidth(); - int ih = img.getHeight(); - - - double cw = (100000-clip.left-clip.right) / 100000.0; - double ch = (100000-clip.top-clip.bottom) / 100000.0; - double sx = anchor.getWidth()/(iw*cw); - double sy = anchor.getHeight()/(ih*ch); - double tx = anchor.getX()-(iw*sx*clip.left/100000.0); - double ty = anchor.getY()-(ih*sy*clip.top/100000.0); - - AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; - - Shape clipOld = graphics.getClip(); - if (isClipped) graphics.clip(anchor.getBounds2D()); - graphics.drawRenderedImage(img, at); - graphics.setClip(clipOld); - - return true; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.AlphaComposite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.awt.image.RescaleOp; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.MemoryCacheImageInputStream; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * For now this class renders only images supported by the javax.imageio.ImageIO framework. + **/ +public class BitmapImageRenderer implements ImageRenderer { + private final static POILogger LOG = POILogFactory.getLogger(ImageRenderer.class); + + protected BufferedImage img; + + @Override + public void loadImage(InputStream data, String contentType) throws IOException { + img = readImage(data, contentType); + } + + @Override + public void loadImage(byte data[], String contentType) throws IOException { + img = readImage(new ByteArrayInputStream(data), contentType); + } + + /** + * Read the image data via ImageIO and optionally try to workaround metadata errors. + * The resulting image is of image type {@link BufferedImage#TYPE_INT_ARGB} + * + * @param data the data stream + * @param contentType the content type + * @return the bufferedImage or null, if there was no image reader for this content type + * @throws IOException thrown if there was an error while processing the image + */ + private static BufferedImage readImage(InputStream data, String contentType) throws IOException { + IOException lastException = null; + BufferedImage img = null; + if (data.markSupported()) { + data.mark(data.available()); + } + + // currently don't use FileCacheImageInputStream, + // because of the risk of filling the file handles (see #59166) + ImageInputStream iis = new MemoryCacheImageInputStream(data); + try { + iis = new MemoryCacheImageInputStream(data); + iis.mark(); + + Iterator iter = ImageIO.getImageReaders(iis); + while (img==null && iter.hasNext()) { + ImageReader reader = iter.next(); + ImageReadParam param = reader.getDefaultReadParam(); + // 0:default mode, 1:fallback mode + for (int mode=0; img==null && mode<3; mode++) { + lastException = null; + try { + iis.reset(); + } catch (IOException e) { + if (data.markSupported()) { + data.reset(); + data.mark(data.available()); + iis.close(); + iis = new MemoryCacheImageInputStream(data); + } else { + // can't restore the input stream, so we need to stop processing here + lastException = e; + break; + } + } + iis.mark(); + + try { + + switch (mode) { + case 0: + reader.setInput(iis, false, true); + img = reader.read(0, param); + break; + case 1: { + // try to load picture in gray scale mode + // fallback mode for invalid image band metadata + // see http://stackoverflow.com/questions/10416378 + Iterator imageTypes = reader.getImageTypes(0); + while (imageTypes.hasNext()) { + ImageTypeSpecifier imageTypeSpecifier = imageTypes.next(); + int bufferedImageType = imageTypeSpecifier.getBufferedImageType(); + if (bufferedImageType == BufferedImage.TYPE_BYTE_GRAY) { + param.setDestinationType(imageTypeSpecifier); + break; + } + } + reader.setInput(iis, false, true); + img = reader.read(0, param); + break; + } + case 2: { + // try to load truncated pictures by supplying a BufferedImage + // and use the processed data up till the point of error + reader.setInput(iis, false, true); + int height = reader.getHeight(0); + int width = reader.getWidth(0); + + Iterator imageTypes = reader.getImageTypes(0); + if (imageTypes.hasNext()) { + ImageTypeSpecifier imageTypeSpecifier = imageTypes.next(); + img = imageTypeSpecifier.createBufferedImage(width, height); + param.setDestination(img); + } else { + lastException = new IOException("unable to load even a truncated version of the image."); + break; + } + + try { + reader.read(0, param); + } finally { + if (img.getType() != BufferedImage.TYPE_INT_ARGB) { + int y = findTruncatedBlackBox(img, width, height); + if (y < height) { + BufferedImage argbImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = argbImg.createGraphics(); + g.clipRect(0, 0, width, y); + g.drawImage(img, 0, 0, null); + g.dispose(); + img.flush(); + img = argbImg; + } + } + } + break; + } + } + + } catch (IOException e) { + if (mode < 2) { + lastException = e; + } + } catch (RuntimeException e) { + if (mode < 2) { + lastException = new IOException("ImageIO runtime exception - "+(mode==0 ? "normal" : "fallback"), e); + } + } + } + reader.dispose(); + } + } finally { + iis.close(); + } + + // If you don't have an image at the end of all readers + if (img == null) { + if (lastException != null) { + // rethrow exception - be aware that the exception source can be in + // multiple locations above ... + throw lastException; + } + LOG.log(POILogger.WARN, "Content-type: "+contentType+" is not support. Image ignored."); + return null; + } + + // add alpha channel + if (img.getType() != BufferedImage.TYPE_INT_ARGB) { + BufferedImage argbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics g = argbImg.getGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); + return argbImg; + } + + return img; + } + + private static int findTruncatedBlackBox(BufferedImage img, int width, int height) { + // scan through the image to find the black box after the truncated data + int h = height-1; + for (; h > 0; h--) { + for (int w = width-1; w > 0; w-=width/10) { + int p = img.getRGB(w, h); + if (p != 0xff000000) { + return h+1; + } + } + } + return 0; + } + + + @Override + public BufferedImage getImage() { + return img; + } + + @Override + public BufferedImage getImage(Dimension dim) { + double w_old = img.getWidth(); + double h_old = img.getHeight(); + BufferedImage scaled = new BufferedImage((int)w_old, (int)h_old, BufferedImage.TYPE_INT_ARGB); + double w_new = dim.getWidth(); + double h_new = dim.getHeight(); + AffineTransform at = new AffineTransform(); + at.scale(w_new/w_old, h_new/h_old); + AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); + scaleOp.filter(img, scaled); + return scaled; + } + + @Override + public Dimension getDimension() { + return (img == null) + ? new Dimension(0,0) + : new Dimension(img.getWidth(),img.getHeight()); + } + + @Override + public void setAlpha(double alpha) { + if (img == null) return; + + Dimension dim = getDimension(); + BufferedImage newImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g = newImg.createGraphics(); + RescaleOp op = new RescaleOp(new float[]{1.0f, 1.0f, 1.0f, (float)alpha}, new float[]{0,0,0,0}, null); + g.drawImage(img, op, 0, 0); + g.dispose(); + + img = newImg; + } + + + @Override + public boolean drawImage( + Graphics2D graphics, + Rectangle2D anchor) { + return drawImage(graphics, anchor, null); + } + + @Override + public boolean drawImage( + Graphics2D graphics, + Rectangle2D anchor, + Insets clip) { + if (img == null) return false; + + boolean isClipped = true; + if (clip == null) { + isClipped = false; + clip = new Insets(0,0,0,0); + } + + int iw = img.getWidth(); + int ih = img.getHeight(); + + + double cw = (100000-clip.left-clip.right) / 100000.0; + double ch = (100000-clip.top-clip.bottom) / 100000.0; + double sx = anchor.getWidth()/(iw*cw); + double sy = anchor.getHeight()/(ih*ch); + double tx = anchor.getX()-(iw*sx*clip.left/100000.0); + double ty = anchor.getY()-(ih*sy*clip.top/100000.0); + + AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; + + Shape clipOld = graphics.getClip(); + if (isClipped) graphics.clip(anchor.getBounds2D()); + graphics.drawRenderedImage(img, at); + graphics.setClip(clipOld); + + return true; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawAutoShape.java b/src/java/org/apache/poi/sl/draw/DrawAutoShape.java index 9cda7a32a6..5503542a10 100644 --- a/src/java/org/apache/poi/sl/draw/DrawAutoShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawAutoShape.java @@ -1,27 +1,27 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import org.apache.poi.sl.usermodel.*; - - -public class DrawAutoShape extends DrawTextShape { - public DrawAutoShape(AutoShape shape) { - super(shape); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import org.apache.poi.sl.usermodel.*; + + +public class DrawAutoShape extends DrawTextShape { + public DrawAutoShape(AutoShape shape) { + super(shape); + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawBackground.java b/src/java/org/apache/poi/sl/draw/DrawBackground.java index aa12b470cb..1e9d5945b3 100644 --- a/src/java/org/apache/poi/sl/draw/DrawBackground.java +++ b/src/java/org/apache/poi/sl/draw/DrawBackground.java @@ -1,69 +1,69 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.geom.Rectangle2D; - -import org.apache.poi.sl.usermodel.Background; -import org.apache.poi.sl.usermodel.PlaceableShape; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.Sheet; - - -public class DrawBackground extends DrawShape { - public DrawBackground(Background shape) { - super(shape); - } - - @SuppressWarnings("rawtypes") - public void draw(Graphics2D graphics) { - Dimension pg = shape.getSheet().getSlideShow().getPageSize(); - final Rectangle2D anchor = new Rectangle2D.Double(0, 0, pg.getWidth(), pg.getHeight()); - - PlaceableShape ps = new PlaceableShape(){ - public ShapeContainer getParent() { return null; } - public Rectangle2D getAnchor() { return anchor; } - public void setAnchor(Rectangle2D newAnchor) {} - public double getRotation() { return 0; } - public void setRotation(double theta) {} - public void setFlipHorizontal(boolean flip) {} - public void setFlipVertical(boolean flip) {} - public boolean getFlipHorizontal() { return false; } - public boolean getFlipVertical() { return false; } - public Sheet getSheet() { return shape.getSheet(); } - }; - - DrawFactory drawFact = DrawFactory.getInstance(graphics); - DrawPaint dp = drawFact.getPaint(ps); - Paint fill = dp.getPaint(graphics, getShape().getFillStyle().getPaint()); - Rectangle2D anchor2 = getAnchor(graphics, anchor); - - if(fill != null) { - graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, anchor); - graphics.setPaint(fill); - graphics.fill(anchor2); - } - } - - protected Background getShape() { - return (Background)shape; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.sl.usermodel.Background; +import org.apache.poi.sl.usermodel.PlaceableShape; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.Sheet; + + +public class DrawBackground extends DrawShape { + public DrawBackground(Background shape) { + super(shape); + } + + @SuppressWarnings("rawtypes") + public void draw(Graphics2D graphics) { + Dimension pg = shape.getSheet().getSlideShow().getPageSize(); + final Rectangle2D anchor = new Rectangle2D.Double(0, 0, pg.getWidth(), pg.getHeight()); + + PlaceableShape ps = new PlaceableShape(){ + public ShapeContainer getParent() { return null; } + public Rectangle2D getAnchor() { return anchor; } + public void setAnchor(Rectangle2D newAnchor) {} + public double getRotation() { return 0; } + public void setRotation(double theta) {} + public void setFlipHorizontal(boolean flip) {} + public void setFlipVertical(boolean flip) {} + public boolean getFlipHorizontal() { return false; } + public boolean getFlipVertical() { return false; } + public Sheet getSheet() { return shape.getSheet(); } + }; + + DrawFactory drawFact = DrawFactory.getInstance(graphics); + DrawPaint dp = drawFact.getPaint(ps); + Paint fill = dp.getPaint(graphics, getShape().getFillStyle().getPaint()); + Rectangle2D anchor2 = getAnchor(graphics, anchor); + + if(fill != null) { + graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, anchor); + graphics.setPaint(fill); + graphics.fill(anchor2); + } + } + + protected Background getShape() { + return (Background)shape; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawConnectorShape.java b/src/java/org/apache/poi/sl/draw/DrawConnectorShape.java index 00bcd1b58e..bb973f5f8a 100644 --- a/src/java/org/apache/poi/sl/draw/DrawConnectorShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawConnectorShape.java @@ -1,26 +1,26 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import org.apache.poi.sl.usermodel.ConnectorShape; - -public class DrawConnectorShape extends DrawSimpleShape { - public DrawConnectorShape(ConnectorShape shape) { - super(shape); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import org.apache.poi.sl.usermodel.ConnectorShape; + +public class DrawConnectorShape extends DrawSimpleShape { + public DrawConnectorShape(ConnectorShape shape) { + super(shape); + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawFactory.java b/src/java/org/apache/poi/sl/draw/DrawFactory.java index f06ccdc1b0..53b2bcba78 100644 --- a/src/java/org/apache/poi/sl/draw/DrawFactory.java +++ b/src/java/org/apache/poi/sl/draw/DrawFactory.java @@ -1,239 +1,239 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; -import java.awt.font.TextLayout; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.text.AttributedString; -import java.util.HashMap; -import java.util.Map; - -import org.apache.poi.sl.usermodel.Background; -import org.apache.poi.sl.usermodel.ConnectorShape; -import org.apache.poi.sl.usermodel.FreeformShape; -import org.apache.poi.sl.usermodel.GraphicalFrame; -import org.apache.poi.sl.usermodel.GroupShape; -import org.apache.poi.sl.usermodel.MasterSheet; -import org.apache.poi.sl.usermodel.PictureShape; -import org.apache.poi.sl.usermodel.PlaceableShape; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.sl.usermodel.Sheet; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.sl.usermodel.TableShape; -import org.apache.poi.sl.usermodel.TextBox; -import org.apache.poi.sl.usermodel.TextParagraph; -import org.apache.poi.sl.usermodel.TextShape; -import org.apache.poi.util.JvmBugs; - -public class DrawFactory { - protected static final ThreadLocal defaultFactory = new ThreadLocal(); - - /** - * Set a custom draw factory for the current thread. - * This is a fallback, for operations where usercode can't set a graphics context. - * Preferably use the rendering hint {@link Drawable#DRAW_FACTORY} to set the factory. - * - * @param factory - */ - public static void setDefaultFactory(DrawFactory factory) { - defaultFactory.set(factory); - } - - /** - * Returns the DrawFactory, preferably via a graphics instance. - * If graphics is null, the current thread local is checked or - * if it is not set, a new factory is created. - * - * @param graphics the current graphics context or null - * @return the draw factory - */ - public static DrawFactory getInstance(Graphics2D graphics) { - // first try to find the factory over the rendering hint - DrawFactory factory = null; - boolean isHint = false; - if (graphics != null) { - factory = (DrawFactory)graphics.getRenderingHint(Drawable.DRAW_FACTORY); - isHint = (factory != null); - } - // secondly try the thread local default - if (factory == null) { - factory = defaultFactory.get(); - } - // and at last, use the default factory - if (factory == null) { - factory = new DrawFactory(); - } - if (graphics != null && !isHint) { - graphics.setRenderingHint(Drawable.DRAW_FACTORY, factory); - } - return factory; - } - - public Drawable getDrawable(Shape shape) { - if (shape instanceof TextBox) { - return getDrawable((TextBox)shape); - } else if (shape instanceof FreeformShape) { - return getDrawable((FreeformShape)shape); - } else if (shape instanceof TextShape) { - return getDrawable((TextShape)shape); - } else if (shape instanceof TableShape) { - return getDrawable((TableShape)shape); - } else if (shape instanceof GroupShape) { - return getDrawable((GroupShape)shape); - } else if (shape instanceof PictureShape) { - return getDrawable((PictureShape)shape); - } else if (shape instanceof GraphicalFrame) { - return getDrawable((GraphicalFrame)shape); - } else if (shape instanceof Background) { - return getDrawable((Background)shape); - } else if (shape instanceof ConnectorShape) { - return getDrawable((ConnectorShape)shape); - } else if (shape instanceof Slide) { - return getDrawable((Slide)shape); - } else if (shape instanceof MasterSheet) { - return getDrawable((MasterSheet)shape); - } else if (shape instanceof Sheet) { - return getDrawable((Sheet)shape); - } else if (shape.getClass().isAnnotationPresent(DrawNotImplemented.class)) { - return new DrawNothing(shape); - } - - throw new IllegalArgumentException("Unsupported shape type: "+shape.getClass()); - } - - public DrawSlide getDrawable(Slide sheet) { - return new DrawSlide(sheet); - } - - public DrawSheet getDrawable(Sheet sheet) { - return new DrawSheet(sheet); - } - - public DrawMasterSheet getDrawable(MasterSheet sheet) { - return new DrawMasterSheet(sheet); - } - - public DrawTextBox getDrawable(TextBox shape) { - return new DrawTextBox(shape); - } - - public DrawFreeformShape getDrawable(FreeformShape shape) { - return new DrawFreeformShape(shape); - } - - public DrawConnectorShape getDrawable(ConnectorShape shape) { - return new DrawConnectorShape(shape); - } - - public DrawTableShape getDrawable(TableShape shape) { - return new DrawTableShape(shape); - } - - public DrawTextShape getDrawable(TextShape shape) { - return new DrawTextShape(shape); - } - - public DrawGroupShape getDrawable(GroupShape shape) { - return new DrawGroupShape(shape); - } - - public DrawPictureShape getDrawable(PictureShape shape) { - return new DrawPictureShape(shape); - } - - public DrawGraphicalFrame getDrawable(GraphicalFrame shape) { - return new DrawGraphicalFrame(shape); - } - - public DrawTextParagraph getDrawable(TextParagraph paragraph) { - return new DrawTextParagraph(paragraph); - } - - public DrawBackground getDrawable(Background shape) { - return new DrawBackground(shape); - } - - public DrawTextFragment getTextFragment(TextLayout layout, AttributedString str) { - return new DrawTextFragment(layout, str); - } - - public DrawPaint getPaint(PlaceableShape shape) { - return new DrawPaint(shape); - } - - /** - * Convenience method for drawing single shapes. - * For drawing whole slides, use {@link Slide#draw(Graphics2D)} - * - * @param graphics the graphics context to draw to - * @param shape the shape - * @param bounds the bounds within the graphics context to draw to - */ - public void drawShape(Graphics2D graphics, Shape shape, Rectangle2D bounds) { - Rectangle2D shapeBounds = shape.getAnchor(); - if (shapeBounds.isEmpty() || (bounds != null && bounds.isEmpty())) { - return; - } - - AffineTransform txg = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); - AffineTransform tx = new AffineTransform(); - try { - if (bounds != null) { - double scaleX = bounds.getWidth()/shapeBounds.getWidth(); - double scaleY = bounds.getHeight()/shapeBounds.getHeight(); - tx.translate(bounds.getCenterX(), bounds.getCenterY()); - tx.scale(scaleX, scaleY); - tx.translate(-shapeBounds.getCenterX(), -shapeBounds.getCenterY()); - } - graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx); - - Drawable d = getDrawable(shape); - d.applyTransform(graphics); - d.draw(graphics); - } finally { - graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, txg); - } - } - - - /** - * Replace font families for Windows JVM 6, which contains a font rendering error. - * This is likely to be removed, when POI upgrades to JDK 7 - * - * @param graphics the graphics context which will contain the font mapping - */ - public void fixFonts(Graphics2D graphics) { - if (!JvmBugs.hasLineBreakMeasurerBug()) return; - @SuppressWarnings("unchecked") - Map fontMap = (Map)graphics.getRenderingHint(Drawable.FONT_MAP); - if (fontMap == null) { - fontMap = new HashMap(); - graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); - } - - String fonts[][] = { { "Calibri", "Lucida Sans" }, { "Cambria", "Lucida Bright" } }; - - for (String f[] : fonts) { - if (!fontMap.containsKey(f[0])) { - fontMap.put(f[0], f[1]); - } - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.text.AttributedString; +import java.util.HashMap; +import java.util.Map; + +import org.apache.poi.sl.usermodel.Background; +import org.apache.poi.sl.usermodel.ConnectorShape; +import org.apache.poi.sl.usermodel.FreeformShape; +import org.apache.poi.sl.usermodel.GraphicalFrame; +import org.apache.poi.sl.usermodel.GroupShape; +import org.apache.poi.sl.usermodel.MasterSheet; +import org.apache.poi.sl.usermodel.PictureShape; +import org.apache.poi.sl.usermodel.PlaceableShape; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.Sheet; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.TableShape; +import org.apache.poi.sl.usermodel.TextBox; +import org.apache.poi.sl.usermodel.TextParagraph; +import org.apache.poi.sl.usermodel.TextShape; +import org.apache.poi.util.JvmBugs; + +public class DrawFactory { + protected static final ThreadLocal defaultFactory = new ThreadLocal(); + + /** + * Set a custom draw factory for the current thread. + * This is a fallback, for operations where usercode can't set a graphics context. + * Preferably use the rendering hint {@link Drawable#DRAW_FACTORY} to set the factory. + * + * @param factory + */ + public static void setDefaultFactory(DrawFactory factory) { + defaultFactory.set(factory); + } + + /** + * Returns the DrawFactory, preferably via a graphics instance. + * If graphics is null, the current thread local is checked or + * if it is not set, a new factory is created. + * + * @param graphics the current graphics context or null + * @return the draw factory + */ + public static DrawFactory getInstance(Graphics2D graphics) { + // first try to find the factory over the rendering hint + DrawFactory factory = null; + boolean isHint = false; + if (graphics != null) { + factory = (DrawFactory)graphics.getRenderingHint(Drawable.DRAW_FACTORY); + isHint = (factory != null); + } + // secondly try the thread local default + if (factory == null) { + factory = defaultFactory.get(); + } + // and at last, use the default factory + if (factory == null) { + factory = new DrawFactory(); + } + if (graphics != null && !isHint) { + graphics.setRenderingHint(Drawable.DRAW_FACTORY, factory); + } + return factory; + } + + public Drawable getDrawable(Shape shape) { + if (shape instanceof TextBox) { + return getDrawable((TextBox)shape); + } else if (shape instanceof FreeformShape) { + return getDrawable((FreeformShape)shape); + } else if (shape instanceof TextShape) { + return getDrawable((TextShape)shape); + } else if (shape instanceof TableShape) { + return getDrawable((TableShape)shape); + } else if (shape instanceof GroupShape) { + return getDrawable((GroupShape)shape); + } else if (shape instanceof PictureShape) { + return getDrawable((PictureShape)shape); + } else if (shape instanceof GraphicalFrame) { + return getDrawable((GraphicalFrame)shape); + } else if (shape instanceof Background) { + return getDrawable((Background)shape); + } else if (shape instanceof ConnectorShape) { + return getDrawable((ConnectorShape)shape); + } else if (shape instanceof Slide) { + return getDrawable((Slide)shape); + } else if (shape instanceof MasterSheet) { + return getDrawable((MasterSheet)shape); + } else if (shape instanceof Sheet) { + return getDrawable((Sheet)shape); + } else if (shape.getClass().isAnnotationPresent(DrawNotImplemented.class)) { + return new DrawNothing(shape); + } + + throw new IllegalArgumentException("Unsupported shape type: "+shape.getClass()); + } + + public DrawSlide getDrawable(Slide sheet) { + return new DrawSlide(sheet); + } + + public DrawSheet getDrawable(Sheet sheet) { + return new DrawSheet(sheet); + } + + public DrawMasterSheet getDrawable(MasterSheet sheet) { + return new DrawMasterSheet(sheet); + } + + public DrawTextBox getDrawable(TextBox shape) { + return new DrawTextBox(shape); + } + + public DrawFreeformShape getDrawable(FreeformShape shape) { + return new DrawFreeformShape(shape); + } + + public DrawConnectorShape getDrawable(ConnectorShape shape) { + return new DrawConnectorShape(shape); + } + + public DrawTableShape getDrawable(TableShape shape) { + return new DrawTableShape(shape); + } + + public DrawTextShape getDrawable(TextShape shape) { + return new DrawTextShape(shape); + } + + public DrawGroupShape getDrawable(GroupShape shape) { + return new DrawGroupShape(shape); + } + + public DrawPictureShape getDrawable(PictureShape shape) { + return new DrawPictureShape(shape); + } + + public DrawGraphicalFrame getDrawable(GraphicalFrame shape) { + return new DrawGraphicalFrame(shape); + } + + public DrawTextParagraph getDrawable(TextParagraph paragraph) { + return new DrawTextParagraph(paragraph); + } + + public DrawBackground getDrawable(Background shape) { + return new DrawBackground(shape); + } + + public DrawTextFragment getTextFragment(TextLayout layout, AttributedString str) { + return new DrawTextFragment(layout, str); + } + + public DrawPaint getPaint(PlaceableShape shape) { + return new DrawPaint(shape); + } + + /** + * Convenience method for drawing single shapes. + * For drawing whole slides, use {@link Slide#draw(Graphics2D)} + * + * @param graphics the graphics context to draw to + * @param shape the shape + * @param bounds the bounds within the graphics context to draw to + */ + public void drawShape(Graphics2D graphics, Shape shape, Rectangle2D bounds) { + Rectangle2D shapeBounds = shape.getAnchor(); + if (shapeBounds.isEmpty() || (bounds != null && bounds.isEmpty())) { + return; + } + + AffineTransform txg = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); + AffineTransform tx = new AffineTransform(); + try { + if (bounds != null) { + double scaleX = bounds.getWidth()/shapeBounds.getWidth(); + double scaleY = bounds.getHeight()/shapeBounds.getHeight(); + tx.translate(bounds.getCenterX(), bounds.getCenterY()); + tx.scale(scaleX, scaleY); + tx.translate(-shapeBounds.getCenterX(), -shapeBounds.getCenterY()); + } + graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx); + + Drawable d = getDrawable(shape); + d.applyTransform(graphics); + d.draw(graphics); + } finally { + graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, txg); + } + } + + + /** + * Replace font families for Windows JVM 6, which contains a font rendering error. + * This is likely to be removed, when POI upgrades to JDK 7 + * + * @param graphics the graphics context which will contain the font mapping + */ + public void fixFonts(Graphics2D graphics) { + if (!JvmBugs.hasLineBreakMeasurerBug()) return; + @SuppressWarnings("unchecked") + Map fontMap = (Map)graphics.getRenderingHint(Drawable.FONT_MAP); + if (fontMap == null) { + fontMap = new HashMap(); + graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); + } + + String fonts[][] = { { "Calibri", "Lucida Sans" }, { "Cambria", "Lucida Bright" } }; + + for (String f[] : fonts) { + if (!fontMap.containsKey(f[0])) { + fontMap.put(f[0], f[1]); + } + } + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/sl/draw/DrawFontManager.java b/src/java/org/apache/poi/sl/draw/DrawFontManager.java index 2416837b09..5b74f8400c 100644 --- a/src/java/org/apache/poi/sl/draw/DrawFontManager.java +++ b/src/java/org/apache/poi/sl/draw/DrawFontManager.java @@ -1,56 +1,56 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.sl.draw; - -/** - * Manages fonts when rendering slides. - * - * Use this class to handle unknown / missing fonts or to substitute fonts - */ -public interface DrawFontManager { - - /** - * select a font to be used to paint text - * - * @param typeface the font family as defined in the .pptx file. - * This can be unknown or missing in the graphic environment. - * @param pitchFamily a pitch-and-family, - * see {@link org.apache.poi.hwmf.record.HwmfFont#getFamily()} and - * {@link org.apache.poi.hwmf.record.HwmfFont#getPitch()} - * for how to calculate those (ancient) values - * - * @return the font to be used to paint text - */ - String getRendererableFont(String typeface, int pitchFamily); - - /** - * In case the original font doesn't contain a glyph, use the - * returned fallback font as an alternative - * - * @param typeface the font family as defined in the .pptx file. - * @param pitchFamily a pitch-and-family, - * see {@link org.apache.poi.hwmf.record.HwmfFont#getFamily()} and - * {@link org.apache.poi.hwmf.record.HwmfFont#getPitch()} - * for how to calculate those (ancient) values - * - * @return the font to be used as a fallback for the original typeface - */ - String getFallbackFont(String typeface, int pitchFamily); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.sl.draw; + +/** + * Manages fonts when rendering slides. + * + * Use this class to handle unknown / missing fonts or to substitute fonts + */ +public interface DrawFontManager { + + /** + * select a font to be used to paint text + * + * @param typeface the font family as defined in the .pptx file. + * This can be unknown or missing in the graphic environment. + * @param pitchFamily a pitch-and-family, + * see {@link org.apache.poi.hwmf.record.HwmfFont#getFamily()} and + * {@link org.apache.poi.hwmf.record.HwmfFont#getPitch()} + * for how to calculate those (ancient) values + * + * @return the font to be used to paint text + */ + String getRendererableFont(String typeface, int pitchFamily); + + /** + * In case the original font doesn't contain a glyph, use the + * returned fallback font as an alternative + * + * @param typeface the font family as defined in the .pptx file. + * @param pitchFamily a pitch-and-family, + * see {@link org.apache.poi.hwmf.record.HwmfFont#getFamily()} and + * {@link org.apache.poi.hwmf.record.HwmfFont#getPitch()} + * for how to calculate those (ancient) values + * + * @return the font to be used as a fallback for the original typeface + */ + String getFallbackFont(String typeface, int pitchFamily); +} diff --git a/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java b/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java index d8f986881d..de9dd5322d 100644 --- a/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java @@ -1,61 +1,61 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Path2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.apache.poi.sl.draw.geom.Outline; -import org.apache.poi.sl.draw.geom.Path; -import org.apache.poi.sl.usermodel.FillStyle; -import org.apache.poi.sl.usermodel.FreeformShape; -import org.apache.poi.sl.usermodel.StrokeStyle; - -public class DrawFreeformShape extends DrawAutoShape { - public DrawFreeformShape(FreeformShape shape) { - super(shape); - } - - protected Collection computeOutlines(Graphics2D graphics) { - List lst = new ArrayList(); - FreeformShape fsh = getShape(); - Path2D sh = fsh.getPath(); - - AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); - if (tx == null) { - tx = new AffineTransform(); - } - - java.awt.Shape canvasShape = tx.createTransformedShape(sh); - - FillStyle fs = fsh.getFillStyle(); - StrokeStyle ss = fsh.getStrokeStyle(); - Path path = new Path(fs != null, ss != null); - lst.add(new Outline(canvasShape, path)); - return lst; - } - - @Override - protected FreeformShape getShape() { - return (FreeformShape)shape; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.poi.sl.draw.geom.Outline; +import org.apache.poi.sl.draw.geom.Path; +import org.apache.poi.sl.usermodel.FillStyle; +import org.apache.poi.sl.usermodel.FreeformShape; +import org.apache.poi.sl.usermodel.StrokeStyle; + +public class DrawFreeformShape extends DrawAutoShape { + public DrawFreeformShape(FreeformShape shape) { + super(shape); + } + + protected Collection computeOutlines(Graphics2D graphics) { + List lst = new ArrayList(); + FreeformShape fsh = getShape(); + Path2D sh = fsh.getPath(); + + AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); + if (tx == null) { + tx = new AffineTransform(); + } + + java.awt.Shape canvasShape = tx.createTransformedShape(sh); + + FillStyle fs = fsh.getFillStyle(); + StrokeStyle ss = fsh.getStrokeStyle(); + Path path = new Path(fs != null, ss != null); + lst.add(new Outline(canvasShape, path)); + return lst; + } + + @Override + protected FreeformShape getShape() { + return (FreeformShape)shape; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawGraphicalFrame.java b/src/java/org/apache/poi/sl/draw/DrawGraphicalFrame.java index c4b75f19d7..0628429f83 100644 --- a/src/java/org/apache/poi/sl/draw/DrawGraphicalFrame.java +++ b/src/java/org/apache/poi/sl/draw/DrawGraphicalFrame.java @@ -1,40 +1,40 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; - -import org.apache.poi.sl.usermodel.GraphicalFrame; -import org.apache.poi.sl.usermodel.PictureShape; - - -public class DrawGraphicalFrame extends DrawShape { - - public DrawGraphicalFrame(GraphicalFrame shape) { - super(shape); - } - - public void draw(Graphics2D context) { - PictureShape ps = ((GraphicalFrame)getShape()).getFallbackPicture(); - if (ps == null) { - return; - } - DrawPictureShape dps = DrawFactory.getInstance(context).getDrawable(ps); - dps.draw(context); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; + +import org.apache.poi.sl.usermodel.GraphicalFrame; +import org.apache.poi.sl.usermodel.PictureShape; + + +public class DrawGraphicalFrame extends DrawShape { + + public DrawGraphicalFrame(GraphicalFrame shape) { + super(shape); + } + + public void draw(Graphics2D context) { + PictureShape ps = ((GraphicalFrame)getShape()).getFallbackPicture(); + if (ps == null) { + return; + } + DrawPictureShape dps = DrawFactory.getInstance(context).getDrawable(ps); + dps.draw(context); + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawGroupShape.java b/src/java/org/apache/poi/sl/draw/DrawGroupShape.java index 999e34c546..3472d85437 100644 --- a/src/java/org/apache/poi/sl/draw/DrawGroupShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawGroupShape.java @@ -1,75 +1,75 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; - -import org.apache.poi.sl.usermodel.*; - - -public class DrawGroupShape extends DrawShape { - - public DrawGroupShape(GroupShape shape) { - super(shape); - } - - public void draw(Graphics2D graphics) { - - // the coordinate system of this group of shape - Rectangle2D interior = getShape().getInteriorAnchor(); - // anchor of this group relative to the parent shape - Rectangle2D exterior = getShape().getAnchor(); - - AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); - AffineTransform tx0 = new AffineTransform(tx); - - double scaleX = interior.getWidth() == 0. ? 1.0 : exterior.getWidth() / interior.getWidth(); - double scaleY = interior.getHeight() == 0. ? 1.0 : exterior.getHeight() / interior.getHeight(); - - tx.translate(exterior.getX(), exterior.getY()); - tx.scale(scaleX, scaleY); - tx.translate(-interior.getX(), -interior.getY()); - - DrawFactory drawFact = DrawFactory.getInstance(graphics); - AffineTransform at2 = graphics.getTransform(); - - for (Shape child : getShape()) { - // remember the initial transform and restore it after we are done with the drawing - AffineTransform at = graphics.getTransform(); - graphics.setRenderingHint(Drawable.GSAVE, true); - - Drawable draw = drawFact.getDrawable(child); - draw.applyTransform(graphics); - draw.draw(graphics); - - // restore the coordinate system - graphics.setTransform(at); - graphics.setRenderingHint(Drawable.GRESTORE, true); - } - - graphics.setTransform(at2); - graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0); - } - - @Override - protected GroupShape getShape() { - return (GroupShape)shape; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.sl.usermodel.*; + + +public class DrawGroupShape extends DrawShape { + + public DrawGroupShape(GroupShape shape) { + super(shape); + } + + public void draw(Graphics2D graphics) { + + // the coordinate system of this group of shape + Rectangle2D interior = getShape().getInteriorAnchor(); + // anchor of this group relative to the parent shape + Rectangle2D exterior = getShape().getAnchor(); + + AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); + AffineTransform tx0 = new AffineTransform(tx); + + double scaleX = interior.getWidth() == 0. ? 1.0 : exterior.getWidth() / interior.getWidth(); + double scaleY = interior.getHeight() == 0. ? 1.0 : exterior.getHeight() / interior.getHeight(); + + tx.translate(exterior.getX(), exterior.getY()); + tx.scale(scaleX, scaleY); + tx.translate(-interior.getX(), -interior.getY()); + + DrawFactory drawFact = DrawFactory.getInstance(graphics); + AffineTransform at2 = graphics.getTransform(); + + for (Shape child : getShape()) { + // remember the initial transform and restore it after we are done with the drawing + AffineTransform at = graphics.getTransform(); + graphics.setRenderingHint(Drawable.GSAVE, true); + + Drawable draw = drawFact.getDrawable(child); + draw.applyTransform(graphics); + draw.draw(graphics); + + // restore the coordinate system + graphics.setTransform(at); + graphics.setRenderingHint(Drawable.GRESTORE, true); + } + + graphics.setTransform(at2); + graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0); + } + + @Override + protected GroupShape getShape() { + return (GroupShape)shape; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java b/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java index a39cf7d68e..9dbbe251cc 100644 --- a/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java +++ b/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java @@ -1,53 +1,53 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; - -import org.apache.poi.sl.usermodel.MasterSheet; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.sl.usermodel.SimpleShape; -import org.apache.poi.sl.usermodel.Slide; - - -public class DrawMasterSheet extends DrawSheet { - - public DrawMasterSheet(MasterSheet sheet) { - super(sheet); - } - - /** - * Checks if this sheet displays the specified shape. - * - * Subclasses can override it and skip certain shapes from drawings, - * for instance, slide masters and layouts don't display placeholders - */ - @Override - protected boolean canDraw(Graphics2D graphics, Shape shape) { - if (shape instanceof SimpleShape) { - // in XSLF, slidenumber and date shapes aren't marked as placeholders opposed to HSLF - Placeholder ph = ((SimpleShape)shape).getPlaceholder(); - if (ph != null) { - Slide slide = (Slide)graphics.getRenderingHint(Drawable.CURRENT_SLIDE); - return slide.getDisplayPlaceholder(ph); - } - } - return true; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; + +import org.apache.poi.sl.usermodel.MasterSheet; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.SimpleShape; +import org.apache.poi.sl.usermodel.Slide; + + +public class DrawMasterSheet extends DrawSheet { + + public DrawMasterSheet(MasterSheet sheet) { + super(sheet); + } + + /** + * Checks if this sheet displays the specified shape. + * + * Subclasses can override it and skip certain shapes from drawings, + * for instance, slide masters and layouts don't display placeholders + */ + @Override + protected boolean canDraw(Graphics2D graphics, Shape shape) { + if (shape instanceof SimpleShape) { + // in XSLF, slidenumber and date shapes aren't marked as placeholders opposed to HSLF + Placeholder ph = ((SimpleShape)shape).getPlaceholder(); + if (ph != null) { + Slide slide = (Slide)graphics.getRenderingHint(Drawable.CURRENT_SLIDE); + return slide.getDisplayPlaceholder(ph); + } + } + return true; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawNotImplemented.java b/src/java/org/apache/poi/sl/draw/DrawNotImplemented.java index 45b80eaaa1..246e8d8a1b 100644 --- a/src/java/org/apache/poi/sl/draw/DrawNotImplemented.java +++ b/src/java/org/apache/poi/sl/draw/DrawNotImplemented.java @@ -1,35 +1,35 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import org.apache.poi.util.Internal; - - -/** - * This is a marker annotation for classes which don't have a defined - * draw implementation. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Internal -public @interface DrawNotImplemented { -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import org.apache.poi.util.Internal; + + +/** + * This is a marker annotation for classes which don't have a defined + * draw implementation. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Internal +public @interface DrawNotImplemented { +} diff --git a/src/java/org/apache/poi/sl/draw/DrawNothing.java b/src/java/org/apache/poi/sl/draw/DrawNothing.java index d1710b2352..f875da7fc5 100644 --- a/src/java/org/apache/poi/sl/draw/DrawNothing.java +++ b/src/java/org/apache/poi/sl/draw/DrawNothing.java @@ -1,47 +1,47 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; - -import org.apache.poi.sl.usermodel.Shape; - - -public class DrawNothing implements Drawable { - - protected final Shape shape; - - public DrawNothing(Shape shape) { - this.shape = shape; - } - - /** - * Apply 2-D transforms before drawing this shape. This includes rotation and flipping. - * - * @param graphics the graphics whos transform matrix will be modified - */ - public void applyTransform(Graphics2D graphics) { - } - - - public void draw(Graphics2D graphics) { - } - - public void drawContent(Graphics2D context) { - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; + +import org.apache.poi.sl.usermodel.Shape; + + +public class DrawNothing implements Drawable { + + protected final Shape shape; + + public DrawNothing(Shape shape) { + this.shape = shape; + } + + /** + * Apply 2-D transforms before drawing this shape. This includes rotation and flipping. + * + * @param graphics the graphics whos transform matrix will be modified + */ + public void applyTransform(Graphics2D graphics) { + } + + + public void draw(Graphics2D graphics) { + } + + public void drawContent(Graphics2D context) { + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawPaint.java b/src/java/org/apache/poi/sl/draw/DrawPaint.java index 4bfbe43004..d42e38338a 100644 --- a/src/java/org/apache/poi/sl/draw/DrawPaint.java +++ b/src/java/org/apache/poi/sl/draw/DrawPaint.java @@ -1,524 +1,524 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.LinearGradientPaint; -import java.awt.MultipleGradientPaint.ColorSpaceType; -import java.awt.MultipleGradientPaint.CycleMethod; -import java.awt.Paint; -import java.awt.RadialGradientPaint; -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.sl.usermodel.ColorStyle; -import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; -import org.apache.poi.sl.usermodel.PlaceableShape; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - - -/** - * This class handles color transformations. - * - * @see HSL code taken from Java Tips Weblog - */ -public class DrawPaint { - // HSL code is public domain - see https://tips4java.wordpress.com/contact-us/ - - private static final POILogger LOG = POILogFactory.getLogger(DrawPaint.class); - - private static final Color TRANSPARENT = new Color(1f,1f,1f,0f); - - protected PlaceableShape shape; - - public DrawPaint(PlaceableShape shape) { - this.shape = shape; - } - - private static class SimpleSolidPaint implements SolidPaint { - private final ColorStyle solidColor; - - SimpleSolidPaint(final Color color) { - if (color == null) { - throw new NullPointerException("Color needs to be specified"); - } - this.solidColor = new ColorStyle(){ - public Color getColor() { - return new Color(color.getRed(), color.getGreen(), color.getBlue()); - } - public int getAlpha() { return (int)Math.round(color.getAlpha()*100000./255.); } - public int getHueOff() { return -1; } - public int getHueMod() { return -1; } - public int getSatOff() { return -1; } - public int getSatMod() { return -1; } - public int getLumOff() { return -1; } - public int getLumMod() { return -1; } - public int getShade() { return -1; } - public int getTint() { return -1; } - }; - } - - SimpleSolidPaint(ColorStyle color) { - if (color == null) { - throw new NullPointerException("Color needs to be specified"); - } - this.solidColor = color; - } - - public ColorStyle getSolidColor() { - return solidColor; - } - } - - public static SolidPaint createSolidPaint(final Color color) { - return (color == null) ? null : new SimpleSolidPaint(color); - } - - public static SolidPaint createSolidPaint(final ColorStyle color) { - return (color == null) ? null : new SimpleSolidPaint(color); - } - - public Paint getPaint(Graphics2D graphics, PaintStyle paint) { - if (paint instanceof SolidPaint) { - return getSolidPaint((SolidPaint)paint, graphics); - } else if (paint instanceof GradientPaint) { - return getGradientPaint((GradientPaint)paint, graphics); - } else if (paint instanceof TexturePaint) { - return getTexturePaint((TexturePaint)paint, graphics); - } - return null; - } - - protected Paint getSolidPaint(SolidPaint fill, Graphics2D graphics) { - return applyColorTransform(fill.getSolidColor()); - } - - protected Paint getGradientPaint(GradientPaint fill, Graphics2D graphics) { - switch (fill.getGradientType()) { - case linear: - return createLinearGradientPaint(fill, graphics); - case circular: - return createRadialGradientPaint(fill, graphics); - case shape: - return createPathGradientPaint(fill, graphics); - default: - throw new UnsupportedOperationException("gradient fill of type "+fill+" not supported."); - } - } - - protected Paint getTexturePaint(TexturePaint fill, Graphics2D graphics) { - InputStream is = fill.getImageData(); - if (is == null) return null; - assert(graphics != null); - - ImageRenderer renderer = DrawPictureShape.getImageRenderer(graphics, fill.getContentType()); - - try { - try { - renderer.loadImage(is, fill.getContentType()); - } finally { - is.close(); - } - } catch (IOException e) { - LOG.log(POILogger.ERROR, "Can't load image data - using transparent color", e); - return null; - } - - int alpha = fill.getAlpha(); - if (0 <= alpha && alpha < 100000) { - renderer.setAlpha(alpha/100000.f); - } - - Rectangle2D textAnchor = shape.getAnchor(); - BufferedImage image; - if ("image/x-wmf".equals(fill.getContentType())) { - // don't rely on wmf dimensions, use dimension of anchor - // TODO: check pixels vs. points for image dimension - image = renderer.getImage(new Dimension((int)textAnchor.getWidth(), (int)textAnchor.getHeight())); - } else { - image = renderer.getImage(); - } - - if(image == null) { - LOG.log(POILogger.ERROR, "Can't load image data"); - return null; - } - Paint paint = new java.awt.TexturePaint(image, textAnchor); - - return paint; - } - - /** - * Convert color transformations in {@link ColorStyle} to a {@link Color} instance - * - * @see Using Office Open XML to Customize Document Formatting in the 2007 Office System - * @see saturation modulation (satMod) - * @see Office Open XML satMod results in more than 100% saturation - */ - public static Color applyColorTransform(ColorStyle color){ - // TODO: The colors don't match 100% the results of Powerpoint, maybe because we still - // operate in sRGB and not scRGB ... work in progress ... - if (color == null || color.getColor() == null) { - return TRANSPARENT; - } - - Color result = color.getColor(); - - double alpha = getAlpha(result, color); - double hsl[] = RGB2HSL(result); // values are in the range [0..100] (usually ...) - applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff()); - applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff()); - applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff()); - applyShade(hsl, color); - applyTint(hsl, color); - - result = HSL2RGB(hsl[0], hsl[1], hsl[2], alpha); - - return result; - } - - private static double getAlpha(Color c, ColorStyle fc) { - double alpha = c.getAlpha()/255d; - int fcAlpha = fc.getAlpha(); - if (fcAlpha != -1) { - alpha *= fcAlpha/100000d; - } - return Math.min(1, Math.max(0, alpha)); - } - - /** - * Apply the modulation and offset adjustments to the given HSL part - * - * Example for lumMod/lumOff: - * The lumMod value is the percent luminance. A lumMod value of "60000", - * is 60% of the luminance of the original color. - * When the color is a shade of the original theme color, the lumMod - * attribute is the only one of the tags shown here that appears. - * The tag appears after the tag when the color is a - * tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation - * - * Despite having different ways to display the tint and shade percentages, - * all of the programs use the same method to calculate the resulting color. - * Convert the original RGB value to HSL ... and then adjust the luminance (L) - * with one of the following equations before converting the HSL value back to RGB. - * (The % tint in the following equations refers to the tint, themetint, themeshade, - * or lumMod values, as applicable.) - * - * @param hsl the hsl values - * @param hslPart the hsl part to modify [0..2] - * @param mod the modulation adjustment - * @param off the offset adjustment - * @return the modified hsl value - * - */ - private static void applyHslModOff(double hsl[], int hslPart, int mod, int off) { - if (mod == -1) mod = 100000; - if (off == -1) off = 0; - if (!(mod == 100000 && off == 0)) { - double fOff = off / 1000d; - double fMod = mod / 100000d; - hsl[hslPart] = hsl[hslPart]*fMod+fOff; - } - } - - /** - * Apply the shade - * - * For a shade, the equation is luminance * %tint. - */ - private static void applyShade(double hsl[], ColorStyle fc) { - int shade = fc.getShade(); - if (shade == -1) return; - - double fshade = shade / 100000.d; - - hsl[2] *= fshade; - } - - /** - * Apply the tint - * - * For a tint, the equation is luminance * %tint + (1-%tint). - * (Note that 1-%tint is equal to the lumOff value in DrawingML.) - */ - private static void applyTint(double hsl[], ColorStyle fc) { - int tint = fc.getTint(); - if (tint == -1) return; - - double ftint = tint / 100000.f; - - hsl[2] = hsl[2] * ftint + (100 - ftint*100.); - } - - - protected Paint createLinearGradientPaint(GradientPaint fill, Graphics2D graphics) { - double angle = fill.getGradientAngle(); - Rectangle2D anchor = DrawShape.getAnchor(graphics, shape); - - AffineTransform at = AffineTransform.getRotateInstance( - Math.toRadians(angle), - anchor.getX() + anchor.getWidth() / 2, - anchor.getY() + anchor.getHeight() / 2); - - double diagonal = Math.sqrt(anchor.getHeight() * anchor.getHeight() + anchor.getWidth() * anchor.getWidth()); - Point2D p1 = new Point2D.Double(anchor.getX() + anchor.getWidth() / 2 - diagonal / 2, - anchor.getY() + anchor.getHeight() / 2); - p1 = at.transform(p1, null); - - Point2D p2 = new Point2D.Double(anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight() / 2); - p2 = at.transform(p2, null); - - snapToAnchor(p1, anchor); - snapToAnchor(p2, anchor); - - if (p1.equals(p2)) { - // gradient paint on the same point throws an exception ... and doesn't make sense - return null; - } - - float[] fractions = fill.getGradientFractions(); - Color[] colors = new Color[fractions.length]; - - int i = 0; - for (ColorStyle fc : fill.getGradientColors()) { - // if fc is null, use transparent color to get color of background - colors[i++] = (fc == null) ? TRANSPARENT : applyColorTransform(fc); - } - - AffineTransform grAt = new AffineTransform(); - if(fill.isRotatedWithShape()) { - double rotation = shape.getRotation(); - if (rotation != 0.) { - double centerX = anchor.getX() + anchor.getWidth() / 2; - double centerY = anchor.getY() + anchor.getHeight() / 2; - - grAt.translate(centerX, centerY); - grAt.rotate(Math.toRadians(-rotation)); - grAt.translate(-centerX, -centerY); - } - } - - return new LinearGradientPaint - (p1, p2, fractions, colors, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, grAt); - } - - protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) { - Rectangle2D anchor = DrawShape.getAnchor(graphics, shape); - - Point2D pCenter = new Point2D.Double(anchor.getX() + anchor.getWidth()/2, - anchor.getY() + anchor.getHeight()/2); - - float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight()); - - float[] fractions = fill.getGradientFractions(); - Color[] colors = new Color[fractions.length]; - - int i=0; - for (ColorStyle fc : fill.getGradientColors()) { - colors[i++] = applyColorTransform(fc); - } - - return new RadialGradientPaint(pCenter, radius, fractions, colors); - } - - protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) { - // currently we ignore an eventually center setting - - float[] fractions = fill.getGradientFractions(); - Color[] colors = new Color[fractions.length]; - - int i=0; - for (ColorStyle fc : fill.getGradientColors()) { - colors[i++] = applyColorTransform(fc); - } - - return new PathGradientPaint(colors, fractions); - } - - protected void snapToAnchor(Point2D p, Rectangle2D anchor) { - if (p.getX() < anchor.getX()) { - p.setLocation(anchor.getX(), p.getY()); - } else if (p.getX() > (anchor.getX() + anchor.getWidth())) { - p.setLocation(anchor.getX() + anchor.getWidth(), p.getY()); - } - - if (p.getY() < anchor.getY()) { - p.setLocation(p.getX(), anchor.getY()); - } else if (p.getY() > (anchor.getY() + anchor.getHeight())) { - p.setLocation(p.getX(), anchor.getY() + anchor.getHeight()); - } - } - - /** - * Convert HSL values to a RGB Color. - * - * @param h Hue is specified as degrees in the range 0 - 360. - * @param s Saturation is specified as a percentage in the range 1 - 100. - * @param l Luminance is specified as a percentage in the range 1 - 100. - * @param alpha the alpha value between 0 - 1 - * - * @return the RGB Color object - */ - public static Color HSL2RGB(double h, double s, double l, double alpha) { - // we clamp the values, as it possible to come up with more than 100% sat/lum - // (see links in applyColorTransform() for more info) - s = Math.max(0, Math.min(100, s)); - l = Math.max(0, Math.min(100, l)); - - if (alpha <0.0f || alpha > 1.0f) { - String message = "Color parameter outside of expected range - Alpha: " + alpha; - throw new IllegalArgumentException( message ); - } - - // Formula needs all values between 0 - 1. - - h = h % 360.0f; - h /= 360f; - s /= 100f; - l /= 100f; - - double q = (l < 0.5d) - ? l * (1d + s) - : (l + s) - (s * l); - - double p = 2d * l - q; - - double r = Math.max(0, HUE2RGB(p, q, h + (1.0d / 3.0d))); - double g = Math.max(0, HUE2RGB(p, q, h)); - double b = Math.max(0, HUE2RGB(p, q, h - (1.0d / 3.0d))); - - r = Math.min(r, 1.0d); - g = Math.min(g, 1.0d); - b = Math.min(b, 1.0d); - - return new Color((float)r, (float)g, (float)b, (float)alpha); - } - - private static double HUE2RGB(double p, double q, double h) { - if (h < 0d) h += 1d; - - if (h > 1d) h -= 1d; - - if (6d * h < 1d) { - return p + ((q - p) * 6d * h); - } - - if (2d * h < 1d) { - return q; - } - - if (3d * h < 2d) { - return p + ( (q - p) * 6d * ((2.0d / 3.0d) - h) ); - } - - return p; - } - - - /** - * Convert a RGB Color to it corresponding HSL values. - * - * @return an array containing the 3 HSL values. - */ - private static double[] RGB2HSL(Color color) - { - // Get RGB values in the range 0 - 1 - - float[] rgb = color.getRGBColorComponents( null ); - double r = rgb[0]; - double g = rgb[1]; - double b = rgb[2]; - - // Minimum and Maximum RGB values are used in the HSL calculations - - double min = Math.min(r, Math.min(g, b)); - double max = Math.max(r, Math.max(g, b)); - - // Calculate the Hue - - double h = 0; - - if (max == min) { - h = 0; - } else if (max == r) { - h = ((60d * (g - b) / (max - min)) + 360d) % 360d; - } else if (max == g) { - h = (60d * (b - r) / (max - min)) + 120d; - } else if (max == b) { - h = (60d * (r - g) / (max - min)) + 240d; - } - - // Calculate the Luminance - - double l = (max + min) / 2d; - - // Calculate the Saturation - - double s = 0; - - if (max == min) { - s = 0; - } else if (l <= .5d) { - s = (max - min) / (max + min); - } else { - s = (max - min) / (2d - max - min); - } - - return new double[] {h, s * 100, l * 100}; - } - - /** - * Convert sRGB float component [0..1] from sRGB to linear RGB [0..100000] - * - * @see Color#getRGBColorComponents(float[]) - */ - public static int srgb2lin(float sRGB) { - // scRGB has a linear gamma of 1.0, scale the AWT-Color which is in sRGB to linear RGB - // see https://en.wikipedia.org/wiki/SRGB (the reverse transformation) - if (sRGB <= 0.04045d) { - return (int)Math.rint(100000d * sRGB / 12.92d); - } else { - return (int)Math.rint(100000d * Math.pow((sRGB + 0.055d) / 1.055d, 2.4d)); - } - } - - /** - * Convert linear RGB [0..100000] to sRGB float component [0..1] - * - * @see Color#getRGBColorComponents(float[]) - */ - public static float lin2srgb(int linRGB) { - // color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color - // see https://en.wikipedia.org/wiki/SRGB (The forward transformation) - if (linRGB <= 0.0031308d) { - return (float)(linRGB / 100000d * 12.92d); - } else { - return (float)(1.055d * Math.pow(linRGB / 100000d, 1.0d/2.4d) - 0.055d); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; +import java.awt.MultipleGradientPaint.ColorSpaceType; +import java.awt.MultipleGradientPaint.CycleMethod; +import java.awt.Paint; +import java.awt.RadialGradientPaint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.sl.usermodel.ColorStyle; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; +import org.apache.poi.sl.usermodel.PlaceableShape; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + + +/** + * This class handles color transformations. + * + * @see HSL code taken from Java Tips Weblog + */ +public class DrawPaint { + // HSL code is public domain - see https://tips4java.wordpress.com/contact-us/ + + private static final POILogger LOG = POILogFactory.getLogger(DrawPaint.class); + + private static final Color TRANSPARENT = new Color(1f,1f,1f,0f); + + protected PlaceableShape shape; + + public DrawPaint(PlaceableShape shape) { + this.shape = shape; + } + + private static class SimpleSolidPaint implements SolidPaint { + private final ColorStyle solidColor; + + SimpleSolidPaint(final Color color) { + if (color == null) { + throw new NullPointerException("Color needs to be specified"); + } + this.solidColor = new ColorStyle(){ + public Color getColor() { + return new Color(color.getRed(), color.getGreen(), color.getBlue()); + } + public int getAlpha() { return (int)Math.round(color.getAlpha()*100000./255.); } + public int getHueOff() { return -1; } + public int getHueMod() { return -1; } + public int getSatOff() { return -1; } + public int getSatMod() { return -1; } + public int getLumOff() { return -1; } + public int getLumMod() { return -1; } + public int getShade() { return -1; } + public int getTint() { return -1; } + }; + } + + SimpleSolidPaint(ColorStyle color) { + if (color == null) { + throw new NullPointerException("Color needs to be specified"); + } + this.solidColor = color; + } + + public ColorStyle getSolidColor() { + return solidColor; + } + } + + public static SolidPaint createSolidPaint(final Color color) { + return (color == null) ? null : new SimpleSolidPaint(color); + } + + public static SolidPaint createSolidPaint(final ColorStyle color) { + return (color == null) ? null : new SimpleSolidPaint(color); + } + + public Paint getPaint(Graphics2D graphics, PaintStyle paint) { + if (paint instanceof SolidPaint) { + return getSolidPaint((SolidPaint)paint, graphics); + } else if (paint instanceof GradientPaint) { + return getGradientPaint((GradientPaint)paint, graphics); + } else if (paint instanceof TexturePaint) { + return getTexturePaint((TexturePaint)paint, graphics); + } + return null; + } + + protected Paint getSolidPaint(SolidPaint fill, Graphics2D graphics) { + return applyColorTransform(fill.getSolidColor()); + } + + protected Paint getGradientPaint(GradientPaint fill, Graphics2D graphics) { + switch (fill.getGradientType()) { + case linear: + return createLinearGradientPaint(fill, graphics); + case circular: + return createRadialGradientPaint(fill, graphics); + case shape: + return createPathGradientPaint(fill, graphics); + default: + throw new UnsupportedOperationException("gradient fill of type "+fill+" not supported."); + } + } + + protected Paint getTexturePaint(TexturePaint fill, Graphics2D graphics) { + InputStream is = fill.getImageData(); + if (is == null) return null; + assert(graphics != null); + + ImageRenderer renderer = DrawPictureShape.getImageRenderer(graphics, fill.getContentType()); + + try { + try { + renderer.loadImage(is, fill.getContentType()); + } finally { + is.close(); + } + } catch (IOException e) { + LOG.log(POILogger.ERROR, "Can't load image data - using transparent color", e); + return null; + } + + int alpha = fill.getAlpha(); + if (0 <= alpha && alpha < 100000) { + renderer.setAlpha(alpha/100000.f); + } + + Rectangle2D textAnchor = shape.getAnchor(); + BufferedImage image; + if ("image/x-wmf".equals(fill.getContentType())) { + // don't rely on wmf dimensions, use dimension of anchor + // TODO: check pixels vs. points for image dimension + image = renderer.getImage(new Dimension((int)textAnchor.getWidth(), (int)textAnchor.getHeight())); + } else { + image = renderer.getImage(); + } + + if(image == null) { + LOG.log(POILogger.ERROR, "Can't load image data"); + return null; + } + Paint paint = new java.awt.TexturePaint(image, textAnchor); + + return paint; + } + + /** + * Convert color transformations in {@link ColorStyle} to a {@link Color} instance + * + * @see Using Office Open XML to Customize Document Formatting in the 2007 Office System + * @see saturation modulation (satMod) + * @see Office Open XML satMod results in more than 100% saturation + */ + public static Color applyColorTransform(ColorStyle color){ + // TODO: The colors don't match 100% the results of Powerpoint, maybe because we still + // operate in sRGB and not scRGB ... work in progress ... + if (color == null || color.getColor() == null) { + return TRANSPARENT; + } + + Color result = color.getColor(); + + double alpha = getAlpha(result, color); + double hsl[] = RGB2HSL(result); // values are in the range [0..100] (usually ...) + applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff()); + applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff()); + applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff()); + applyShade(hsl, color); + applyTint(hsl, color); + + result = HSL2RGB(hsl[0], hsl[1], hsl[2], alpha); + + return result; + } + + private static double getAlpha(Color c, ColorStyle fc) { + double alpha = c.getAlpha()/255d; + int fcAlpha = fc.getAlpha(); + if (fcAlpha != -1) { + alpha *= fcAlpha/100000d; + } + return Math.min(1, Math.max(0, alpha)); + } + + /** + * Apply the modulation and offset adjustments to the given HSL part + * + * Example for lumMod/lumOff: + * The lumMod value is the percent luminance. A lumMod value of "60000", + * is 60% of the luminance of the original color. + * When the color is a shade of the original theme color, the lumMod + * attribute is the only one of the tags shown here that appears. + * The tag appears after the tag when the color is a + * tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation + * + * Despite having different ways to display the tint and shade percentages, + * all of the programs use the same method to calculate the resulting color. + * Convert the original RGB value to HSL ... and then adjust the luminance (L) + * with one of the following equations before converting the HSL value back to RGB. + * (The % tint in the following equations refers to the tint, themetint, themeshade, + * or lumMod values, as applicable.) + * + * @param hsl the hsl values + * @param hslPart the hsl part to modify [0..2] + * @param mod the modulation adjustment + * @param off the offset adjustment + * @return the modified hsl value + * + */ + private static void applyHslModOff(double hsl[], int hslPart, int mod, int off) { + if (mod == -1) mod = 100000; + if (off == -1) off = 0; + if (!(mod == 100000 && off == 0)) { + double fOff = off / 1000d; + double fMod = mod / 100000d; + hsl[hslPart] = hsl[hslPart]*fMod+fOff; + } + } + + /** + * Apply the shade + * + * For a shade, the equation is luminance * %tint. + */ + private static void applyShade(double hsl[], ColorStyle fc) { + int shade = fc.getShade(); + if (shade == -1) return; + + double fshade = shade / 100000.d; + + hsl[2] *= fshade; + } + + /** + * Apply the tint + * + * For a tint, the equation is luminance * %tint + (1-%tint). + * (Note that 1-%tint is equal to the lumOff value in DrawingML.) + */ + private static void applyTint(double hsl[], ColorStyle fc) { + int tint = fc.getTint(); + if (tint == -1) return; + + double ftint = tint / 100000.f; + + hsl[2] = hsl[2] * ftint + (100 - ftint*100.); + } + + + protected Paint createLinearGradientPaint(GradientPaint fill, Graphics2D graphics) { + double angle = fill.getGradientAngle(); + Rectangle2D anchor = DrawShape.getAnchor(graphics, shape); + + AffineTransform at = AffineTransform.getRotateInstance( + Math.toRadians(angle), + anchor.getX() + anchor.getWidth() / 2, + anchor.getY() + anchor.getHeight() / 2); + + double diagonal = Math.sqrt(anchor.getHeight() * anchor.getHeight() + anchor.getWidth() * anchor.getWidth()); + Point2D p1 = new Point2D.Double(anchor.getX() + anchor.getWidth() / 2 - diagonal / 2, + anchor.getY() + anchor.getHeight() / 2); + p1 = at.transform(p1, null); + + Point2D p2 = new Point2D.Double(anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight() / 2); + p2 = at.transform(p2, null); + + snapToAnchor(p1, anchor); + snapToAnchor(p2, anchor); + + if (p1.equals(p2)) { + // gradient paint on the same point throws an exception ... and doesn't make sense + return null; + } + + float[] fractions = fill.getGradientFractions(); + Color[] colors = new Color[fractions.length]; + + int i = 0; + for (ColorStyle fc : fill.getGradientColors()) { + // if fc is null, use transparent color to get color of background + colors[i++] = (fc == null) ? TRANSPARENT : applyColorTransform(fc); + } + + AffineTransform grAt = new AffineTransform(); + if(fill.isRotatedWithShape()) { + double rotation = shape.getRotation(); + if (rotation != 0.) { + double centerX = anchor.getX() + anchor.getWidth() / 2; + double centerY = anchor.getY() + anchor.getHeight() / 2; + + grAt.translate(centerX, centerY); + grAt.rotate(Math.toRadians(-rotation)); + grAt.translate(-centerX, -centerY); + } + } + + return new LinearGradientPaint + (p1, p2, fractions, colors, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, grAt); + } + + protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) { + Rectangle2D anchor = DrawShape.getAnchor(graphics, shape); + + Point2D pCenter = new Point2D.Double(anchor.getX() + anchor.getWidth()/2, + anchor.getY() + anchor.getHeight()/2); + + float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight()); + + float[] fractions = fill.getGradientFractions(); + Color[] colors = new Color[fractions.length]; + + int i=0; + for (ColorStyle fc : fill.getGradientColors()) { + colors[i++] = applyColorTransform(fc); + } + + return new RadialGradientPaint(pCenter, radius, fractions, colors); + } + + protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) { + // currently we ignore an eventually center setting + + float[] fractions = fill.getGradientFractions(); + Color[] colors = new Color[fractions.length]; + + int i=0; + for (ColorStyle fc : fill.getGradientColors()) { + colors[i++] = applyColorTransform(fc); + } + + return new PathGradientPaint(colors, fractions); + } + + protected void snapToAnchor(Point2D p, Rectangle2D anchor) { + if (p.getX() < anchor.getX()) { + p.setLocation(anchor.getX(), p.getY()); + } else if (p.getX() > (anchor.getX() + anchor.getWidth())) { + p.setLocation(anchor.getX() + anchor.getWidth(), p.getY()); + } + + if (p.getY() < anchor.getY()) { + p.setLocation(p.getX(), anchor.getY()); + } else if (p.getY() > (anchor.getY() + anchor.getHeight())) { + p.setLocation(p.getX(), anchor.getY() + anchor.getHeight()); + } + } + + /** + * Convert HSL values to a RGB Color. + * + * @param h Hue is specified as degrees in the range 0 - 360. + * @param s Saturation is specified as a percentage in the range 1 - 100. + * @param l Luminance is specified as a percentage in the range 1 - 100. + * @param alpha the alpha value between 0 - 1 + * + * @return the RGB Color object + */ + public static Color HSL2RGB(double h, double s, double l, double alpha) { + // we clamp the values, as it possible to come up with more than 100% sat/lum + // (see links in applyColorTransform() for more info) + s = Math.max(0, Math.min(100, s)); + l = Math.max(0, Math.min(100, l)); + + if (alpha <0.0f || alpha > 1.0f) { + String message = "Color parameter outside of expected range - Alpha: " + alpha; + throw new IllegalArgumentException( message ); + } + + // Formula needs all values between 0 - 1. + + h = h % 360.0f; + h /= 360f; + s /= 100f; + l /= 100f; + + double q = (l < 0.5d) + ? l * (1d + s) + : (l + s) - (s * l); + + double p = 2d * l - q; + + double r = Math.max(0, HUE2RGB(p, q, h + (1.0d / 3.0d))); + double g = Math.max(0, HUE2RGB(p, q, h)); + double b = Math.max(0, HUE2RGB(p, q, h - (1.0d / 3.0d))); + + r = Math.min(r, 1.0d); + g = Math.min(g, 1.0d); + b = Math.min(b, 1.0d); + + return new Color((float)r, (float)g, (float)b, (float)alpha); + } + + private static double HUE2RGB(double p, double q, double h) { + if (h < 0d) h += 1d; + + if (h > 1d) h -= 1d; + + if (6d * h < 1d) { + return p + ((q - p) * 6d * h); + } + + if (2d * h < 1d) { + return q; + } + + if (3d * h < 2d) { + return p + ( (q - p) * 6d * ((2.0d / 3.0d) - h) ); + } + + return p; + } + + + /** + * Convert a RGB Color to it corresponding HSL values. + * + * @return an array containing the 3 HSL values. + */ + private static double[] RGB2HSL(Color color) + { + // Get RGB values in the range 0 - 1 + + float[] rgb = color.getRGBColorComponents( null ); + double r = rgb[0]; + double g = rgb[1]; + double b = rgb[2]; + + // Minimum and Maximum RGB values are used in the HSL calculations + + double min = Math.min(r, Math.min(g, b)); + double max = Math.max(r, Math.max(g, b)); + + // Calculate the Hue + + double h = 0; + + if (max == min) { + h = 0; + } else if (max == r) { + h = ((60d * (g - b) / (max - min)) + 360d) % 360d; + } else if (max == g) { + h = (60d * (b - r) / (max - min)) + 120d; + } else if (max == b) { + h = (60d * (r - g) / (max - min)) + 240d; + } + + // Calculate the Luminance + + double l = (max + min) / 2d; + + // Calculate the Saturation + + double s = 0; + + if (max == min) { + s = 0; + } else if (l <= .5d) { + s = (max - min) / (max + min); + } else { + s = (max - min) / (2d - max - min); + } + + return new double[] {h, s * 100, l * 100}; + } + + /** + * Convert sRGB float component [0..1] from sRGB to linear RGB [0..100000] + * + * @see Color#getRGBColorComponents(float[]) + */ + public static int srgb2lin(float sRGB) { + // scRGB has a linear gamma of 1.0, scale the AWT-Color which is in sRGB to linear RGB + // see https://en.wikipedia.org/wiki/SRGB (the reverse transformation) + if (sRGB <= 0.04045d) { + return (int)Math.rint(100000d * sRGB / 12.92d); + } else { + return (int)Math.rint(100000d * Math.pow((sRGB + 0.055d) / 1.055d, 2.4d)); + } + } + + /** + * Convert linear RGB [0..100000] to sRGB float component [0..1] + * + * @see Color#getRGBColorComponents(float[]) + */ + public static float lin2srgb(int linRGB) { + // color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color + // see https://en.wikipedia.org/wiki/SRGB (The forward transformation) + if (linRGB <= 0.0031308d) { + return (float)(linRGB / 100000d * 12.92d); + } else { + return (float)(1.055d * Math.pow(linRGB / 100000d, 1.0d/2.4d) - 0.055d); + } + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawPictureShape.java b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java index bdc5ab68c4..2d3764e8a2 100644 --- a/src/java/org/apache/poi/sl/draw/DrawPictureShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java @@ -1,204 +1,204 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import org.apache.poi.sl.usermodel.PictureData; -import org.apache.poi.sl.usermodel.PictureData.PictureType; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.sl.usermodel.PictureShape; -import org.apache.poi.sl.usermodel.RectAlign; - - -public class DrawPictureShape extends DrawSimpleShape { - private static final POILogger LOG = POILogFactory.getLogger(DrawPictureShape.class); - private static final String WMF_IMAGE_RENDERER = "org.apache.poi.hwmf.draw.HwmfSLImageRenderer"; - - public DrawPictureShape(PictureShape shape) { - super(shape); - } - - @Override - public void drawContent(Graphics2D graphics) { - PictureData data = getShape().getPictureData(); - if(data == null) return; - - Rectangle2D anchor = getAnchor(graphics, getShape()); - Insets insets = getShape().getClipping(); - - try { - ImageRenderer renderer = getImageRenderer(graphics, data.getContentType()); - renderer.loadImage(data.getData(), data.getContentType()); - renderer.drawImage(graphics, anchor, insets); - } catch (IOException e) { - LOG.log(POILogger.ERROR, "image can't be loaded/rendered.", e); - } - } - - /** - * Returns an ImageRenderer for the PictureData - * - * @param graphics - * @return the image renderer - */ - public static ImageRenderer getImageRenderer(Graphics2D graphics, String contentType) { - ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER); - if (renderer != null) { - return renderer; - } - - if (PictureType.WMF.contentType.equals(contentType)) { - try { - @SuppressWarnings("unchecked") - Class irc = (Class) - Thread.currentThread().getContextClassLoader().loadClass(WMF_IMAGE_RENDERER); - return irc.newInstance(); - } catch (Exception e) { - // WMF image renderer is not on the classpath, continuing with BitmapRenderer - // although this doesn't make much sense ... - LOG.log(POILogger.ERROR, "WMF image renderer is not on the classpath - include poi-scratchpad jar!", e); - } - } - - return new BitmapImageRenderer(); - } - - @Override - protected PictureShape getShape() { - return (PictureShape)shape; - } - - /** - * Resize this picture to the default size. - * - * For PNG and JPEG resizes the image to 100%, - * for other types, if the size can't be determined it will be 200x200 pixels. - */ - public void resize() { - PictureShape ps = getShape(); - Dimension dim = ps.getPictureData().getImageDimension(); - - Rectangle2D origRect = ps.getAnchor(); - double x = origRect.getX(); - double y = origRect.getY(); - double w = dim.getWidth(); - double h = dim.getHeight(); - ps.setAnchor(new Rectangle2D.Double(x, y, w, h)); - } - - - /** - * Fit picture shape into the target rectangle, maintaining the aspect ratio - * and repositioning within the target rectangle with a centered alignment. - * - * @param target The target rectangle - */ - public void resize(Rectangle2D target) { - resize(target, RectAlign.CENTER); - } - - - /** - * Fit picture shape into the target rectangle, maintaining the aspect ratio - * and repositioning within the target rectangle based on the specified - * alignment (gravity). - * - * @param target The target rectangle - * @param align - * The alignment within the target rectangle when resizing. - * A null value corresponds to RectAlign.CENTER - */ - public void resize(Rectangle2D target, RectAlign align) { - PictureShape ps = getShape(); - Dimension dim = ps.getPictureData().getImageDimension(); - if (dim.width <= 0 || dim.height <= 0) { - // nothing useful to be done for this case - ps.setAnchor(target); - return; - } - - double w = target.getWidth(); - double h = target.getHeight(); - - // scaling - double sx = w / dim.width; - double sy = h / dim.height; - - // position adjustments - double dx = 0, dy = 0; - - if (sx > sy) { - // use y-scaling for both, reposition x accordingly - w = sy * dim.width; - dx = target.getWidth() - w; - } else if (sy > sx) { - // use x-scaling for both, reposition y accordingly - h = sx * dim.height; - dy = target.getHeight() - h; - } else { - // uniform scaling, can use target values directly - ps.setAnchor(target); - return; - } - - // the positioning - double x = target.getX(); - double y = target.getY(); - switch (align) { - case TOP: // X=balance, Y=ok - x += dx/2; - break; - case TOP_RIGHT: // X=shift, Y=ok - x += dx; - break; - case RIGHT: // X=shift, Y=balance - x += dx; - y += dy/2; - break; - case BOTTOM_RIGHT: // X=shift, Y=shift - x += dx; - y += dy; - break; - case BOTTOM: // X=balance, Y=shift - x += dx/2; - y += dy; - break; - case BOTTOM_LEFT: // X=ok, Y=shift - y += dy; - break; - case LEFT: // X=ok, Y=balance - y += dy/2; - break; - case TOP_LEFT: // X=ok, Y=ok - /* no-op */ - break; - default: // CENTER: X=balance, Y=balance - x += dx/2; - y += dy/2; - break; - } - - ps.setAnchor(new Rectangle2D.Double(x, y, w, h)); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.sl.usermodel.PictureData.PictureType; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.sl.usermodel.PictureShape; +import org.apache.poi.sl.usermodel.RectAlign; + + +public class DrawPictureShape extends DrawSimpleShape { + private static final POILogger LOG = POILogFactory.getLogger(DrawPictureShape.class); + private static final String WMF_IMAGE_RENDERER = "org.apache.poi.hwmf.draw.HwmfSLImageRenderer"; + + public DrawPictureShape(PictureShape shape) { + super(shape); + } + + @Override + public void drawContent(Graphics2D graphics) { + PictureData data = getShape().getPictureData(); + if(data == null) return; + + Rectangle2D anchor = getAnchor(graphics, getShape()); + Insets insets = getShape().getClipping(); + + try { + ImageRenderer renderer = getImageRenderer(graphics, data.getContentType()); + renderer.loadImage(data.getData(), data.getContentType()); + renderer.drawImage(graphics, anchor, insets); + } catch (IOException e) { + LOG.log(POILogger.ERROR, "image can't be loaded/rendered.", e); + } + } + + /** + * Returns an ImageRenderer for the PictureData + * + * @param graphics + * @return the image renderer + */ + public static ImageRenderer getImageRenderer(Graphics2D graphics, String contentType) { + ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER); + if (renderer != null) { + return renderer; + } + + if (PictureType.WMF.contentType.equals(contentType)) { + try { + @SuppressWarnings("unchecked") + Class irc = (Class) + Thread.currentThread().getContextClassLoader().loadClass(WMF_IMAGE_RENDERER); + return irc.newInstance(); + } catch (Exception e) { + // WMF image renderer is not on the classpath, continuing with BitmapRenderer + // although this doesn't make much sense ... + LOG.log(POILogger.ERROR, "WMF image renderer is not on the classpath - include poi-scratchpad jar!", e); + } + } + + return new BitmapImageRenderer(); + } + + @Override + protected PictureShape getShape() { + return (PictureShape)shape; + } + + /** + * Resize this picture to the default size. + * + * For PNG and JPEG resizes the image to 100%, + * for other types, if the size can't be determined it will be 200x200 pixels. + */ + public void resize() { + PictureShape ps = getShape(); + Dimension dim = ps.getPictureData().getImageDimension(); + + Rectangle2D origRect = ps.getAnchor(); + double x = origRect.getX(); + double y = origRect.getY(); + double w = dim.getWidth(); + double h = dim.getHeight(); + ps.setAnchor(new Rectangle2D.Double(x, y, w, h)); + } + + + /** + * Fit picture shape into the target rectangle, maintaining the aspect ratio + * and repositioning within the target rectangle with a centered alignment. + * + * @param target The target rectangle + */ + public void resize(Rectangle2D target) { + resize(target, RectAlign.CENTER); + } + + + /** + * Fit picture shape into the target rectangle, maintaining the aspect ratio + * and repositioning within the target rectangle based on the specified + * alignment (gravity). + * + * @param target The target rectangle + * @param align + * The alignment within the target rectangle when resizing. + * A null value corresponds to RectAlign.CENTER + */ + public void resize(Rectangle2D target, RectAlign align) { + PictureShape ps = getShape(); + Dimension dim = ps.getPictureData().getImageDimension(); + if (dim.width <= 0 || dim.height <= 0) { + // nothing useful to be done for this case + ps.setAnchor(target); + return; + } + + double w = target.getWidth(); + double h = target.getHeight(); + + // scaling + double sx = w / dim.width; + double sy = h / dim.height; + + // position adjustments + double dx = 0, dy = 0; + + if (sx > sy) { + // use y-scaling for both, reposition x accordingly + w = sy * dim.width; + dx = target.getWidth() - w; + } else if (sy > sx) { + // use x-scaling for both, reposition y accordingly + h = sx * dim.height; + dy = target.getHeight() - h; + } else { + // uniform scaling, can use target values directly + ps.setAnchor(target); + return; + } + + // the positioning + double x = target.getX(); + double y = target.getY(); + switch (align) { + case TOP: // X=balance, Y=ok + x += dx/2; + break; + case TOP_RIGHT: // X=shift, Y=ok + x += dx; + break; + case RIGHT: // X=shift, Y=balance + x += dx; + y += dy/2; + break; + case BOTTOM_RIGHT: // X=shift, Y=shift + x += dx; + y += dy; + break; + case BOTTOM: // X=balance, Y=shift + x += dx/2; + y += dy; + break; + case BOTTOM_LEFT: // X=ok, Y=shift + y += dy; + break; + case LEFT: // X=ok, Y=balance + y += dy/2; + break; + case TOP_LEFT: // X=ok, Y=ok + /* no-op */ + break; + default: // CENTER: X=balance, Y=balance + x += dx/2; + y += dy/2; + break; + } + + ps.setAnchor(new Rectangle2D.Double(x, y, w, h)); + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawShape.java b/src/java/org/apache/poi/sl/draw/DrawShape.java index bb1f490bf6..6ce586f1a5 100644 --- a/src/java/org/apache/poi/sl/draw/DrawShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawShape.java @@ -1,241 +1,241 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.BasicStroke; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.util.Locale; - -import org.apache.poi.sl.usermodel.PlaceableShape; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.sl.usermodel.StrokeStyle; -import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; -import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; - - -public class DrawShape implements Drawable { - - protected final Shape shape; - - public DrawShape(Shape shape) { - this.shape = shape; - } - - /** - * Sometimes it's necessary to distinguish between XSLF/HSLF for the rendering. - * Use this method on the shape to determine, if we work on the BIFF implementation - * - * @param shape the shape to render - * @return {@code true} if HSLF implementation is used - */ - protected static boolean isHSLF(Shape shape) { - return shape.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf"); - } - - /** - * Apply 2-D transforms before drawing this shape. This includes rotation and flipping. - * - * @param graphics the graphics whos transform matrix will be modified - */ - @Override - public void applyTransform(Graphics2D graphics) { - if (!(shape instanceof PlaceableShape)) { - return; - } - - PlaceableShape ps = (PlaceableShape)shape; - final boolean isHSLF = isHSLF(shape); - AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); - if (tx == null) { - tx = new AffineTransform(); - } - final Rectangle2D anchor = tx.createTransformedShape(ps.getAnchor()).getBounds2D(); - - char cmds[] = isHSLF ? new char[]{ 'h','v','r' } : new char[]{ 'r','h','v' }; - for (char ch : cmds) { - switch (ch) { - case 'h': - //flip horizontal - if (ps.getFlipHorizontal()) { - graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY()); - graphics.scale(-1, 1); - graphics.translate(-anchor.getX(), -anchor.getY()); - } - break; - case 'v': - //flip vertical - if (ps.getFlipVertical()) { - graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight()); - graphics.scale(1, -1); - graphics.translate(-anchor.getX(), -anchor.getY()); - } - break; - case 'r': - // rotation - double rotation = ps.getRotation(); - if (rotation != 0.) { - // PowerPoint rotates shapes relative to the geometric center - double centerX = anchor.getCenterX(); - double centerY = anchor.getCenterY(); - - // normalize rotation - rotation %= 360.; - if (rotation < 0) { - rotation += 360.; - } - - int quadrant = (((int)rotation+45)/90)%4; - double scaleX = 1.0, scaleY = 1.0; - - // scale to bounding box (bug #53176) - if (quadrant == 1 || quadrant == 3) { - // In quadrant 1 and 3, which is basically a shape in a more or less portrait orientation - // (45-135 degrees and 225-315 degrees), we need to first rotate the shape by a multiple - // of 90 degrees and then resize the bounding box to its original bbox. After that we can - // rotate the shape to the exact rotation amount. - // It's strange that you'll need to rotate the shape back and forth again, but you can - // think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might - // be already (differently) scaled, so you can paint the shape in its default orientation - // and later on, turn it around again to compare it with its original size ... - - AffineTransform txs; - if (isHSLF) { - txs = new AffineTransform(tx); - } else { - // this handling is only based on try and error ... not sure why xslf is handled differently. - txs = new AffineTransform(); - txs.translate(centerX, centerY); - txs.rotate(Math.PI/2.); // actually doesn't matter if +/- 90 degrees - txs.translate(-centerX, -centerY); - txs.concatenate(tx); - } - - txs.translate(centerX, centerY); - txs.rotate(Math.PI/2.); - txs.translate(-centerX, -centerY); - - Rectangle2D anchor2 = txs.createTransformedShape(ps.getAnchor()).getBounds2D(); - - scaleX = safeScale(anchor.getWidth(), anchor2.getWidth()); - scaleY = safeScale(anchor.getHeight(), anchor2.getHeight()); - } else { - quadrant = 0; - } - - // transformation is applied reversed ... - graphics.translate(centerX, centerY); - double rot = Math.toRadians(rotation-quadrant*90.); - if (rot != 0) { - graphics.rotate(rot); - } - graphics.scale(scaleX, scaleY); - rot = Math.toRadians(quadrant*90.); - if (rot != 0) { - graphics.rotate(rot); - } - graphics.translate(-centerX, -centerY); - } - break; - default: - throw new RuntimeException("unexpected transform code " + ch); - } - } - } - - private static double safeScale(double dim1, double dim2) { - if (dim1 == 0.) { - return 1; - } - return (dim2 == 0.) ? 1 : dim1/dim2; - } - - @Override - public void draw(Graphics2D graphics) { - } - - @Override - public void drawContent(Graphics2D graphics) { - } - - public static Rectangle2D getAnchor(Graphics2D graphics, PlaceableShape shape) { - return getAnchor(graphics, shape.getAnchor()); - } - - public static Rectangle2D getAnchor(Graphics2D graphics, Rectangle2D anchor) { - if(graphics == null) { - return anchor; - } - - AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); - if(tx != null) { - anchor = tx.createTransformedShape(anchor).getBounds2D(); - } - return anchor; - } - - protected Shape getShape() { - return shape; - } - - protected static BasicStroke getStroke(StrokeStyle strokeStyle) { - float lineWidth = (float) strokeStyle.getLineWidth(); - if (lineWidth == 0.0f) { - // Both PowerPoint and OOo draw zero-length lines as 0.25pt - lineWidth = 0.25f; - } - - LineDash lineDash = strokeStyle.getLineDash(); - if (lineDash == null) { - lineDash = LineDash.SOLID; - } - - int dashPatI[] = lineDash.pattern; - final float dash_phase = 0; - float[] dashPatF = null; - if (dashPatI != null) { - dashPatF = new float[dashPatI.length]; - for (int i=0; i shape; + + public DrawShape(Shape shape) { + this.shape = shape; + } + + /** + * Sometimes it's necessary to distinguish between XSLF/HSLF for the rendering. + * Use this method on the shape to determine, if we work on the BIFF implementation + * + * @param shape the shape to render + * @return {@code true} if HSLF implementation is used + */ + protected static boolean isHSLF(Shape shape) { + return shape.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf"); + } + + /** + * Apply 2-D transforms before drawing this shape. This includes rotation and flipping. + * + * @param graphics the graphics whos transform matrix will be modified + */ + @Override + public void applyTransform(Graphics2D graphics) { + if (!(shape instanceof PlaceableShape)) { + return; + } + + PlaceableShape ps = (PlaceableShape)shape; + final boolean isHSLF = isHSLF(shape); + AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); + if (tx == null) { + tx = new AffineTransform(); + } + final Rectangle2D anchor = tx.createTransformedShape(ps.getAnchor()).getBounds2D(); + + char cmds[] = isHSLF ? new char[]{ 'h','v','r' } : new char[]{ 'r','h','v' }; + for (char ch : cmds) { + switch (ch) { + case 'h': + //flip horizontal + if (ps.getFlipHorizontal()) { + graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY()); + graphics.scale(-1, 1); + graphics.translate(-anchor.getX(), -anchor.getY()); + } + break; + case 'v': + //flip vertical + if (ps.getFlipVertical()) { + graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight()); + graphics.scale(1, -1); + graphics.translate(-anchor.getX(), -anchor.getY()); + } + break; + case 'r': + // rotation + double rotation = ps.getRotation(); + if (rotation != 0.) { + // PowerPoint rotates shapes relative to the geometric center + double centerX = anchor.getCenterX(); + double centerY = anchor.getCenterY(); + + // normalize rotation + rotation %= 360.; + if (rotation < 0) { + rotation += 360.; + } + + int quadrant = (((int)rotation+45)/90)%4; + double scaleX = 1.0, scaleY = 1.0; + + // scale to bounding box (bug #53176) + if (quadrant == 1 || quadrant == 3) { + // In quadrant 1 and 3, which is basically a shape in a more or less portrait orientation + // (45-135 degrees and 225-315 degrees), we need to first rotate the shape by a multiple + // of 90 degrees and then resize the bounding box to its original bbox. After that we can + // rotate the shape to the exact rotation amount. + // It's strange that you'll need to rotate the shape back and forth again, but you can + // think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might + // be already (differently) scaled, so you can paint the shape in its default orientation + // and later on, turn it around again to compare it with its original size ... + + AffineTransform txs; + if (isHSLF) { + txs = new AffineTransform(tx); + } else { + // this handling is only based on try and error ... not sure why xslf is handled differently. + txs = new AffineTransform(); + txs.translate(centerX, centerY); + txs.rotate(Math.PI/2.); // actually doesn't matter if +/- 90 degrees + txs.translate(-centerX, -centerY); + txs.concatenate(tx); + } + + txs.translate(centerX, centerY); + txs.rotate(Math.PI/2.); + txs.translate(-centerX, -centerY); + + Rectangle2D anchor2 = txs.createTransformedShape(ps.getAnchor()).getBounds2D(); + + scaleX = safeScale(anchor.getWidth(), anchor2.getWidth()); + scaleY = safeScale(anchor.getHeight(), anchor2.getHeight()); + } else { + quadrant = 0; + } + + // transformation is applied reversed ... + graphics.translate(centerX, centerY); + double rot = Math.toRadians(rotation-quadrant*90.); + if (rot != 0) { + graphics.rotate(rot); + } + graphics.scale(scaleX, scaleY); + rot = Math.toRadians(quadrant*90.); + if (rot != 0) { + graphics.rotate(rot); + } + graphics.translate(-centerX, -centerY); + } + break; + default: + throw new RuntimeException("unexpected transform code " + ch); + } + } + } + + private static double safeScale(double dim1, double dim2) { + if (dim1 == 0.) { + return 1; + } + return (dim2 == 0.) ? 1 : dim1/dim2; + } + + @Override + public void draw(Graphics2D graphics) { + } + + @Override + public void drawContent(Graphics2D graphics) { + } + + public static Rectangle2D getAnchor(Graphics2D graphics, PlaceableShape shape) { + return getAnchor(graphics, shape.getAnchor()); + } + + public static Rectangle2D getAnchor(Graphics2D graphics, Rectangle2D anchor) { + if(graphics == null) { + return anchor; + } + + AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM); + if(tx != null) { + anchor = tx.createTransformedShape(anchor).getBounds2D(); + } + return anchor; + } + + protected Shape getShape() { + return shape; + } + + protected static BasicStroke getStroke(StrokeStyle strokeStyle) { + float lineWidth = (float) strokeStyle.getLineWidth(); + if (lineWidth == 0.0f) { + // Both PowerPoint and OOo draw zero-length lines as 0.25pt + lineWidth = 0.25f; + } + + LineDash lineDash = strokeStyle.getLineDash(); + if (lineDash == null) { + lineDash = LineDash.SOLID; + } + + int dashPatI[] = lineDash.pattern; + final float dash_phase = 0; + float[] dashPatF = null; + if (dashPatI != null) { + dashPatF = new float[dashPatI.length]; + for (int i=0; i sheet; - - public DrawSheet(Sheet sheet) { - this.sheet = sheet; - } - - @Override - public void draw(Graphics2D graphics) { - Dimension dim = sheet.getSlideShow().getPageSize(); - Color whiteTrans = new Color(1f,1f,1f,0f); - graphics.setColor(whiteTrans); - graphics.fillRect(0, 0, (int)dim.getWidth(), (int)dim.getHeight()); - - DrawFactory drawFact = DrawFactory.getInstance(graphics); - MasterSheet master = sheet.getMasterSheet(); - - if(sheet.getFollowMasterGraphics() && master != null) { - Drawable drawer = drawFact.getDrawable(master); - drawer.draw(graphics); - } - - graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, new AffineTransform()); - - for (Shape shape : sheet.getShapes()) { - if(!canDraw(graphics, shape)) { - continue; - } - - // remember the initial transform and restore it after we are done with drawing - AffineTransform at = graphics.getTransform(); - - // concrete implementations can make sense of this hint, - // for example PSGraphics2D or PDFGraphics2D would call gsave() / grestore - graphics.setRenderingHint(Drawable.GSAVE, true); - - // apply rotation and flipping - Drawable drawer = drawFact.getDrawable(shape); - drawer.applyTransform(graphics); - // draw stuff - drawer.draw(graphics); - - // restore the coordinate system - graphics.setTransform(at); - - graphics.setRenderingHint(Drawable.GRESTORE, true); - } - } - - @Override - public void applyTransform(Graphics2D context) { - } - - @Override - public void drawContent(Graphics2D context) { - } - - /** - * Checks if this sheet displays the specified shape. - * - * Subclasses can override it and skip certain shapes from drawings, - * for instance, slide masters and layouts don't display placeholders - */ - protected boolean canDraw(Graphics2D graphics, Shape shape){ - return true; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; + +import org.apache.poi.sl.usermodel.MasterSheet; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.Sheet; + + +public class DrawSheet implements Drawable { + + protected final Sheet sheet; + + public DrawSheet(Sheet sheet) { + this.sheet = sheet; + } + + @Override + public void draw(Graphics2D graphics) { + Dimension dim = sheet.getSlideShow().getPageSize(); + Color whiteTrans = new Color(1f,1f,1f,0f); + graphics.setColor(whiteTrans); + graphics.fillRect(0, 0, (int)dim.getWidth(), (int)dim.getHeight()); + + DrawFactory drawFact = DrawFactory.getInstance(graphics); + MasterSheet master = sheet.getMasterSheet(); + + if(sheet.getFollowMasterGraphics() && master != null) { + Drawable drawer = drawFact.getDrawable(master); + drawer.draw(graphics); + } + + graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, new AffineTransform()); + + for (Shape shape : sheet.getShapes()) { + if(!canDraw(graphics, shape)) { + continue; + } + + // remember the initial transform and restore it after we are done with drawing + AffineTransform at = graphics.getTransform(); + + // concrete implementations can make sense of this hint, + // for example PSGraphics2D or PDFGraphics2D would call gsave() / grestore + graphics.setRenderingHint(Drawable.GSAVE, true); + + // apply rotation and flipping + Drawable drawer = drawFact.getDrawable(shape); + drawer.applyTransform(graphics); + // draw stuff + drawer.draw(graphics); + + // restore the coordinate system + graphics.setTransform(at); + + graphics.setRenderingHint(Drawable.GRESTORE, true); + } + } + + @Override + public void applyTransform(Graphics2D context) { + } + + @Override + public void drawContent(Graphics2D context) { + } + + /** + * Checks if this sheet displays the specified shape. + * + * Subclasses can override it and skip certain shapes from drawings, + * for instance, slide masters and layouts don't display placeholders + */ + protected boolean canDraw(Graphics2D graphics, Shape shape){ + return true; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java index ef0cc08478..ed52a6c9e1 100644 --- a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java @@ -1,446 +1,446 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.geom.AffineTransform; -import java.awt.geom.Ellipse2D; -import java.awt.geom.Path2D; -import java.awt.geom.Rectangle2D; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.Unmarshaller; -import javax.xml.stream.EventFilter; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; - -import org.apache.poi.sl.draw.binding.CTCustomGeometry2D; -import org.apache.poi.sl.draw.geom.Context; -import org.apache.poi.sl.draw.geom.CustomGeometry; -import org.apache.poi.sl.draw.geom.Outline; -import org.apache.poi.sl.draw.geom.Path; -import org.apache.poi.sl.usermodel.LineDecoration; -import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; -import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.apache.poi.sl.usermodel.Shadow; -import org.apache.poi.sl.usermodel.SimpleShape; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.Units; - - -public class DrawSimpleShape extends DrawShape { - - private static final double DECO_SIZE_POW = 1.5d; - - public DrawSimpleShape(SimpleShape shape) { - super(shape); - } - - @Override - public void draw(Graphics2D graphics) { - DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(getShape()); - Paint fill = drawPaint.getPaint(graphics, getShape().getFillStyle().getPaint()); - Paint line = drawPaint.getPaint(graphics, getShape().getStrokeStyle().getPaint()); - BasicStroke stroke = getStroke(); // the stroke applies both to the shadow and the shape - graphics.setStroke(stroke); - - Collection elems = computeOutlines(graphics); - - // first paint the shadow - drawShadow(graphics, elems, fill, line); - - // then fill the shape interior - if (fill != null) { - graphics.setPaint(fill); - for (Outline o : elems) { - if (o.getPath().isFilled()){ - java.awt.Shape s = o.getOutline(); - graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); - graphics.fill(s); - } - } - } - - // then draw any content within this shape (text, image, etc.) - drawContent(graphics); - - // then stroke the shape outline - if(line != null) { - graphics.setPaint(line); - graphics.setStroke(stroke); - for(Outline o : elems){ - if(o.getPath().isStroked()){ - java.awt.Shape s = o.getOutline(); - graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); - graphics.draw(s); - } - } - } - - // draw line decorations - drawDecoration(graphics, line, stroke); - } - - protected void drawDecoration(Graphics2D graphics, Paint line, BasicStroke stroke) { - if(line == null) { - return; - } - graphics.setPaint(line); - - List lst = new ArrayList(); - LineDecoration deco = getShape().getLineDecoration(); - Outline head = getHeadDecoration(graphics, deco, stroke); - if (head != null) { - lst.add(head); - } - Outline tail = getTailDecoration(graphics, deco, stroke); - if (tail != null) { - lst.add(tail); - } - - - for(Outline o : lst){ - java.awt.Shape s = o.getOutline(); - Path p = o.getPath(); - graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); - - if(p.isFilled()) { - graphics.fill(s); - } - if(p.isStroked()) { - graphics.draw(s); - } - } - } - - protected Outline getTailDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) { - if (deco == null || stroke == null) { - return null; - } - DecorationSize tailLength = deco.getTailLength(); - if (tailLength == null) { - tailLength = DecorationSize.MEDIUM; - } - DecorationSize tailWidth = deco.getTailWidth(); - if (tailWidth == null) { - tailWidth = DecorationSize.MEDIUM; - } - - double lineWidth = Math.max(2.5, stroke.getLineWidth()); - - Rectangle2D anchor = getAnchor(graphics, getShape()); - double x2 = anchor.getX() + anchor.getWidth(), - y2 = anchor.getY() + anchor.getHeight(); - - double alpha = Math.atan(anchor.getHeight() / anchor.getWidth()); - - AffineTransform at = new AffineTransform(); - java.awt.Shape tailShape = null; - Path p = null; - Rectangle2D bounds; - final double scaleY = Math.pow(DECO_SIZE_POW, tailWidth.ordinal()+1.); - final double scaleX = Math.pow(DECO_SIZE_POW, tailLength.ordinal()+1.); - - DecorationShape tailShapeEnum = deco.getTailShape(); - - if (tailShapeEnum == null) { - return null; - } - - switch (tailShapeEnum) { - case OVAL: - p = new Path(); - tailShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); - bounds = tailShape.getBounds2D(); - at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2); - at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); - break; - case STEALTH: - case ARROW: - p = new Path(false, true); - Path2D.Double arrow = new Path2D.Double(); - arrow.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2)); - arrow.lineTo(0, 0); - arrow.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2)); - tailShape = arrow; - at.translate(x2, y2); - at.rotate(alpha); - break; - case TRIANGLE: - p = new Path(); - Path2D.Double triangle = new Path2D.Double(); - triangle.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2)); - triangle.lineTo(0, 0); - triangle.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2)); - triangle.closePath(); - tailShape = triangle; - at.translate(x2, y2); - at.rotate(alpha); - break; - default: - break; - } - - if (tailShape != null) { - tailShape = at.createTransformedShape(tailShape); - } - return tailShape == null ? null : new Outline(tailShape, p); - } - - protected Outline getHeadDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) { - if (deco == null || stroke == null) { - return null; - } - DecorationSize headLength = deco.getHeadLength(); - if (headLength == null) { - headLength = DecorationSize.MEDIUM; - } - DecorationSize headWidth = deco.getHeadWidth(); - if (headWidth == null) { - headWidth = DecorationSize.MEDIUM; - } - - double lineWidth = Math.max(2.5, stroke.getLineWidth()); - - Rectangle2D anchor = getAnchor(graphics, getShape()); - double x1 = anchor.getX(), y1 = anchor.getY(); - - double alpha = Math.atan(anchor.getHeight() / anchor.getWidth()); - - AffineTransform at = new AffineTransform(); - java.awt.Shape headShape = null; - Path p = null; - Rectangle2D bounds; - final double scaleY = Math.pow(DECO_SIZE_POW, headWidth.ordinal()+1.); - final double scaleX = Math.pow(DECO_SIZE_POW, headLength.ordinal()+1.); - DecorationShape headShapeEnum = deco.getHeadShape(); - - if (headShapeEnum == null) { - return null; - } - - switch (headShapeEnum) { - case OVAL: - p = new Path(); - headShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); - bounds = headShape.getBounds2D(); - at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2); - at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); - break; - case STEALTH: - case ARROW: - p = new Path(false, true); - Path2D.Double arrow = new Path2D.Double(); - arrow.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2)); - arrow.lineTo(0, 0); - arrow.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2)); - headShape = arrow; - at.translate(x1, y1); - at.rotate(alpha); - break; - case TRIANGLE: - p = new Path(); - Path2D.Double triangle = new Path2D.Double(); - triangle.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2)); - triangle.lineTo(0, 0); - triangle.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2)); - triangle.closePath(); - headShape = triangle; - at.translate(x1, y1); - at.rotate(alpha); - break; - default: - break; - } - - if (headShape != null) { - headShape = at.createTransformedShape(headShape); - } - return headShape == null ? null : new Outline(headShape, p); - } - - public BasicStroke getStroke() { - return getStroke(getShape().getStrokeStyle()); - } - - protected void drawShadow( - Graphics2D graphics - , Collection outlines - , Paint fill - , Paint line - ) { - Shadow shadow = getShape().getShadow(); - if (shadow == null || (fill == null && line == null)) { - return; - } - - SolidPaint shadowPaint = shadow.getFillStyle(); - Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor()); - - double shapeRotation = getShape().getRotation(); - if(getShape().getFlipVertical()) { - shapeRotation += 180; - } - double angle = shadow.getAngle() - shapeRotation; - double dist = shadow.getDistance(); - double dx = dist * Math.cos(Math.toRadians(angle)); - double dy = dist * Math.sin(Math.toRadians(angle)); - - graphics.translate(dx, dy); - - for(Outline o : outlines){ - java.awt.Shape s = o.getOutline(); - Path p = o.getPath(); - graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); - graphics.setPaint(shadowColor); - - if(fill != null && p.isFilled()){ - graphics.fill(s); - } else if (line != null && p.isStroked()) { - graphics.draw(s); - } - } - - graphics.translate(-dx, -dy); - } - - protected static CustomGeometry getCustomGeometry(String name) { - return getCustomGeometry(name, null); - } - - protected static CustomGeometry getCustomGeometry(String name, Graphics2D graphics) { - @SuppressWarnings("unchecked") - Map presets = (graphics == null) - ? null - : (Map)graphics.getRenderingHint(Drawable.PRESET_GEOMETRY_CACHE); - - if (presets == null) { - presets = new HashMap(); - if (graphics != null) { - graphics.setRenderingHint(Drawable.PRESET_GEOMETRY_CACHE, presets); - } - - String packageName = "org.apache.poi.sl.draw.binding"; - InputStream presetIS = Drawable.class.getResourceAsStream("presetShapeDefinitions.xml"); - - // StAX: - EventFilter startElementFilter = new EventFilter() { - @Override - public boolean accept(XMLEvent event) { - return event.isStartElement(); - } - }; - - try { - XMLInputFactory staxFactory = XMLInputFactory.newInstance(); - XMLEventReader staxReader = staxFactory.createXMLEventReader(presetIS); - XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter); - // Ignore StartElement: - staxFiltRd.nextEvent(); - // JAXB: - JAXBContext jaxbContext = JAXBContext.newInstance(packageName); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - - while (staxFiltRd.peek() != null) { - StartElement evRoot = (StartElement)staxFiltRd.peek(); - String cusName = evRoot.getName().getLocalPart(); - // XMLEvent ev = staxReader.nextEvent(); - JAXBElement el = unmarshaller.unmarshal(staxReader, CTCustomGeometry2D.class); - CTCustomGeometry2D cusGeom = el.getValue(); - - presets.put(cusName, new CustomGeometry(cusGeom)); - } - - staxFiltRd.close(); - staxReader.close(); - } catch (Exception e) { - throw new RuntimeException("Unable to load preset geometries.", e); - } finally { - IOUtils.closeQuietly(presetIS); - } - } - - return presets.get(name); - } - - protected Collection computeOutlines(Graphics2D graphics) { - - List lst = new ArrayList(); - CustomGeometry geom = getShape().getGeometry(); - if(geom == null) { - return lst; - } - - Rectangle2D anchor = getAnchor(graphics, getShape()); - for (Path p : geom) { - - double w = p.getW() == -1 ? anchor.getWidth() * Units.EMU_PER_POINT : p.getW(); - double h = p.getH() == -1 ? anchor.getHeight() * Units.EMU_PER_POINT : p.getH(); - - // the guides in the shape definitions are all defined relative to each other, - // so we build the path starting from (0,0). - final Rectangle2D pathAnchor = new Rectangle2D.Double(0,0,w,h); - - Context ctx = new Context(geom, pathAnchor, getShape()); - - java.awt.Shape gp = p.getPath(ctx); - - // translate the result to the canvas coordinates in points - AffineTransform at = new AffineTransform(); - at.translate(anchor.getX(), anchor.getY()); - - double scaleX, scaleY; - if (p.getW() != -1) { - scaleX = anchor.getWidth() / p.getW(); - } else { - scaleX = 1.0 / Units.EMU_PER_POINT; - } - if (p.getH() != -1) { - scaleY = anchor.getHeight() / p.getH(); - } else { - scaleY = 1.0 / Units.EMU_PER_POINT; - } - - at.scale(scaleX, scaleY); - - java.awt.Shape canvasShape = at.createTransformedShape(gp); - - lst.add(new Outline(canvasShape, p)); - } - - return lst; - } - - @Override - protected SimpleShape getShape() { - return (SimpleShape)shape; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.EventFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.apache.poi.sl.draw.binding.CTCustomGeometry2D; +import org.apache.poi.sl.draw.geom.Context; +import org.apache.poi.sl.draw.geom.CustomGeometry; +import org.apache.poi.sl.draw.geom.Outline; +import org.apache.poi.sl.draw.geom.Path; +import org.apache.poi.sl.usermodel.LineDecoration; +import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; +import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.Shadow; +import org.apache.poi.sl.usermodel.SimpleShape; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.Units; + + +public class DrawSimpleShape extends DrawShape { + + private static final double DECO_SIZE_POW = 1.5d; + + public DrawSimpleShape(SimpleShape shape) { + super(shape); + } + + @Override + public void draw(Graphics2D graphics) { + DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(getShape()); + Paint fill = drawPaint.getPaint(graphics, getShape().getFillStyle().getPaint()); + Paint line = drawPaint.getPaint(graphics, getShape().getStrokeStyle().getPaint()); + BasicStroke stroke = getStroke(); // the stroke applies both to the shadow and the shape + graphics.setStroke(stroke); + + Collection elems = computeOutlines(graphics); + + // first paint the shadow + drawShadow(graphics, elems, fill, line); + + // then fill the shape interior + if (fill != null) { + graphics.setPaint(fill); + for (Outline o : elems) { + if (o.getPath().isFilled()){ + java.awt.Shape s = o.getOutline(); + graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); + graphics.fill(s); + } + } + } + + // then draw any content within this shape (text, image, etc.) + drawContent(graphics); + + // then stroke the shape outline + if(line != null) { + graphics.setPaint(line); + graphics.setStroke(stroke); + for(Outline o : elems){ + if(o.getPath().isStroked()){ + java.awt.Shape s = o.getOutline(); + graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); + graphics.draw(s); + } + } + } + + // draw line decorations + drawDecoration(graphics, line, stroke); + } + + protected void drawDecoration(Graphics2D graphics, Paint line, BasicStroke stroke) { + if(line == null) { + return; + } + graphics.setPaint(line); + + List lst = new ArrayList(); + LineDecoration deco = getShape().getLineDecoration(); + Outline head = getHeadDecoration(graphics, deco, stroke); + if (head != null) { + lst.add(head); + } + Outline tail = getTailDecoration(graphics, deco, stroke); + if (tail != null) { + lst.add(tail); + } + + + for(Outline o : lst){ + java.awt.Shape s = o.getOutline(); + Path p = o.getPath(); + graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); + + if(p.isFilled()) { + graphics.fill(s); + } + if(p.isStroked()) { + graphics.draw(s); + } + } + } + + protected Outline getTailDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) { + if (deco == null || stroke == null) { + return null; + } + DecorationSize tailLength = deco.getTailLength(); + if (tailLength == null) { + tailLength = DecorationSize.MEDIUM; + } + DecorationSize tailWidth = deco.getTailWidth(); + if (tailWidth == null) { + tailWidth = DecorationSize.MEDIUM; + } + + double lineWidth = Math.max(2.5, stroke.getLineWidth()); + + Rectangle2D anchor = getAnchor(graphics, getShape()); + double x2 = anchor.getX() + anchor.getWidth(), + y2 = anchor.getY() + anchor.getHeight(); + + double alpha = Math.atan(anchor.getHeight() / anchor.getWidth()); + + AffineTransform at = new AffineTransform(); + java.awt.Shape tailShape = null; + Path p = null; + Rectangle2D bounds; + final double scaleY = Math.pow(DECO_SIZE_POW, tailWidth.ordinal()+1.); + final double scaleX = Math.pow(DECO_SIZE_POW, tailLength.ordinal()+1.); + + DecorationShape tailShapeEnum = deco.getTailShape(); + + if (tailShapeEnum == null) { + return null; + } + + switch (tailShapeEnum) { + case OVAL: + p = new Path(); + tailShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); + bounds = tailShape.getBounds2D(); + at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2); + at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); + break; + case STEALTH: + case ARROW: + p = new Path(false, true); + Path2D.Double arrow = new Path2D.Double(); + arrow.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2)); + arrow.lineTo(0, 0); + arrow.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2)); + tailShape = arrow; + at.translate(x2, y2); + at.rotate(alpha); + break; + case TRIANGLE: + p = new Path(); + Path2D.Double triangle = new Path2D.Double(); + triangle.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2)); + triangle.lineTo(0, 0); + triangle.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2)); + triangle.closePath(); + tailShape = triangle; + at.translate(x2, y2); + at.rotate(alpha); + break; + default: + break; + } + + if (tailShape != null) { + tailShape = at.createTransformedShape(tailShape); + } + return tailShape == null ? null : new Outline(tailShape, p); + } + + protected Outline getHeadDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) { + if (deco == null || stroke == null) { + return null; + } + DecorationSize headLength = deco.getHeadLength(); + if (headLength == null) { + headLength = DecorationSize.MEDIUM; + } + DecorationSize headWidth = deco.getHeadWidth(); + if (headWidth == null) { + headWidth = DecorationSize.MEDIUM; + } + + double lineWidth = Math.max(2.5, stroke.getLineWidth()); + + Rectangle2D anchor = getAnchor(graphics, getShape()); + double x1 = anchor.getX(), y1 = anchor.getY(); + + double alpha = Math.atan(anchor.getHeight() / anchor.getWidth()); + + AffineTransform at = new AffineTransform(); + java.awt.Shape headShape = null; + Path p = null; + Rectangle2D bounds; + final double scaleY = Math.pow(DECO_SIZE_POW, headWidth.ordinal()+1.); + final double scaleX = Math.pow(DECO_SIZE_POW, headLength.ordinal()+1.); + DecorationShape headShapeEnum = deco.getHeadShape(); + + if (headShapeEnum == null) { + return null; + } + + switch (headShapeEnum) { + case OVAL: + p = new Path(); + headShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); + bounds = headShape.getBounds2D(); + at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2); + at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); + break; + case STEALTH: + case ARROW: + p = new Path(false, true); + Path2D.Double arrow = new Path2D.Double(); + arrow.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2)); + arrow.lineTo(0, 0); + arrow.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2)); + headShape = arrow; + at.translate(x1, y1); + at.rotate(alpha); + break; + case TRIANGLE: + p = new Path(); + Path2D.Double triangle = new Path2D.Double(); + triangle.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2)); + triangle.lineTo(0, 0); + triangle.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2)); + triangle.closePath(); + headShape = triangle; + at.translate(x1, y1); + at.rotate(alpha); + break; + default: + break; + } + + if (headShape != null) { + headShape = at.createTransformedShape(headShape); + } + return headShape == null ? null : new Outline(headShape, p); + } + + public BasicStroke getStroke() { + return getStroke(getShape().getStrokeStyle()); + } + + protected void drawShadow( + Graphics2D graphics + , Collection outlines + , Paint fill + , Paint line + ) { + Shadow shadow = getShape().getShadow(); + if (shadow == null || (fill == null && line == null)) { + return; + } + + SolidPaint shadowPaint = shadow.getFillStyle(); + Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor()); + + double shapeRotation = getShape().getRotation(); + if(getShape().getFlipVertical()) { + shapeRotation += 180; + } + double angle = shadow.getAngle() - shapeRotation; + double dist = shadow.getDistance(); + double dx = dist * Math.cos(Math.toRadians(angle)); + double dy = dist * Math.sin(Math.toRadians(angle)); + + graphics.translate(dx, dy); + + for(Outline o : outlines){ + java.awt.Shape s = o.getOutline(); + Path p = o.getPath(); + graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s); + graphics.setPaint(shadowColor); + + if(fill != null && p.isFilled()){ + graphics.fill(s); + } else if (line != null && p.isStroked()) { + graphics.draw(s); + } + } + + graphics.translate(-dx, -dy); + } + + protected static CustomGeometry getCustomGeometry(String name) { + return getCustomGeometry(name, null); + } + + protected static CustomGeometry getCustomGeometry(String name, Graphics2D graphics) { + @SuppressWarnings("unchecked") + Map presets = (graphics == null) + ? null + : (Map)graphics.getRenderingHint(Drawable.PRESET_GEOMETRY_CACHE); + + if (presets == null) { + presets = new HashMap(); + if (graphics != null) { + graphics.setRenderingHint(Drawable.PRESET_GEOMETRY_CACHE, presets); + } + + String packageName = "org.apache.poi.sl.draw.binding"; + InputStream presetIS = Drawable.class.getResourceAsStream("presetShapeDefinitions.xml"); + + // StAX: + EventFilter startElementFilter = new EventFilter() { + @Override + public boolean accept(XMLEvent event) { + return event.isStartElement(); + } + }; + + try { + XMLInputFactory staxFactory = XMLInputFactory.newInstance(); + XMLEventReader staxReader = staxFactory.createXMLEventReader(presetIS); + XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter); + // Ignore StartElement: + staxFiltRd.nextEvent(); + // JAXB: + JAXBContext jaxbContext = JAXBContext.newInstance(packageName); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + + while (staxFiltRd.peek() != null) { + StartElement evRoot = (StartElement)staxFiltRd.peek(); + String cusName = evRoot.getName().getLocalPart(); + // XMLEvent ev = staxReader.nextEvent(); + JAXBElement el = unmarshaller.unmarshal(staxReader, CTCustomGeometry2D.class); + CTCustomGeometry2D cusGeom = el.getValue(); + + presets.put(cusName, new CustomGeometry(cusGeom)); + } + + staxFiltRd.close(); + staxReader.close(); + } catch (Exception e) { + throw new RuntimeException("Unable to load preset geometries.", e); + } finally { + IOUtils.closeQuietly(presetIS); + } + } + + return presets.get(name); + } + + protected Collection computeOutlines(Graphics2D graphics) { + + List lst = new ArrayList(); + CustomGeometry geom = getShape().getGeometry(); + if(geom == null) { + return lst; + } + + Rectangle2D anchor = getAnchor(graphics, getShape()); + for (Path p : geom) { + + double w = p.getW() == -1 ? anchor.getWidth() * Units.EMU_PER_POINT : p.getW(); + double h = p.getH() == -1 ? anchor.getHeight() * Units.EMU_PER_POINT : p.getH(); + + // the guides in the shape definitions are all defined relative to each other, + // so we build the path starting from (0,0). + final Rectangle2D pathAnchor = new Rectangle2D.Double(0,0,w,h); + + Context ctx = new Context(geom, pathAnchor, getShape()); + + java.awt.Shape gp = p.getPath(ctx); + + // translate the result to the canvas coordinates in points + AffineTransform at = new AffineTransform(); + at.translate(anchor.getX(), anchor.getY()); + + double scaleX, scaleY; + if (p.getW() != -1) { + scaleX = anchor.getWidth() / p.getW(); + } else { + scaleX = 1.0 / Units.EMU_PER_POINT; + } + if (p.getH() != -1) { + scaleY = anchor.getHeight() / p.getH(); + } else { + scaleY = 1.0 / Units.EMU_PER_POINT; + } + + at.scale(scaleX, scaleY); + + java.awt.Shape canvasShape = at.createTransformedShape(gp); + + lst.add(new Outline(canvasShape, p)); + } + + return lst; + } + + @Override + protected SimpleShape getShape() { + return (SimpleShape)shape; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawSlide.java b/src/java/org/apache/poi/sl/draw/DrawSlide.java index 2320e907a6..295c584387 100644 --- a/src/java/org/apache/poi/sl/draw/DrawSlide.java +++ b/src/java/org/apache/poi/sl/draw/DrawSlide.java @@ -1,44 +1,44 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; - -import org.apache.poi.sl.usermodel.*; - - -public class DrawSlide extends DrawSheet { - - public DrawSlide(Slide slide) { - super(slide); - } - - public void draw(Graphics2D graphics) { - graphics.setRenderingHint(Drawable.CURRENT_SLIDE, this.sheet); - - Background bg = sheet.getBackground(); - if(bg != null) { - DrawFactory drawFact = DrawFactory.getInstance(graphics); - Drawable db = drawFact.getDrawable(bg); - db.draw(graphics); - } - - super.draw(graphics); - graphics.setRenderingHint(Drawable.CURRENT_SLIDE, null); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; + +import org.apache.poi.sl.usermodel.*; + + +public class DrawSlide extends DrawSheet { + + public DrawSlide(Slide slide) { + super(slide); + } + + public void draw(Graphics2D graphics) { + graphics.setRenderingHint(Drawable.CURRENT_SLIDE, this.sheet); + + Background bg = sheet.getBackground(); + if(bg != null) { + DrawFactory drawFact = DrawFactory.getInstance(graphics); + Drawable db = drawFact.getDrawable(bg); + db.draw(graphics); + } + + super.draw(graphics); + graphics.setRenderingHint(Drawable.CURRENT_SLIDE, null); + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawTableShape.java b/src/java/org/apache/poi/sl/draw/DrawTableShape.java index 947b2ad13c..905196fc90 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTableShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawTableShape.java @@ -1,257 +1,257 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.geom.Line2D; -import java.awt.geom.Rectangle2D; - -import org.apache.poi.sl.usermodel.GroupShape; -import org.apache.poi.sl.usermodel.StrokeStyle; -import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; -import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; -import org.apache.poi.sl.usermodel.TableCell; -import org.apache.poi.sl.usermodel.TableCell.BorderEdge; -import org.apache.poi.util.Internal; -import org.apache.poi.sl.usermodel.TableShape; - -public class DrawTableShape extends DrawShape { - /** - * Additional spacing between cells - */ - @Internal - public static final int borderSize = 2; - - public DrawTableShape(TableShape shape) { - super(shape); - } - - protected Drawable getGroupShape(Graphics2D graphics) { - if (shape instanceof GroupShape) { - DrawFactory df = DrawFactory.getInstance(graphics); - return df.getDrawable((GroupShape)shape); - } - return null; - } - - public void applyTransform(Graphics2D graphics) { - Drawable d = getGroupShape(graphics); - if (d != null) { - d.applyTransform(graphics); - } else { - super.applyTransform(graphics); - } - } - - public void draw(Graphics2D graphics) { - Drawable d = getGroupShape(graphics); - if (d != null) { - d.draw(graphics); - return; - } - - TableShape ts = getShape(); - DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(ts); - final int rows = ts.getNumberOfRows(); - final int cols = ts.getNumberOfColumns(); - - // draw background boxes - for (int row=0; row tc = ts.getCell(row, col); - if (tc == null || tc.isMerged()) { - continue; - } - - Paint fillPaint = drawPaint.getPaint(graphics, tc.getFillStyle().getPaint()); - graphics.setPaint(fillPaint); - Rectangle2D cellAnc = tc.getAnchor(); - graphics.fill(cellAnc); - - for (BorderEdge edge : BorderEdge.values()) { - StrokeStyle stroke = tc.getBorderStyle(edge); - if (stroke == null) { - continue; - } - graphics.setStroke(getStroke(stroke)); - Paint linePaint = drawPaint.getPaint(graphics, stroke.getPaint()); - graphics.setPaint(linePaint); - - double x=cellAnc.getX(), y=cellAnc.getY(), w=cellAnc.getWidth(), h=cellAnc.getHeight(); - Line2D line; - switch (edge) { - default: - case bottom: - line = new Line2D.Double(x-borderSize, y+h, x+w+borderSize, y+h); - break; - case left: - line = new Line2D.Double(x, y, x, y+h+borderSize); - break; - case right: - line = new Line2D.Double(x+w, y, x+w, y+h+borderSize); - break; - case top: - line = new Line2D.Double(x-borderSize, y, x+w+borderSize, y); - break; - } - - graphics.draw(line); - } - } - } - - // draw text - drawContent(graphics); - } - - public void drawContent(Graphics2D graphics) { - Drawable d = getGroupShape(graphics); - if (d != null) { - d.drawContent(graphics); - return; - } - - TableShape ts = getShape(); - DrawFactory df = DrawFactory.getInstance(graphics); - - final int rows = ts.getNumberOfRows(); - final int cols = ts.getNumberOfColumns(); - - for (int row=0; row tc = ts.getCell(row, col); - if (tc != null) { - DrawTextShape dts = df.getDrawable(tc); - dts.drawContent(graphics); - } - } - } - } - - @Override - protected TableShape getShape() { - return (TableShape)shape; - } - - /** - * Format the table and apply the specified Line to all cell boundaries, - * both outside and inside. - * An empty args parameter removes the affected border. - * - * @param args a varargs array possible containing {@link Double} (width), - * {@link LineCompound}, {@link Color}, {@link LineDash} - */ - public void setAllBorders(Object... args) { - TableShape table = getShape(); - final int rows = table.getNumberOfRows(); - final int cols = table.getNumberOfColumns(); - - BorderEdge edges[] = { BorderEdge.top, BorderEdge.left, null, null }; - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { - edges[2] = (col == cols - 1) ? BorderEdge.right : null; - edges[3] = (row == rows - 1) ? BorderEdge.bottom : null; - setEdges(table.getCell(row, col), edges, args); - } - } - } - - /** - * Format the outside border using the specified Line object - * An empty args parameter removes the affected border. - * - * @param args a varargs array possible containing {@link Double} (width), - * {@link LineCompound}, {@link Color}, {@link LineDash} - */ - public void setOutsideBorders(Object... args){ - if (args.length == 0) return; - - TableShape table = getShape(); - final int rows = table.getNumberOfRows(); - final int cols = table.getNumberOfColumns(); - - BorderEdge edges[] = new BorderEdge[4]; - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { - edges[0] = (col == 0) ? BorderEdge.left : null; - edges[1] = (col == cols - 1) ? BorderEdge.right : null; - edges[2] = (row == 0) ? BorderEdge.top : null; - edges[3] = (row == rows - 1) ? BorderEdge.bottom : null; - setEdges(table.getCell(row, col), edges, args); - } - } - } - - /** - * Format the inside border using the specified Line object - * An empty args parameter removes the affected border. - * - * @param args a varargs array possible containing {@link Double} (width), - * {@link LineCompound}, {@link Color}, {@link LineDash} - */ - public void setInsideBorders(Object... args) { - if (args.length == 0) return; - - TableShape table = getShape(); - final int rows = table.getNumberOfRows(); - final int cols = table.getNumberOfColumns(); - - BorderEdge edges[] = new BorderEdge[2]; - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { - edges[0] = (col > 0 && col < cols - 1) ? BorderEdge.right : null; - edges[1] = (row > 0 && row < rows - 1) ? BorderEdge.bottom : null; - setEdges(table.getCell(row, col), edges, args); - } - } - } - - /** - * Apply the border attributes (args) to the given cell and edges - * - * @param cell the cell - * @param edges the border edges - * @param args the border attributes - */ - private static void setEdges(TableCell cell, BorderEdge edges[], Object... args) { - if (cell == null) { - return; - } - for (BorderEdge be : edges) { - if (be != null) { - if (args.length == 0) { - cell.removeBorder(be); - } else { - for (Object o : args) { - if (o instanceof Double) { - cell.setBorderWidth(be, (Double)o); - } else if (o instanceof Color) { - cell.setBorderColor(be, (Color)o); - } else if (o instanceof LineDash) { - cell.setBorderDash(be, (LineDash)o); - } else if (o instanceof LineCompound) { - cell.setBorderCompound(be, (LineCompound)o); - } - } - } - } - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.sl.usermodel.GroupShape; +import org.apache.poi.sl.usermodel.StrokeStyle; +import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; +import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; +import org.apache.poi.sl.usermodel.TableCell; +import org.apache.poi.sl.usermodel.TableCell.BorderEdge; +import org.apache.poi.util.Internal; +import org.apache.poi.sl.usermodel.TableShape; + +public class DrawTableShape extends DrawShape { + /** + * Additional spacing between cells + */ + @Internal + public static final int borderSize = 2; + + public DrawTableShape(TableShape shape) { + super(shape); + } + + protected Drawable getGroupShape(Graphics2D graphics) { + if (shape instanceof GroupShape) { + DrawFactory df = DrawFactory.getInstance(graphics); + return df.getDrawable((GroupShape)shape); + } + return null; + } + + public void applyTransform(Graphics2D graphics) { + Drawable d = getGroupShape(graphics); + if (d != null) { + d.applyTransform(graphics); + } else { + super.applyTransform(graphics); + } + } + + public void draw(Graphics2D graphics) { + Drawable d = getGroupShape(graphics); + if (d != null) { + d.draw(graphics); + return; + } + + TableShape ts = getShape(); + DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(ts); + final int rows = ts.getNumberOfRows(); + final int cols = ts.getNumberOfColumns(); + + // draw background boxes + for (int row=0; row tc = ts.getCell(row, col); + if (tc == null || tc.isMerged()) { + continue; + } + + Paint fillPaint = drawPaint.getPaint(graphics, tc.getFillStyle().getPaint()); + graphics.setPaint(fillPaint); + Rectangle2D cellAnc = tc.getAnchor(); + graphics.fill(cellAnc); + + for (BorderEdge edge : BorderEdge.values()) { + StrokeStyle stroke = tc.getBorderStyle(edge); + if (stroke == null) { + continue; + } + graphics.setStroke(getStroke(stroke)); + Paint linePaint = drawPaint.getPaint(graphics, stroke.getPaint()); + graphics.setPaint(linePaint); + + double x=cellAnc.getX(), y=cellAnc.getY(), w=cellAnc.getWidth(), h=cellAnc.getHeight(); + Line2D line; + switch (edge) { + default: + case bottom: + line = new Line2D.Double(x-borderSize, y+h, x+w+borderSize, y+h); + break; + case left: + line = new Line2D.Double(x, y, x, y+h+borderSize); + break; + case right: + line = new Line2D.Double(x+w, y, x+w, y+h+borderSize); + break; + case top: + line = new Line2D.Double(x-borderSize, y, x+w+borderSize, y); + break; + } + + graphics.draw(line); + } + } + } + + // draw text + drawContent(graphics); + } + + public void drawContent(Graphics2D graphics) { + Drawable d = getGroupShape(graphics); + if (d != null) { + d.drawContent(graphics); + return; + } + + TableShape ts = getShape(); + DrawFactory df = DrawFactory.getInstance(graphics); + + final int rows = ts.getNumberOfRows(); + final int cols = ts.getNumberOfColumns(); + + for (int row=0; row tc = ts.getCell(row, col); + if (tc != null) { + DrawTextShape dts = df.getDrawable(tc); + dts.drawContent(graphics); + } + } + } + } + + @Override + protected TableShape getShape() { + return (TableShape)shape; + } + + /** + * Format the table and apply the specified Line to all cell boundaries, + * both outside and inside. + * An empty args parameter removes the affected border. + * + * @param args a varargs array possible containing {@link Double} (width), + * {@link LineCompound}, {@link Color}, {@link LineDash} + */ + public void setAllBorders(Object... args) { + TableShape table = getShape(); + final int rows = table.getNumberOfRows(); + final int cols = table.getNumberOfColumns(); + + BorderEdge edges[] = { BorderEdge.top, BorderEdge.left, null, null }; + for (int row = 0; row < rows; row++) { + for (int col = 0; col < cols; col++) { + edges[2] = (col == cols - 1) ? BorderEdge.right : null; + edges[3] = (row == rows - 1) ? BorderEdge.bottom : null; + setEdges(table.getCell(row, col), edges, args); + } + } + } + + /** + * Format the outside border using the specified Line object + * An empty args parameter removes the affected border. + * + * @param args a varargs array possible containing {@link Double} (width), + * {@link LineCompound}, {@link Color}, {@link LineDash} + */ + public void setOutsideBorders(Object... args){ + if (args.length == 0) return; + + TableShape table = getShape(); + final int rows = table.getNumberOfRows(); + final int cols = table.getNumberOfColumns(); + + BorderEdge edges[] = new BorderEdge[4]; + for (int row = 0; row < rows; row++) { + for (int col = 0; col < cols; col++) { + edges[0] = (col == 0) ? BorderEdge.left : null; + edges[1] = (col == cols - 1) ? BorderEdge.right : null; + edges[2] = (row == 0) ? BorderEdge.top : null; + edges[3] = (row == rows - 1) ? BorderEdge.bottom : null; + setEdges(table.getCell(row, col), edges, args); + } + } + } + + /** + * Format the inside border using the specified Line object + * An empty args parameter removes the affected border. + * + * @param args a varargs array possible containing {@link Double} (width), + * {@link LineCompound}, {@link Color}, {@link LineDash} + */ + public void setInsideBorders(Object... args) { + if (args.length == 0) return; + + TableShape table = getShape(); + final int rows = table.getNumberOfRows(); + final int cols = table.getNumberOfColumns(); + + BorderEdge edges[] = new BorderEdge[2]; + for (int row = 0; row < rows; row++) { + for (int col = 0; col < cols; col++) { + edges[0] = (col > 0 && col < cols - 1) ? BorderEdge.right : null; + edges[1] = (row > 0 && row < rows - 1) ? BorderEdge.bottom : null; + setEdges(table.getCell(row, col), edges, args); + } + } + } + + /** + * Apply the border attributes (args) to the given cell and edges + * + * @param cell the cell + * @param edges the border edges + * @param args the border attributes + */ + private static void setEdges(TableCell cell, BorderEdge edges[], Object... args) { + if (cell == null) { + return; + } + for (BorderEdge be : edges) { + if (be != null) { + if (args.length == 0) { + cell.removeBorder(be); + } else { + for (Object o : args) { + if (o instanceof Double) { + cell.setBorderWidth(be, (Double)o); + } else if (o instanceof Color) { + cell.setBorderColor(be, (Color)o); + } else if (o instanceof LineDash) { + cell.setBorderDash(be, (LineDash)o); + } else if (o instanceof LineCompound) { + cell.setBorderCompound(be, (LineCompound)o); + } + } + } + } + } + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawTextBox.java b/src/java/org/apache/poi/sl/draw/DrawTextBox.java index d44d10807e..1b2b2f444c 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextBox.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextBox.java @@ -1,26 +1,26 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import org.apache.poi.sl.usermodel.*; - -public class DrawTextBox extends DrawAutoShape { - public DrawTextBox(TextBox shape) { - super(shape); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import org.apache.poi.sl.usermodel.*; + +public class DrawTextBox extends DrawAutoShape { + public DrawTextBox(TextBox shape) { + super(shape); + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawTextFragment.java b/src/java/org/apache/poi/sl/draw/DrawTextFragment.java index acb6b4c766..178983d5e1 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextFragment.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextFragment.java @@ -1,105 +1,105 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; -import java.awt.font.TextLayout; -import java.text.*; - -public class DrawTextFragment implements Drawable { - final TextLayout layout; - final AttributedString str; - double x, y; - - public DrawTextFragment(TextLayout layout, AttributedString str) { - this.layout = layout; - this.str = str; - } - - public void setPosition(double x, double y) { - // TODO: replace it, by applyTransform???? - this.x = x; - this.y = y; - } - - public void draw(Graphics2D graphics){ - if(str == null) { - return; - } - - double yBaseline = y + layout.getAscent(); - - Integer textMode = (Integer)graphics.getRenderingHint(Drawable.TEXT_RENDERING_MODE); - if(textMode != null && textMode == Drawable.TEXT_AS_SHAPES){ - layout.draw(graphics, (float)x, (float)yBaseline); - } else { - graphics.drawString(str.getIterator(), (float)x, (float)yBaseline ); - } - } - - public void applyTransform(Graphics2D graphics) { - } - - public void drawContent(Graphics2D graphics) { - } - - public TextLayout getLayout() { - return layout; - } - - public AttributedString getAttributedString() { - return str; - } - - /** - * @return full height of this text run which is sum of ascent, descent and leading - */ - public float getHeight(){ - double h = Math.ceil(layout.getAscent()) + Math.ceil(layout.getDescent()) + layout.getLeading(); - return (float)h; - } - - /** - * - * @return width if this text run - */ - public float getWidth(){ - return layout.getAdvance(); - } - - /** - * - * @return the string to be painted - */ - public String getString(){ - if (str == null) return ""; - - AttributedCharacterIterator it = str.getIterator(); - StringBuilder buf = new StringBuilder(); - for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) { - buf.append(c); - } - return buf.toString(); - } - - @Override - public String toString(){ - return "[" + getClass().getSimpleName() + "] " + getString(); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; +import java.awt.font.TextLayout; +import java.text.*; + +public class DrawTextFragment implements Drawable { + final TextLayout layout; + final AttributedString str; + double x, y; + + public DrawTextFragment(TextLayout layout, AttributedString str) { + this.layout = layout; + this.str = str; + } + + public void setPosition(double x, double y) { + // TODO: replace it, by applyTransform???? + this.x = x; + this.y = y; + } + + public void draw(Graphics2D graphics){ + if(str == null) { + return; + } + + double yBaseline = y + layout.getAscent(); + + Integer textMode = (Integer)graphics.getRenderingHint(Drawable.TEXT_RENDERING_MODE); + if(textMode != null && textMode == Drawable.TEXT_AS_SHAPES){ + layout.draw(graphics, (float)x, (float)yBaseline); + } else { + graphics.drawString(str.getIterator(), (float)x, (float)yBaseline ); + } + } + + public void applyTransform(Graphics2D graphics) { + } + + public void drawContent(Graphics2D graphics) { + } + + public TextLayout getLayout() { + return layout; + } + + public AttributedString getAttributedString() { + return str; + } + + /** + * @return full height of this text run which is sum of ascent, descent and leading + */ + public float getHeight(){ + double h = Math.ceil(layout.getAscent()) + Math.ceil(layout.getDescent()) + layout.getLeading(); + return (float)h; + } + + /** + * + * @return width if this text run + */ + public float getWidth(){ + return layout.getAdvance(); + } + + /** + * + * @return the string to be painted + */ + public String getString(){ + if (str == null) return ""; + + AttributedCharacterIterator it = str.getIterator(); + StringBuilder buf = new StringBuilder(); + for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) { + buf.append(c); + } + return buf.toString(); + } + + @Override + public String toString(){ + return "[" + getClass().getSimpleName() + "] " + getString(); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java index f2b24b0ff2..c60d0b45c7 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java @@ -1,731 +1,731 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.font.FontRenderContext; -import java.awt.font.LineBreakMeasurer; -import java.awt.font.TextAttribute; -import java.awt.font.TextLayout; -import java.awt.geom.Rectangle2D; -import java.io.InvalidObjectException; -import java.text.AttributedCharacterIterator; -import java.text.AttributedCharacterIterator.Attribute; -import java.text.AttributedString; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.poi.sl.usermodel.AutoNumberingScheme; -import org.apache.poi.sl.usermodel.Hyperlink; -import org.apache.poi.sl.usermodel.Insets2D; -import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.sl.usermodel.PlaceableShape; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.Sheet; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.sl.usermodel.TextParagraph; -import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle; -import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; -import org.apache.poi.sl.usermodel.TextRun; -import org.apache.poi.sl.usermodel.TextRun.FieldType; -import org.apache.poi.sl.usermodel.TextRun.TextCap; -import org.apache.poi.sl.usermodel.TextShape; -import org.apache.poi.sl.usermodel.TextShape.TextDirection; -import org.apache.poi.util.StringUtil; -import org.apache.poi.util.Units; - - -public class DrawTextParagraph implements Drawable { - /** Keys for passing hyperlinks to the graphics context */ - public static final XlinkAttribute HYPERLINK_HREF = new XlinkAttribute("href"); - public static final XlinkAttribute HYPERLINK_LABEL = new XlinkAttribute("label"); - - protected TextParagraph paragraph; - double x, y; - protected List lines = new ArrayList(); - protected String rawText; - protected DrawTextFragment bullet; - protected int autoNbrIdx; - - /** - * the highest line in this paragraph. Used for line spacing. - */ - protected double maxLineHeight; - - /** - * Defines an attribute used for storing the hyperlink associated with - * some renderable text. - */ - private static class XlinkAttribute extends Attribute { - - XlinkAttribute(String name) { - super(name); - } - - /** - * Resolves instances being deserialized to the predefined constants. - */ - @Override - protected Object readResolve() throws InvalidObjectException { - if (HYPERLINK_HREF.getName().equals(getName())) { - return HYPERLINK_HREF; - } - if (HYPERLINK_LABEL.getName().equals(getName())) { - return HYPERLINK_LABEL; - } - throw new InvalidObjectException("unknown attribute name"); - } - } - - - public DrawTextParagraph(TextParagraph paragraph) { - this.paragraph = paragraph; - } - - public void setPosition(double x, double y) { - // TODO: replace it, by applyTransform???? - this.x = x; - this.y = y; - } - - public double getY() { - return y; - } - - /** - * Sets the auto numbering index of the handled paragraph - * @param index the auto numbering index - */ - public void setAutoNumberingIdx(int index) { - autoNbrIdx = index; - } - - @Override - public void draw(Graphics2D graphics){ - if (lines.isEmpty()) { - return; - } - - double penY = y; - - boolean firstLine = true; - int indentLevel = paragraph.getIndentLevel(); - Double leftMargin = paragraph.getLeftMargin(); - if (leftMargin == null) { - // if the marL attribute is omitted, then a value of 347663 is implied - leftMargin = Units.toPoints(347663L*indentLevel); - } - Double indent = paragraph.getIndent(); - if (indent == null) { - indent = Units.toPoints(347663L*indentLevel); - } - if (isHSLF()) { - // special handling for HSLF - indent -= leftMargin; - } - -// Double rightMargin = paragraph.getRightMargin(); -// if (rightMargin == null) { -// rightMargin = 0d; -// } - - //The vertical line spacing - Double spacing = paragraph.getLineSpacing(); - if (spacing == null) { - spacing = 100d; - } - - for(DrawTextFragment line : lines){ - double penX; - - if(firstLine) { - if (!isEmptyParagraph()) { - // TODO: find out character style for empty, but bulleted/numbered lines - bullet = getBullet(graphics, line.getAttributedString().getIterator()); - } - - if (bullet != null){ - bullet.setPosition(x+leftMargin+indent, penY); - bullet.draw(graphics); - // don't let text overlay the bullet and advance by the bullet width - double bulletWidth = bullet.getLayout().getAdvance() + 1; - penX = x + Math.max(leftMargin, leftMargin+indent+bulletWidth); - } else { - penX = x + leftMargin; - } - } else { - penX = x + leftMargin; - } - - Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape()); - // Insets are already applied on DrawTextShape.drawContent - // but (outer) anchor need to be adjusted - Insets2D insets = paragraph.getParentShape().getInsets(); - double leftInset = insets.left; - double rightInset = insets.right; - - TextAlign ta = paragraph.getTextAlign(); - if (ta == null) { - ta = TextAlign.LEFT; - } - switch (ta) { - case CENTER: - penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset - leftMargin) / 2; - break; - case RIGHT: - penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset); - break; - default: - break; - } - - line.setPosition(penX, penY); - line.draw(graphics); - - if(spacing > 0) { - // If linespacing >= 0, then linespacing is a percentage of normal line height. - penY += spacing*0.01* line.getHeight(); - } else { - // negative value means absolute spacing in points - penY += -spacing; - } - - firstLine = false; - } - - y = penY - y; - } - - public float getFirstLineHeight() { - return (lines.isEmpty()) ? 0 : lines.get(0).getHeight(); - } - - public float getLastLineHeight() { - return (lines.isEmpty()) ? 0 : lines.get(lines.size()-1).getHeight(); - } - - public boolean isEmptyParagraph() { - return (lines.isEmpty() || rawText.trim().isEmpty()); - } - - @Override - public void applyTransform(Graphics2D graphics) { - } - - @Override - public void drawContent(Graphics2D graphics) { - } - - /** - * break text into lines, each representing a line of text that fits in the wrapping width - * - * @param graphics The drawing context for computing text-lengths. - */ - protected void breakText(Graphics2D graphics){ - lines.clear(); - - DrawFactory fact = DrawFactory.getInstance(graphics); - StringBuilder text = new StringBuilder(); - AttributedString at = getAttributedString(graphics, text); - boolean emptyParagraph = ("".equals(text.toString().trim())); - - AttributedCharacterIterator it = at.getIterator(); - LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext()); - for (;;) { - int startIndex = measurer.getPosition(); - - double wrappingWidth = getWrappingWidth(lines.size() == 0, graphics) + 1; // add a pixel to compensate rounding errors - // shape width can be smaller that the sum of insets (this was proved by a test file) - if(wrappingWidth < 0) { - wrappingWidth = 1; - } - - int nextBreak = text.indexOf("\n", startIndex + 1); - if (nextBreak == -1) { - nextBreak = it.getEndIndex(); - } - - TextLayout layout = measurer.nextLayout((float)wrappingWidth, nextBreak, true); - if (layout == null) { - // layout can be null if the entire word at the current position - // does not fit within the wrapping width. Try with requireNextWord=false. - layout = measurer.nextLayout((float)wrappingWidth, nextBreak, false); - } - - if(layout == null) { - // exit if can't break any more - break; - } - - int endIndex = measurer.getPosition(); - // skip over new line breaks (we paint 'clear' text runs not starting or ending with \n) - if(endIndex < it.getEndIndex() && text.charAt(endIndex) == '\n'){ - measurer.setPosition(endIndex + 1); - } - - TextAlign hAlign = paragraph.getTextAlign(); - if(hAlign == TextAlign.JUSTIFY || hAlign == TextAlign.JUSTIFY_LOW) { - layout = layout.getJustifiedLayout((float)wrappingWidth); - } - - AttributedString str = (emptyParagraph) - ? null // we will not paint empty paragraphs - : new AttributedString(it, startIndex, endIndex); - DrawTextFragment line = fact.getTextFragment(layout, str); - lines.add(line); - - maxLineHeight = Math.max(maxLineHeight, line.getHeight()); - - if(endIndex == it.getEndIndex()) { - break; - } - } - - rawText = text.toString(); - } - - protected DrawTextFragment getBullet(Graphics2D graphics, AttributedCharacterIterator firstLineAttr) { - BulletStyle bulletStyle = paragraph.getBulletStyle(); - if (bulletStyle == null) { - return null; - } - - String buCharacter; - AutoNumberingScheme ans = bulletStyle.getAutoNumberingScheme(); - if (ans != null) { - buCharacter = ans.format(autoNbrIdx); - } else { - buCharacter = bulletStyle.getBulletCharacter(); - } - if (buCharacter == null) { - return null; - } - - String buFont = bulletStyle.getBulletFont(); - if (buFont == null) { - buFont = paragraph.getDefaultFontFamily(); - } - assert(buFont != null); - - PlaceableShape ps = getParagraphShape(); - PaintStyle fgPaintStyle = bulletStyle.getBulletFontColor(); - Paint fgPaint; - if (fgPaintStyle == null) { - fgPaint = (Paint)firstLineAttr.getAttribute(TextAttribute.FOREGROUND); - } else { - fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle); - } - - float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE); - Double buSz = bulletStyle.getBulletFontSize(); - if (buSz == null) { - buSz = 100d; - } - if (buSz > 0) { - fontSize *= buSz* 0.01; - } else { - fontSize = (float)-buSz; - } - - - AttributedString str = new AttributedString(mapFontCharset(buCharacter,buFont)); - str.addAttribute(TextAttribute.FOREGROUND, fgPaint); - str.addAttribute(TextAttribute.FAMILY, buFont); - str.addAttribute(TextAttribute.SIZE, fontSize); - - TextLayout layout = new TextLayout(str.getIterator(), graphics.getFontRenderContext()); - DrawFactory fact = DrawFactory.getInstance(graphics); - return fact.getTextFragment(layout, str); - } - - protected String getRenderableText(Graphics2D graphics, TextRun tr) { - if (tr.getFieldType() == FieldType.SLIDE_NUMBER) { - Slide slide = (Slide)graphics.getRenderingHint(Drawable.CURRENT_SLIDE); - return (slide == null) ? "" : Integer.toString(slide.getSlideNumber()); - } - StringBuilder buf = new StringBuilder(); - TextCap cap = tr.getTextCap(); - String tabs = null; - for (char c : tr.getRawText().toCharArray()) { - switch (c) { - case '\t': - if (tabs == null) { - tabs = tab2space(tr); - } - buf.append(tabs); - break; - case '\u000b': - buf.append('\n'); - break; - default: - switch (cap) { - case ALL: c = Character.toUpperCase(c); break; - case SMALL: c = Character.toLowerCase(c); break; - case NONE: break; - } - - buf.append(c); - break; - } - } - - return buf.toString(); - } - - /** - * Replace a tab with the effective number of white spaces. - */ - private String tab2space(TextRun tr) { - AttributedString string = new AttributedString(" "); - String fontFamily = tr.getFontFamily(); - if (fontFamily == null) { - fontFamily = "Lucida Sans"; - } - string.addAttribute(TextAttribute.FAMILY, fontFamily); - - Double fs = tr.getFontSize(); - if (fs == null) { - fs = 12d; - } - string.addAttribute(TextAttribute.SIZE, fs.floatValue()); - - TextLayout l = new TextLayout(string.getIterator(), new FontRenderContext(null, true, true)); - double wspace = l.getAdvance(); - - Double tabSz = paragraph.getDefaultTabSize(); - if (tabSz == null) { - tabSz = wspace*4; - } - - int numSpaces = (int)Math.ceil(tabSz / wspace); - StringBuilder buf = new StringBuilder(); - for(int i = 0; i < numSpaces; i++) { - buf.append(' '); - } - return buf.toString(); - } - - - /** - * Returns wrapping width to break lines in this paragraph - * - * @param firstLine whether the first line is breaking - * - * @return wrapping width in points - */ - protected double getWrappingWidth(boolean firstLine, Graphics2D graphics){ - TextShape ts = paragraph.getParentShape(); - - // internal margins for the text box - Insets2D insets = ts.getInsets(); - double leftInset = insets.left; - double rightInset = insets.right; - - int indentLevel = paragraph.getIndentLevel(); - if (indentLevel == -1) { - // default to 0, if indentLevel is not set - indentLevel = 0; - } - Double leftMargin = paragraph.getLeftMargin(); - if (leftMargin == null) { - // if the marL attribute is omitted, then a value of 347663 is implied - leftMargin = Units.toPoints(347663L*(indentLevel+1)); - } - Double indent = paragraph.getIndent(); - if (indent == null) { - indent = Units.toPoints(347663L*indentLevel); - } - Double rightMargin = paragraph.getRightMargin(); - if (rightMargin == null) { - rightMargin = 0d; - } - - Rectangle2D anchor = DrawShape.getAnchor(graphics, ts); - TextDirection textDir = ts.getTextDirection(); - double width; - if (!ts.getWordWrap()) { - Dimension pageDim = ts.getSheet().getSlideShow().getPageSize(); - // if wordWrap == false then we return the advance to the (right) border of the sheet - switch (textDir) { - default: - width = pageDim.getWidth() - anchor.getX(); - break; - case VERTICAL: - width = pageDim.getHeight() - anchor.getX(); - break; - case VERTICAL_270: - width = anchor.getX(); - break; - } - } else { - switch (textDir) { - default: - width = anchor.getWidth() - leftInset - rightInset - leftMargin - rightMargin; - break; - case VERTICAL: - case VERTICAL_270: - width = anchor.getHeight() - leftInset - rightInset - leftMargin - rightMargin; - break; - } - if (firstLine && !isHSLF()) { - if (bullet != null){ - if (indent > 0) { - width -= indent; - } - } else { - if (indent > 0) { - width -= indent; // first line indentation - } else if (indent < 0) { // hanging indentation: the first line start at the left margin - width += leftMargin; - } - } - } - } - - return width; - } - - private static class AttributedStringData { - Attribute attribute; - Object value; - int beginIndex, endIndex; - AttributedStringData(Attribute attribute, Object value, int beginIndex, int endIndex) { - this.attribute = attribute; - this.value = value; - this.beginIndex = beginIndex; - this.endIndex = endIndex; - } - } - - /** - * Helper method for paint style relative to bounds, e.g. gradient paint - */ - @SuppressWarnings("rawtypes") - private PlaceableShape getParagraphShape() { - return new PlaceableShape(){ - @Override - public ShapeContainer getParent() { return null; } - @Override - public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); } - @Override - public void setAnchor(Rectangle2D anchor) {} - @Override - public double getRotation() { return 0; } - @Override - public void setRotation(double theta) {} - @Override - public void setFlipHorizontal(boolean flip) {} - @Override - public void setFlipVertical(boolean flip) {} - @Override - public boolean getFlipHorizontal() { return false; } - @Override - public boolean getFlipVertical() { return false; } - @Override - public Sheet getSheet() { return paragraph.getParentShape().getSheet(); } - }; - } - - protected AttributedString getAttributedString(Graphics2D graphics, StringBuilder text){ - List attList = new ArrayList(); - if (text == null) { - text = new StringBuilder(); - } - - PlaceableShape ps = getParagraphShape(); - DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER); - @SuppressWarnings("unchecked") - Map fontMap = (Map)graphics.getRenderingHint(Drawable.FONT_MAP); - @SuppressWarnings("unchecked") - Map fallbackMap = (Map)graphics.getRenderingHint(Drawable.FONT_FALLBACK); - - for (TextRun run : paragraph){ - String runText = getRenderableText(graphics, run); - // skip empty runs - if (runText.isEmpty()) { - continue; - } - - // user can pass an custom object to convert fonts - String mappedFont = run.getFontFamily(); - String fallbackFont = Font.SANS_SERIF; - - if (mappedFont == null) { - mappedFont = paragraph.getDefaultFontFamily(); - } - if (mappedFont == null) { - mappedFont = Font.SANS_SERIF; - } - if (fontHandler != null) { - String font = fontHandler.getRendererableFont(mappedFont, run.getPitchAndFamily()); - if (font != null) { - mappedFont = font; - } - font = fontHandler.getFallbackFont(mappedFont, run.getPitchAndFamily()); - if (font != null) { - fallbackFont = font; - } - } else { - if (fontMap != null) { - if (fontMap.containsKey(mappedFont)) { - mappedFont = fontMap.get(mappedFont); - } else if (fontMap.containsKey("*")) { - mappedFont = fontMap.get("*"); - } - } - if (fallbackMap != null) { - if (fallbackMap.containsKey(mappedFont)) { - fallbackFont = fallbackMap.get(mappedFont); - } else if (fallbackMap.containsKey("*")) { - fallbackFont = fallbackMap.get("*"); - } - } - } - - runText = mapFontCharset(runText,mappedFont); - int beginIndex = text.length(); - text.append(runText); - int endIndex = text.length(); - - attList.add(new AttributedStringData(TextAttribute.FAMILY, mappedFont, beginIndex, endIndex)); - - PaintStyle fgPaintStyle = run.getFontColor(); - Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle); - attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex)); - - Double fontSz = run.getFontSize(); - if (fontSz == null) { - fontSz = paragraph.getDefaultFontSize(); - } - attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), beginIndex, endIndex)); - - if(run.isBold()) { - attList.add(new AttributedStringData(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, beginIndex, endIndex)); - } - if(run.isItalic()) { - attList.add(new AttributedStringData(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, beginIndex, endIndex)); - } - if(run.isUnderlined()) { - attList.add(new AttributedStringData(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, beginIndex, endIndex)); - attList.add(new AttributedStringData(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_TWO_PIXEL, beginIndex, endIndex)); - } - if(run.isStrikethrough()) { - attList.add(new AttributedStringData(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, beginIndex, endIndex)); - } - if(run.isSubscript()) { - attList.add(new AttributedStringData(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB, beginIndex, endIndex)); - } - if(run.isSuperscript()) { - attList.add(new AttributedStringData(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, beginIndex, endIndex)); - } - - Hyperlink hl = run.getHyperlink(); - if (hl != null) { - attList.add(new AttributedStringData(HYPERLINK_HREF, hl.getAddress(), beginIndex, endIndex)); - attList.add(new AttributedStringData(HYPERLINK_LABEL, hl.getLabel(), beginIndex, endIndex)); - } - - int style = (run.isBold() ? Font.BOLD : 0) | (run.isItalic() ? Font.ITALIC : 0); - Font f = new Font(mappedFont, style, (int)Math.rint(fontSz)); - - // check for unsupported characters and add a fallback font for these - char textChr[] = runText.toCharArray(); - int nextEnd = f.canDisplayUpTo(textChr, 0, textChr.length); - int last = nextEnd; - boolean isNextValid = (nextEnd == 0); - while ( nextEnd != -1 && nextEnd <= textChr.length ) { - if (isNextValid) { - nextEnd = f.canDisplayUpTo(textChr, nextEnd, textChr.length); - isNextValid = false; - } else { - if (nextEnd >= textChr.length || f.canDisplay(Character.codePointAt(textChr, nextEnd, textChr.length)) ) { - attList.add(new AttributedStringData(TextAttribute.FAMILY, fallbackFont, beginIndex+last, beginIndex+Math.min(nextEnd,textChr.length))); - if (nextEnd >= textChr.length) { - break; - } - last = nextEnd; - isNextValid = true; - } else { - boolean isHS = Character.isHighSurrogate(textChr[nextEnd]); - nextEnd+=(isHS?2:1); - } - } - } - } - - // ensure that the paragraph contains at least one character - // We need this trick to correctly measure text - if (text.length() == 0) { - Double fontSz = paragraph.getDefaultFontSize(); - text.append(" "); - attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), 0, 1)); - } - - AttributedString string = new AttributedString(text.toString()); - for (AttributedStringData asd : attList) { - string.addAttribute(asd.attribute, asd.value, asd.beginIndex, asd.endIndex); - } - - return string; - } - - /** - * @return {@code true} if the HSLF implementation is used - */ - protected boolean isHSLF() { - return DrawShape.isHSLF(paragraph.getParentShape()); - } - - /** - * Map text charset depending on font family. - * Currently this only maps for wingdings font (into unicode private use area) - * - * @param text the raw text - * @param fontFamily the font family - * @return AttributedString with mapped codepoints - * - * @see Drawing exotic fonts in a java applet - * @see StringUtil#mapMsCodepointString(String) - */ - protected String mapFontCharset(String text, String fontFamily) { - // TODO: find a real charset mapping solution instead of hard coding for Wingdings - String attStr = text; - if ("Wingdings".equalsIgnoreCase(fontFamily)) { - // wingdings doesn't contain high-surrogates, so chars are ok - boolean changed = false; - char chrs[] = attStr.toCharArray(); - for (int i=0; i paragraph; + double x, y; + protected List lines = new ArrayList(); + protected String rawText; + protected DrawTextFragment bullet; + protected int autoNbrIdx; + + /** + * the highest line in this paragraph. Used for line spacing. + */ + protected double maxLineHeight; + + /** + * Defines an attribute used for storing the hyperlink associated with + * some renderable text. + */ + private static class XlinkAttribute extends Attribute { + + XlinkAttribute(String name) { + super(name); + } + + /** + * Resolves instances being deserialized to the predefined constants. + */ + @Override + protected Object readResolve() throws InvalidObjectException { + if (HYPERLINK_HREF.getName().equals(getName())) { + return HYPERLINK_HREF; + } + if (HYPERLINK_LABEL.getName().equals(getName())) { + return HYPERLINK_LABEL; + } + throw new InvalidObjectException("unknown attribute name"); + } + } + + + public DrawTextParagraph(TextParagraph paragraph) { + this.paragraph = paragraph; + } + + public void setPosition(double x, double y) { + // TODO: replace it, by applyTransform???? + this.x = x; + this.y = y; + } + + public double getY() { + return y; + } + + /** + * Sets the auto numbering index of the handled paragraph + * @param index the auto numbering index + */ + public void setAutoNumberingIdx(int index) { + autoNbrIdx = index; + } + + @Override + public void draw(Graphics2D graphics){ + if (lines.isEmpty()) { + return; + } + + double penY = y; + + boolean firstLine = true; + int indentLevel = paragraph.getIndentLevel(); + Double leftMargin = paragraph.getLeftMargin(); + if (leftMargin == null) { + // if the marL attribute is omitted, then a value of 347663 is implied + leftMargin = Units.toPoints(347663L*indentLevel); + } + Double indent = paragraph.getIndent(); + if (indent == null) { + indent = Units.toPoints(347663L*indentLevel); + } + if (isHSLF()) { + // special handling for HSLF + indent -= leftMargin; + } + +// Double rightMargin = paragraph.getRightMargin(); +// if (rightMargin == null) { +// rightMargin = 0d; +// } + + //The vertical line spacing + Double spacing = paragraph.getLineSpacing(); + if (spacing == null) { + spacing = 100d; + } + + for(DrawTextFragment line : lines){ + double penX; + + if(firstLine) { + if (!isEmptyParagraph()) { + // TODO: find out character style for empty, but bulleted/numbered lines + bullet = getBullet(graphics, line.getAttributedString().getIterator()); + } + + if (bullet != null){ + bullet.setPosition(x+leftMargin+indent, penY); + bullet.draw(graphics); + // don't let text overlay the bullet and advance by the bullet width + double bulletWidth = bullet.getLayout().getAdvance() + 1; + penX = x + Math.max(leftMargin, leftMargin+indent+bulletWidth); + } else { + penX = x + leftMargin; + } + } else { + penX = x + leftMargin; + } + + Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape()); + // Insets are already applied on DrawTextShape.drawContent + // but (outer) anchor need to be adjusted + Insets2D insets = paragraph.getParentShape().getInsets(); + double leftInset = insets.left; + double rightInset = insets.right; + + TextAlign ta = paragraph.getTextAlign(); + if (ta == null) { + ta = TextAlign.LEFT; + } + switch (ta) { + case CENTER: + penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset - leftMargin) / 2; + break; + case RIGHT: + penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset); + break; + default: + break; + } + + line.setPosition(penX, penY); + line.draw(graphics); + + if(spacing > 0) { + // If linespacing >= 0, then linespacing is a percentage of normal line height. + penY += spacing*0.01* line.getHeight(); + } else { + // negative value means absolute spacing in points + penY += -spacing; + } + + firstLine = false; + } + + y = penY - y; + } + + public float getFirstLineHeight() { + return (lines.isEmpty()) ? 0 : lines.get(0).getHeight(); + } + + public float getLastLineHeight() { + return (lines.isEmpty()) ? 0 : lines.get(lines.size()-1).getHeight(); + } + + public boolean isEmptyParagraph() { + return (lines.isEmpty() || rawText.trim().isEmpty()); + } + + @Override + public void applyTransform(Graphics2D graphics) { + } + + @Override + public void drawContent(Graphics2D graphics) { + } + + /** + * break text into lines, each representing a line of text that fits in the wrapping width + * + * @param graphics The drawing context for computing text-lengths. + */ + protected void breakText(Graphics2D graphics){ + lines.clear(); + + DrawFactory fact = DrawFactory.getInstance(graphics); + StringBuilder text = new StringBuilder(); + AttributedString at = getAttributedString(graphics, text); + boolean emptyParagraph = ("".equals(text.toString().trim())); + + AttributedCharacterIterator it = at.getIterator(); + LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext()); + for (;;) { + int startIndex = measurer.getPosition(); + + double wrappingWidth = getWrappingWidth(lines.size() == 0, graphics) + 1; // add a pixel to compensate rounding errors + // shape width can be smaller that the sum of insets (this was proved by a test file) + if(wrappingWidth < 0) { + wrappingWidth = 1; + } + + int nextBreak = text.indexOf("\n", startIndex + 1); + if (nextBreak == -1) { + nextBreak = it.getEndIndex(); + } + + TextLayout layout = measurer.nextLayout((float)wrappingWidth, nextBreak, true); + if (layout == null) { + // layout can be null if the entire word at the current position + // does not fit within the wrapping width. Try with requireNextWord=false. + layout = measurer.nextLayout((float)wrappingWidth, nextBreak, false); + } + + if(layout == null) { + // exit if can't break any more + break; + } + + int endIndex = measurer.getPosition(); + // skip over new line breaks (we paint 'clear' text runs not starting or ending with \n) + if(endIndex < it.getEndIndex() && text.charAt(endIndex) == '\n'){ + measurer.setPosition(endIndex + 1); + } + + TextAlign hAlign = paragraph.getTextAlign(); + if(hAlign == TextAlign.JUSTIFY || hAlign == TextAlign.JUSTIFY_LOW) { + layout = layout.getJustifiedLayout((float)wrappingWidth); + } + + AttributedString str = (emptyParagraph) + ? null // we will not paint empty paragraphs + : new AttributedString(it, startIndex, endIndex); + DrawTextFragment line = fact.getTextFragment(layout, str); + lines.add(line); + + maxLineHeight = Math.max(maxLineHeight, line.getHeight()); + + if(endIndex == it.getEndIndex()) { + break; + } + } + + rawText = text.toString(); + } + + protected DrawTextFragment getBullet(Graphics2D graphics, AttributedCharacterIterator firstLineAttr) { + BulletStyle bulletStyle = paragraph.getBulletStyle(); + if (bulletStyle == null) { + return null; + } + + String buCharacter; + AutoNumberingScheme ans = bulletStyle.getAutoNumberingScheme(); + if (ans != null) { + buCharacter = ans.format(autoNbrIdx); + } else { + buCharacter = bulletStyle.getBulletCharacter(); + } + if (buCharacter == null) { + return null; + } + + String buFont = bulletStyle.getBulletFont(); + if (buFont == null) { + buFont = paragraph.getDefaultFontFamily(); + } + assert(buFont != null); + + PlaceableShape ps = getParagraphShape(); + PaintStyle fgPaintStyle = bulletStyle.getBulletFontColor(); + Paint fgPaint; + if (fgPaintStyle == null) { + fgPaint = (Paint)firstLineAttr.getAttribute(TextAttribute.FOREGROUND); + } else { + fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle); + } + + float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE); + Double buSz = bulletStyle.getBulletFontSize(); + if (buSz == null) { + buSz = 100d; + } + if (buSz > 0) { + fontSize *= buSz* 0.01; + } else { + fontSize = (float)-buSz; + } + + + AttributedString str = new AttributedString(mapFontCharset(buCharacter,buFont)); + str.addAttribute(TextAttribute.FOREGROUND, fgPaint); + str.addAttribute(TextAttribute.FAMILY, buFont); + str.addAttribute(TextAttribute.SIZE, fontSize); + + TextLayout layout = new TextLayout(str.getIterator(), graphics.getFontRenderContext()); + DrawFactory fact = DrawFactory.getInstance(graphics); + return fact.getTextFragment(layout, str); + } + + protected String getRenderableText(Graphics2D graphics, TextRun tr) { + if (tr.getFieldType() == FieldType.SLIDE_NUMBER) { + Slide slide = (Slide)graphics.getRenderingHint(Drawable.CURRENT_SLIDE); + return (slide == null) ? "" : Integer.toString(slide.getSlideNumber()); + } + StringBuilder buf = new StringBuilder(); + TextCap cap = tr.getTextCap(); + String tabs = null; + for (char c : tr.getRawText().toCharArray()) { + switch (c) { + case '\t': + if (tabs == null) { + tabs = tab2space(tr); + } + buf.append(tabs); + break; + case '\u000b': + buf.append('\n'); + break; + default: + switch (cap) { + case ALL: c = Character.toUpperCase(c); break; + case SMALL: c = Character.toLowerCase(c); break; + case NONE: break; + } + + buf.append(c); + break; + } + } + + return buf.toString(); + } + + /** + * Replace a tab with the effective number of white spaces. + */ + private String tab2space(TextRun tr) { + AttributedString string = new AttributedString(" "); + String fontFamily = tr.getFontFamily(); + if (fontFamily == null) { + fontFamily = "Lucida Sans"; + } + string.addAttribute(TextAttribute.FAMILY, fontFamily); + + Double fs = tr.getFontSize(); + if (fs == null) { + fs = 12d; + } + string.addAttribute(TextAttribute.SIZE, fs.floatValue()); + + TextLayout l = new TextLayout(string.getIterator(), new FontRenderContext(null, true, true)); + double wspace = l.getAdvance(); + + Double tabSz = paragraph.getDefaultTabSize(); + if (tabSz == null) { + tabSz = wspace*4; + } + + int numSpaces = (int)Math.ceil(tabSz / wspace); + StringBuilder buf = new StringBuilder(); + for(int i = 0; i < numSpaces; i++) { + buf.append(' '); + } + return buf.toString(); + } + + + /** + * Returns wrapping width to break lines in this paragraph + * + * @param firstLine whether the first line is breaking + * + * @return wrapping width in points + */ + protected double getWrappingWidth(boolean firstLine, Graphics2D graphics){ + TextShape ts = paragraph.getParentShape(); + + // internal margins for the text box + Insets2D insets = ts.getInsets(); + double leftInset = insets.left; + double rightInset = insets.right; + + int indentLevel = paragraph.getIndentLevel(); + if (indentLevel == -1) { + // default to 0, if indentLevel is not set + indentLevel = 0; + } + Double leftMargin = paragraph.getLeftMargin(); + if (leftMargin == null) { + // if the marL attribute is omitted, then a value of 347663 is implied + leftMargin = Units.toPoints(347663L*(indentLevel+1)); + } + Double indent = paragraph.getIndent(); + if (indent == null) { + indent = Units.toPoints(347663L*indentLevel); + } + Double rightMargin = paragraph.getRightMargin(); + if (rightMargin == null) { + rightMargin = 0d; + } + + Rectangle2D anchor = DrawShape.getAnchor(graphics, ts); + TextDirection textDir = ts.getTextDirection(); + double width; + if (!ts.getWordWrap()) { + Dimension pageDim = ts.getSheet().getSlideShow().getPageSize(); + // if wordWrap == false then we return the advance to the (right) border of the sheet + switch (textDir) { + default: + width = pageDim.getWidth() - anchor.getX(); + break; + case VERTICAL: + width = pageDim.getHeight() - anchor.getX(); + break; + case VERTICAL_270: + width = anchor.getX(); + break; + } + } else { + switch (textDir) { + default: + width = anchor.getWidth() - leftInset - rightInset - leftMargin - rightMargin; + break; + case VERTICAL: + case VERTICAL_270: + width = anchor.getHeight() - leftInset - rightInset - leftMargin - rightMargin; + break; + } + if (firstLine && !isHSLF()) { + if (bullet != null){ + if (indent > 0) { + width -= indent; + } + } else { + if (indent > 0) { + width -= indent; // first line indentation + } else if (indent < 0) { // hanging indentation: the first line start at the left margin + width += leftMargin; + } + } + } + } + + return width; + } + + private static class AttributedStringData { + Attribute attribute; + Object value; + int beginIndex, endIndex; + AttributedStringData(Attribute attribute, Object value, int beginIndex, int endIndex) { + this.attribute = attribute; + this.value = value; + this.beginIndex = beginIndex; + this.endIndex = endIndex; + } + } + + /** + * Helper method for paint style relative to bounds, e.g. gradient paint + */ + @SuppressWarnings("rawtypes") + private PlaceableShape getParagraphShape() { + return new PlaceableShape(){ + @Override + public ShapeContainer getParent() { return null; } + @Override + public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); } + @Override + public void setAnchor(Rectangle2D anchor) {} + @Override + public double getRotation() { return 0; } + @Override + public void setRotation(double theta) {} + @Override + public void setFlipHorizontal(boolean flip) {} + @Override + public void setFlipVertical(boolean flip) {} + @Override + public boolean getFlipHorizontal() { return false; } + @Override + public boolean getFlipVertical() { return false; } + @Override + public Sheet getSheet() { return paragraph.getParentShape().getSheet(); } + }; + } + + protected AttributedString getAttributedString(Graphics2D graphics, StringBuilder text){ + List attList = new ArrayList(); + if (text == null) { + text = new StringBuilder(); + } + + PlaceableShape ps = getParagraphShape(); + DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER); + @SuppressWarnings("unchecked") + Map fontMap = (Map)graphics.getRenderingHint(Drawable.FONT_MAP); + @SuppressWarnings("unchecked") + Map fallbackMap = (Map)graphics.getRenderingHint(Drawable.FONT_FALLBACK); + + for (TextRun run : paragraph){ + String runText = getRenderableText(graphics, run); + // skip empty runs + if (runText.isEmpty()) { + continue; + } + + // user can pass an custom object to convert fonts + String mappedFont = run.getFontFamily(); + String fallbackFont = Font.SANS_SERIF; + + if (mappedFont == null) { + mappedFont = paragraph.getDefaultFontFamily(); + } + if (mappedFont == null) { + mappedFont = Font.SANS_SERIF; + } + if (fontHandler != null) { + String font = fontHandler.getRendererableFont(mappedFont, run.getPitchAndFamily()); + if (font != null) { + mappedFont = font; + } + font = fontHandler.getFallbackFont(mappedFont, run.getPitchAndFamily()); + if (font != null) { + fallbackFont = font; + } + } else { + if (fontMap != null) { + if (fontMap.containsKey(mappedFont)) { + mappedFont = fontMap.get(mappedFont); + } else if (fontMap.containsKey("*")) { + mappedFont = fontMap.get("*"); + } + } + if (fallbackMap != null) { + if (fallbackMap.containsKey(mappedFont)) { + fallbackFont = fallbackMap.get(mappedFont); + } else if (fallbackMap.containsKey("*")) { + fallbackFont = fallbackMap.get("*"); + } + } + } + + runText = mapFontCharset(runText,mappedFont); + int beginIndex = text.length(); + text.append(runText); + int endIndex = text.length(); + + attList.add(new AttributedStringData(TextAttribute.FAMILY, mappedFont, beginIndex, endIndex)); + + PaintStyle fgPaintStyle = run.getFontColor(); + Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle); + attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex)); + + Double fontSz = run.getFontSize(); + if (fontSz == null) { + fontSz = paragraph.getDefaultFontSize(); + } + attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), beginIndex, endIndex)); + + if(run.isBold()) { + attList.add(new AttributedStringData(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, beginIndex, endIndex)); + } + if(run.isItalic()) { + attList.add(new AttributedStringData(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, beginIndex, endIndex)); + } + if(run.isUnderlined()) { + attList.add(new AttributedStringData(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, beginIndex, endIndex)); + attList.add(new AttributedStringData(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_TWO_PIXEL, beginIndex, endIndex)); + } + if(run.isStrikethrough()) { + attList.add(new AttributedStringData(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, beginIndex, endIndex)); + } + if(run.isSubscript()) { + attList.add(new AttributedStringData(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB, beginIndex, endIndex)); + } + if(run.isSuperscript()) { + attList.add(new AttributedStringData(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, beginIndex, endIndex)); + } + + Hyperlink hl = run.getHyperlink(); + if (hl != null) { + attList.add(new AttributedStringData(HYPERLINK_HREF, hl.getAddress(), beginIndex, endIndex)); + attList.add(new AttributedStringData(HYPERLINK_LABEL, hl.getLabel(), beginIndex, endIndex)); + } + + int style = (run.isBold() ? Font.BOLD : 0) | (run.isItalic() ? Font.ITALIC : 0); + Font f = new Font(mappedFont, style, (int)Math.rint(fontSz)); + + // check for unsupported characters and add a fallback font for these + char textChr[] = runText.toCharArray(); + int nextEnd = f.canDisplayUpTo(textChr, 0, textChr.length); + int last = nextEnd; + boolean isNextValid = (nextEnd == 0); + while ( nextEnd != -1 && nextEnd <= textChr.length ) { + if (isNextValid) { + nextEnd = f.canDisplayUpTo(textChr, nextEnd, textChr.length); + isNextValid = false; + } else { + if (nextEnd >= textChr.length || f.canDisplay(Character.codePointAt(textChr, nextEnd, textChr.length)) ) { + attList.add(new AttributedStringData(TextAttribute.FAMILY, fallbackFont, beginIndex+last, beginIndex+Math.min(nextEnd,textChr.length))); + if (nextEnd >= textChr.length) { + break; + } + last = nextEnd; + isNextValid = true; + } else { + boolean isHS = Character.isHighSurrogate(textChr[nextEnd]); + nextEnd+=(isHS?2:1); + } + } + } + } + + // ensure that the paragraph contains at least one character + // We need this trick to correctly measure text + if (text.length() == 0) { + Double fontSz = paragraph.getDefaultFontSize(); + text.append(" "); + attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), 0, 1)); + } + + AttributedString string = new AttributedString(text.toString()); + for (AttributedStringData asd : attList) { + string.addAttribute(asd.attribute, asd.value, asd.beginIndex, asd.endIndex); + } + + return string; + } + + /** + * @return {@code true} if the HSLF implementation is used + */ + protected boolean isHSLF() { + return DrawShape.isHSLF(paragraph.getParentShape()); + } + + /** + * Map text charset depending on font family. + * Currently this only maps for wingdings font (into unicode private use area) + * + * @param text the raw text + * @param fontFamily the font family + * @return AttributedString with mapped codepoints + * + * @see Drawing exotic fonts in a java applet + * @see StringUtil#mapMsCodepointString(String) + */ + protected String mapFontCharset(String text, String fontFamily) { + // TODO: find a real charset mapping solution instead of hard coding for Wingdings + String attStr = text; + if ("Wingdings".equalsIgnoreCase(fontFamily)) { + // wingdings doesn't contain high-surrogates, so chars are ok + boolean changed = false; + char chrs[] = attStr.toCharArray(); + for (int i=0; i shape) { - super(shape); - } - - @Override - public void drawContent(Graphics2D graphics) { - DrawFactory.getInstance(graphics).fixFonts(graphics); - - TextShape s = getShape(); - - Rectangle2D anchor = DrawShape.getAnchor(graphics, s); - Insets2D insets = s.getInsets(); - double x = anchor.getX() + insets.left; - double y = anchor.getY(); - - // remember the initial transform - AffineTransform tx = graphics.getTransform(); - - // Transform of text in flipped shapes is special. - // At this point the flip and rotation transform is already applied - // (see DrawShape#applyTransform ), but we need to restore it to avoid painting "upside down". - // See Bugzilla 54210. - - boolean vertFlip = s.getFlipVertical(); - boolean horzFlip = s.getFlipHorizontal(); - ShapeContainer sc = s.getParent(); - while (sc instanceof PlaceableShape) { - PlaceableShape ps = (PlaceableShape)sc; - vertFlip ^= ps.getFlipVertical(); - horzFlip ^= ps.getFlipHorizontal(); - sc = ps.getParent(); - } - - // Horizontal flipping applies only to shape outline and not to the text in the shape. - // Applying flip second time restores the original not-flipped transform - if (horzFlip ^ vertFlip) { - final double ax = anchor.getX(); - final double ay = anchor.getY(); - graphics.translate(ax + anchor.getWidth(), ay); - graphics.scale(-1, 1); - graphics.translate(-ax, -ay); - } - - Double textRot = s.getTextRotation(); - if (textRot != null && textRot != 0) { - final double cx = anchor.getCenterX(); - final double cy = anchor.getCenterY(); - graphics.translate(cx, cy); - graphics.rotate(Math.toRadians(textRot)); - graphics.translate(-cx, -cy); - } - - // first dry-run to calculate the total height of the text - double textHeight; - - switch (s.getVerticalAlignment()){ - default: - case TOP: - y += insets.top; - break; - case BOTTOM: - textHeight = getTextHeight(graphics); - y += anchor.getHeight() - textHeight - insets.bottom; - break; - case MIDDLE: - textHeight = getTextHeight(graphics); - double delta = anchor.getHeight() - textHeight - insets.top - insets.bottom; - y += insets.top + delta/2; - break; - } - - TextDirection textDir = s.getTextDirection(); - if (textDir == TextDirection.VERTICAL || textDir == TextDirection.VERTICAL_270) { - final double deg = (textDir == TextDirection.VERTICAL) ? 90 : 270; - final double cx = anchor.getCenterX(); - final double cy = anchor.getCenterY(); - graphics.translate(cx, cy); - graphics.rotate(Math.toRadians(deg)); - graphics.translate(-cx, -cy); - - // old top/left edge is now bottom/left or top/right - as we operate on the already - // rotated drawing context, both verticals can be moved in the same direction - final double w = anchor.getWidth(); - final double h = anchor.getHeight(); - final double dx = (w-h)/2d; - graphics.translate(dx,-dx); - } - - drawParagraphs(graphics, x, y); - - // restore the transform - graphics.setTransform(tx); - } - - /** - * paint the paragraphs starting from top left (x,y) - * - * @return the vertical advance, i.e. the cumulative space occupied by the text - */ - public double drawParagraphs(Graphics2D graphics, double x, double y) { - DrawFactory fact = DrawFactory.getInstance(graphics); - - double y0 = y; - //noinspection RedundantCast - @SuppressWarnings("cast") - Iterator> paragraphs = - (Iterator>) getShape().iterator(); - - boolean isFirstLine = true; - for (int autoNbrIdx=0; paragraphs.hasNext(); autoNbrIdx++){ - TextParagraph p = paragraphs.next(); - DrawTextParagraph dp = fact.getDrawable(p); - BulletStyle bs = p.getBulletStyle(); - if (bs == null || bs.getAutoNumberingScheme() == null) { - autoNbrIdx = -1; - } else { - Integer startAt = bs.getAutoNumberingStartAt(); - if (startAt == null) startAt = 1; - // TODO: handle reset auto number indexes - if (startAt > autoNbrIdx) autoNbrIdx = startAt; - } - dp.setAutoNumberingIdx(autoNbrIdx); - dp.breakText(graphics); - - if (!isFirstLine) { - // the amount of vertical white space before the paragraph - Double spaceBefore = p.getSpaceBefore(); - if (spaceBefore == null) spaceBefore = 0d; - if(spaceBefore > 0) { - // positive value means percentage spacing of the height of the first line, e.g. - // the higher the first line, the bigger the space before the paragraph - y += spaceBefore*0.01*dp.getFirstLineHeight(); - } else { - // negative value means the absolute spacing in points - y += -spaceBefore; - } - } - isFirstLine = false; - - dp.setPosition(x, y); - dp.draw(graphics); - y += dp.getY(); - - if (paragraphs.hasNext()) { - Double spaceAfter = p.getSpaceAfter(); - if (spaceAfter == null) spaceAfter = 0d; - if(spaceAfter > 0) { - // positive value means percentage spacing of the height of the last line, e.g. - // the higher the last line, the bigger the space after the paragraph - y += spaceAfter*0.01*dp.getLastLineHeight(); - } else { - // negative value means the absolute spacing in points - y += -spaceAfter; - } - } - } - return y - y0; - } - - /** - * Compute the cumulative height occupied by the text - * - * @return the height in points - */ - public double getTextHeight() { - return getTextHeight(null); - } - - /** - * Compute the cumulative height occupied by the text - * - * @param oldGraphics the graphics context, which properties are to be copied, may be null - * @return the height in points - */ - protected double getTextHeight(Graphics2D oldGraphics) { - // dry-run in a 1x1 image and return the vertical advance - BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - Graphics2D graphics = img.createGraphics(); - if (oldGraphics != null) { - graphics.addRenderingHints(oldGraphics.getRenderingHints()); - graphics.setTransform(oldGraphics.getTransform()); - } - DrawFactory.getInstance(graphics).fixFonts(graphics); - return drawParagraphs(graphics, 0, 0); - } - - @Override - protected TextShape getShape() { - return (TextShape)shape; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.util.Iterator; + +import org.apache.poi.sl.usermodel.Insets2D; +import org.apache.poi.sl.usermodel.PlaceableShape; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.TextParagraph; +import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle; +import org.apache.poi.sl.usermodel.TextRun; +import org.apache.poi.sl.usermodel.TextShape; +import org.apache.poi.sl.usermodel.TextShape.TextDirection; + +public class DrawTextShape extends DrawSimpleShape { + + public DrawTextShape(TextShape shape) { + super(shape); + } + + @Override + public void drawContent(Graphics2D graphics) { + DrawFactory.getInstance(graphics).fixFonts(graphics); + + TextShape s = getShape(); + + Rectangle2D anchor = DrawShape.getAnchor(graphics, s); + Insets2D insets = s.getInsets(); + double x = anchor.getX() + insets.left; + double y = anchor.getY(); + + // remember the initial transform + AffineTransform tx = graphics.getTransform(); + + // Transform of text in flipped shapes is special. + // At this point the flip and rotation transform is already applied + // (see DrawShape#applyTransform ), but we need to restore it to avoid painting "upside down". + // See Bugzilla 54210. + + boolean vertFlip = s.getFlipVertical(); + boolean horzFlip = s.getFlipHorizontal(); + ShapeContainer sc = s.getParent(); + while (sc instanceof PlaceableShape) { + PlaceableShape ps = (PlaceableShape)sc; + vertFlip ^= ps.getFlipVertical(); + horzFlip ^= ps.getFlipHorizontal(); + sc = ps.getParent(); + } + + // Horizontal flipping applies only to shape outline and not to the text in the shape. + // Applying flip second time restores the original not-flipped transform + if (horzFlip ^ vertFlip) { + final double ax = anchor.getX(); + final double ay = anchor.getY(); + graphics.translate(ax + anchor.getWidth(), ay); + graphics.scale(-1, 1); + graphics.translate(-ax, -ay); + } + + Double textRot = s.getTextRotation(); + if (textRot != null && textRot != 0) { + final double cx = anchor.getCenterX(); + final double cy = anchor.getCenterY(); + graphics.translate(cx, cy); + graphics.rotate(Math.toRadians(textRot)); + graphics.translate(-cx, -cy); + } + + // first dry-run to calculate the total height of the text + double textHeight; + + switch (s.getVerticalAlignment()){ + default: + case TOP: + y += insets.top; + break; + case BOTTOM: + textHeight = getTextHeight(graphics); + y += anchor.getHeight() - textHeight - insets.bottom; + break; + case MIDDLE: + textHeight = getTextHeight(graphics); + double delta = anchor.getHeight() - textHeight - insets.top - insets.bottom; + y += insets.top + delta/2; + break; + } + + TextDirection textDir = s.getTextDirection(); + if (textDir == TextDirection.VERTICAL || textDir == TextDirection.VERTICAL_270) { + final double deg = (textDir == TextDirection.VERTICAL) ? 90 : 270; + final double cx = anchor.getCenterX(); + final double cy = anchor.getCenterY(); + graphics.translate(cx, cy); + graphics.rotate(Math.toRadians(deg)); + graphics.translate(-cx, -cy); + + // old top/left edge is now bottom/left or top/right - as we operate on the already + // rotated drawing context, both verticals can be moved in the same direction + final double w = anchor.getWidth(); + final double h = anchor.getHeight(); + final double dx = (w-h)/2d; + graphics.translate(dx,-dx); + } + + drawParagraphs(graphics, x, y); + + // restore the transform + graphics.setTransform(tx); + } + + /** + * paint the paragraphs starting from top left (x,y) + * + * @return the vertical advance, i.e. the cumulative space occupied by the text + */ + public double drawParagraphs(Graphics2D graphics, double x, double y) { + DrawFactory fact = DrawFactory.getInstance(graphics); + + double y0 = y; + //noinspection RedundantCast + @SuppressWarnings("cast") + Iterator> paragraphs = + (Iterator>) getShape().iterator(); + + boolean isFirstLine = true; + for (int autoNbrIdx=0; paragraphs.hasNext(); autoNbrIdx++){ + TextParagraph p = paragraphs.next(); + DrawTextParagraph dp = fact.getDrawable(p); + BulletStyle bs = p.getBulletStyle(); + if (bs == null || bs.getAutoNumberingScheme() == null) { + autoNbrIdx = -1; + } else { + Integer startAt = bs.getAutoNumberingStartAt(); + if (startAt == null) startAt = 1; + // TODO: handle reset auto number indexes + if (startAt > autoNbrIdx) autoNbrIdx = startAt; + } + dp.setAutoNumberingIdx(autoNbrIdx); + dp.breakText(graphics); + + if (!isFirstLine) { + // the amount of vertical white space before the paragraph + Double spaceBefore = p.getSpaceBefore(); + if (spaceBefore == null) spaceBefore = 0d; + if(spaceBefore > 0) { + // positive value means percentage spacing of the height of the first line, e.g. + // the higher the first line, the bigger the space before the paragraph + y += spaceBefore*0.01*dp.getFirstLineHeight(); + } else { + // negative value means the absolute spacing in points + y += -spaceBefore; + } + } + isFirstLine = false; + + dp.setPosition(x, y); + dp.draw(graphics); + y += dp.getY(); + + if (paragraphs.hasNext()) { + Double spaceAfter = p.getSpaceAfter(); + if (spaceAfter == null) spaceAfter = 0d; + if(spaceAfter > 0) { + // positive value means percentage spacing of the height of the last line, e.g. + // the higher the last line, the bigger the space after the paragraph + y += spaceAfter*0.01*dp.getLastLineHeight(); + } else { + // negative value means the absolute spacing in points + y += -spaceAfter; + } + } + } + return y - y0; + } + + /** + * Compute the cumulative height occupied by the text + * + * @return the height in points + */ + public double getTextHeight() { + return getTextHeight(null); + } + + /** + * Compute the cumulative height occupied by the text + * + * @param oldGraphics the graphics context, which properties are to be copied, may be null + * @return the height in points + */ + protected double getTextHeight(Graphics2D oldGraphics) { + // dry-run in a 1x1 image and return the vertical advance + BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + Graphics2D graphics = img.createGraphics(); + if (oldGraphics != null) { + graphics.addRenderingHints(oldGraphics.getRenderingHints()); + graphics.setTransform(oldGraphics.getTransform()); + } + DrawFactory.getInstance(graphics).fixFonts(graphics); + return drawParagraphs(graphics, 0, 0); + } + + @Override + protected TextShape getShape() { + return (TextShape)shape; + } +} diff --git a/src/java/org/apache/poi/sl/draw/Drawable.java b/src/java/org/apache/poi/sl/draw/Drawable.java index cc85dde905..4ec653ae50 100644 --- a/src/java/org/apache/poi/sl/draw/Drawable.java +++ b/src/java/org/apache/poi/sl/draw/Drawable.java @@ -1,161 +1,161 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.Graphics2D; -import java.awt.RenderingHints; - -import org.apache.poi.util.Internal; - - -public interface Drawable { - class DrawableHint extends RenderingHints.Key { - protected DrawableHint(int id) { - super(id); - } - - public boolean isCompatibleValue(Object val) { - return true; - } - - public String toString() { - switch (intKey()) { - case 1: return "DRAW_FACTORY"; - case 2: return "GROUP_TRANSFORM"; - case 3: return "IMAGE_RENDERER"; - case 4: return "TEXT_RENDERING_MODE"; - case 5: return "GRADIENT_SHAPE"; - case 6: return "PRESET_GEOMETRY_CACHE"; - case 7: return "FONT_HANDLER"; - case 8: return "FONT_FALLBACK"; - case 9: return "FONT_MAP"; - case 10: return "GSAVE"; - case 11: return "GRESTORE"; - default: return "UNKNOWN_ID "+intKey(); - } - } - } - - /** - * {@link DrawFactory} which will be used to draw objects into this graphics context - */ - DrawableHint DRAW_FACTORY = new DrawableHint(1); - - /** - * Key will be internally used to store affine transformation temporarily within group shapes - */ - @Internal - DrawableHint GROUP_TRANSFORM = new DrawableHint(2); - - /** - * Use a custom image renderer of an instance of {@link ImageRenderer} - */ - DrawableHint IMAGE_RENDERER = new DrawableHint(3); - - /** - * how to render text: - * - * {@link #TEXT_AS_CHARACTERS} (default) means to draw via - * {@link java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float)}. - * This mode draws text as characters. Use it if the target graphics writes the actual - * character codes instead of glyph outlines (PDFGraphics2D, SVGGraphics2D, etc.) - * - * {@link #TEXT_AS_SHAPES} means to render via - * {@link java.awt.font.TextLayout#draw(java.awt.Graphics2D, float, float)}. - * This mode draws glyphs as shapes and provides some advanced capabilities such as - * justification and font substitution. Use it if the target graphics is an image. - * - */ - DrawableHint TEXT_RENDERING_MODE = new DrawableHint(4); - - /** - * PathGradientPaint needs the shape to be set. - * It will be achieved through setting it in the rendering hints - */ - DrawableHint GRADIENT_SHAPE = new DrawableHint(5); - - - /** - * Internal key for caching the preset geometries - */ - DrawableHint PRESET_GEOMETRY_CACHE = new DrawableHint(6); - - /** - * draw text via {@link java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float)} - */ - int TEXT_AS_CHARACTERS = 1; - - /** - * draw text via {@link java.awt.font.TextLayout#draw(java.awt.Graphics2D, float, float)} - */ - int TEXT_AS_SHAPES = 2; - - /** - * Use this object to resolve unknown / missing fonts when rendering slides. - * The font handler must be of type {@link DrawFontManager}.

- * - * In case a {@code FONT_HANDLER} is register, {@code FONT_FALLBACK} and {@code FONT_MAP} are ignored - */ - DrawableHint FONT_HANDLER = new DrawableHint(7); - - /** - * Key for a font fallback map of type {@code Map} which maps - * the original font family (key) to the fallback font family (value). - * In case there is also a {@code FONT_MAP} registered, the original font - * is first mapped via the font_map and then the fallback font is determined - */ - DrawableHint FONT_FALLBACK = new DrawableHint(8); - - /** - * Key for a font map of type {@code Map} which maps - * the original font family (key) to the mapped font family (value) - */ - DrawableHint FONT_MAP = new DrawableHint(9); - - DrawableHint GSAVE = new DrawableHint(10); - DrawableHint GRESTORE = new DrawableHint(11); - - /** - * The Common SL Draw API works sometimes cascading, but there are places - * where the current slide context need to be evaluated, e.g. when slide numbers - * are printed. In this situation we need to have a way to access the current slide - */ - DrawableHint CURRENT_SLIDE = new DrawableHint(12); - - - /** - * Apply 2-D transforms before drawing this shape. This includes rotation and flipping. - * - * @param graphics the graphics whos transform matrix will be modified - */ - void applyTransform(Graphics2D graphics); - - /** - * Draw this shape into the supplied canvas - * - * @param graphics the graphics to draw into - */ - void draw(Graphics2D graphics); - - /** - * draw any content within this shape (image, text, etc.). - * - * @param graphics the graphics to draw into - */ - void drawContent(Graphics2D graphics); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.Graphics2D; +import java.awt.RenderingHints; + +import org.apache.poi.util.Internal; + + +public interface Drawable { + class DrawableHint extends RenderingHints.Key { + protected DrawableHint(int id) { + super(id); + } + + public boolean isCompatibleValue(Object val) { + return true; + } + + public String toString() { + switch (intKey()) { + case 1: return "DRAW_FACTORY"; + case 2: return "GROUP_TRANSFORM"; + case 3: return "IMAGE_RENDERER"; + case 4: return "TEXT_RENDERING_MODE"; + case 5: return "GRADIENT_SHAPE"; + case 6: return "PRESET_GEOMETRY_CACHE"; + case 7: return "FONT_HANDLER"; + case 8: return "FONT_FALLBACK"; + case 9: return "FONT_MAP"; + case 10: return "GSAVE"; + case 11: return "GRESTORE"; + default: return "UNKNOWN_ID "+intKey(); + } + } + } + + /** + * {@link DrawFactory} which will be used to draw objects into this graphics context + */ + DrawableHint DRAW_FACTORY = new DrawableHint(1); + + /** + * Key will be internally used to store affine transformation temporarily within group shapes + */ + @Internal + DrawableHint GROUP_TRANSFORM = new DrawableHint(2); + + /** + * Use a custom image renderer of an instance of {@link ImageRenderer} + */ + DrawableHint IMAGE_RENDERER = new DrawableHint(3); + + /** + * how to render text: + * + * {@link #TEXT_AS_CHARACTERS} (default) means to draw via + * {@link java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float)}. + * This mode draws text as characters. Use it if the target graphics writes the actual + * character codes instead of glyph outlines (PDFGraphics2D, SVGGraphics2D, etc.) + * + * {@link #TEXT_AS_SHAPES} means to render via + * {@link java.awt.font.TextLayout#draw(java.awt.Graphics2D, float, float)}. + * This mode draws glyphs as shapes and provides some advanced capabilities such as + * justification and font substitution. Use it if the target graphics is an image. + * + */ + DrawableHint TEXT_RENDERING_MODE = new DrawableHint(4); + + /** + * PathGradientPaint needs the shape to be set. + * It will be achieved through setting it in the rendering hints + */ + DrawableHint GRADIENT_SHAPE = new DrawableHint(5); + + + /** + * Internal key for caching the preset geometries + */ + DrawableHint PRESET_GEOMETRY_CACHE = new DrawableHint(6); + + /** + * draw text via {@link java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float)} + */ + int TEXT_AS_CHARACTERS = 1; + + /** + * draw text via {@link java.awt.font.TextLayout#draw(java.awt.Graphics2D, float, float)} + */ + int TEXT_AS_SHAPES = 2; + + /** + * Use this object to resolve unknown / missing fonts when rendering slides. + * The font handler must be of type {@link DrawFontManager}.

+ * + * In case a {@code FONT_HANDLER} is register, {@code FONT_FALLBACK} and {@code FONT_MAP} are ignored + */ + DrawableHint FONT_HANDLER = new DrawableHint(7); + + /** + * Key for a font fallback map of type {@code Map} which maps + * the original font family (key) to the fallback font family (value). + * In case there is also a {@code FONT_MAP} registered, the original font + * is first mapped via the font_map and then the fallback font is determined + */ + DrawableHint FONT_FALLBACK = new DrawableHint(8); + + /** + * Key for a font map of type {@code Map} which maps + * the original font family (key) to the mapped font family (value) + */ + DrawableHint FONT_MAP = new DrawableHint(9); + + DrawableHint GSAVE = new DrawableHint(10); + DrawableHint GRESTORE = new DrawableHint(11); + + /** + * The Common SL Draw API works sometimes cascading, but there are places + * where the current slide context need to be evaluated, e.g. when slide numbers + * are printed. In this situation we need to have a way to access the current slide + */ + DrawableHint CURRENT_SLIDE = new DrawableHint(12); + + + /** + * Apply 2-D transforms before drawing this shape. This includes rotation and flipping. + * + * @param graphics the graphics whos transform matrix will be modified + */ + void applyTransform(Graphics2D graphics); + + /** + * Draw this shape into the supplied canvas + * + * @param graphics the graphics to draw into + */ + void draw(Graphics2D graphics); + + /** + * draw any content within this shape (image, text, etc.). + * + * @param graphics the graphics to draw into + */ + void drawContent(Graphics2D graphics); +} diff --git a/src/java/org/apache/poi/sl/draw/ImageRenderer.java b/src/java/org/apache/poi/sl/draw/ImageRenderer.java index 6b8c49a143..7ecc96a967 100644 --- a/src/java/org/apache/poi/sl/draw/ImageRenderer.java +++ b/src/java/org/apache/poi/sl/draw/ImageRenderer.java @@ -1,130 +1,130 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.sl.draw; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; - -/** - * Classes can implement this interfaces to support other formats, for - * example, use Apache Batik to render WMF, PICT can be rendered using Apple QuickTime API for Java: - * - *

- * 
- * public class MyImageRendener implements ImageRendener {
- *     InputStream data;
- *
- *     public boolean drawImage(Graphics2D graphics,Rectangle2D anchor,Insets clip) {
- *         // draw image
- *       DataInputStream is = new DataInputStream(data);
- *       org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore wmfStore =
- *               new org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore();
- *       try {
- *           wmfStore.read(is);
- *       } catch (IOException e){
- *           return;
- *       }
- *
- *       float scale = (float)anchor.width/wmfStore.getWidthPixels();
- *
- *       org.apache.batik.transcoder.wmf.tosvg.WMFPainter painter =
- *               new org.apache.batik.transcoder.wmf.tosvg.WMFPainter(wmfStore, 0, 0, scale);
- *       graphics.translate(anchor.x, anchor.y);
- *       painter.paint(graphics);
- *     }
- *
- *     public void loadImage(InputStream data, String contentType) throws IOException {
- *         if ("image/wmf".equals(contentType)) {
- *             this.data = data;
- *             // use Apache Batik to handle WMF
- *         } else {
- *             super.loadImage(data,contentType);
- *         }
- *     }
- * }
- * 
- * 
- * - * and then pass this class to your instance of java.awt.Graphics2D: - * - *
- * 
- * graphics.setRenderingHint(Drawable.IMAGE_RENDERER, new MyImageRendener());
- * 
- * 
- */ -public interface ImageRenderer { - /** - * Load and buffer the image - * - * @param data the raw image stream - * @param contentType the content type - */ - void loadImage(InputStream data, String contentType) throws IOException; - - /** - * Load and buffer the image - * - * @param data the raw image bytes - * @param contentType the content type - */ - void loadImage(byte data[], String contentType) throws IOException; - - /** - * @return the dimension of the buffered image - */ - Dimension getDimension(); - - /** - * @param alpha the alpha [0..1] to be added to the image (possibly already containing an alpha channel) - */ - void setAlpha(double alpha); - - /** - * @return the image as buffered image - */ - BufferedImage getImage(); - - /** - * @param dim the dimension in pixels of the returned image - * @return the image as buffered image - * - * @since POI 3.15-beta2 - */ - BufferedImage getImage(Dimension dim); - - /** - * Render picture data into the supplied graphics - * - * @return true if the picture data was successfully rendered - */ - boolean drawImage(Graphics2D graphics, Rectangle2D anchor); - - /** - * Render picture data into the supplied graphics - * - * @return true if the picture data was successfully rendered - */ - boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip); +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.sl.draw; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +/** + * Classes can implement this interfaces to support other formats, for + * example, use Apache Batik to render WMF, PICT can be rendered using Apple QuickTime API for Java: + * + *
+ * 
+ * public class MyImageRendener implements ImageRendener {
+ *     InputStream data;
+ *
+ *     public boolean drawImage(Graphics2D graphics,Rectangle2D anchor,Insets clip) {
+ *         // draw image
+ *       DataInputStream is = new DataInputStream(data);
+ *       org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore wmfStore =
+ *               new org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore();
+ *       try {
+ *           wmfStore.read(is);
+ *       } catch (IOException e){
+ *           return;
+ *       }
+ *
+ *       float scale = (float)anchor.width/wmfStore.getWidthPixels();
+ *
+ *       org.apache.batik.transcoder.wmf.tosvg.WMFPainter painter =
+ *               new org.apache.batik.transcoder.wmf.tosvg.WMFPainter(wmfStore, 0, 0, scale);
+ *       graphics.translate(anchor.x, anchor.y);
+ *       painter.paint(graphics);
+ *     }
+ *
+ *     public void loadImage(InputStream data, String contentType) throws IOException {
+ *         if ("image/wmf".equals(contentType)) {
+ *             this.data = data;
+ *             // use Apache Batik to handle WMF
+ *         } else {
+ *             super.loadImage(data,contentType);
+ *         }
+ *     }
+ * }
+ * 
+ * 
+ * + * and then pass this class to your instance of java.awt.Graphics2D: + * + *
+ * 
+ * graphics.setRenderingHint(Drawable.IMAGE_RENDERER, new MyImageRendener());
+ * 
+ * 
+ */ +public interface ImageRenderer { + /** + * Load and buffer the image + * + * @param data the raw image stream + * @param contentType the content type + */ + void loadImage(InputStream data, String contentType) throws IOException; + + /** + * Load and buffer the image + * + * @param data the raw image bytes + * @param contentType the content type + */ + void loadImage(byte data[], String contentType) throws IOException; + + /** + * @return the dimension of the buffered image + */ + Dimension getDimension(); + + /** + * @param alpha the alpha [0..1] to be added to the image (possibly already containing an alpha channel) + */ + void setAlpha(double alpha); + + /** + * @return the image as buffered image + */ + BufferedImage getImage(); + + /** + * @param dim the dimension in pixels of the returned image + * @return the image as buffered image + * + * @since POI 3.15-beta2 + */ + BufferedImage getImage(Dimension dim); + + /** + * Render picture data into the supplied graphics + * + * @return true if the picture data was successfully rendered + */ + boolean drawImage(Graphics2D graphics, Rectangle2D anchor); + + /** + * Render picture data into the supplied graphics + * + * @return true if the picture data was successfully rendered + */ + boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip); } \ No newline at end of file diff --git a/src/java/org/apache/poi/sl/draw/PathGradientPaint.java b/src/java/org/apache/poi/sl/draw/PathGradientPaint.java index 63cae11e9e..d4a2a5fa5f 100644 --- a/src/java/org/apache/poi/sl/draw/PathGradientPaint.java +++ b/src/java/org/apache/poi/sl/draw/PathGradientPaint.java @@ -1,188 +1,188 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - -import java.awt.*; -import java.awt.MultipleGradientPaint.ColorSpaceType; -import java.awt.MultipleGradientPaint.CycleMethod; -import java.awt.geom.*; -import java.awt.image.*; - -class PathGradientPaint implements Paint { - - // http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html - protected final Color colors[]; - protected final float fractions[]; - protected final int capStyle; - protected final int joinStyle; - protected final int transparency; - - - public PathGradientPaint(Color colors[], float fractions[]) { - this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND); - } - - public PathGradientPaint(Color colors[], float fractions[], int capStyle, int joinStyle) { - this.colors = colors.clone(); - this.fractions = fractions.clone(); - this.capStyle = capStyle; - this.joinStyle = joinStyle; - - // determine transparency - boolean opaque = true; - for (Color c : colors) { - if (c != null) { - opaque = opaque && (c.getAlpha() == 0xff); - } - } - this.transparency = opaque ? OPAQUE : TRANSLUCENT; - } - - public PaintContext createContext(ColorModel cm, - Rectangle deviceBounds, - Rectangle2D userBounds, - AffineTransform transform, - RenderingHints hints) { - return new PathGradientContext(cm, deviceBounds, userBounds, transform, hints); - } - - public int getTransparency() { - return transparency; - } - - class PathGradientContext implements PaintContext { - protected final Rectangle deviceBounds; - protected final Rectangle2D userBounds; - protected final AffineTransform xform; - protected final RenderingHints hints; - - /** - * for POI: the shape will be only known when the subclasses determines the concrete implementation - * in the draw/-content method, so we need to postpone the setting/creation as long as possible - **/ - protected final Shape shape; - protected final PaintContext pCtx; - protected final int gradientSteps; - WritableRaster raster; - - public PathGradientContext( - ColorModel cm - , Rectangle deviceBounds - , Rectangle2D userBounds - , AffineTransform xform - , RenderingHints hints - ) { - shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE); - if (shape == null) { - throw new IllegalPathStateException("PathGradientPaint needs a shape to be set via the rendering hint Drawable.GRADIANT_SHAPE."); - } - - this.deviceBounds = deviceBounds; - this.userBounds = userBounds; - this.xform = xform; - this.hints = hints; - - gradientSteps = getGradientSteps(shape); - - Point2D start = new Point2D.Double(0, 0); - Point2D end = new Point2D.Double(gradientSteps, 0); - LinearGradientPaint gradientPaint = new LinearGradientPaint(start, end, fractions, colors, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, new AffineTransform()); - - Rectangle bounds = new Rectangle(0, 0, gradientSteps, 1); - pCtx = gradientPaint.createContext(cm, bounds, bounds, new AffineTransform(), hints); - } - - public void dispose() {} - - public ColorModel getColorModel() { - return pCtx.getColorModel(); - } - - public Raster getRaster(int xOffset, int yOffset, int w, int h) { - ColorModel cm = getColorModel(); - if (raster == null) createRaster(); - - // TODO: eventually use caching here - WritableRaster childRaster = cm.createCompatibleWritableRaster(w, h); - Rectangle2D childRect = new Rectangle2D.Double(xOffset, yOffset, w, h); - if (!childRect.intersects(deviceBounds)) { - // usually doesn't happen ... - return childRaster; - } - - Rectangle2D destRect = new Rectangle2D.Double(); - Rectangle2D.intersect(childRect, deviceBounds, destRect); - int dx = (int)(destRect.getX()-deviceBounds.getX()); - int dy = (int)(destRect.getY()-deviceBounds.getY()); - int dw = (int)destRect.getWidth(); - int dh = (int)destRect.getHeight(); - Object data = raster.getDataElements(dx, dy, dw, dh, null); - dx = (int)(destRect.getX()-childRect.getX()); - dy = (int)(destRect.getY()-childRect.getY()); - childRaster.setDataElements(dx, dy, dw, dh, data); - - return childRaster; - } - - protected int getGradientSteps(Shape gradientShape) { - Rectangle rect = gradientShape.getBounds(); - int lower = 1; - int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0); - while (lower < upper-1) { - int mid = lower + (upper - lower) / 2; - BasicStroke bs = new BasicStroke(mid, capStyle, joinStyle); - Area area = new Area(bs.createStrokedShape(gradientShape)); - if (area.isSingular()) { - upper = mid; - } else { - lower = mid; - } - } - return upper; - } - - - - protected void createRaster() { - ColorModel cm = getColorModel(); - raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight()); - BufferedImage img = new BufferedImage(cm, raster, false, null); - Graphics2D graphics = img.createGraphics(); - graphics.setRenderingHints(hints); - graphics.translate(-deviceBounds.getX(), -deviceBounds.getY()); - graphics.transform(xform); - - Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1); - int rgb[] = new int[cm.getNumComponents()]; - - for (int i = gradientSteps-1; i>=0; i--) { - img2.getPixel(i, 0, rgb); - Color c = new Color(rgb[0],rgb[1],rgb[2]); - if (rgb.length == 4) { - // it doesn't work to use just a color with transparency ... - graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f)); - } - graphics.setStroke(new BasicStroke(i+1, capStyle, joinStyle)); - graphics.setColor(c); - graphics.draw(shape); - } - - graphics.dispose(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + +import java.awt.*; +import java.awt.MultipleGradientPaint.ColorSpaceType; +import java.awt.MultipleGradientPaint.CycleMethod; +import java.awt.geom.*; +import java.awt.image.*; + +class PathGradientPaint implements Paint { + + // http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html + protected final Color colors[]; + protected final float fractions[]; + protected final int capStyle; + protected final int joinStyle; + protected final int transparency; + + + public PathGradientPaint(Color colors[], float fractions[]) { + this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND); + } + + public PathGradientPaint(Color colors[], float fractions[], int capStyle, int joinStyle) { + this.colors = colors.clone(); + this.fractions = fractions.clone(); + this.capStyle = capStyle; + this.joinStyle = joinStyle; + + // determine transparency + boolean opaque = true; + for (Color c : colors) { + if (c != null) { + opaque = opaque && (c.getAlpha() == 0xff); + } + } + this.transparency = opaque ? OPAQUE : TRANSLUCENT; + } + + public PaintContext createContext(ColorModel cm, + Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform transform, + RenderingHints hints) { + return new PathGradientContext(cm, deviceBounds, userBounds, transform, hints); + } + + public int getTransparency() { + return transparency; + } + + class PathGradientContext implements PaintContext { + protected final Rectangle deviceBounds; + protected final Rectangle2D userBounds; + protected final AffineTransform xform; + protected final RenderingHints hints; + + /** + * for POI: the shape will be only known when the subclasses determines the concrete implementation + * in the draw/-content method, so we need to postpone the setting/creation as long as possible + **/ + protected final Shape shape; + protected final PaintContext pCtx; + protected final int gradientSteps; + WritableRaster raster; + + public PathGradientContext( + ColorModel cm + , Rectangle deviceBounds + , Rectangle2D userBounds + , AffineTransform xform + , RenderingHints hints + ) { + shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE); + if (shape == null) { + throw new IllegalPathStateException("PathGradientPaint needs a shape to be set via the rendering hint Drawable.GRADIANT_SHAPE."); + } + + this.deviceBounds = deviceBounds; + this.userBounds = userBounds; + this.xform = xform; + this.hints = hints; + + gradientSteps = getGradientSteps(shape); + + Point2D start = new Point2D.Double(0, 0); + Point2D end = new Point2D.Double(gradientSteps, 0); + LinearGradientPaint gradientPaint = new LinearGradientPaint(start, end, fractions, colors, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, new AffineTransform()); + + Rectangle bounds = new Rectangle(0, 0, gradientSteps, 1); + pCtx = gradientPaint.createContext(cm, bounds, bounds, new AffineTransform(), hints); + } + + public void dispose() {} + + public ColorModel getColorModel() { + return pCtx.getColorModel(); + } + + public Raster getRaster(int xOffset, int yOffset, int w, int h) { + ColorModel cm = getColorModel(); + if (raster == null) createRaster(); + + // TODO: eventually use caching here + WritableRaster childRaster = cm.createCompatibleWritableRaster(w, h); + Rectangle2D childRect = new Rectangle2D.Double(xOffset, yOffset, w, h); + if (!childRect.intersects(deviceBounds)) { + // usually doesn't happen ... + return childRaster; + } + + Rectangle2D destRect = new Rectangle2D.Double(); + Rectangle2D.intersect(childRect, deviceBounds, destRect); + int dx = (int)(destRect.getX()-deviceBounds.getX()); + int dy = (int)(destRect.getY()-deviceBounds.getY()); + int dw = (int)destRect.getWidth(); + int dh = (int)destRect.getHeight(); + Object data = raster.getDataElements(dx, dy, dw, dh, null); + dx = (int)(destRect.getX()-childRect.getX()); + dy = (int)(destRect.getY()-childRect.getY()); + childRaster.setDataElements(dx, dy, dw, dh, data); + + return childRaster; + } + + protected int getGradientSteps(Shape gradientShape) { + Rectangle rect = gradientShape.getBounds(); + int lower = 1; + int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0); + while (lower < upper-1) { + int mid = lower + (upper - lower) / 2; + BasicStroke bs = new BasicStroke(mid, capStyle, joinStyle); + Area area = new Area(bs.createStrokedShape(gradientShape)); + if (area.isSingular()) { + upper = mid; + } else { + lower = mid; + } + } + return upper; + } + + + + protected void createRaster() { + ColorModel cm = getColorModel(); + raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight()); + BufferedImage img = new BufferedImage(cm, raster, false, null); + Graphics2D graphics = img.createGraphics(); + graphics.setRenderingHints(hints); + graphics.translate(-deviceBounds.getX(), -deviceBounds.getY()); + graphics.transform(xform); + + Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1); + int rgb[] = new int[cm.getNumComponents()]; + + for (int i = gradientSteps-1; i>=0; i--) { + img2.getPixel(i, 0, rgb); + Color c = new Color(rgb[0],rgb[1],rgb[2]); + if (rgb.length == 4) { + // it doesn't work to use just a color with transparency ... + graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f)); + } + graphics.setStroke(new BasicStroke(i+1, capStyle, joinStyle)); + graphics.setColor(c); + graphics.draw(shape); + } + + graphics.dispose(); + } + } +} diff --git a/src/java/org/apache/poi/sl/draw/SLGraphics.java b/src/java/org/apache/poi/sl/draw/SLGraphics.java index 47dba62884..c9b70cfba0 100644 --- a/src/java/org/apache/poi/sl/draw/SLGraphics.java +++ b/src/java/org/apache/poi/sl/draw/SLGraphics.java @@ -1,1846 +1,1846 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw; - - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsEnvironment; -import java.awt.Image; -import java.awt.Paint; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.Toolkit; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.font.TextLayout; -import java.awt.geom.AffineTransform; -import java.awt.geom.Arc2D; -import java.awt.geom.Ellipse2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.Line2D; -import java.awt.geom.Path2D; -import java.awt.geom.RoundRectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ImageObserver; -import java.awt.image.RenderedImage; -import java.awt.image.renderable.RenderableImage; -import java.text.AttributedCharacterIterator; -import java.util.Map; - -import org.apache.poi.sl.usermodel.FreeformShape; -import org.apache.poi.sl.usermodel.GroupShape; -import org.apache.poi.sl.usermodel.Insets2D; -import org.apache.poi.sl.usermodel.SimpleShape; -import org.apache.poi.sl.usermodel.StrokeStyle; -import org.apache.poi.sl.usermodel.TextBox; -import org.apache.poi.sl.usermodel.TextRun; -import org.apache.poi.sl.usermodel.VerticalAlignment; -import org.apache.poi.util.NotImplemented; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.SuppressForbidden; - -/** - * Translates Graphics2D calls into PowerPoint. - * - * @author Yegor Kozlov - */ -public final class SLGraphics extends Graphics2D implements Cloneable { - - protected POILogger log = POILogFactory.getLogger(this.getClass()); - - //The ppt object to write into. - private GroupShape _group; - - private AffineTransform _transform; - private Stroke _stroke; - private Paint _paint; - private Font _font; - private Color _foreground; - private Color _background; - private RenderingHints _hints; - - /** - * Construct Java Graphics object which translates graphic calls in ppt drawing layer. - * - * @param group The shape group to write the graphics calls into. - */ - public SLGraphics(GroupShape group){ - this._group = group; - - _transform = new AffineTransform(); - _stroke = new BasicStroke(); - _paint = Color.black; - _font = new Font("Arial", Font.PLAIN, 12); - _background = Color.black; - _foreground = Color.white; - _hints = new RenderingHints(null); - } - - /** - * @return the shape group being used for drawing - */ - public GroupShape getShapeGroup(){ - return _group; - } - - /** - * Gets the current font. - * @return this graphics context's current font. - * @see java.awt.Font - * @see java.awt.Graphics#setFont(Font) - */ - public Font getFont(){ - return _font; - } - - /** - * Sets this graphics context's font to the specified font. - * All subsequent text operations using this graphics context - * use this font. - * @param font the font. - * @see java.awt.Graphics#getFont - * @see java.awt.Graphics#drawString(java.lang.String, int, int) - * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int) - * @see java.awt.Graphics#drawChars(char[], int, int, int, int) - */ - public void setFont(Font font){ - this._font = font; - } - - /** - * Gets this graphics context's current color. - * @return this graphics context's current color. - * @see java.awt.Color - * @see java.awt.Graphics#setColor - */ - public Color getColor(){ - return _foreground; - } - - /** - * Sets this graphics context's current color to the specified - * color. All subsequent graphics operations using this graphics - * context use this specified color. - * @param c the new rendering color. - * @see java.awt.Color - * @see java.awt.Graphics#getColor - */ - public void setColor(Color c) { - setPaint(c); - } - - /** - * Returns the current Stroke in the - * Graphics2D context. - * @return the current Graphics2D Stroke, - * which defines the line style. - * @see #setStroke - */ - public Stroke getStroke(){ - return _stroke; - } - - /** - * Sets the Stroke for the Graphics2D context. - * @param s the Stroke object to be used to stroke a - * Shape during the rendering process - */ - public void setStroke(Stroke s){ - this._stroke = s; - } - - /** - * Returns the current Paint of the - * Graphics2D context. - * @return the current Graphics2D Paint, - * which defines a color or pattern. - * @see #setPaint - * @see java.awt.Graphics#setColor - */ - public Paint getPaint(){ - return _paint; - } - - /** - * Sets the Paint attribute for the - * Graphics2D context. Calling this method - * with a null Paint object does - * not have any effect on the current Paint attribute - * of this Graphics2D. - * @param paint the Paint object to be used to generate - * color during the rendering process, or null - * @see java.awt.Graphics#setColor - */ - public void setPaint(Paint paint){ - if(paint == null) return; - - this._paint = paint; - if (paint instanceof Color) _foreground = (Color)paint; - } - - /** - * Returns a copy of the current Transform in the - * Graphics2D context. - * @return the current AffineTransform in the - * Graphics2D context. - * @see #_transform - * @see #setTransform - */ - public AffineTransform getTransform(){ - return new AffineTransform(_transform); - } - - /** - * Sets the Transform in the Graphics2D - * context. - * @param Tx the AffineTransform object to be used in the - * rendering process - * @see #_transform - * @see AffineTransform - */ - public void setTransform(AffineTransform Tx) { - _transform = new AffineTransform(Tx); - } - - /** - * Strokes the outline of a Shape using the settings of the - * current Graphics2D context. The rendering attributes - * applied include the Clip, Transform, - * Paint, Composite and - * Stroke attributes. - * @param shape the Shape to be rendered - * @see #setStroke - * @see #setPaint - * @see java.awt.Graphics#setColor - * @see #_transform - * @see #setTransform - * @see #clip - * @see #setClip - * @see #setComposite - */ - public void draw(Shape shape){ - Path2D.Double path = new Path2D.Double(_transform.createTransformedShape(shape)); - FreeformShape p = _group.createFreeform(); - p.setPath(path); - p.setFillColor(null); - applyStroke(p); - if (_paint instanceof Color) { - p.setStrokeStyle((Color)_paint); - } - } - - /** - * Renders the text specified by the specified String, - * using the current text attribute state in the Graphics2D context. - * The baseline of the first character is at position - * (xy) in the User Space. - * The rendering attributes applied include the Clip, - * Transform, Paint, Font and - * Composite attributes. For characters in script systems - * such as Hebrew and Arabic, the glyphs can be rendered from right to - * left, in which case the coordinate supplied is the location of the - * leftmost character on the baseline. - * @param s the String to be rendered - * @param x the x coordinate of the location where the - * String should be rendered - * @param y the y coordinate of the location where the - * String should be rendered - * @throws NullPointerException if str is - * null - * @see #setPaint - * @see java.awt.Graphics#setColor - * @see java.awt.Graphics#setFont - * @see #setTransform - * @see #setComposite - * @see #setClip - */ - public void drawString(String s, float x, float y) { - TextBox txt = _group.createTextBox(); - - TextRun rt = txt.getTextParagraphs().get(0).getTextRuns().get(0); - rt.setFontSize((double)_font.getSize()); - rt.setFontFamily(_font.getFamily()); - - if (getColor() != null) rt.setFontColor(DrawPaint.createSolidPaint(getColor())); - if (_font.isBold()) rt.setBold(true); - if (_font.isItalic()) rt.setItalic(true); - - txt.setText(s); - - txt.setInsets(new Insets2D(0,0,0,0)); - txt.setWordWrap(false); - txt.setHorizontalCentered(false); - txt.setVerticalAlignment(VerticalAlignment.MIDDLE); - - - TextLayout layout = new TextLayout(s, _font, getFontRenderContext()); - float ascent = layout.getAscent(); - - float width = (float) Math.floor(layout.getAdvance()); - /** - * Even if top and bottom margins are set to 0 PowerPoint - * always sets extra space between the text and its bounding box. - * - * The approximation height = ascent*2 works good enough in most cases - */ - float height = ascent * 2; - - /* - In powerpoint anchor of a shape is its top left corner. - Java graphics sets string coordinates by the baseline of the first character - so we need to shift up by the height of the textbox - */ - y -= height / 2 + ascent / 2; - - /* - In powerpoint anchor of a shape is its top left corner. - Java graphics sets string coordinates by the baseline of the first character - so we need to shift down by the height of the textbox - */ - txt.setAnchor(new Rectangle((int)x, (int)y, (int)width, (int)height)); - } - - /** - * Fills the interior of a Shape using the settings of the - * Graphics2D context. The rendering attributes applied - * include the Clip, Transform, - * Paint, and Composite. - * @param shape the Shape to be filled - * @see #setPaint - * @see java.awt.Graphics#setColor - * @see #_transform - * @see #setTransform - * @see #setComposite - * @see #clip - * @see #setClip - */ - public void fill(Shape shape){ - Path2D.Double path = new Path2D.Double(_transform.createTransformedShape(shape)); - FreeformShape p = _group.createFreeform(); - p.setPath(path); - applyPaint(p); - p.setStrokeStyle(); //Fills must be "No Line" - } - - /** - * Translates the origin of the graphics context to the point - * (xy) in the current coordinate system. - * Modifies this graphics context so that its new origin corresponds - * to the point (xy) in this graphics context's - * original coordinate system. All coordinates used in subsequent - * rendering operations on this graphics context will be relative - * to this new origin. - * @param x the x coordinate. - * @param y the y coordinate. - */ - public void translate(int x, int y){ - _transform.translate(x, y); - } - - /** - * Intersects the current Clip with the interior of the - * specified Shape and sets the Clip to the - * resulting intersection. The specified Shape is - * transformed with the current Graphics2D - * Transform before being intersected with the current - * Clip. This method is used to make the current - * Clip smaller. - * To make the Clip larger, use setClip. - * The user clip modified by this method is independent of the - * clipping associated with device bounds and visibility. If no clip has - * previously been set, or if the clip has been cleared using - * {@link java.awt.Graphics#setClip(Shape) setClip} with a - * null argument, the specified Shape becomes - * the new user clip. - * @param s the Shape to be intersected with the current - * Clip. If s is null, - * this method clears the current Clip. - */ - @NotImplemented - public void clip(Shape s){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - /** - * Gets the current clipping area. - * This method returns the user clip, which is independent of the - * clipping associated with device bounds and window visibility. - * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns - * null. - * @return a Shape object representing the - * current clipping area, or null if - * no clip is set. - * @see java.awt.Graphics#getClipBounds() - * @see java.awt.Graphics#clipRect - * @see java.awt.Graphics#setClip(int, int, int, int) - * @see java.awt.Graphics#setClip(Shape) - * @since JDK1.1 - */ - @NotImplemented - public Shape getClip(){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - return null; - } - - /** - * Concatenates the current Graphics2D - * Transform with a scaling transformation - * Subsequent rendering is resized according to the specified scaling - * factors relative to the previous scaling. - * This is equivalent to calling transform(S), where S is an - * AffineTransform represented by the following matrix: - *
-     *          [   sx   0    0   ]
-     *          [   0    sy   0   ]
-     *          [   0    0    1   ]
-     * 
- * @param sx the amount by which X coordinates in subsequent - * rendering operations are multiplied relative to previous - * rendering operations. - * @param sy the amount by which Y coordinates in subsequent - * rendering operations are multiplied relative to previous - * rendering operations. - */ - public void scale(double sx, double sy){ - _transform.scale(sx, sy); - } - - /** - * Draws an outlined round-cornered rectangle using this graphics - * context's current color. The left and right edges of the rectangle - * are at x and x + width, - * respectively. The top and bottom edges of the rectangle are at - * y and y + height. - * @param x the x coordinate of the rectangle to be drawn. - * @param y the y coordinate of the rectangle to be drawn. - * @param width the width of the rectangle to be drawn. - * @param height the height of the rectangle to be drawn. - * @param arcWidth the horizontal diameter of the arc - * at the four corners. - * @param arcHeight the vertical diameter of the arc - * at the four corners. - * @see java.awt.Graphics#fillRoundRect - */ - public void drawRoundRect(int x, int y, int width, int height, - int arcWidth, int arcHeight){ - RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight); - draw(rect); - } - - /** - * Draws the text given by the specified string, using this - * graphics context's current font and color. The baseline of the - * first character is at position (xy) in this - * graphics context's coordinate system. - * @param str the string to be drawn. - * @param x the x coordinate. - * @param y the y coordinate. - * @see java.awt.Graphics#drawBytes - * @see java.awt.Graphics#drawChars - */ - public void drawString(String str, int x, int y){ - drawString(str, (float)x, (float)y); - } - - /** - * Fills an oval bounded by the specified rectangle with the - * current color. - * @param x the x coordinate of the upper left corner - * of the oval to be filled. - * @param y the y coordinate of the upper left corner - * of the oval to be filled. - * @param width the width of the oval to be filled. - * @param height the height of the oval to be filled. - * @see java.awt.Graphics#drawOval - */ - public void fillOval(int x, int y, int width, int height){ - Ellipse2D oval = new Ellipse2D.Double(x, y, width, height); - fill(oval); - } - - /** - * Fills the specified rounded corner rectangle with the current color. - * The left and right edges of the rectangle - * are at x and x + width - 1, - * respectively. The top and bottom edges of the rectangle are at - * y and y + height - 1. - * @param x the x coordinate of the rectangle to be filled. - * @param y the y coordinate of the rectangle to be filled. - * @param width the width of the rectangle to be filled. - * @param height the height of the rectangle to be filled. - * @param arcWidth the horizontal diameter - * of the arc at the four corners. - * @param arcHeight the vertical diameter - * of the arc at the four corners. - * @see java.awt.Graphics#drawRoundRect - */ - public void fillRoundRect(int x, int y, int width, int height, - int arcWidth, int arcHeight){ - - RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight); - fill(rect); - } - - /** - * Fills a circular or elliptical arc covering the specified rectangle. - *

- * The resulting arc begins at startAngle and extends - * for arcAngle degrees. - * Angles are interpreted such that 0 degrees - * is at the 3 o'clock position. - * A positive value indicates a counter-clockwise rotation - * while a negative value indicates a clockwise rotation. - *

- * The center of the arc is the center of the rectangle whose origin - * is (xy) and whose size is specified by the - * width and height arguments. - *

- * The resulting arc covers an area - * width + 1 pixels wide - * by height + 1 pixels tall. - *

- * The angles are specified relative to the non-square extents of - * the bounding rectangle such that 45 degrees always falls on the - * line from the center of the ellipse to the upper right corner of - * the bounding rectangle. As a result, if the bounding rectangle is - * noticeably longer in one axis than the other, the angles to the - * start and end of the arc segment will be skewed farther along the - * longer axis of the bounds. - * @param x the x coordinate of the - * upper-left corner of the arc to be filled. - * @param y the y coordinate of the - * upper-left corner of the arc to be filled. - * @param width the width of the arc to be filled. - * @param height the height of the arc to be filled. - * @param startAngle the beginning angle. - * @param arcAngle the angular extent of the arc, - * relative to the start angle. - * @see java.awt.Graphics#drawArc - */ - public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle){ - Arc2D arc = new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.PIE); - fill(arc); - } - - /** - * Draws the outline of a circular or elliptical arc - * covering the specified rectangle. - *

- * The resulting arc begins at startAngle and extends - * for arcAngle degrees, using the current color. - * Angles are interpreted such that 0 degrees - * is at the 3 o'clock position. - * A positive value indicates a counter-clockwise rotation - * while a negative value indicates a clockwise rotation. - *

- * The center of the arc is the center of the rectangle whose origin - * is (xy) and whose size is specified by the - * width and height arguments. - *

- * The resulting arc covers an area - * width + 1 pixels wide - * by height + 1 pixels tall. - *

- * The angles are specified relative to the non-square extents of - * the bounding rectangle such that 45 degrees always falls on the - * line from the center of the ellipse to the upper right corner of - * the bounding rectangle. As a result, if the bounding rectangle is - * noticeably longer in one axis than the other, the angles to the - * start and end of the arc segment will be skewed farther along the - * longer axis of the bounds. - * @param x the x coordinate of the - * upper-left corner of the arc to be drawn. - * @param y the y coordinate of the - * upper-left corner of the arc to be drawn. - * @param width the width of the arc to be drawn. - * @param height the height of the arc to be drawn. - * @param startAngle the beginning angle. - * @param arcAngle the angular extent of the arc, - * relative to the start angle. - * @see java.awt.Graphics#fillArc - */ - public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { - Arc2D arc = new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN); - draw(arc); - } - - - /** - * Draws a sequence of connected lines defined by - * arrays of x and y coordinates. - * Each pair of (xy) coordinates defines a point. - * The figure is not closed if the first point - * differs from the last point. - * @param xPoints an array of x points - * @param yPoints an array of y points - * @param nPoints the total number of points - * @see java.awt.Graphics#drawPolygon(int[], int[], int) - * @since JDK1.1 - */ - public void drawPolyline(int[] xPoints, int[] yPoints, - int nPoints){ - if(nPoints > 0){ - GeneralPath path = new GeneralPath(); - path.moveTo(xPoints[0], yPoints[0]); - for(int i=1; ix, y, - * width, and height arguments. - *

- * The oval covers an area that is - * width + 1 pixels wide - * and height + 1 pixels tall. - * @param x the x coordinate of the upper left - * corner of the oval to be drawn. - * @param y the y coordinate of the upper left - * corner of the oval to be drawn. - * @param width the width of the oval to be drawn. - * @param height the height of the oval to be drawn. - * @see java.awt.Graphics#fillOval - */ - public void drawOval(int x, int y, int width, int height){ - Ellipse2D oval = new Ellipse2D.Double(x, y, width, height); - draw(oval); - } - - /** - * Draws as much of the specified image as is currently available. - * The image is drawn with its top-left corner at - * (xy) in this graphics context's coordinate - * space. Transparent pixels are drawn in the specified - * background color. - *

- * This operation is equivalent to filling a rectangle of the - * width and height of the specified image with the given color and then - * drawing the image on top of it, but possibly more efficient. - *

- * This method returns immediately in all cases, even if the - * complete image has not yet been loaded, and it has not been dithered - * and converted for the current output device. - *

- * If the image has not yet been completely loaded, then - * drawImage returns false. As more of - * the image becomes available, the process that draws the image notifies - * the specified image observer. - * @param img the specified image to be drawn. - * @param x the x coordinate. - * @param y the y coordinate. - * @param bgcolor the background color to paint under the - * non-opaque portions of the image. - * @param observer object to be notified as more of - * the image is converted. - * @see java.awt.Image - * @see java.awt.image.ImageObserver - * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) - */ - @NotImplemented - public boolean drawImage(Image img, int x, int y, - Color bgcolor, - ImageObserver observer){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - - return false; - } - - /** - * Draws as much of the specified image as has already been scaled - * to fit inside the specified rectangle. - *

- * The image is drawn inside the specified rectangle of this - * graphics context's coordinate space, and is scaled if - * necessary. Transparent pixels are drawn in the specified - * background color. - * This operation is equivalent to filling a rectangle of the - * width and height of the specified image with the given color and then - * drawing the image on top of it, but possibly more efficient. - *

- * This method returns immediately in all cases, even if the - * entire image has not yet been scaled, dithered, and converted - * for the current output device. - * If the current output representation is not yet complete then - * drawImage returns false. As more of - * the image becomes available, the process that draws the image notifies - * the specified image observer. - *

- * A scaled version of an image will not necessarily be - * available immediately just because an unscaled version of the - * image has been constructed for this output device. Each size of - * the image may be cached separately and generated from the original - * data in a separate image production sequence. - * @param img the specified image to be drawn. - * @param x the x coordinate. - * @param y the y coordinate. - * @param width the width of the rectangle. - * @param height the height of the rectangle. - * @param bgcolor the background color to paint under the - * non-opaque portions of the image. - * @param observer object to be notified as more of - * the image is converted. - * @see java.awt.Image - * @see java.awt.image.ImageObserver - * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) - */ - @NotImplemented - public boolean drawImage(Image img, int x, int y, - int width, int height, - Color bgcolor, - ImageObserver observer){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - - return false; - } - - - /** - * Draws as much of the specified area of the specified image as is - * currently available, scaling it on the fly to fit inside the - * specified area of the destination drawable surface. Transparent pixels - * do not affect whatever pixels are already there. - *

- * This method returns immediately in all cases, even if the - * image area to be drawn has not yet been scaled, dithered, and converted - * for the current output device. - * If the current output representation is not yet complete then - * drawImage returns false. As more of - * the image becomes available, the process that draws the image notifies - * the specified image observer. - *

- * This method always uses the unscaled version of the image - * to render the scaled rectangle and performs the required - * scaling on the fly. It does not use a cached, scaled version - * of the image for this operation. Scaling of the image from source - * to destination is performed such that the first coordinate - * of the source rectangle is mapped to the first coordinate of - * the destination rectangle, and the second source coordinate is - * mapped to the second destination coordinate. The subimage is - * scaled and flipped as needed to preserve those mappings. - * @param img the specified image to be drawn - * @param dx1 the x coordinate of the first corner of the - * destination rectangle. - * @param dy1 the y coordinate of the first corner of the - * destination rectangle. - * @param dx2 the x coordinate of the second corner of the - * destination rectangle. - * @param dy2 the y coordinate of the second corner of the - * destination rectangle. - * @param sx1 the x coordinate of the first corner of the - * source rectangle. - * @param sy1 the y coordinate of the first corner of the - * source rectangle. - * @param sx2 the x coordinate of the second corner of the - * source rectangle. - * @param sy2 the y coordinate of the second corner of the - * source rectangle. - * @param observer object to be notified as more of the image is - * scaled and converted. - * @see java.awt.Image - * @see java.awt.image.ImageObserver - * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) - * @since JDK1.1 - */ - @NotImplemented - public boolean drawImage(Image img, - int dx1, int dy1, int dx2, int dy2, - int sx1, int sy1, int sx2, int sy2, - ImageObserver observer){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - return false; - } - - /** - * Draws as much of the specified area of the specified image as is - * currently available, scaling it on the fly to fit inside the - * specified area of the destination drawable surface. - *

- * Transparent pixels are drawn in the specified background color. - * This operation is equivalent to filling a rectangle of the - * width and height of the specified image with the given color and then - * drawing the image on top of it, but possibly more efficient. - *

- * This method returns immediately in all cases, even if the - * image area to be drawn has not yet been scaled, dithered, and converted - * for the current output device. - * If the current output representation is not yet complete then - * drawImage returns false. As more of - * the image becomes available, the process that draws the image notifies - * the specified image observer. - *

- * This method always uses the unscaled version of the image - * to render the scaled rectangle and performs the required - * scaling on the fly. It does not use a cached, scaled version - * of the image for this operation. Scaling of the image from source - * to destination is performed such that the first coordinate - * of the source rectangle is mapped to the first coordinate of - * the destination rectangle, and the second source coordinate is - * mapped to the second destination coordinate. The subimage is - * scaled and flipped as needed to preserve those mappings. - * @param img the specified image to be drawn - * @param dx1 the x coordinate of the first corner of the - * destination rectangle. - * @param dy1 the y coordinate of the first corner of the - * destination rectangle. - * @param dx2 the x coordinate of the second corner of the - * destination rectangle. - * @param dy2 the y coordinate of the second corner of the - * destination rectangle. - * @param sx1 the x coordinate of the first corner of the - * source rectangle. - * @param sy1 the y coordinate of the first corner of the - * source rectangle. - * @param sx2 the x coordinate of the second corner of the - * source rectangle. - * @param sy2 the y coordinate of the second corner of the - * source rectangle. - * @param bgcolor the background color to paint under the - * non-opaque portions of the image. - * @param observer object to be notified as more of the image is - * scaled and converted. - * @see java.awt.Image - * @see java.awt.image.ImageObserver - * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) - * @since JDK1.1 - */ - @NotImplemented - public boolean drawImage(Image img, - int dx1, int dy1, int dx2, int dy2, - int sx1, int sy1, int sx2, int sy2, - Color bgcolor, - ImageObserver observer){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - return false; - } - - /** - * Draws as much of the specified image as is currently available. - * The image is drawn with its top-left corner at - * (xy) in this graphics context's coordinate - * space. Transparent pixels in the image do not affect whatever - * pixels are already there. - *

- * This method returns immediately in all cases, even if the - * complete image has not yet been loaded, and it has not been dithered - * and converted for the current output device. - *

- * If the image has completely loaded and its pixels are - * no longer being changed, then - * drawImage returns true. - * Otherwise, drawImage returns false - * and as more of - * the image becomes available - * or it is time to draw another frame of animation, - * the process that loads the image notifies - * the specified image observer. - * @param img the specified image to be drawn. This method does - * nothing if img is null. - * @param x the x coordinate. - * @param y the y coordinate. - * @param observer object to be notified as more of - * the image is converted. - * @return false if the image pixels are still changing; - * true otherwise. - * @see java.awt.Image - * @see java.awt.image.ImageObserver - * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) - */ - @NotImplemented - public boolean drawImage(Image img, int x, int y, - ImageObserver observer) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - return false; - } - - /** - * Disposes of this graphics context and releases - * any system resources that it is using. - * A Graphics object cannot be used after - * disposehas been called. - *

- * When a Java program runs, a large number of Graphics - * objects can be created within a short time frame. - * Although the finalization process of the garbage collector - * also disposes of the same system resources, it is preferable - * to manually free the associated resources by calling this - * method rather than to rely on a finalization process which - * may not run to completion for a long period of time. - *

- * Graphics objects which are provided as arguments to the - * paint and update methods - * of components are automatically released by the system when - * those methods return. For efficiency, programmers should - * call dispose when finished using - * a Graphics object only if it was created - * directly from a component or another Graphics object. - * @see java.awt.Graphics#finalize - * @see java.awt.Component#paint - * @see java.awt.Component#update - * @see java.awt.Component#getGraphics - * @see java.awt.Graphics#create - */ - public void dispose() { - } - - /** - * Draws a line, using the current color, between the points - * (x1, y1) and (x2, y2) - * in this graphics context's coordinate system. - * @param x1 the first point's x coordinate. - * @param y1 the first point's y coordinate. - * @param x2 the second point's x coordinate. - * @param y2 the second point's y coordinate. - */ - public void drawLine(int x1, int y1, int x2, int y2){ - Line2D line = new Line2D.Double(x1, y1, x2, y2); - draw(line); - } - - /** - * Fills a closed polygon defined by - * arrays of x and y coordinates. - *

- * This method draws the polygon defined by nPoint line - * segments, where the first nPoint - 1 - * line segments are line segments from - * (xPoints[i - 1], yPoints[i - 1]) - * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. - * The figure is automatically closed by drawing a line connecting - * the final point to the first point, if those points are different. - *

- * The area inside the polygon is defined using an - * even-odd fill rule, also known as the alternating rule. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. - * @param nPoints a the total number of points. - * @see java.awt.Graphics#drawPolygon(int[], int[], int) - */ - public void fillPolygon(int[] xPoints, int[] yPoints, - int nPoints){ - java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints); - fill(polygon); - } - - /** - * Fills the specified rectangle. - * The left and right edges of the rectangle are at - * x and x + width - 1. - * The top and bottom edges are at - * y and y + height - 1. - * The resulting rectangle covers an area - * width pixels wide by - * height pixels tall. - * The rectangle is filled using the graphics context's current color. - * @param x the x coordinate - * of the rectangle to be filled. - * @param y the y coordinate - * of the rectangle to be filled. - * @param width the width of the rectangle to be filled. - * @param height the height of the rectangle to be filled. - * @see java.awt.Graphics#clearRect - * @see java.awt.Graphics#drawRect - */ - public void fillRect(int x, int y, int width, int height){ - Rectangle rect = new Rectangle(x, y, width, height); - fill(rect); - } - - /** - * Draws the outline of the specified rectangle. - * The left and right edges of the rectangle are at - * x and x + width. - * The top and bottom edges are at - * y and y + height. - * The rectangle is drawn using the graphics context's current color. - * @param x the x coordinate - * of the rectangle to be drawn. - * @param y the y coordinate - * of the rectangle to be drawn. - * @param width the width of the rectangle to be drawn. - * @param height the height of the rectangle to be drawn. - * @see java.awt.Graphics#fillRect - * @see java.awt.Graphics#clearRect - */ - public void drawRect(int x, int y, int width, int height) { - Rectangle rect = new Rectangle(x, y, width, height); - draw(rect); - } - - /** - * Draws a closed polygon defined by - * arrays of x and y coordinates. - * Each pair of (xy) coordinates defines a point. - *

- * This method draws the polygon defined by nPoint line - * segments, where the first nPoint - 1 - * line segments are line segments from - * (xPoints[i - 1], yPoints[i - 1]) - * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. - * The figure is automatically closed by drawing a line connecting - * the final point to the first point, if those points are different. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. - * @param nPoints a the total number of points. - * @see java.awt.Graphics#fillPolygon(int[],int[],int) - * @see java.awt.Graphics#drawPolyline - */ - public void drawPolygon(int[] xPoints, int[] yPoints, - int nPoints){ - java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints); - draw(polygon); - } - - /** - * Intersects the current clip with the specified rectangle. - * The resulting clipping area is the intersection of the current - * clipping area and the specified rectangle. If there is no - * current clipping area, either because the clip has never been - * set, or the clip has been cleared using setClip(null), - * the specified rectangle becomes the new clip. - * This method sets the user clip, which is independent of the - * clipping associated with device bounds and window visibility. - * This method can only be used to make the current clip smaller. - * To set the current clip larger, use any of the setClip methods. - * Rendering operations have no effect outside of the clipping area. - * @param x the x coordinate of the rectangle to intersect the clip with - * @param y the y coordinate of the rectangle to intersect the clip with - * @param width the width of the rectangle to intersect the clip with - * @param height the height of the rectangle to intersect the clip with - * @see #setClip(int, int, int, int) - * @see #setClip(Shape) - */ - public void clipRect(int x, int y, int width, int height){ - clip(new Rectangle(x, y, width, height)); - } - - /** - * Sets the current clipping area to an arbitrary clip shape. - * Not all objects that implement the Shape - * interface can be used to set the clip. The only - * Shape objects that are guaranteed to be - * supported are Shape objects that are - * obtained via the getClip method and via - * Rectangle objects. This method sets the - * user clip, which is independent of the clipping associated - * with device bounds and window visibility. - * @param clip the Shape to use to set the clip - * @see java.awt.Graphics#getClip() - * @see java.awt.Graphics#clipRect - * @see java.awt.Graphics#setClip(int, int, int, int) - * @since JDK1.1 - */ - @NotImplemented - public void setClip(Shape clip) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - /** - * Returns the bounding rectangle of the current clipping area. - * This method refers to the user clip, which is independent of the - * clipping associated with device bounds and window visibility. - * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns - * null. - * The coordinates in the rectangle are relative to the coordinate - * system origin of this graphics context. - * @return the bounding rectangle of the current clipping area, - * or null if no clip is set. - * @see java.awt.Graphics#getClip - * @see java.awt.Graphics#clipRect - * @see java.awt.Graphics#setClip(int, int, int, int) - * @see java.awt.Graphics#setClip(Shape) - * @since JDK1.1 - */ - public Rectangle getClipBounds(){ - Shape c = getClip(); - if (c==null) { - return null; - } - return c.getBounds(); - } - - /** - * Draws the text given by the specified iterator, using this - * graphics context's current color. The iterator has to specify a font - * for each character. The baseline of the - * first character is at position (xy) in this - * graphics context's coordinate system. - * @param iterator the iterator whose text is to be drawn - * @param x the x coordinate. - * @param y the y coordinate. - * @see java.awt.Graphics#drawBytes - * @see java.awt.Graphics#drawChars - */ - public void drawString(AttributedCharacterIterator iterator, - int x, int y){ - drawString(iterator, (float)x, (float)y); - } - - /** - * Clears the specified rectangle by filling it with the background - * color of the current drawing surface. This operation does not - * use the current paint mode. - *

- * Beginning with Java 1.1, the background color - * of offscreen images may be system dependent. Applications should - * use setColor followed by fillRect to - * ensure that an offscreen image is cleared to a specific color. - * @param x the x coordinate of the rectangle to clear. - * @param y the y coordinate of the rectangle to clear. - * @param width the width of the rectangle to clear. - * @param height the height of the rectangle to clear. - * @see java.awt.Graphics#fillRect(int, int, int, int) - * @see java.awt.Graphics#drawRect - * @see java.awt.Graphics#setColor(java.awt.Color) - * @see java.awt.Graphics#setPaintMode - * @see java.awt.Graphics#setXORMode(java.awt.Color) - */ - public void clearRect(int x, int y, int width, int height) { - Paint paint = getPaint(); - setColor(getBackground()); - fillRect(x, y, width, height); - setPaint(paint); - } - - public void copyArea(int x, int y, int width, int height, int dx, int dy) { - } - - /** - * Sets the current clip to the rectangle specified by the given - * coordinates. This method sets the user clip, which is - * independent of the clipping associated with device bounds - * and window visibility. - * Rendering operations have no effect outside of the clipping area. - * @param x the x coordinate of the new clip rectangle. - * @param y the y coordinate of the new clip rectangle. - * @param width the width of the new clip rectangle. - * @param height the height of the new clip rectangle. - * @see java.awt.Graphics#clipRect - * @see java.awt.Graphics#setClip(Shape) - * @since JDK1.1 - */ - public void setClip(int x, int y, int width, int height){ - setClip(new Rectangle(x, y, width, height)); - } - - /** - * Concatenates the current Graphics2D - * Transform with a rotation transform. - * Subsequent rendering is rotated by the specified radians relative - * to the previous origin. - * This is equivalent to calling transform(R), where R is an - * AffineTransform represented by the following matrix: - *

-     *          [   cos(theta)    -sin(theta)    0   ]
-     *          [   sin(theta)     cos(theta)    0   ]
-     *          [       0              0         1   ]
-     * 
- * Rotating with a positive angle theta rotates points on the positive - * x axis toward the positive y axis. - * @param theta the angle of rotation in radians - */ - public void rotate(double theta){ - _transform.rotate(theta); - } - - /** - * Concatenates the current Graphics2D - * Transform with a translated rotation - * transform. Subsequent rendering is transformed by a transform - * which is constructed by translating to the specified location, - * rotating by the specified radians, and translating back by the same - * amount as the original translation. This is equivalent to the - * following sequence of calls: - *
-     *          translate(x, y);
-     *          rotate(theta);
-     *          translate(-x, -y);
-     * 
- * Rotating with a positive angle theta rotates points on the positive - * x axis toward the positive y axis. - * @param theta the angle of rotation in radians - * @param x x coordinate of the origin of the rotation - * @param y y coordinate of the origin of the rotation - */ - public void rotate(double theta, double x, double y){ - _transform.rotate(theta, x, y); - } - - /** - * Concatenates the current Graphics2D - * Transform with a shearing transform. - * Subsequent renderings are sheared by the specified - * multiplier relative to the previous position. - * This is equivalent to calling transform(SH), where SH - * is an AffineTransform represented by the following - * matrix: - *
-     *          [   1   shx   0   ]
-     *          [  shy   1    0   ]
-     *          [   0    0    1   ]
-     * 
- * @param shx the multiplier by which coordinates are shifted in - * the positive X axis direction as a function of their Y coordinate - * @param shy the multiplier by which coordinates are shifted in - * the positive Y axis direction as a function of their X coordinate - */ - public void shear(double shx, double shy){ - _transform.shear(shx, shy); - } - - /** - * Get the rendering context of the Font within this - * Graphics2D context. - * The {@link FontRenderContext} - * encapsulates application hints such as anti-aliasing and - * fractional metrics, as well as target device specific information - * such as dots-per-inch. This information should be provided by the - * application when using objects that perform typographical - * formatting, such as Font and - * TextLayout. This information should also be provided - * by applications that perform their own layout and need accurate - * measurements of various characteristics of glyphs such as advance - * and line height when various rendering hints have been applied to - * the text rendering. - * - * @return a reference to an instance of FontRenderContext. - * @see java.awt.font.FontRenderContext - * @see java.awt.Font#createGlyphVector(FontRenderContext,char[]) - * @see java.awt.font.TextLayout - * @since JDK1.2 - */ - public FontRenderContext getFontRenderContext() { - boolean isAntiAliased = RenderingHints.VALUE_TEXT_ANTIALIAS_ON.equals( - getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING)); - boolean usesFractionalMetrics = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals( - getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS)); - - - return new FontRenderContext(new AffineTransform(), isAntiAliased, usesFractionalMetrics); - } - - /** - * Composes an AffineTransform object with the - * Transform in this Graphics2D according - * to the rule last-specified-first-applied. If the current - * Transform is Cx, the result of composition - * with Tx is a new Transform Cx'. Cx' becomes the - * current Transform for this Graphics2D. - * Transforming a point p by the updated Transform Cx' is - * equivalent to first transforming p by Tx and then transforming - * the result by the original Transform Cx. In other - * words, Cx'(p) = Cx(Tx(p)). A copy of the Tx is made, if necessary, - * so further modifications to Tx do not affect rendering. - * @param Tx the AffineTransform object to be composed with - * the current Transform - * @see #setTransform - * @see AffineTransform - */ - public void transform(AffineTransform Tx) { - _transform.concatenate(Tx); - } - - /** - * Renders a BufferedImage that is - * filtered with a - * {@link BufferedImageOp}. - * The rendering attributes applied include the Clip, - * Transform - * and Composite attributes. This is equivalent to: - *
-     * img1 = op.filter(img, null);
-     * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
-     * 
- * @param img the BufferedImage to be rendered - * @param op the filter to be applied to the image before rendering - * @param x the x coordinate in user space where the image is rendered - * @param y the y coordinate in user space where the image is rendered - * @see #_transform - * @see #setTransform - * @see #setComposite - * @see #clip - * @see #setClip(Shape) - */ - public void drawImage(BufferedImage img, - BufferedImageOp op, - int x, - int y){ - img = op.filter(img, null); - drawImage(img, x, y, null); - } - - /** - * Sets the background color for the Graphics2D context. - * The background color is used for clearing a region. - * When a Graphics2D is constructed for a - * Component, the background color is - * inherited from the Component. Setting the background color - * in the Graphics2D context only affects the subsequent - * clearRect calls and not the background color of the - * Component. To change the background - * of the Component, use appropriate methods of - * the Component. - * @param color the background color that isused in - * subsequent calls to clearRect - * @see #getBackground - * @see java.awt.Graphics#clearRect - */ - public void setBackground(Color color) { - if(color == null) - return; - - _background = color; - } - - /** - * Returns the background color used for clearing a region. - * @return the current Graphics2D Color, - * which defines the background color. - * @see #setBackground - */ - public Color getBackground(){ - return _background; - } - - /** - * Sets the Composite for the Graphics2D context. - * The Composite is used in all drawing methods such as - * drawImage, drawString, draw, - * and fill. It specifies how new pixels are to be combined - * with the existing pixels on the graphics device during the rendering - * process. - *

If this Graphics2D context is drawing to a - * Component on the display screen and the - * Composite is a custom object rather than an - * instance of the AlphaComposite class, and if - * there is a security manager, its checkPermission - * method is called with an AWTPermission("readDisplayPixels") - * permission. - * - * @param comp the Composite object to be used for rendering - * @throws SecurityException - * if a custom Composite object is being - * used to render to the screen and a security manager - * is set and its checkPermission method - * does not allow the operation. - * @see java.awt.Graphics#setXORMode - * @see java.awt.Graphics#setPaintMode - * @see java.awt.AlphaComposite - */ - @NotImplemented - public void setComposite(Composite comp){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - /** - * Returns the current Composite in the - * Graphics2D context. - * @return the current Graphics2D Composite, - * which defines a compositing style. - * @see #setComposite - */ - @NotImplemented - public Composite getComposite(){ - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - return null; - } - - /** - * Returns the value of a single preference for the rendering algorithms. - * Hint categories include controls for rendering quality and overall - * time/quality trade-off in the rendering process. Refer to the - * RenderingHints class for definitions of some common - * keys and values. - * @param hintKey the key corresponding to the hint to get. - * @return an object representing the value for the specified hint key. - * Some of the keys and their associated values are defined in the - * RenderingHints class. - * @see RenderingHints - */ - public Object getRenderingHint(RenderingHints.Key hintKey){ - return _hints.get(hintKey); - } - - /** - * Sets the value of a single preference for the rendering algorithms. - * Hint categories include controls for rendering quality and overall - * time/quality trade-off in the rendering process. Refer to the - * RenderingHints class for definitions of some common - * keys and values. - * @param hintKey the key of the hint to be set. - * @param hintValue the value indicating preferences for the specified - * hint category. - * @see RenderingHints - */ - public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue){ - _hints.put(hintKey, hintValue); - } - - - /** - * Renders the text of the specified - * {@link GlyphVector} using - * the Graphics2D context's rendering attributes. - * The rendering attributes applied include the Clip, - * Transform, Paint, and - * Composite attributes. The GlyphVector - * specifies individual glyphs from a {@link Font}. - * The GlyphVector can also contain the glyph positions. - * This is the fastest way to render a set of characters to the - * screen. - * - * @param g the GlyphVector to be rendered - * @param x the x position in user space where the glyphs should be - * rendered - * @param y the y position in user space where the glyphs should be - * rendered - * - * @see java.awt.Font#createGlyphVector(FontRenderContext, char[]) - * @see java.awt.font.GlyphVector - * @see #setPaint - * @see java.awt.Graphics#setColor - * @see #setTransform - * @see #setComposite - * @see #setClip(Shape) - */ - public void drawGlyphVector(GlyphVector g, float x, float y) { - Shape glyphOutline = g.getOutline(x, y); - fill(glyphOutline); - } - - /** - * Returns the device configuration associated with this - * Graphics2D. - * @return the device configuration - */ - public GraphicsConfiguration getDeviceConfiguration() { - return GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); - } - - /** - * Sets the values of an arbitrary number of preferences for the - * rendering algorithms. - * Only values for the rendering hints that are present in the - * specified Map object are modified. - * All other preferences not present in the specified - * object are left unmodified. - * Hint categories include controls for rendering quality and - * overall time/quality trade-off in the rendering process. - * Refer to the RenderingHints class for definitions of - * some common keys and values. - * @param hints the rendering hints to be set - * @see RenderingHints - */ - public void addRenderingHints(Map hints){ - this._hints.putAll(hints); - } - - /** - * Concatenates the current - * Graphics2D Transform - * with a translation transform. - * Subsequent rendering is translated by the specified - * distance relative to the previous position. - * This is equivalent to calling transform(T), where T is an - * AffineTransform represented by the following matrix: - *

-     *          [   1    0    tx  ]
-     *          [   0    1    ty  ]
-     *          [   0    0    1   ]
-     * 
- * @param tx the distance to translate along the x-axis - * @param ty the distance to translate along the y-axis - */ - public void translate(double tx, double ty){ - _transform.translate(tx, ty); - } - - /** - * Renders the text of the specified iterator, using the - * Graphics2D context's current Paint. The - * iterator must specify a font - * for each character. The baseline of the - * first character is at position (xy) in the - * User Space. - * The rendering attributes applied include the Clip, - * Transform, Paint, and - * Composite attributes. - * For characters in script systems such as Hebrew and Arabic, - * the glyphs can be rendered from right to left, in which case the - * coordinate supplied is the location of the leftmost character - * on the baseline. - * @param iterator the iterator whose text is to be rendered - * @param x the x coordinate where the iterator's text is to be - * rendered - * @param y the y coordinate where the iterator's text is to be - * rendered - * @see #setPaint - * @see java.awt.Graphics#setColor - * @see #setTransform - * @see #setComposite - * @see #setClip - */ - @NotImplemented - public void drawString(AttributedCharacterIterator iterator, float x, float y) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - /** - * Checks whether or not the specified Shape intersects - * the specified {@link Rectangle}, which is in device - * space. If onStroke is false, this method checks - * whether or not the interior of the specified Shape - * intersects the specified Rectangle. If - * onStroke is true, this method checks - * whether or not the Stroke of the specified - * Shape outline intersects the specified - * Rectangle. - * The rendering attributes taken into account include the - * Clip, Transform, and Stroke - * attributes. - * @param rect the area in device space to check for a hit - * @param s the Shape to check for a hit - * @param onStroke flag used to choose between testing the - * stroked or the filled shape. If the flag is true, the - * Stroke oultine is tested. If the flag is - * false, the filled Shape is tested. - * @return true if there is a hit; false - * otherwise. - * @see #setStroke - * @see #fill(Shape) - * @see #draw(Shape) - * @see #_transform - * @see #setTransform - * @see #clip - * @see #setClip(Shape) - */ - public boolean hit(Rectangle rect, - Shape s, - boolean onStroke){ - if (onStroke) { - s = getStroke().createStrokedShape(s); - } - - s = getTransform().createTransformedShape(s); - - return s.intersects(rect); - } - - /** - * Gets the preferences for the rendering algorithms. Hint categories - * include controls for rendering quality and overall time/quality - * trade-off in the rendering process. - * Returns all of the hint key/value pairs that were ever specified in - * one operation. Refer to the - * RenderingHints class for definitions of some common - * keys and values. - * @return a reference to an instance of RenderingHints - * that contains the current preferences. - * @see RenderingHints - */ - public RenderingHints getRenderingHints(){ - return _hints; - } - - /** - * Replaces the values of all preferences for the rendering - * algorithms with the specified hints. - * The existing values for all rendering hints are discarded and - * the new set of known hints and values are initialized from the - * specified {@link Map} object. - * Hint categories include controls for rendering quality and - * overall time/quality trade-off in the rendering process. - * Refer to the RenderingHints class for definitions of - * some common keys and values. - * @param hints the rendering hints to be set - * @see RenderingHints - */ - public void setRenderingHints(Map hints){ - this._hints = new RenderingHints(null); - this._hints.putAll(hints); - } - - /** - * Renders an image, applying a transform from image space into user space - * before drawing. - * The transformation from user space into device space is done with - * the current Transform in the Graphics2D. - * The specified transformation is applied to the image before the - * transform attribute in the Graphics2D context is applied. - * The rendering attributes applied include the Clip, - * Transform, and Composite attributes. - * Note that no rendering is done if the specified transform is - * noninvertible. - * @param img the Image to be rendered - * @param xform the transformation from image space into user space - * @param obs the {@link ImageObserver} - * to be notified as more of the Image - * is converted - * @return true if the Image is - * fully loaded and completely rendered; - * false if the Image is still being loaded. - * @see #_transform - * @see #setTransform - * @see #setComposite - * @see #clip - * @see #setClip(Shape) - */ - @NotImplemented - public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - return false; - } - - /** - * Draws as much of the specified image as has already been scaled - * to fit inside the specified rectangle. - *

- * The image is drawn inside the specified rectangle of this - * graphics context's coordinate space, and is scaled if - * necessary. Transparent pixels do not affect whatever pixels - * are already there. - *

- * This method returns immediately in all cases, even if the - * entire image has not yet been scaled, dithered, and converted - * for the current output device. - * If the current output representation is not yet complete, then - * drawImage returns false. As more of - * the image becomes available, the process that loads the image notifies - * the image observer by calling its imageUpdate method. - *

- * A scaled version of an image will not necessarily be - * available immediately just because an unscaled version of the - * image has been constructed for this output device. Each size of - * the image may be cached separately and generated from the original - * data in a separate image production sequence. - * @param img the specified image to be drawn. This method does - * nothing if img is null. - * @param x the x coordinate. - * @param y the y coordinate. - * @param width the width of the rectangle. - * @param height the height of the rectangle. - * @param observer object to be notified as more of - * the image is converted. - * @return false if the image pixels are still changing; - * true otherwise. - * @see java.awt.Image - * @see java.awt.image.ImageObserver - * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) - */ - @NotImplemented - public boolean drawImage(Image img, int x, int y, - int width, int height, - ImageObserver observer) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - return false; - } - - /** - * Creates a new Graphics object that is - * a copy of this Graphics object. - * @return a new graphics context that is a copy of - * this graphics context. - */ - public Graphics create() { - try { - return (Graphics)clone(); - } catch (CloneNotSupportedException e){ - throw new RuntimeException(e); - } - } - - /** - * Gets the font metrics for the specified font. - * @return the font metrics for the specified font. - * @param f the specified font - * @see java.awt.Graphics#getFont - * @see java.awt.FontMetrics - * @see java.awt.Graphics#getFontMetrics() - */ - @SuppressWarnings("deprecation") - @SuppressForbidden - public FontMetrics getFontMetrics(Font f) { - return Toolkit.getDefaultToolkit().getFontMetrics(f); - } - - /** - * Sets the paint mode of this graphics context to alternate between - * this graphics context's current color and the new specified color. - * This specifies that logical pixel operations are performed in the - * XOR mode, which alternates pixels between the current color and - * a specified XOR color. - *

- * When drawing operations are performed, pixels which are the - * current color are changed to the specified color, and vice versa. - *

- * Pixels that are of colors other than those two colors are changed - * in an unpredictable but reversible manner; if the same figure is - * drawn twice, then all pixels are restored to their original values. - * @param c1 the XOR alternation color - */ - @NotImplemented - public void setXORMode(Color c1) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - /** - * Sets the paint mode of this graphics context to overwrite the - * destination with this graphics context's current color. - * This sets the logical pixel operation function to the paint or - * overwrite mode. All subsequent rendering operations will - * overwrite the destination with the current color. - */ - @NotImplemented - public void setPaintMode() { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - /** - * Renders a - * {@link RenderableImage}, - * applying a transform from image space into user space before drawing. - * The transformation from user space into device space is done with - * the current Transform in the Graphics2D. - * The specified transformation is applied to the image before the - * transform attribute in the Graphics2D context is applied. - * The rendering attributes applied include the Clip, - * Transform, and Composite attributes. Note - * that no rendering is done if the specified transform is - * noninvertible. - *

- * Rendering hints set on the Graphics2D object might - * be used in rendering the RenderableImage. - * If explicit control is required over specific hints recognized by a - * specific RenderableImage, or if knowledge of which hints - * are used is required, then a RenderedImage should be - * obtained directly from the RenderableImage - * and rendered using - *{@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}. - * @param img the image to be rendered. This method does - * nothing if img is null. - * @param xform the transformation from image space into user space - * @see #_transform - * @see #setTransform - * @see #setComposite - * @see #clip - * @see #setClip - * @see #drawRenderedImage - */ - @NotImplemented - public void drawRenderedImage(RenderedImage img, AffineTransform xform) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - /** - * Renders a {@link RenderedImage}, - * applying a transform from image - * space into user space before drawing. - * The transformation from user space into device space is done with - * the current Transform in the Graphics2D. - * The specified transformation is applied to the image before the - * transform attribute in the Graphics2D context is applied. - * The rendering attributes applied include the Clip, - * Transform, and Composite attributes. Note - * that no rendering is done if the specified transform is - * noninvertible. - * @param img the image to be rendered. This method does - * nothing if img is null. - * @param xform the transformation from image space into user space - * @see #_transform - * @see #setTransform - * @see #setComposite - * @see #clip - * @see #setClip - */ - @NotImplemented - public void drawRenderableImage(RenderableImage img, AffineTransform xform) { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "Not implemented"); - } - } - - protected void applyStroke(SimpleShape shape) { - if (_stroke instanceof BasicStroke){ - BasicStroke bs = (BasicStroke)_stroke; - shape.setStrokeStyle((double)bs.getLineWidth()); - float[] dash = bs.getDashArray(); - if (dash != null) { - //TODO: implement more dashing styles - shape.setStrokeStyle(StrokeStyle.LineDash.DASH); - } - } - } - - protected void applyPaint(SimpleShape shape) { - if (_paint instanceof Color) { - shape.setFillColor((Color)_paint); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw; + + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.Toolkit; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Arc2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Path2D; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.Map; + +import org.apache.poi.sl.usermodel.FreeformShape; +import org.apache.poi.sl.usermodel.GroupShape; +import org.apache.poi.sl.usermodel.Insets2D; +import org.apache.poi.sl.usermodel.SimpleShape; +import org.apache.poi.sl.usermodel.StrokeStyle; +import org.apache.poi.sl.usermodel.TextBox; +import org.apache.poi.sl.usermodel.TextRun; +import org.apache.poi.sl.usermodel.VerticalAlignment; +import org.apache.poi.util.NotImplemented; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.SuppressForbidden; + +/** + * Translates Graphics2D calls into PowerPoint. + * + * @author Yegor Kozlov + */ +public final class SLGraphics extends Graphics2D implements Cloneable { + + protected POILogger log = POILogFactory.getLogger(this.getClass()); + + //The ppt object to write into. + private GroupShape _group; + + private AffineTransform _transform; + private Stroke _stroke; + private Paint _paint; + private Font _font; + private Color _foreground; + private Color _background; + private RenderingHints _hints; + + /** + * Construct Java Graphics object which translates graphic calls in ppt drawing layer. + * + * @param group The shape group to write the graphics calls into. + */ + public SLGraphics(GroupShape group){ + this._group = group; + + _transform = new AffineTransform(); + _stroke = new BasicStroke(); + _paint = Color.black; + _font = new Font("Arial", Font.PLAIN, 12); + _background = Color.black; + _foreground = Color.white; + _hints = new RenderingHints(null); + } + + /** + * @return the shape group being used for drawing + */ + public GroupShape getShapeGroup(){ + return _group; + } + + /** + * Gets the current font. + * @return this graphics context's current font. + * @see java.awt.Font + * @see java.awt.Graphics#setFont(Font) + */ + public Font getFont(){ + return _font; + } + + /** + * Sets this graphics context's font to the specified font. + * All subsequent text operations using this graphics context + * use this font. + * @param font the font. + * @see java.awt.Graphics#getFont + * @see java.awt.Graphics#drawString(java.lang.String, int, int) + * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int) + * @see java.awt.Graphics#drawChars(char[], int, int, int, int) + */ + public void setFont(Font font){ + this._font = font; + } + + /** + * Gets this graphics context's current color. + * @return this graphics context's current color. + * @see java.awt.Color + * @see java.awt.Graphics#setColor + */ + public Color getColor(){ + return _foreground; + } + + /** + * Sets this graphics context's current color to the specified + * color. All subsequent graphics operations using this graphics + * context use this specified color. + * @param c the new rendering color. + * @see java.awt.Color + * @see java.awt.Graphics#getColor + */ + public void setColor(Color c) { + setPaint(c); + } + + /** + * Returns the current Stroke in the + * Graphics2D context. + * @return the current Graphics2D Stroke, + * which defines the line style. + * @see #setStroke + */ + public Stroke getStroke(){ + return _stroke; + } + + /** + * Sets the Stroke for the Graphics2D context. + * @param s the Stroke object to be used to stroke a + * Shape during the rendering process + */ + public void setStroke(Stroke s){ + this._stroke = s; + } + + /** + * Returns the current Paint of the + * Graphics2D context. + * @return the current Graphics2D Paint, + * which defines a color or pattern. + * @see #setPaint + * @see java.awt.Graphics#setColor + */ + public Paint getPaint(){ + return _paint; + } + + /** + * Sets the Paint attribute for the + * Graphics2D context. Calling this method + * with a null Paint object does + * not have any effect on the current Paint attribute + * of this Graphics2D. + * @param paint the Paint object to be used to generate + * color during the rendering process, or null + * @see java.awt.Graphics#setColor + */ + public void setPaint(Paint paint){ + if(paint == null) return; + + this._paint = paint; + if (paint instanceof Color) _foreground = (Color)paint; + } + + /** + * Returns a copy of the current Transform in the + * Graphics2D context. + * @return the current AffineTransform in the + * Graphics2D context. + * @see #_transform + * @see #setTransform + */ + public AffineTransform getTransform(){ + return new AffineTransform(_transform); + } + + /** + * Sets the Transform in the Graphics2D + * context. + * @param Tx the AffineTransform object to be used in the + * rendering process + * @see #_transform + * @see AffineTransform + */ + public void setTransform(AffineTransform Tx) { + _transform = new AffineTransform(Tx); + } + + /** + * Strokes the outline of a Shape using the settings of the + * current Graphics2D context. The rendering attributes + * applied include the Clip, Transform, + * Paint, Composite and + * Stroke attributes. + * @param shape the Shape to be rendered + * @see #setStroke + * @see #setPaint + * @see java.awt.Graphics#setColor + * @see #_transform + * @see #setTransform + * @see #clip + * @see #setClip + * @see #setComposite + */ + public void draw(Shape shape){ + Path2D.Double path = new Path2D.Double(_transform.createTransformedShape(shape)); + FreeformShape p = _group.createFreeform(); + p.setPath(path); + p.setFillColor(null); + applyStroke(p); + if (_paint instanceof Color) { + p.setStrokeStyle((Color)_paint); + } + } + + /** + * Renders the text specified by the specified String, + * using the current text attribute state in the Graphics2D context. + * The baseline of the first character is at position + * (xy) in the User Space. + * The rendering attributes applied include the Clip, + * Transform, Paint, Font and + * Composite attributes. For characters in script systems + * such as Hebrew and Arabic, the glyphs can be rendered from right to + * left, in which case the coordinate supplied is the location of the + * leftmost character on the baseline. + * @param s the String to be rendered + * @param x the x coordinate of the location where the + * String should be rendered + * @param y the y coordinate of the location where the + * String should be rendered + * @throws NullPointerException if str is + * null + * @see #setPaint + * @see java.awt.Graphics#setColor + * @see java.awt.Graphics#setFont + * @see #setTransform + * @see #setComposite + * @see #setClip + */ + public void drawString(String s, float x, float y) { + TextBox txt = _group.createTextBox(); + + TextRun rt = txt.getTextParagraphs().get(0).getTextRuns().get(0); + rt.setFontSize((double)_font.getSize()); + rt.setFontFamily(_font.getFamily()); + + if (getColor() != null) rt.setFontColor(DrawPaint.createSolidPaint(getColor())); + if (_font.isBold()) rt.setBold(true); + if (_font.isItalic()) rt.setItalic(true); + + txt.setText(s); + + txt.setInsets(new Insets2D(0,0,0,0)); + txt.setWordWrap(false); + txt.setHorizontalCentered(false); + txt.setVerticalAlignment(VerticalAlignment.MIDDLE); + + + TextLayout layout = new TextLayout(s, _font, getFontRenderContext()); + float ascent = layout.getAscent(); + + float width = (float) Math.floor(layout.getAdvance()); + /** + * Even if top and bottom margins are set to 0 PowerPoint + * always sets extra space between the text and its bounding box. + * + * The approximation height = ascent*2 works good enough in most cases + */ + float height = ascent * 2; + + /* + In powerpoint anchor of a shape is its top left corner. + Java graphics sets string coordinates by the baseline of the first character + so we need to shift up by the height of the textbox + */ + y -= height / 2 + ascent / 2; + + /* + In powerpoint anchor of a shape is its top left corner. + Java graphics sets string coordinates by the baseline of the first character + so we need to shift down by the height of the textbox + */ + txt.setAnchor(new Rectangle((int)x, (int)y, (int)width, (int)height)); + } + + /** + * Fills the interior of a Shape using the settings of the + * Graphics2D context. The rendering attributes applied + * include the Clip, Transform, + * Paint, and Composite. + * @param shape the Shape to be filled + * @see #setPaint + * @see java.awt.Graphics#setColor + * @see #_transform + * @see #setTransform + * @see #setComposite + * @see #clip + * @see #setClip + */ + public void fill(Shape shape){ + Path2D.Double path = new Path2D.Double(_transform.createTransformedShape(shape)); + FreeformShape p = _group.createFreeform(); + p.setPath(path); + applyPaint(p); + p.setStrokeStyle(); //Fills must be "No Line" + } + + /** + * Translates the origin of the graphics context to the point + * (xy) in the current coordinate system. + * Modifies this graphics context so that its new origin corresponds + * to the point (xy) in this graphics context's + * original coordinate system. All coordinates used in subsequent + * rendering operations on this graphics context will be relative + * to this new origin. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void translate(int x, int y){ + _transform.translate(x, y); + } + + /** + * Intersects the current Clip with the interior of the + * specified Shape and sets the Clip to the + * resulting intersection. The specified Shape is + * transformed with the current Graphics2D + * Transform before being intersected with the current + * Clip. This method is used to make the current + * Clip smaller. + * To make the Clip larger, use setClip. + * The user clip modified by this method is independent of the + * clipping associated with device bounds and visibility. If no clip has + * previously been set, or if the clip has been cleared using + * {@link java.awt.Graphics#setClip(Shape) setClip} with a + * null argument, the specified Shape becomes + * the new user clip. + * @param s the Shape to be intersected with the current + * Clip. If s is null, + * this method clears the current Clip. + */ + @NotImplemented + public void clip(Shape s){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + /** + * Gets the current clipping area. + * This method returns the user clip, which is independent of the + * clipping associated with device bounds and window visibility. + * If no clip has previously been set, or if the clip has been + * cleared using setClip(null), this method returns + * null. + * @return a Shape object representing the + * current clipping area, or null if + * no clip is set. + * @see java.awt.Graphics#getClipBounds() + * @see java.awt.Graphics#clipRect + * @see java.awt.Graphics#setClip(int, int, int, int) + * @see java.awt.Graphics#setClip(Shape) + * @since JDK1.1 + */ + @NotImplemented + public Shape getClip(){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + return null; + } + + /** + * Concatenates the current Graphics2D + * Transform with a scaling transformation + * Subsequent rendering is resized according to the specified scaling + * factors relative to the previous scaling. + * This is equivalent to calling transform(S), where S is an + * AffineTransform represented by the following matrix: + *

+     *          [   sx   0    0   ]
+     *          [   0    sy   0   ]
+     *          [   0    0    1   ]
+     * 
+ * @param sx the amount by which X coordinates in subsequent + * rendering operations are multiplied relative to previous + * rendering operations. + * @param sy the amount by which Y coordinates in subsequent + * rendering operations are multiplied relative to previous + * rendering operations. + */ + public void scale(double sx, double sy){ + _transform.scale(sx, sy); + } + + /** + * Draws an outlined round-cornered rectangle using this graphics + * context's current color. The left and right edges of the rectangle + * are at x and x + width, + * respectively. The top and bottom edges of the rectangle are at + * y and y + height. + * @param x the x coordinate of the rectangle to be drawn. + * @param y the y coordinate of the rectangle to be drawn. + * @param width the width of the rectangle to be drawn. + * @param height the height of the rectangle to be drawn. + * @param arcWidth the horizontal diameter of the arc + * at the four corners. + * @param arcHeight the vertical diameter of the arc + * at the four corners. + * @see java.awt.Graphics#fillRoundRect + */ + public void drawRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight){ + RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight); + draw(rect); + } + + /** + * Draws the text given by the specified string, using this + * graphics context's current font and color. The baseline of the + * first character is at position (xy) in this + * graphics context's coordinate system. + * @param str the string to be drawn. + * @param x the x coordinate. + * @param y the y coordinate. + * @see java.awt.Graphics#drawBytes + * @see java.awt.Graphics#drawChars + */ + public void drawString(String str, int x, int y){ + drawString(str, (float)x, (float)y); + } + + /** + * Fills an oval bounded by the specified rectangle with the + * current color. + * @param x the x coordinate of the upper left corner + * of the oval to be filled. + * @param y the y coordinate of the upper left corner + * of the oval to be filled. + * @param width the width of the oval to be filled. + * @param height the height of the oval to be filled. + * @see java.awt.Graphics#drawOval + */ + public void fillOval(int x, int y, int width, int height){ + Ellipse2D oval = new Ellipse2D.Double(x, y, width, height); + fill(oval); + } + + /** + * Fills the specified rounded corner rectangle with the current color. + * The left and right edges of the rectangle + * are at x and x + width - 1, + * respectively. The top and bottom edges of the rectangle are at + * y and y + height - 1. + * @param x the x coordinate of the rectangle to be filled. + * @param y the y coordinate of the rectangle to be filled. + * @param width the width of the rectangle to be filled. + * @param height the height of the rectangle to be filled. + * @param arcWidth the horizontal diameter + * of the arc at the four corners. + * @param arcHeight the vertical diameter + * of the arc at the four corners. + * @see java.awt.Graphics#drawRoundRect + */ + public void fillRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight){ + + RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight); + fill(rect); + } + + /** + * Fills a circular or elliptical arc covering the specified rectangle. + *

+ * The resulting arc begins at startAngle and extends + * for arcAngle degrees. + * Angles are interpreted such that 0 degrees + * is at the 3 o'clock position. + * A positive value indicates a counter-clockwise rotation + * while a negative value indicates a clockwise rotation. + *

+ * The center of the arc is the center of the rectangle whose origin + * is (xy) and whose size is specified by the + * width and height arguments. + *

+ * The resulting arc covers an area + * width + 1 pixels wide + * by height + 1 pixels tall. + *

+ * The angles are specified relative to the non-square extents of + * the bounding rectangle such that 45 degrees always falls on the + * line from the center of the ellipse to the upper right corner of + * the bounding rectangle. As a result, if the bounding rectangle is + * noticeably longer in one axis than the other, the angles to the + * start and end of the arc segment will be skewed farther along the + * longer axis of the bounds. + * @param x the x coordinate of the + * upper-left corner of the arc to be filled. + * @param y the y coordinate of the + * upper-left corner of the arc to be filled. + * @param width the width of the arc to be filled. + * @param height the height of the arc to be filled. + * @param startAngle the beginning angle. + * @param arcAngle the angular extent of the arc, + * relative to the start angle. + * @see java.awt.Graphics#drawArc + */ + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle){ + Arc2D arc = new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.PIE); + fill(arc); + } + + /** + * Draws the outline of a circular or elliptical arc + * covering the specified rectangle. + *

+ * The resulting arc begins at startAngle and extends + * for arcAngle degrees, using the current color. + * Angles are interpreted such that 0 degrees + * is at the 3 o'clock position. + * A positive value indicates a counter-clockwise rotation + * while a negative value indicates a clockwise rotation. + *

+ * The center of the arc is the center of the rectangle whose origin + * is (xy) and whose size is specified by the + * width and height arguments. + *

+ * The resulting arc covers an area + * width + 1 pixels wide + * by height + 1 pixels tall. + *

+ * The angles are specified relative to the non-square extents of + * the bounding rectangle such that 45 degrees always falls on the + * line from the center of the ellipse to the upper right corner of + * the bounding rectangle. As a result, if the bounding rectangle is + * noticeably longer in one axis than the other, the angles to the + * start and end of the arc segment will be skewed farther along the + * longer axis of the bounds. + * @param x the x coordinate of the + * upper-left corner of the arc to be drawn. + * @param y the y coordinate of the + * upper-left corner of the arc to be drawn. + * @param width the width of the arc to be drawn. + * @param height the height of the arc to be drawn. + * @param startAngle the beginning angle. + * @param arcAngle the angular extent of the arc, + * relative to the start angle. + * @see java.awt.Graphics#fillArc + */ + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + Arc2D arc = new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN); + draw(arc); + } + + + /** + * Draws a sequence of connected lines defined by + * arrays of x and y coordinates. + * Each pair of (xy) coordinates defines a point. + * The figure is not closed if the first point + * differs from the last point. + * @param xPoints an array of x points + * @param yPoints an array of y points + * @param nPoints the total number of points + * @see java.awt.Graphics#drawPolygon(int[], int[], int) + * @since JDK1.1 + */ + public void drawPolyline(int[] xPoints, int[] yPoints, + int nPoints){ + if(nPoints > 0){ + GeneralPath path = new GeneralPath(); + path.moveTo(xPoints[0], yPoints[0]); + for(int i=1; ix, y, + * width, and height arguments. + *

+ * The oval covers an area that is + * width + 1 pixels wide + * and height + 1 pixels tall. + * @param x the x coordinate of the upper left + * corner of the oval to be drawn. + * @param y the y coordinate of the upper left + * corner of the oval to be drawn. + * @param width the width of the oval to be drawn. + * @param height the height of the oval to be drawn. + * @see java.awt.Graphics#fillOval + */ + public void drawOval(int x, int y, int width, int height){ + Ellipse2D oval = new Ellipse2D.Double(x, y, width, height); + draw(oval); + } + + /** + * Draws as much of the specified image as is currently available. + * The image is drawn with its top-left corner at + * (xy) in this graphics context's coordinate + * space. Transparent pixels are drawn in the specified + * background color. + *

+ * This operation is equivalent to filling a rectangle of the + * width and height of the specified image with the given color and then + * drawing the image on top of it, but possibly more efficient. + *

+ * This method returns immediately in all cases, even if the + * complete image has not yet been loaded, and it has not been dithered + * and converted for the current output device. + *

+ * If the image has not yet been completely loaded, then + * drawImage returns false. As more of + * the image becomes available, the process that draws the image notifies + * the specified image observer. + * @param img the specified image to be drawn. + * @param x the x coordinate. + * @param y the y coordinate. + * @param bgcolor the background color to paint under the + * non-opaque portions of the image. + * @param observer object to be notified as more of + * the image is converted. + * @see java.awt.Image + * @see java.awt.image.ImageObserver + * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + @NotImplemented + public boolean drawImage(Image img, int x, int y, + Color bgcolor, + ImageObserver observer){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + + return false; + } + + /** + * Draws as much of the specified image as has already been scaled + * to fit inside the specified rectangle. + *

+ * The image is drawn inside the specified rectangle of this + * graphics context's coordinate space, and is scaled if + * necessary. Transparent pixels are drawn in the specified + * background color. + * This operation is equivalent to filling a rectangle of the + * width and height of the specified image with the given color and then + * drawing the image on top of it, but possibly more efficient. + *

+ * This method returns immediately in all cases, even if the + * entire image has not yet been scaled, dithered, and converted + * for the current output device. + * If the current output representation is not yet complete then + * drawImage returns false. As more of + * the image becomes available, the process that draws the image notifies + * the specified image observer. + *

+ * A scaled version of an image will not necessarily be + * available immediately just because an unscaled version of the + * image has been constructed for this output device. Each size of + * the image may be cached separately and generated from the original + * data in a separate image production sequence. + * @param img the specified image to be drawn. + * @param x the x coordinate. + * @param y the y coordinate. + * @param width the width of the rectangle. + * @param height the height of the rectangle. + * @param bgcolor the background color to paint under the + * non-opaque portions of the image. + * @param observer object to be notified as more of + * the image is converted. + * @see java.awt.Image + * @see java.awt.image.ImageObserver + * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + @NotImplemented + public boolean drawImage(Image img, int x, int y, + int width, int height, + Color bgcolor, + ImageObserver observer){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + + return false; + } + + + /** + * Draws as much of the specified area of the specified image as is + * currently available, scaling it on the fly to fit inside the + * specified area of the destination drawable surface. Transparent pixels + * do not affect whatever pixels are already there. + *

+ * This method returns immediately in all cases, even if the + * image area to be drawn has not yet been scaled, dithered, and converted + * for the current output device. + * If the current output representation is not yet complete then + * drawImage returns false. As more of + * the image becomes available, the process that draws the image notifies + * the specified image observer. + *

+ * This method always uses the unscaled version of the image + * to render the scaled rectangle and performs the required + * scaling on the fly. It does not use a cached, scaled version + * of the image for this operation. Scaling of the image from source + * to destination is performed such that the first coordinate + * of the source rectangle is mapped to the first coordinate of + * the destination rectangle, and the second source coordinate is + * mapped to the second destination coordinate. The subimage is + * scaled and flipped as needed to preserve those mappings. + * @param img the specified image to be drawn + * @param dx1 the x coordinate of the first corner of the + * destination rectangle. + * @param dy1 the y coordinate of the first corner of the + * destination rectangle. + * @param dx2 the x coordinate of the second corner of the + * destination rectangle. + * @param dy2 the y coordinate of the second corner of the + * destination rectangle. + * @param sx1 the x coordinate of the first corner of the + * source rectangle. + * @param sy1 the y coordinate of the first corner of the + * source rectangle. + * @param sx2 the x coordinate of the second corner of the + * source rectangle. + * @param sy2 the y coordinate of the second corner of the + * source rectangle. + * @param observer object to be notified as more of the image is + * scaled and converted. + * @see java.awt.Image + * @see java.awt.image.ImageObserver + * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + * @since JDK1.1 + */ + @NotImplemented + public boolean drawImage(Image img, + int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + ImageObserver observer){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + return false; + } + + /** + * Draws as much of the specified area of the specified image as is + * currently available, scaling it on the fly to fit inside the + * specified area of the destination drawable surface. + *

+ * Transparent pixels are drawn in the specified background color. + * This operation is equivalent to filling a rectangle of the + * width and height of the specified image with the given color and then + * drawing the image on top of it, but possibly more efficient. + *

+ * This method returns immediately in all cases, even if the + * image area to be drawn has not yet been scaled, dithered, and converted + * for the current output device. + * If the current output representation is not yet complete then + * drawImage returns false. As more of + * the image becomes available, the process that draws the image notifies + * the specified image observer. + *

+ * This method always uses the unscaled version of the image + * to render the scaled rectangle and performs the required + * scaling on the fly. It does not use a cached, scaled version + * of the image for this operation. Scaling of the image from source + * to destination is performed such that the first coordinate + * of the source rectangle is mapped to the first coordinate of + * the destination rectangle, and the second source coordinate is + * mapped to the second destination coordinate. The subimage is + * scaled and flipped as needed to preserve those mappings. + * @param img the specified image to be drawn + * @param dx1 the x coordinate of the first corner of the + * destination rectangle. + * @param dy1 the y coordinate of the first corner of the + * destination rectangle. + * @param dx2 the x coordinate of the second corner of the + * destination rectangle. + * @param dy2 the y coordinate of the second corner of the + * destination rectangle. + * @param sx1 the x coordinate of the first corner of the + * source rectangle. + * @param sy1 the y coordinate of the first corner of the + * source rectangle. + * @param sx2 the x coordinate of the second corner of the + * source rectangle. + * @param sy2 the y coordinate of the second corner of the + * source rectangle. + * @param bgcolor the background color to paint under the + * non-opaque portions of the image. + * @param observer object to be notified as more of the image is + * scaled and converted. + * @see java.awt.Image + * @see java.awt.image.ImageObserver + * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + * @since JDK1.1 + */ + @NotImplemented + public boolean drawImage(Image img, + int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + Color bgcolor, + ImageObserver observer){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + return false; + } + + /** + * Draws as much of the specified image as is currently available. + * The image is drawn with its top-left corner at + * (xy) in this graphics context's coordinate + * space. Transparent pixels in the image do not affect whatever + * pixels are already there. + *

+ * This method returns immediately in all cases, even if the + * complete image has not yet been loaded, and it has not been dithered + * and converted for the current output device. + *

+ * If the image has completely loaded and its pixels are + * no longer being changed, then + * drawImage returns true. + * Otherwise, drawImage returns false + * and as more of + * the image becomes available + * or it is time to draw another frame of animation, + * the process that loads the image notifies + * the specified image observer. + * @param img the specified image to be drawn. This method does + * nothing if img is null. + * @param x the x coordinate. + * @param y the y coordinate. + * @param observer object to be notified as more of + * the image is converted. + * @return false if the image pixels are still changing; + * true otherwise. + * @see java.awt.Image + * @see java.awt.image.ImageObserver + * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + @NotImplemented + public boolean drawImage(Image img, int x, int y, + ImageObserver observer) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + return false; + } + + /** + * Disposes of this graphics context and releases + * any system resources that it is using. + * A Graphics object cannot be used after + * disposehas been called. + *

+ * When a Java program runs, a large number of Graphics + * objects can be created within a short time frame. + * Although the finalization process of the garbage collector + * also disposes of the same system resources, it is preferable + * to manually free the associated resources by calling this + * method rather than to rely on a finalization process which + * may not run to completion for a long period of time. + *

+ * Graphics objects which are provided as arguments to the + * paint and update methods + * of components are automatically released by the system when + * those methods return. For efficiency, programmers should + * call dispose when finished using + * a Graphics object only if it was created + * directly from a component or another Graphics object. + * @see java.awt.Graphics#finalize + * @see java.awt.Component#paint + * @see java.awt.Component#update + * @see java.awt.Component#getGraphics + * @see java.awt.Graphics#create + */ + public void dispose() { + } + + /** + * Draws a line, using the current color, between the points + * (x1, y1) and (x2, y2) + * in this graphics context's coordinate system. + * @param x1 the first point's x coordinate. + * @param y1 the first point's y coordinate. + * @param x2 the second point's x coordinate. + * @param y2 the second point's y coordinate. + */ + public void drawLine(int x1, int y1, int x2, int y2){ + Line2D line = new Line2D.Double(x1, y1, x2, y2); + draw(line); + } + + /** + * Fills a closed polygon defined by + * arrays of x and y coordinates. + *

+ * This method draws the polygon defined by nPoint line + * segments, where the first nPoint - 1 + * line segments are line segments from + * (xPoints[i - 1], yPoints[i - 1]) + * to (xPoints[i], yPoints[i]), for + * 1 ≤ i ≤ nPoints. + * The figure is automatically closed by drawing a line connecting + * the final point to the first point, if those points are different. + *

+ * The area inside the polygon is defined using an + * even-odd fill rule, also known as the alternating rule. + * @param xPoints a an array of x coordinates. + * @param yPoints a an array of y coordinates. + * @param nPoints a the total number of points. + * @see java.awt.Graphics#drawPolygon(int[], int[], int) + */ + public void fillPolygon(int[] xPoints, int[] yPoints, + int nPoints){ + java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints); + fill(polygon); + } + + /** + * Fills the specified rectangle. + * The left and right edges of the rectangle are at + * x and x + width - 1. + * The top and bottom edges are at + * y and y + height - 1. + * The resulting rectangle covers an area + * width pixels wide by + * height pixels tall. + * The rectangle is filled using the graphics context's current color. + * @param x the x coordinate + * of the rectangle to be filled. + * @param y the y coordinate + * of the rectangle to be filled. + * @param width the width of the rectangle to be filled. + * @param height the height of the rectangle to be filled. + * @see java.awt.Graphics#clearRect + * @see java.awt.Graphics#drawRect + */ + public void fillRect(int x, int y, int width, int height){ + Rectangle rect = new Rectangle(x, y, width, height); + fill(rect); + } + + /** + * Draws the outline of the specified rectangle. + * The left and right edges of the rectangle are at + * x and x + width. + * The top and bottom edges are at + * y and y + height. + * The rectangle is drawn using the graphics context's current color. + * @param x the x coordinate + * of the rectangle to be drawn. + * @param y the y coordinate + * of the rectangle to be drawn. + * @param width the width of the rectangle to be drawn. + * @param height the height of the rectangle to be drawn. + * @see java.awt.Graphics#fillRect + * @see java.awt.Graphics#clearRect + */ + public void drawRect(int x, int y, int width, int height) { + Rectangle rect = new Rectangle(x, y, width, height); + draw(rect); + } + + /** + * Draws a closed polygon defined by + * arrays of x and y coordinates. + * Each pair of (xy) coordinates defines a point. + *

+ * This method draws the polygon defined by nPoint line + * segments, where the first nPoint - 1 + * line segments are line segments from + * (xPoints[i - 1], yPoints[i - 1]) + * to (xPoints[i], yPoints[i]), for + * 1 ≤ i ≤ nPoints. + * The figure is automatically closed by drawing a line connecting + * the final point to the first point, if those points are different. + * @param xPoints a an array of x coordinates. + * @param yPoints a an array of y coordinates. + * @param nPoints a the total number of points. + * @see java.awt.Graphics#fillPolygon(int[],int[],int) + * @see java.awt.Graphics#drawPolyline + */ + public void drawPolygon(int[] xPoints, int[] yPoints, + int nPoints){ + java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints); + draw(polygon); + } + + /** + * Intersects the current clip with the specified rectangle. + * The resulting clipping area is the intersection of the current + * clipping area and the specified rectangle. If there is no + * current clipping area, either because the clip has never been + * set, or the clip has been cleared using setClip(null), + * the specified rectangle becomes the new clip. + * This method sets the user clip, which is independent of the + * clipping associated with device bounds and window visibility. + * This method can only be used to make the current clip smaller. + * To set the current clip larger, use any of the setClip methods. + * Rendering operations have no effect outside of the clipping area. + * @param x the x coordinate of the rectangle to intersect the clip with + * @param y the y coordinate of the rectangle to intersect the clip with + * @param width the width of the rectangle to intersect the clip with + * @param height the height of the rectangle to intersect the clip with + * @see #setClip(int, int, int, int) + * @see #setClip(Shape) + */ + public void clipRect(int x, int y, int width, int height){ + clip(new Rectangle(x, y, width, height)); + } + + /** + * Sets the current clipping area to an arbitrary clip shape. + * Not all objects that implement the Shape + * interface can be used to set the clip. The only + * Shape objects that are guaranteed to be + * supported are Shape objects that are + * obtained via the getClip method and via + * Rectangle objects. This method sets the + * user clip, which is independent of the clipping associated + * with device bounds and window visibility. + * @param clip the Shape to use to set the clip + * @see java.awt.Graphics#getClip() + * @see java.awt.Graphics#clipRect + * @see java.awt.Graphics#setClip(int, int, int, int) + * @since JDK1.1 + */ + @NotImplemented + public void setClip(Shape clip) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + /** + * Returns the bounding rectangle of the current clipping area. + * This method refers to the user clip, which is independent of the + * clipping associated with device bounds and window visibility. + * If no clip has previously been set, or if the clip has been + * cleared using setClip(null), this method returns + * null. + * The coordinates in the rectangle are relative to the coordinate + * system origin of this graphics context. + * @return the bounding rectangle of the current clipping area, + * or null if no clip is set. + * @see java.awt.Graphics#getClip + * @see java.awt.Graphics#clipRect + * @see java.awt.Graphics#setClip(int, int, int, int) + * @see java.awt.Graphics#setClip(Shape) + * @since JDK1.1 + */ + public Rectangle getClipBounds(){ + Shape c = getClip(); + if (c==null) { + return null; + } + return c.getBounds(); + } + + /** + * Draws the text given by the specified iterator, using this + * graphics context's current color. The iterator has to specify a font + * for each character. The baseline of the + * first character is at position (xy) in this + * graphics context's coordinate system. + * @param iterator the iterator whose text is to be drawn + * @param x the x coordinate. + * @param y the y coordinate. + * @see java.awt.Graphics#drawBytes + * @see java.awt.Graphics#drawChars + */ + public void drawString(AttributedCharacterIterator iterator, + int x, int y){ + drawString(iterator, (float)x, (float)y); + } + + /** + * Clears the specified rectangle by filling it with the background + * color of the current drawing surface. This operation does not + * use the current paint mode. + *

+ * Beginning with Java 1.1, the background color + * of offscreen images may be system dependent. Applications should + * use setColor followed by fillRect to + * ensure that an offscreen image is cleared to a specific color. + * @param x the x coordinate of the rectangle to clear. + * @param y the y coordinate of the rectangle to clear. + * @param width the width of the rectangle to clear. + * @param height the height of the rectangle to clear. + * @see java.awt.Graphics#fillRect(int, int, int, int) + * @see java.awt.Graphics#drawRect + * @see java.awt.Graphics#setColor(java.awt.Color) + * @see java.awt.Graphics#setPaintMode + * @see java.awt.Graphics#setXORMode(java.awt.Color) + */ + public void clearRect(int x, int y, int width, int height) { + Paint paint = getPaint(); + setColor(getBackground()); + fillRect(x, y, width, height); + setPaint(paint); + } + + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + } + + /** + * Sets the current clip to the rectangle specified by the given + * coordinates. This method sets the user clip, which is + * independent of the clipping associated with device bounds + * and window visibility. + * Rendering operations have no effect outside of the clipping area. + * @param x the x coordinate of the new clip rectangle. + * @param y the y coordinate of the new clip rectangle. + * @param width the width of the new clip rectangle. + * @param height the height of the new clip rectangle. + * @see java.awt.Graphics#clipRect + * @see java.awt.Graphics#setClip(Shape) + * @since JDK1.1 + */ + public void setClip(int x, int y, int width, int height){ + setClip(new Rectangle(x, y, width, height)); + } + + /** + * Concatenates the current Graphics2D + * Transform with a rotation transform. + * Subsequent rendering is rotated by the specified radians relative + * to the previous origin. + * This is equivalent to calling transform(R), where R is an + * AffineTransform represented by the following matrix: + *

+     *          [   cos(theta)    -sin(theta)    0   ]
+     *          [   sin(theta)     cos(theta)    0   ]
+     *          [       0              0         1   ]
+     * 
+ * Rotating with a positive angle theta rotates points on the positive + * x axis toward the positive y axis. + * @param theta the angle of rotation in radians + */ + public void rotate(double theta){ + _transform.rotate(theta); + } + + /** + * Concatenates the current Graphics2D + * Transform with a translated rotation + * transform. Subsequent rendering is transformed by a transform + * which is constructed by translating to the specified location, + * rotating by the specified radians, and translating back by the same + * amount as the original translation. This is equivalent to the + * following sequence of calls: + *
+     *          translate(x, y);
+     *          rotate(theta);
+     *          translate(-x, -y);
+     * 
+ * Rotating with a positive angle theta rotates points on the positive + * x axis toward the positive y axis. + * @param theta the angle of rotation in radians + * @param x x coordinate of the origin of the rotation + * @param y y coordinate of the origin of the rotation + */ + public void rotate(double theta, double x, double y){ + _transform.rotate(theta, x, y); + } + + /** + * Concatenates the current Graphics2D + * Transform with a shearing transform. + * Subsequent renderings are sheared by the specified + * multiplier relative to the previous position. + * This is equivalent to calling transform(SH), where SH + * is an AffineTransform represented by the following + * matrix: + *
+     *          [   1   shx   0   ]
+     *          [  shy   1    0   ]
+     *          [   0    0    1   ]
+     * 
+ * @param shx the multiplier by which coordinates are shifted in + * the positive X axis direction as a function of their Y coordinate + * @param shy the multiplier by which coordinates are shifted in + * the positive Y axis direction as a function of their X coordinate + */ + public void shear(double shx, double shy){ + _transform.shear(shx, shy); + } + + /** + * Get the rendering context of the Font within this + * Graphics2D context. + * The {@link FontRenderContext} + * encapsulates application hints such as anti-aliasing and + * fractional metrics, as well as target device specific information + * such as dots-per-inch. This information should be provided by the + * application when using objects that perform typographical + * formatting, such as Font and + * TextLayout. This information should also be provided + * by applications that perform their own layout and need accurate + * measurements of various characteristics of glyphs such as advance + * and line height when various rendering hints have been applied to + * the text rendering. + * + * @return a reference to an instance of FontRenderContext. + * @see java.awt.font.FontRenderContext + * @see java.awt.Font#createGlyphVector(FontRenderContext,char[]) + * @see java.awt.font.TextLayout + * @since JDK1.2 + */ + public FontRenderContext getFontRenderContext() { + boolean isAntiAliased = RenderingHints.VALUE_TEXT_ANTIALIAS_ON.equals( + getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING)); + boolean usesFractionalMetrics = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals( + getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS)); + + + return new FontRenderContext(new AffineTransform(), isAntiAliased, usesFractionalMetrics); + } + + /** + * Composes an AffineTransform object with the + * Transform in this Graphics2D according + * to the rule last-specified-first-applied. If the current + * Transform is Cx, the result of composition + * with Tx is a new Transform Cx'. Cx' becomes the + * current Transform for this Graphics2D. + * Transforming a point p by the updated Transform Cx' is + * equivalent to first transforming p by Tx and then transforming + * the result by the original Transform Cx. In other + * words, Cx'(p) = Cx(Tx(p)). A copy of the Tx is made, if necessary, + * so further modifications to Tx do not affect rendering. + * @param Tx the AffineTransform object to be composed with + * the current Transform + * @see #setTransform + * @see AffineTransform + */ + public void transform(AffineTransform Tx) { + _transform.concatenate(Tx); + } + + /** + * Renders a BufferedImage that is + * filtered with a + * {@link BufferedImageOp}. + * The rendering attributes applied include the Clip, + * Transform + * and Composite attributes. This is equivalent to: + *
+     * img1 = op.filter(img, null);
+     * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
+     * 
+ * @param img the BufferedImage to be rendered + * @param op the filter to be applied to the image before rendering + * @param x the x coordinate in user space where the image is rendered + * @param y the y coordinate in user space where the image is rendered + * @see #_transform + * @see #setTransform + * @see #setComposite + * @see #clip + * @see #setClip(Shape) + */ + public void drawImage(BufferedImage img, + BufferedImageOp op, + int x, + int y){ + img = op.filter(img, null); + drawImage(img, x, y, null); + } + + /** + * Sets the background color for the Graphics2D context. + * The background color is used for clearing a region. + * When a Graphics2D is constructed for a + * Component, the background color is + * inherited from the Component. Setting the background color + * in the Graphics2D context only affects the subsequent + * clearRect calls and not the background color of the + * Component. To change the background + * of the Component, use appropriate methods of + * the Component. + * @param color the background color that isused in + * subsequent calls to clearRect + * @see #getBackground + * @see java.awt.Graphics#clearRect + */ + public void setBackground(Color color) { + if(color == null) + return; + + _background = color; + } + + /** + * Returns the background color used for clearing a region. + * @return the current Graphics2D Color, + * which defines the background color. + * @see #setBackground + */ + public Color getBackground(){ + return _background; + } + + /** + * Sets the Composite for the Graphics2D context. + * The Composite is used in all drawing methods such as + * drawImage, drawString, draw, + * and fill. It specifies how new pixels are to be combined + * with the existing pixels on the graphics device during the rendering + * process. + *

If this Graphics2D context is drawing to a + * Component on the display screen and the + * Composite is a custom object rather than an + * instance of the AlphaComposite class, and if + * there is a security manager, its checkPermission + * method is called with an AWTPermission("readDisplayPixels") + * permission. + * + * @param comp the Composite object to be used for rendering + * @throws SecurityException + * if a custom Composite object is being + * used to render to the screen and a security manager + * is set and its checkPermission method + * does not allow the operation. + * @see java.awt.Graphics#setXORMode + * @see java.awt.Graphics#setPaintMode + * @see java.awt.AlphaComposite + */ + @NotImplemented + public void setComposite(Composite comp){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + /** + * Returns the current Composite in the + * Graphics2D context. + * @return the current Graphics2D Composite, + * which defines a compositing style. + * @see #setComposite + */ + @NotImplemented + public Composite getComposite(){ + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + return null; + } + + /** + * Returns the value of a single preference for the rendering algorithms. + * Hint categories include controls for rendering quality and overall + * time/quality trade-off in the rendering process. Refer to the + * RenderingHints class for definitions of some common + * keys and values. + * @param hintKey the key corresponding to the hint to get. + * @return an object representing the value for the specified hint key. + * Some of the keys and their associated values are defined in the + * RenderingHints class. + * @see RenderingHints + */ + public Object getRenderingHint(RenderingHints.Key hintKey){ + return _hints.get(hintKey); + } + + /** + * Sets the value of a single preference for the rendering algorithms. + * Hint categories include controls for rendering quality and overall + * time/quality trade-off in the rendering process. Refer to the + * RenderingHints class for definitions of some common + * keys and values. + * @param hintKey the key of the hint to be set. + * @param hintValue the value indicating preferences for the specified + * hint category. + * @see RenderingHints + */ + public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue){ + _hints.put(hintKey, hintValue); + } + + + /** + * Renders the text of the specified + * {@link GlyphVector} using + * the Graphics2D context's rendering attributes. + * The rendering attributes applied include the Clip, + * Transform, Paint, and + * Composite attributes. The GlyphVector + * specifies individual glyphs from a {@link Font}. + * The GlyphVector can also contain the glyph positions. + * This is the fastest way to render a set of characters to the + * screen. + * + * @param g the GlyphVector to be rendered + * @param x the x position in user space where the glyphs should be + * rendered + * @param y the y position in user space where the glyphs should be + * rendered + * + * @see java.awt.Font#createGlyphVector(FontRenderContext, char[]) + * @see java.awt.font.GlyphVector + * @see #setPaint + * @see java.awt.Graphics#setColor + * @see #setTransform + * @see #setComposite + * @see #setClip(Shape) + */ + public void drawGlyphVector(GlyphVector g, float x, float y) { + Shape glyphOutline = g.getOutline(x, y); + fill(glyphOutline); + } + + /** + * Returns the device configuration associated with this + * Graphics2D. + * @return the device configuration + */ + public GraphicsConfiguration getDeviceConfiguration() { + return GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + + /** + * Sets the values of an arbitrary number of preferences for the + * rendering algorithms. + * Only values for the rendering hints that are present in the + * specified Map object are modified. + * All other preferences not present in the specified + * object are left unmodified. + * Hint categories include controls for rendering quality and + * overall time/quality trade-off in the rendering process. + * Refer to the RenderingHints class for definitions of + * some common keys and values. + * @param hints the rendering hints to be set + * @see RenderingHints + */ + public void addRenderingHints(Map hints){ + this._hints.putAll(hints); + } + + /** + * Concatenates the current + * Graphics2D Transform + * with a translation transform. + * Subsequent rendering is translated by the specified + * distance relative to the previous position. + * This is equivalent to calling transform(T), where T is an + * AffineTransform represented by the following matrix: + *

+     *          [   1    0    tx  ]
+     *          [   0    1    ty  ]
+     *          [   0    0    1   ]
+     * 
+ * @param tx the distance to translate along the x-axis + * @param ty the distance to translate along the y-axis + */ + public void translate(double tx, double ty){ + _transform.translate(tx, ty); + } + + /** + * Renders the text of the specified iterator, using the + * Graphics2D context's current Paint. The + * iterator must specify a font + * for each character. The baseline of the + * first character is at position (xy) in the + * User Space. + * The rendering attributes applied include the Clip, + * Transform, Paint, and + * Composite attributes. + * For characters in script systems such as Hebrew and Arabic, + * the glyphs can be rendered from right to left, in which case the + * coordinate supplied is the location of the leftmost character + * on the baseline. + * @param iterator the iterator whose text is to be rendered + * @param x the x coordinate where the iterator's text is to be + * rendered + * @param y the y coordinate where the iterator's text is to be + * rendered + * @see #setPaint + * @see java.awt.Graphics#setColor + * @see #setTransform + * @see #setComposite + * @see #setClip + */ + @NotImplemented + public void drawString(AttributedCharacterIterator iterator, float x, float y) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + /** + * Checks whether or not the specified Shape intersects + * the specified {@link Rectangle}, which is in device + * space. If onStroke is false, this method checks + * whether or not the interior of the specified Shape + * intersects the specified Rectangle. If + * onStroke is true, this method checks + * whether or not the Stroke of the specified + * Shape outline intersects the specified + * Rectangle. + * The rendering attributes taken into account include the + * Clip, Transform, and Stroke + * attributes. + * @param rect the area in device space to check for a hit + * @param s the Shape to check for a hit + * @param onStroke flag used to choose between testing the + * stroked or the filled shape. If the flag is true, the + * Stroke oultine is tested. If the flag is + * false, the filled Shape is tested. + * @return true if there is a hit; false + * otherwise. + * @see #setStroke + * @see #fill(Shape) + * @see #draw(Shape) + * @see #_transform + * @see #setTransform + * @see #clip + * @see #setClip(Shape) + */ + public boolean hit(Rectangle rect, + Shape s, + boolean onStroke){ + if (onStroke) { + s = getStroke().createStrokedShape(s); + } + + s = getTransform().createTransformedShape(s); + + return s.intersects(rect); + } + + /** + * Gets the preferences for the rendering algorithms. Hint categories + * include controls for rendering quality and overall time/quality + * trade-off in the rendering process. + * Returns all of the hint key/value pairs that were ever specified in + * one operation. Refer to the + * RenderingHints class for definitions of some common + * keys and values. + * @return a reference to an instance of RenderingHints + * that contains the current preferences. + * @see RenderingHints + */ + public RenderingHints getRenderingHints(){ + return _hints; + } + + /** + * Replaces the values of all preferences for the rendering + * algorithms with the specified hints. + * The existing values for all rendering hints are discarded and + * the new set of known hints and values are initialized from the + * specified {@link Map} object. + * Hint categories include controls for rendering quality and + * overall time/quality trade-off in the rendering process. + * Refer to the RenderingHints class for definitions of + * some common keys and values. + * @param hints the rendering hints to be set + * @see RenderingHints + */ + public void setRenderingHints(Map hints){ + this._hints = new RenderingHints(null); + this._hints.putAll(hints); + } + + /** + * Renders an image, applying a transform from image space into user space + * before drawing. + * The transformation from user space into device space is done with + * the current Transform in the Graphics2D. + * The specified transformation is applied to the image before the + * transform attribute in the Graphics2D context is applied. + * The rendering attributes applied include the Clip, + * Transform, and Composite attributes. + * Note that no rendering is done if the specified transform is + * noninvertible. + * @param img the Image to be rendered + * @param xform the transformation from image space into user space + * @param obs the {@link ImageObserver} + * to be notified as more of the Image + * is converted + * @return true if the Image is + * fully loaded and completely rendered; + * false if the Image is still being loaded. + * @see #_transform + * @see #setTransform + * @see #setComposite + * @see #clip + * @see #setClip(Shape) + */ + @NotImplemented + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + return false; + } + + /** + * Draws as much of the specified image as has already been scaled + * to fit inside the specified rectangle. + *

+ * The image is drawn inside the specified rectangle of this + * graphics context's coordinate space, and is scaled if + * necessary. Transparent pixels do not affect whatever pixels + * are already there. + *

+ * This method returns immediately in all cases, even if the + * entire image has not yet been scaled, dithered, and converted + * for the current output device. + * If the current output representation is not yet complete, then + * drawImage returns false. As more of + * the image becomes available, the process that loads the image notifies + * the image observer by calling its imageUpdate method. + *

+ * A scaled version of an image will not necessarily be + * available immediately just because an unscaled version of the + * image has been constructed for this output device. Each size of + * the image may be cached separately and generated from the original + * data in a separate image production sequence. + * @param img the specified image to be drawn. This method does + * nothing if img is null. + * @param x the x coordinate. + * @param y the y coordinate. + * @param width the width of the rectangle. + * @param height the height of the rectangle. + * @param observer object to be notified as more of + * the image is converted. + * @return false if the image pixels are still changing; + * true otherwise. + * @see java.awt.Image + * @see java.awt.image.ImageObserver + * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) + */ + @NotImplemented + public boolean drawImage(Image img, int x, int y, + int width, int height, + ImageObserver observer) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + return false; + } + + /** + * Creates a new Graphics object that is + * a copy of this Graphics object. + * @return a new graphics context that is a copy of + * this graphics context. + */ + public Graphics create() { + try { + return (Graphics)clone(); + } catch (CloneNotSupportedException e){ + throw new RuntimeException(e); + } + } + + /** + * Gets the font metrics for the specified font. + * @return the font metrics for the specified font. + * @param f the specified font + * @see java.awt.Graphics#getFont + * @see java.awt.FontMetrics + * @see java.awt.Graphics#getFontMetrics() + */ + @SuppressWarnings("deprecation") + @SuppressForbidden + public FontMetrics getFontMetrics(Font f) { + return Toolkit.getDefaultToolkit().getFontMetrics(f); + } + + /** + * Sets the paint mode of this graphics context to alternate between + * this graphics context's current color and the new specified color. + * This specifies that logical pixel operations are performed in the + * XOR mode, which alternates pixels between the current color and + * a specified XOR color. + *

+ * When drawing operations are performed, pixels which are the + * current color are changed to the specified color, and vice versa. + *

+ * Pixels that are of colors other than those two colors are changed + * in an unpredictable but reversible manner; if the same figure is + * drawn twice, then all pixels are restored to their original values. + * @param c1 the XOR alternation color + */ + @NotImplemented + public void setXORMode(Color c1) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + /** + * Sets the paint mode of this graphics context to overwrite the + * destination with this graphics context's current color. + * This sets the logical pixel operation function to the paint or + * overwrite mode. All subsequent rendering operations will + * overwrite the destination with the current color. + */ + @NotImplemented + public void setPaintMode() { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + /** + * Renders a + * {@link RenderableImage}, + * applying a transform from image space into user space before drawing. + * The transformation from user space into device space is done with + * the current Transform in the Graphics2D. + * The specified transformation is applied to the image before the + * transform attribute in the Graphics2D context is applied. + * The rendering attributes applied include the Clip, + * Transform, and Composite attributes. Note + * that no rendering is done if the specified transform is + * noninvertible. + *

+ * Rendering hints set on the Graphics2D object might + * be used in rendering the RenderableImage. + * If explicit control is required over specific hints recognized by a + * specific RenderableImage, or if knowledge of which hints + * are used is required, then a RenderedImage should be + * obtained directly from the RenderableImage + * and rendered using + *{@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}. + * @param img the image to be rendered. This method does + * nothing if img is null. + * @param xform the transformation from image space into user space + * @see #_transform + * @see #setTransform + * @see #setComposite + * @see #clip + * @see #setClip + * @see #drawRenderedImage + */ + @NotImplemented + public void drawRenderedImage(RenderedImage img, AffineTransform xform) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + /** + * Renders a {@link RenderedImage}, + * applying a transform from image + * space into user space before drawing. + * The transformation from user space into device space is done with + * the current Transform in the Graphics2D. + * The specified transformation is applied to the image before the + * transform attribute in the Graphics2D context is applied. + * The rendering attributes applied include the Clip, + * Transform, and Composite attributes. Note + * that no rendering is done if the specified transform is + * noninvertible. + * @param img the image to be rendered. This method does + * nothing if img is null. + * @param xform the transformation from image space into user space + * @see #_transform + * @see #setTransform + * @see #setComposite + * @see #clip + * @see #setClip + */ + @NotImplemented + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "Not implemented"); + } + } + + protected void applyStroke(SimpleShape shape) { + if (_stroke instanceof BasicStroke){ + BasicStroke bs = (BasicStroke)_stroke; + shape.setStrokeStyle((double)bs.getLineWidth()); + float[] dash = bs.getDashArray(); + if (dash != null) { + //TODO: implement more dashing styles + shape.setStrokeStyle(StrokeStyle.LineDash.DASH); + } + } + } + + protected void applyPaint(SimpleShape shape) { + if (_paint instanceof Color) { + shape.setFillColor((Color)_paint); + } + } +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java b/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java index 32ee2a03b0..98a9b1822f 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java @@ -1,109 +1,109 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_AdjPoint2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_AdjPoint2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="x" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="y" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_AdjPoint2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTAdjPoint2D { - - @XmlAttribute(required = true) - protected String x; - @XmlAttribute(required = true) - protected String y; - - /** - * Gets the value of the x property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getX() { - return x; - } - - /** - * Sets the value of the x property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setX(String value) { - this.x = value; - } - - public boolean isSetX() { - return (this.x!= null); - } - - /** - * Gets the value of the y property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getY() { - return y; - } - - /** - * Sets the value of the y property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setY(String value) { - this.y = value; - } - - public boolean isSetY() { - return (this.y!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_AdjPoint2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_AdjPoint2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="x" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="y" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_AdjPoint2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTAdjPoint2D { + + @XmlAttribute(required = true) + protected String x; + @XmlAttribute(required = true) + protected String y; + + /** + * Gets the value of the x property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getX() { + return x; + } + + /** + * Sets the value of the x property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setX(String value) { + this.x = value; + } + + public boolean isSetX() { + return (this.x!= null); + } + + /** + * Gets the value of the y property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getY() { + return y; + } + + /** + * Sets the value of the y property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setY(String value) { + this.y = value; + } + + public boolean isSetY() { + return (this.y!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java b/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java index d684cccb74..0ca4ce5371 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java @@ -1,99 +1,99 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElements; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_AdjustHandleList complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_AdjustHandleList">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <choice maxOccurs="unbounded" minOccurs="0">
- *         <element name="ahXY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_XYAdjustHandle"/>
- *         <element name="ahPolar" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PolarAdjustHandle"/>
- *       </choice>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_AdjustHandleList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "ahXYOrAhPolar" -}) -public class CTAdjustHandleList { - - @XmlElements({ - @XmlElement(name = "ahXY", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTXYAdjustHandle.class), - @XmlElement(name = "ahPolar", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPolarAdjustHandle.class) - }) - protected List ahXYOrAhPolar; - - /** - * Gets the value of the ahXYOrAhPolar property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the ahXYOrAhPolar property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getAhXYOrAhPolar().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTXYAdjustHandle } - * {@link CTPolarAdjustHandle } - * - * - */ - public List getAhXYOrAhPolar() { - if (ahXYOrAhPolar == null) { - ahXYOrAhPolar = new ArrayList(); - } - return this.ahXYOrAhPolar; - } - - public boolean isSetAhXYOrAhPolar() { - return ((this.ahXYOrAhPolar!= null)&&(!this.ahXYOrAhPolar.isEmpty())); - } - - public void unsetAhXYOrAhPolar() { - this.ahXYOrAhPolar = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_AdjustHandleList complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_AdjustHandleList">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <choice maxOccurs="unbounded" minOccurs="0">
+ *         <element name="ahXY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_XYAdjustHandle"/>
+ *         <element name="ahPolar" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PolarAdjustHandle"/>
+ *       </choice>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_AdjustHandleList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "ahXYOrAhPolar" +}) +public class CTAdjustHandleList { + + @XmlElements({ + @XmlElement(name = "ahXY", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTXYAdjustHandle.class), + @XmlElement(name = "ahPolar", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPolarAdjustHandle.class) + }) + protected List ahXYOrAhPolar; + + /** + * Gets the value of the ahXYOrAhPolar property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ahXYOrAhPolar property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAhXYOrAhPolar().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTXYAdjustHandle } + * {@link CTPolarAdjustHandle } + * + * + */ + public List getAhXYOrAhPolar() { + if (ahXYOrAhPolar == null) { + ahXYOrAhPolar = new ArrayList(); + } + return this.ahXYOrAhPolar; + } + + public boolean isSetAhXYOrAhPolar() { + return ((this.ahXYOrAhPolar!= null)&&(!this.ahXYOrAhPolar.isEmpty())); + } + + public void unsetAhXYOrAhPolar() { + this.ahXYOrAhPolar = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTAngle.java b/src/java/org/apache/poi/sl/draw/binding/CTAngle.java index 2e39602dad..c1b8fa5604 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTAngle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTAngle.java @@ -1,70 +1,70 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Angle complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Angle">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Angle" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Angle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTAngle { - - @XmlAttribute(required = true) - protected int val; - - /** - * Gets the value of the val property. - * - */ - public int getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - */ - public void setVal(int value) { - this.val = value; - } - - public boolean isSetVal() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Angle complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Angle">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Angle" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Angle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTAngle { + + @XmlAttribute(required = true) + protected int val; + + /** + * Gets the value of the val property. + * + */ + public int getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + */ + public void setVal(int value) { + this.val = value; + } + + public boolean isSetVal() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTColor.java b/src/java/org/apache/poi/sl/draw/binding/CTColor.java index dd3cca3602..aa92831fec 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTColor.java @@ -1,237 +1,237 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Color complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Color">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorChoice"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Color", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "scrgbClr", - "srgbClr", - "hslClr", - "sysClr", - "schemeClr", - "prstClr" -}) -public class CTColor { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTScRgbColor scrgbClr; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTSRgbColor srgbClr; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTHslColor hslClr; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTSystemColor sysClr; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTSchemeColor schemeClr; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTPresetColor prstClr; - - /** - * Gets the value of the scrgbClr property. - * - * @return - * possible object is - * {@link CTScRgbColor } - * - */ - public CTScRgbColor getScrgbClr() { - return scrgbClr; - } - - /** - * Sets the value of the scrgbClr property. - * - * @param value - * allowed object is - * {@link CTScRgbColor } - * - */ - public void setScrgbClr(CTScRgbColor value) { - this.scrgbClr = value; - } - - public boolean isSetScrgbClr() { - return (this.scrgbClr!= null); - } - - /** - * Gets the value of the srgbClr property. - * - * @return - * possible object is - * {@link CTSRgbColor } - * - */ - public CTSRgbColor getSrgbClr() { - return srgbClr; - } - - /** - * Sets the value of the srgbClr property. - * - * @param value - * allowed object is - * {@link CTSRgbColor } - * - */ - public void setSrgbClr(CTSRgbColor value) { - this.srgbClr = value; - } - - public boolean isSetSrgbClr() { - return (this.srgbClr!= null); - } - - /** - * Gets the value of the hslClr property. - * - * @return - * possible object is - * {@link CTHslColor } - * - */ - public CTHslColor getHslClr() { - return hslClr; - } - - /** - * Sets the value of the hslClr property. - * - * @param value - * allowed object is - * {@link CTHslColor } - * - */ - public void setHslClr(CTHslColor value) { - this.hslClr = value; - } - - public boolean isSetHslClr() { - return (this.hslClr!= null); - } - - /** - * Gets the value of the sysClr property. - * - * @return - * possible object is - * {@link CTSystemColor } - * - */ - public CTSystemColor getSysClr() { - return sysClr; - } - - /** - * Sets the value of the sysClr property. - * - * @param value - * allowed object is - * {@link CTSystemColor } - * - */ - public void setSysClr(CTSystemColor value) { - this.sysClr = value; - } - - public boolean isSetSysClr() { - return (this.sysClr!= null); - } - - /** - * Gets the value of the schemeClr property. - * - * @return - * possible object is - * {@link CTSchemeColor } - * - */ - public CTSchemeColor getSchemeClr() { - return schemeClr; - } - - /** - * Sets the value of the schemeClr property. - * - * @param value - * allowed object is - * {@link CTSchemeColor } - * - */ - public void setSchemeClr(CTSchemeColor value) { - this.schemeClr = value; - } - - public boolean isSetSchemeClr() { - return (this.schemeClr!= null); - } - - /** - * Gets the value of the prstClr property. - * - * @return - * possible object is - * {@link CTPresetColor } - * - */ - public CTPresetColor getPrstClr() { - return prstClr; - } - - /** - * Sets the value of the prstClr property. - * - * @param value - * allowed object is - * {@link CTPresetColor } - * - */ - public void setPrstClr(CTPresetColor value) { - this.prstClr = value; - } - - public boolean isSetPrstClr() { - return (this.prstClr!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Color complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Color">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorChoice"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Color", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "scrgbClr", + "srgbClr", + "hslClr", + "sysClr", + "schemeClr", + "prstClr" +}) +public class CTColor { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTScRgbColor scrgbClr; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTSRgbColor srgbClr; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTHslColor hslClr; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTSystemColor sysClr; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTSchemeColor schemeClr; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTPresetColor prstClr; + + /** + * Gets the value of the scrgbClr property. + * + * @return + * possible object is + * {@link CTScRgbColor } + * + */ + public CTScRgbColor getScrgbClr() { + return scrgbClr; + } + + /** + * Sets the value of the scrgbClr property. + * + * @param value + * allowed object is + * {@link CTScRgbColor } + * + */ + public void setScrgbClr(CTScRgbColor value) { + this.scrgbClr = value; + } + + public boolean isSetScrgbClr() { + return (this.scrgbClr!= null); + } + + /** + * Gets the value of the srgbClr property. + * + * @return + * possible object is + * {@link CTSRgbColor } + * + */ + public CTSRgbColor getSrgbClr() { + return srgbClr; + } + + /** + * Sets the value of the srgbClr property. + * + * @param value + * allowed object is + * {@link CTSRgbColor } + * + */ + public void setSrgbClr(CTSRgbColor value) { + this.srgbClr = value; + } + + public boolean isSetSrgbClr() { + return (this.srgbClr!= null); + } + + /** + * Gets the value of the hslClr property. + * + * @return + * possible object is + * {@link CTHslColor } + * + */ + public CTHslColor getHslClr() { + return hslClr; + } + + /** + * Sets the value of the hslClr property. + * + * @param value + * allowed object is + * {@link CTHslColor } + * + */ + public void setHslClr(CTHslColor value) { + this.hslClr = value; + } + + public boolean isSetHslClr() { + return (this.hslClr!= null); + } + + /** + * Gets the value of the sysClr property. + * + * @return + * possible object is + * {@link CTSystemColor } + * + */ + public CTSystemColor getSysClr() { + return sysClr; + } + + /** + * Sets the value of the sysClr property. + * + * @param value + * allowed object is + * {@link CTSystemColor } + * + */ + public void setSysClr(CTSystemColor value) { + this.sysClr = value; + } + + public boolean isSetSysClr() { + return (this.sysClr!= null); + } + + /** + * Gets the value of the schemeClr property. + * + * @return + * possible object is + * {@link CTSchemeColor } + * + */ + public CTSchemeColor getSchemeClr() { + return schemeClr; + } + + /** + * Sets the value of the schemeClr property. + * + * @param value + * allowed object is + * {@link CTSchemeColor } + * + */ + public void setSchemeClr(CTSchemeColor value) { + this.schemeClr = value; + } + + public boolean isSetSchemeClr() { + return (this.schemeClr!= null); + } + + /** + * Gets the value of the prstClr property. + * + * @return + * possible object is + * {@link CTPresetColor } + * + */ + public CTPresetColor getPrstClr() { + return prstClr; + } + + /** + * Sets the value of the prstClr property. + * + * @param value + * allowed object is + * {@link CTPresetColor } + * + */ + public void setPrstClr(CTPresetColor value) { + this.prstClr = value; + } + + public boolean isSetPrstClr() { + return (this.prstClr!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java b/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java index 973603de45..e0d281e28c 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java @@ -1,106 +1,106 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElements; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_ColorMRU complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_ColorMRU">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorChoice" maxOccurs="10" minOccurs="0"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_ColorMRU", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "egColorChoice" -}) -public class CTColorMRU { - - @XmlElements({ - @XmlElement(name = "prstClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPresetColor.class), - @XmlElement(name = "sysClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSystemColor.class), - @XmlElement(name = "hslClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTHslColor.class), - @XmlElement(name = "srgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSRgbColor.class), - @XmlElement(name = "scrgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTScRgbColor.class), - @XmlElement(name = "schemeClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSchemeColor.class) - }) - protected List egColorChoice; - - /** - * Gets the value of the egColorChoice property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the egColorChoice property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getEGColorChoice().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTPresetColor } - * {@link CTSystemColor } - * {@link CTHslColor } - * {@link CTSRgbColor } - * {@link CTScRgbColor } - * {@link CTSchemeColor } - * - * - */ - public List getEGColorChoice() { - if (egColorChoice == null) { - egColorChoice = new ArrayList(); - } - return this.egColorChoice; - } - - public boolean isSetEGColorChoice() { - return ((this.egColorChoice!= null)&&(!this.egColorChoice.isEmpty())); - } - - public void unsetEGColorChoice() { - this.egColorChoice = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_ColorMRU complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_ColorMRU">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorChoice" maxOccurs="10" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_ColorMRU", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "egColorChoice" +}) +public class CTColorMRU { + + @XmlElements({ + @XmlElement(name = "prstClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPresetColor.class), + @XmlElement(name = "sysClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSystemColor.class), + @XmlElement(name = "hslClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTHslColor.class), + @XmlElement(name = "srgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSRgbColor.class), + @XmlElement(name = "scrgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTScRgbColor.class), + @XmlElement(name = "schemeClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSchemeColor.class) + }) + protected List egColorChoice; + + /** + * Gets the value of the egColorChoice property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egColorChoice property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEGColorChoice().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTPresetColor } + * {@link CTSystemColor } + * {@link CTHslColor } + * {@link CTSRgbColor } + * {@link CTScRgbColor } + * {@link CTSchemeColor } + * + * + */ + public List getEGColorChoice() { + if (egColorChoice == null) { + egColorChoice = new ArrayList(); + } + return this.egColorChoice; + } + + public boolean isSetEGColorChoice() { + return ((this.egColorChoice!= null)&&(!this.egColorChoice.isEmpty())); + } + + public void unsetEGColorChoice() { + this.egColorChoice = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java index dd1a56c0b9..b020a55bdd 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java @@ -1,46 +1,46 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_ComplementTransform complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_ComplementTransform">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_ComplementTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTComplementTransform { - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_ComplementTransform complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_ComplementTransform">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_ComplementTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTComplementTransform { + + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTConnection.java b/src/java/org/apache/poi/sl/draw/binding/CTConnection.java index 4af3fac719..79b924fb48 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTConnection.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTConnection.java @@ -1,95 +1,95 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Connection complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Connection">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="id" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_DrawingElementId" />
- *       <attribute name="idx" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Connection", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTConnection { - - @XmlAttribute(required = true) - protected long id; - @XmlAttribute(required = true) - @XmlSchemaType(name = "unsignedInt") - protected long idx; - - /** - * Gets the value of the id property. - * - */ - public long getId() { - return id; - } - - /** - * Sets the value of the id property. - * - */ - public void setId(long value) { - this.id = value; - } - - public boolean isSetId() { - return true; - } - - /** - * Gets the value of the idx property. - * - */ - public long getIdx() { - return idx; - } - - /** - * Sets the value of the idx property. - * - */ - public void setIdx(long value) { - this.idx = value; - } - - public boolean isSetIdx() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Connection complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Connection">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="id" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_DrawingElementId" />
+ *       <attribute name="idx" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Connection", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTConnection { + + @XmlAttribute(required = true) + protected long id; + @XmlAttribute(required = true) + @XmlSchemaType(name = "unsignedInt") + protected long idx; + + /** + * Gets the value of the id property. + * + */ + public long getId() { + return id; + } + + /** + * Sets the value of the id property. + * + */ + public void setId(long value) { + this.id = value; + } + + public boolean isSetId() { + return true; + } + + /** + * Gets the value of the idx property. + * + */ + public long getIdx() { + return idx; + } + + /** + * Sets the value of the idx property. + * + */ + public void setIdx(long value) { + this.idx = value; + } + + public boolean isSetIdx() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java index 7ec62972dd..061d2a1bf5 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java @@ -1,114 +1,114 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_ConnectionSite complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_ConnectionSite">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="pos" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
- *       </sequence>
- *       <attribute name="ang" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_ConnectionSite", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "pos" -}) -public class CTConnectionSite { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTAdjPoint2D pos; - @XmlAttribute(required = true) - protected String ang; - - /** - * Gets the value of the pos property. - * - * @return - * possible object is - * {@link CTAdjPoint2D } - * - */ - public CTAdjPoint2D getPos() { - return pos; - } - - /** - * Sets the value of the pos property. - * - * @param value - * allowed object is - * {@link CTAdjPoint2D } - * - */ - public void setPos(CTAdjPoint2D value) { - this.pos = value; - } - - public boolean isSetPos() { - return (this.pos!= null); - } - - /** - * Gets the value of the ang property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getAng() { - return ang; - } - - /** - * Sets the value of the ang property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setAng(String value) { - this.ang = value; - } - - public boolean isSetAng() { - return (this.ang!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_ConnectionSite complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_ConnectionSite">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pos" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
+ *       </sequence>
+ *       <attribute name="ang" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_ConnectionSite", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "pos" +}) +public class CTConnectionSite { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTAdjPoint2D pos; + @XmlAttribute(required = true) + protected String ang; + + /** + * Gets the value of the pos property. + * + * @return + * possible object is + * {@link CTAdjPoint2D } + * + */ + public CTAdjPoint2D getPos() { + return pos; + } + + /** + * Sets the value of the pos property. + * + * @param value + * allowed object is + * {@link CTAdjPoint2D } + * + */ + public void setPos(CTAdjPoint2D value) { + this.pos = value; + } + + public boolean isSetPos() { + return (this.pos!= null); + } + + /** + * Gets the value of the ang property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAng() { + return ang; + } + + /** + * Sets the value of the ang property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAng(String value) { + this.ang = value; + } + + public boolean isSetAng() { + return (this.ang!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java index a3c98898c4..0ae1ee14e6 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_ConnectionSiteList complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_ConnectionSiteList">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="cxn" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_ConnectionSite" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_ConnectionSiteList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "cxn" -}) -public class CTConnectionSiteList { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected List cxn; - - /** - * Gets the value of the cxn property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the cxn property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getCxn().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTConnectionSite } - * - * - */ - public List getCxn() { - if (cxn == null) { - cxn = new ArrayList(); - } - return this.cxn; - } - - public boolean isSetCxn() { - return ((this.cxn!= null)&&(!this.cxn.isEmpty())); - } - - public void unsetCxn() { - this.cxn = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_ConnectionSiteList complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_ConnectionSiteList">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="cxn" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_ConnectionSite" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_ConnectionSiteList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "cxn" +}) +public class CTConnectionSiteList { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected List cxn; + + /** + * Gets the value of the cxn property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the cxn property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getCxn().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTConnectionSite } + * + * + */ + public List getCxn() { + if (cxn == null) { + cxn = new ArrayList(); + } + return this.cxn; + } + + public boolean isSetCxn() { + return ((this.cxn!= null)&&(!this.cxn.isEmpty())); + } + + public void unsetCxn() { + this.cxn = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java b/src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java index d6856ee637..3a8f744fc1 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java @@ -1,242 +1,242 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_CustomGeometry2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_CustomGeometry2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="avLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
- *         <element name="gdLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
- *         <element name="ahLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjustHandleList" minOccurs="0"/>
- *         <element name="cxnLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_ConnectionSiteList" minOccurs="0"/>
- *         <element name="rect" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomRect" minOccurs="0"/>
- *         <element name="pathLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DList"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_CustomGeometry2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "avLst", - "gdLst", - "ahLst", - "cxnLst", - "rect", - "pathLst" -}) -public class CTCustomGeometry2D { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTGeomGuideList avLst; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTGeomGuideList gdLst; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTAdjustHandleList ahLst; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTConnectionSiteList cxnLst; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTGeomRect rect; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTPath2DList pathLst; - - /** - * Gets the value of the avLst property. - * - * @return - * possible object is - * {@link CTGeomGuideList } - * - */ - public CTGeomGuideList getAvLst() { - return avLst; - } - - /** - * Sets the value of the avLst property. - * - * @param value - * allowed object is - * {@link CTGeomGuideList } - * - */ - public void setAvLst(CTGeomGuideList value) { - this.avLst = value; - } - - public boolean isSetAvLst() { - return (this.avLst!= null); - } - - /** - * Gets the value of the gdLst property. - * - * @return - * possible object is - * {@link CTGeomGuideList } - * - */ - public CTGeomGuideList getGdLst() { - return gdLst; - } - - /** - * Sets the value of the gdLst property. - * - * @param value - * allowed object is - * {@link CTGeomGuideList } - * - */ - public void setGdLst(CTGeomGuideList value) { - this.gdLst = value; - } - - public boolean isSetGdLst() { - return (this.gdLst!= null); - } - - /** - * Gets the value of the ahLst property. - * - * @return - * possible object is - * {@link CTAdjustHandleList } - * - */ - public CTAdjustHandleList getAhLst() { - return ahLst; - } - - /** - * Sets the value of the ahLst property. - * - * @param value - * allowed object is - * {@link CTAdjustHandleList } - * - */ - public void setAhLst(CTAdjustHandleList value) { - this.ahLst = value; - } - - public boolean isSetAhLst() { - return (this.ahLst!= null); - } - - /** - * Gets the value of the cxnLst property. - * - * @return - * possible object is - * {@link CTConnectionSiteList } - * - */ - public CTConnectionSiteList getCxnLst() { - return cxnLst; - } - - /** - * Sets the value of the cxnLst property. - * - * @param value - * allowed object is - * {@link CTConnectionSiteList } - * - */ - public void setCxnLst(CTConnectionSiteList value) { - this.cxnLst = value; - } - - public boolean isSetCxnLst() { - return (this.cxnLst!= null); - } - - /** - * Gets the value of the rect property. - * - * @return - * possible object is - * {@link CTGeomRect } - * - */ - public CTGeomRect getRect() { - return rect; - } - - /** - * Sets the value of the rect property. - * - * @param value - * allowed object is - * {@link CTGeomRect } - * - */ - public void setRect(CTGeomRect value) { - this.rect = value; - } - - public boolean isSetRect() { - return (this.rect!= null); - } - - /** - * Gets the value of the pathLst property. - * - * @return - * possible object is - * {@link CTPath2DList } - * - */ - public CTPath2DList getPathLst() { - return pathLst; - } - - /** - * Sets the value of the pathLst property. - * - * @param value - * allowed object is - * {@link CTPath2DList } - * - */ - public void setPathLst(CTPath2DList value) { - this.pathLst = value; - } - - public boolean isSetPathLst() { - return (this.pathLst!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_CustomGeometry2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_CustomGeometry2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="avLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
+ *         <element name="gdLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
+ *         <element name="ahLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjustHandleList" minOccurs="0"/>
+ *         <element name="cxnLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_ConnectionSiteList" minOccurs="0"/>
+ *         <element name="rect" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomRect" minOccurs="0"/>
+ *         <element name="pathLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DList"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_CustomGeometry2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "avLst", + "gdLst", + "ahLst", + "cxnLst", + "rect", + "pathLst" +}) +public class CTCustomGeometry2D { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTGeomGuideList avLst; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTGeomGuideList gdLst; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTAdjustHandleList ahLst; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTConnectionSiteList cxnLst; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTGeomRect rect; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTPath2DList pathLst; + + /** + * Gets the value of the avLst property. + * + * @return + * possible object is + * {@link CTGeomGuideList } + * + */ + public CTGeomGuideList getAvLst() { + return avLst; + } + + /** + * Sets the value of the avLst property. + * + * @param value + * allowed object is + * {@link CTGeomGuideList } + * + */ + public void setAvLst(CTGeomGuideList value) { + this.avLst = value; + } + + public boolean isSetAvLst() { + return (this.avLst!= null); + } + + /** + * Gets the value of the gdLst property. + * + * @return + * possible object is + * {@link CTGeomGuideList } + * + */ + public CTGeomGuideList getGdLst() { + return gdLst; + } + + /** + * Sets the value of the gdLst property. + * + * @param value + * allowed object is + * {@link CTGeomGuideList } + * + */ + public void setGdLst(CTGeomGuideList value) { + this.gdLst = value; + } + + public boolean isSetGdLst() { + return (this.gdLst!= null); + } + + /** + * Gets the value of the ahLst property. + * + * @return + * possible object is + * {@link CTAdjustHandleList } + * + */ + public CTAdjustHandleList getAhLst() { + return ahLst; + } + + /** + * Sets the value of the ahLst property. + * + * @param value + * allowed object is + * {@link CTAdjustHandleList } + * + */ + public void setAhLst(CTAdjustHandleList value) { + this.ahLst = value; + } + + public boolean isSetAhLst() { + return (this.ahLst!= null); + } + + /** + * Gets the value of the cxnLst property. + * + * @return + * possible object is + * {@link CTConnectionSiteList } + * + */ + public CTConnectionSiteList getCxnLst() { + return cxnLst; + } + + /** + * Sets the value of the cxnLst property. + * + * @param value + * allowed object is + * {@link CTConnectionSiteList } + * + */ + public void setCxnLst(CTConnectionSiteList value) { + this.cxnLst = value; + } + + public boolean isSetCxnLst() { + return (this.cxnLst!= null); + } + + /** + * Gets the value of the rect property. + * + * @return + * possible object is + * {@link CTGeomRect } + * + */ + public CTGeomRect getRect() { + return rect; + } + + /** + * Sets the value of the rect property. + * + * @param value + * allowed object is + * {@link CTGeomRect } + * + */ + public void setRect(CTGeomRect value) { + this.rect = value; + } + + public boolean isSetRect() { + return (this.rect!= null); + } + + /** + * Gets the value of the pathLst property. + * + * @return + * possible object is + * {@link CTPath2DList } + * + */ + public CTPath2DList getPathLst() { + return pathLst; + } + + /** + * Sets the value of the pathLst property. + * + * @param value + * allowed object is + * {@link CTPath2DList } + * + */ + public void setPathLst(CTPath2DList value) { + this.pathLst = value; + } + + public boolean isSetPathLst() { + return (this.pathLst!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java b/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java index 94d44ece22..84a4f70ec5 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java @@ -1,152 +1,152 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_EmbeddedWAVAudioFile complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_EmbeddedWAVAudioFile">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute ref="{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed use="required""/>
- *       <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
- *       <attribute name="builtIn" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_EmbeddedWAVAudioFile", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTEmbeddedWAVAudioFile { - - @XmlAttribute(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", required = true) - protected String embed; - @XmlAttribute - protected String name; - @XmlAttribute - protected Boolean builtIn; - - /** - * Embedded Audio File Relationship ID - * - * @return - * possible object is - * {@link String } - * - */ - public String getEmbed() { - return embed; - } - - /** - * Sets the value of the embed property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setEmbed(String value) { - this.embed = value; - } - - public boolean isSetEmbed() { - return (this.embed!= null); - } - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - if (name == null) { - return ""; - } else { - return name; - } - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - public boolean isSetName() { - return (this.name!= null); - } - - /** - * Gets the value of the builtIn property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isBuiltIn() { - if (builtIn == null) { - return false; - } else { - return builtIn; - } - } - - /** - * Sets the value of the builtIn property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setBuiltIn(boolean value) { - this.builtIn = value; - } - - public boolean isSetBuiltIn() { - return (this.builtIn!= null); - } - - public void unsetBuiltIn() { - this.builtIn = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_EmbeddedWAVAudioFile complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_EmbeddedWAVAudioFile">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute ref="{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed use="required""/>
+ *       <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
+ *       <attribute name="builtIn" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_EmbeddedWAVAudioFile", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTEmbeddedWAVAudioFile { + + @XmlAttribute(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", required = true) + protected String embed; + @XmlAttribute + protected String name; + @XmlAttribute + protected Boolean builtIn; + + /** + * Embedded Audio File Relationship ID + * + * @return + * possible object is + * {@link String } + * + */ + public String getEmbed() { + return embed; + } + + /** + * Sets the value of the embed property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setEmbed(String value) { + this.embed = value; + } + + public boolean isSetEmbed() { + return (this.embed!= null); + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + if (name == null) { + return ""; + } else { + return name; + } + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + public boolean isSetName() { + return (this.name!= null); + } + + /** + * Gets the value of the builtIn property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isBuiltIn() { + if (builtIn == null) { + return false; + } else { + return builtIn; + } + } + + /** + * Sets the value of the builtIn property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setBuiltIn(boolean value) { + this.builtIn = value; + } + + public boolean isSetBuiltIn() { + return (this.builtIn!= null); + } + + public void unsetBuiltIn() { + this.builtIn = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java index 92f41aee89..676c7a8762 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java @@ -1,70 +1,70 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_FixedPercentage complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_FixedPercentage">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_FixedPercentage" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_FixedPercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTFixedPercentage { - - @XmlAttribute(required = true) - protected int val; - - /** - * Gets the value of the val property. - * - */ - public int getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - */ - public void setVal(int value) { - this.val = value; - } - - public boolean isSetVal() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_FixedPercentage complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_FixedPercentage">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_FixedPercentage" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_FixedPercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTFixedPercentage { + + @XmlAttribute(required = true) + protected int val; + + /** + * Gets the value of the val property. + * + */ + public int getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + */ + public void setVal(int value) { + this.val = value; + } + + public boolean isSetVal() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java index 7cf6cb195c..d397b1d5dd 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java @@ -1,46 +1,46 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_GammaTransform complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_GammaTransform">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_GammaTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTGammaTransform { - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_GammaTransform complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_GammaTransform">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_GammaTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTGammaTransform { + + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java index 3df22093ca..c249356008 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java @@ -1,112 +1,112 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; - - -/** - *

Java class for CT_GeomGuide complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_GeomGuide">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="name" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
- *       <attribute name="fmla" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideFormula" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_GeomGuide", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTGeomGuide { - - @XmlAttribute(required = true) - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - protected String name; - @XmlAttribute(required = true) - protected String fmla; - - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - public boolean isSetName() { - return (this.name!= null); - } - - /** - * Gets the value of the fmla property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getFmla() { - return fmla; - } - - /** - * Sets the value of the fmla property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setFmla(String value) { - this.fmla = value; - } - - public boolean isSetFmla() { - return (this.fmla!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + +/** + *

Java class for CT_GeomGuide complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_GeomGuide">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="name" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
+ *       <attribute name="fmla" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideFormula" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_GeomGuide", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTGeomGuide { + + @XmlAttribute(required = true) + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + protected String name; + @XmlAttribute(required = true) + protected String fmla; + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + public boolean isSetName() { + return (this.name!= null); + } + + /** + * Gets the value of the fmla property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFmla() { + return fmla; + } + + /** + * Sets the value of the fmla property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFmla(String value) { + this.fmla = value; + } + + public boolean isSetFmla() { + return (this.fmla!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java index 4490933b4f..96886d49bb 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_GeomGuideList complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_GeomGuideList">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="gd" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuide" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_GeomGuideList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "gd" -}) -public class CTGeomGuideList { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected List gd; - - /** - * Gets the value of the gd property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the gd property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getGd().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTGeomGuide } - * - * - */ - public List getGd() { - if (gd == null) { - gd = new ArrayList(); - } - return this.gd; - } - - public boolean isSetGd() { - return ((this.gd!= null)&&(!this.gd.isEmpty())); - } - - public void unsetGd() { - this.gd = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_GeomGuideList complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_GeomGuideList">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="gd" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuide" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_GeomGuideList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "gd" +}) +public class CTGeomGuideList { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected List gd; + + /** + * Gets the value of the gd property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the gd property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getGd().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTGeomGuide } + * + * + */ + public List getGd() { + if (gd == null) { + gd = new ArrayList(); + } + return this.gd; + } + + public boolean isSetGd() { + return ((this.gd!= null)&&(!this.gd.isEmpty())); + } + + public void unsetGd() { + this.gd = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java index b1368be295..d8b9df8de2 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java @@ -1,171 +1,171 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_GeomRect complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_GeomRect">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="l" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="t" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="r" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="b" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_GeomRect", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTGeomRect { - - @XmlAttribute(required = true) - protected String l; - @XmlAttribute(required = true) - protected String t; - @XmlAttribute(required = true) - protected String r; - @XmlAttribute(required = true) - protected String b; - - /** - * Gets the value of the l property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getL() { - return l; - } - - /** - * Sets the value of the l property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setL(String value) { - this.l = value; - } - - public boolean isSetL() { - return (this.l!= null); - } - - /** - * Gets the value of the t property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getT() { - return t; - } - - /** - * Sets the value of the t property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setT(String value) { - this.t = value; - } - - public boolean isSetT() { - return (this.t!= null); - } - - /** - * Gets the value of the r property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getR() { - return r; - } - - /** - * Sets the value of the r property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setR(String value) { - this.r = value; - } - - public boolean isSetR() { - return (this.r!= null); - } - - /** - * Gets the value of the b property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getB() { - return b; - } - - /** - * Sets the value of the b property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setB(String value) { - this.b = value; - } - - public boolean isSetB() { - return (this.b!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_GeomRect complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_GeomRect">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="l" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="t" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="r" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="b" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_GeomRect", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTGeomRect { + + @XmlAttribute(required = true) + protected String l; + @XmlAttribute(required = true) + protected String t; + @XmlAttribute(required = true) + protected String r; + @XmlAttribute(required = true) + protected String b; + + /** + * Gets the value of the l property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getL() { + return l; + } + + /** + * Sets the value of the l property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setL(String value) { + this.l = value; + } + + public boolean isSetL() { + return (this.l!= null); + } + + /** + * Gets the value of the t property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getT() { + return t; + } + + /** + * Sets the value of the t property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setT(String value) { + this.t = value; + } + + public boolean isSetT() { + return (this.t!= null); + } + + /** + * Gets the value of the r property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getR() { + return r; + } + + /** + * Sets the value of the r property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setR(String value) { + this.r = value; + } + + public boolean isSetR() { + return (this.r!= null); + } + + /** + * Gets the value of the b property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getB() { + return b; + } + + /** + * Sets the value of the b property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setB(String value) { + this.b = value; + } + + public boolean isSetB() { + return (this.b!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java index 643db025a2..a1359273ed 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java @@ -1,46 +1,46 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_GrayscaleTransform complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_GrayscaleTransform">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_GrayscaleTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTGrayscaleTransform { - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_GrayscaleTransform complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_GrayscaleTransform">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_GrayscaleTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTGrayscaleTransform { + + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java b/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java index 6508613b16..2dafafc889 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java @@ -1,296 +1,296 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_GroupTransform2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_GroupTransform2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="off" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Point2D" minOccurs="0"/>
- *         <element name="ext" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PositiveSize2D" minOccurs="0"/>
- *         <element name="chOff" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Point2D" minOccurs="0"/>
- *         <element name="chExt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PositiveSize2D" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="rot" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Angle" default="0" />
- *       <attribute name="flipH" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
- *       <attribute name="flipV" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_GroupTransform2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "off", - "ext", - "chOff", - "chExt" -}) -public class CTGroupTransform2D { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTPoint2D off; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTPositiveSize2D ext; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTPoint2D chOff; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTPositiveSize2D chExt; - @XmlAttribute - protected Integer rot; - @XmlAttribute - protected Boolean flipH; - @XmlAttribute - protected Boolean flipV; - - /** - * Gets the value of the off property. - * - * @return - * possible object is - * {@link CTPoint2D } - * - */ - public CTPoint2D getOff() { - return off; - } - - /** - * Sets the value of the off property. - * - * @param value - * allowed object is - * {@link CTPoint2D } - * - */ - public void setOff(CTPoint2D value) { - this.off = value; - } - - public boolean isSetOff() { - return (this.off!= null); - } - - /** - * Gets the value of the ext property. - * - * @return - * possible object is - * {@link CTPositiveSize2D } - * - */ - public CTPositiveSize2D getExt() { - return ext; - } - - /** - * Sets the value of the ext property. - * - * @param value - * allowed object is - * {@link CTPositiveSize2D } - * - */ - public void setExt(CTPositiveSize2D value) { - this.ext = value; - } - - public boolean isSetExt() { - return (this.ext!= null); - } - - /** - * Gets the value of the chOff property. - * - * @return - * possible object is - * {@link CTPoint2D } - * - */ - public CTPoint2D getChOff() { - return chOff; - } - - /** - * Sets the value of the chOff property. - * - * @param value - * allowed object is - * {@link CTPoint2D } - * - */ - public void setChOff(CTPoint2D value) { - this.chOff = value; - } - - public boolean isSetChOff() { - return (this.chOff!= null); - } - - /** - * Gets the value of the chExt property. - * - * @return - * possible object is - * {@link CTPositiveSize2D } - * - */ - public CTPositiveSize2D getChExt() { - return chExt; - } - - /** - * Sets the value of the chExt property. - * - * @param value - * allowed object is - * {@link CTPositiveSize2D } - * - */ - public void setChExt(CTPositiveSize2D value) { - this.chExt = value; - } - - public boolean isSetChExt() { - return (this.chExt!= null); - } - - /** - * Gets the value of the rot property. - * - * @return - * possible object is - * {@link Integer } - * - */ - public int getRot() { - if (rot == null) { - return 0; - } else { - return rot; - } - } - - /** - * Sets the value of the rot property. - * - * @param value - * allowed object is - * {@link Integer } - * - */ - public void setRot(int value) { - this.rot = value; - } - - public boolean isSetRot() { - return (this.rot!= null); - } - - public void unsetRot() { - this.rot = null; - } - - /** - * Gets the value of the flipH property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isFlipH() { - if (flipH == null) { - return false; - } else { - return flipH; - } - } - - /** - * Sets the value of the flipH property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setFlipH(boolean value) { - this.flipH = value; - } - - public boolean isSetFlipH() { - return (this.flipH!= null); - } - - public void unsetFlipH() { - this.flipH = null; - } - - /** - * Gets the value of the flipV property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isFlipV() { - if (flipV == null) { - return false; - } else { - return flipV; - } - } - - /** - * Sets the value of the flipV property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setFlipV(boolean value) { - this.flipV = value; - } - - public boolean isSetFlipV() { - return (this.flipV!= null); - } - - public void unsetFlipV() { - this.flipV = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_GroupTransform2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_GroupTransform2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="off" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Point2D" minOccurs="0"/>
+ *         <element name="ext" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PositiveSize2D" minOccurs="0"/>
+ *         <element name="chOff" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Point2D" minOccurs="0"/>
+ *         <element name="chExt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PositiveSize2D" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="rot" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Angle" default="0" />
+ *       <attribute name="flipH" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *       <attribute name="flipV" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_GroupTransform2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "off", + "ext", + "chOff", + "chExt" +}) +public class CTGroupTransform2D { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTPoint2D off; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTPositiveSize2D ext; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTPoint2D chOff; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTPositiveSize2D chExt; + @XmlAttribute + protected Integer rot; + @XmlAttribute + protected Boolean flipH; + @XmlAttribute + protected Boolean flipV; + + /** + * Gets the value of the off property. + * + * @return + * possible object is + * {@link CTPoint2D } + * + */ + public CTPoint2D getOff() { + return off; + } + + /** + * Sets the value of the off property. + * + * @param value + * allowed object is + * {@link CTPoint2D } + * + */ + public void setOff(CTPoint2D value) { + this.off = value; + } + + public boolean isSetOff() { + return (this.off!= null); + } + + /** + * Gets the value of the ext property. + * + * @return + * possible object is + * {@link CTPositiveSize2D } + * + */ + public CTPositiveSize2D getExt() { + return ext; + } + + /** + * Sets the value of the ext property. + * + * @param value + * allowed object is + * {@link CTPositiveSize2D } + * + */ + public void setExt(CTPositiveSize2D value) { + this.ext = value; + } + + public boolean isSetExt() { + return (this.ext!= null); + } + + /** + * Gets the value of the chOff property. + * + * @return + * possible object is + * {@link CTPoint2D } + * + */ + public CTPoint2D getChOff() { + return chOff; + } + + /** + * Sets the value of the chOff property. + * + * @param value + * allowed object is + * {@link CTPoint2D } + * + */ + public void setChOff(CTPoint2D value) { + this.chOff = value; + } + + public boolean isSetChOff() { + return (this.chOff!= null); + } + + /** + * Gets the value of the chExt property. + * + * @return + * possible object is + * {@link CTPositiveSize2D } + * + */ + public CTPositiveSize2D getChExt() { + return chExt; + } + + /** + * Sets the value of the chExt property. + * + * @param value + * allowed object is + * {@link CTPositiveSize2D } + * + */ + public void setChExt(CTPositiveSize2D value) { + this.chExt = value; + } + + public boolean isSetChExt() { + return (this.chExt!= null); + } + + /** + * Gets the value of the rot property. + * + * @return + * possible object is + * {@link Integer } + * + */ + public int getRot() { + if (rot == null) { + return 0; + } else { + return rot; + } + } + + /** + * Sets the value of the rot property. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setRot(int value) { + this.rot = value; + } + + public boolean isSetRot() { + return (this.rot!= null); + } + + public void unsetRot() { + this.rot = null; + } + + /** + * Gets the value of the flipH property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isFlipH() { + if (flipH == null) { + return false; + } else { + return flipH; + } + } + + /** + * Sets the value of the flipH property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setFlipH(boolean value) { + this.flipH = value; + } + + public boolean isSetFlipH() { + return (this.flipH!= null); + } + + public void unsetFlipH() { + this.flipH = null; + } + + /** + * Gets the value of the flipV property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isFlipV() { + if (flipV == null) { + return false; + } else { + return flipV; + } + } + + /** + * Sets the value of the flipV property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setFlipV(boolean value) { + this.flipV = value; + } + + public boolean isSetFlipV() { + return (this.flipV!= null); + } + + public void unsetFlipV() { + this.flipV = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java b/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java index 53ced8d65d..3d9f376072 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java @@ -1,221 +1,221 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlElementRefs; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_HslColor complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_HslColor">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="hue" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
- *       <attribute name="sat" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
- *       <attribute name="lum" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_HslColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "egColorTransform" -}) -public class CTHslColor { - - @XmlElementRefs({ - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) - }) - protected List> egColorTransform; - @XmlAttribute(required = true) - protected int hue; - @XmlAttribute(required = true) - protected int sat; - @XmlAttribute(required = true) - protected int lum; - - /** - * Gets the value of the egColorTransform property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the egColorTransform property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getEGColorTransform().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * - * - */ - public List> getEGColorTransform() { - if (egColorTransform == null) { - egColorTransform = new ArrayList>(); - } - return this.egColorTransform; - } - - public boolean isSetEGColorTransform() { - return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); - } - - public void unsetEGColorTransform() { - this.egColorTransform = null; - } - - /** - * Gets the value of the hue property. - * - */ - public int getHue() { - return hue; - } - - /** - * Sets the value of the hue property. - * - */ - public void setHue(int value) { - this.hue = value; - } - - public boolean isSetHue() { - return true; - } - - /** - * Gets the value of the sat property. - * - */ - public int getSat() { - return sat; - } - - /** - * Sets the value of the sat property. - * - */ - public void setSat(int value) { - this.sat = value; - } - - public boolean isSetSat() { - return true; - } - - /** - * Gets the value of the lum property. - * - */ - public int getLum() { - return lum; - } - - /** - * Sets the value of the lum property. - * - */ - public void setLum(int value) { - this.lum = value; - } - - public boolean isSetLum() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_HslColor complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_HslColor">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="hue" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
+ *       <attribute name="sat" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
+ *       <attribute name="lum" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_HslColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "egColorTransform" +}) +public class CTHslColor { + + @XmlElementRefs({ + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + }) + protected List> egColorTransform; + @XmlAttribute(required = true) + protected int hue; + @XmlAttribute(required = true) + protected int sat; + @XmlAttribute(required = true) + protected int lum; + + /** + * Gets the value of the egColorTransform property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egColorTransform property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEGColorTransform().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * + * + */ + public List> getEGColorTransform() { + if (egColorTransform == null) { + egColorTransform = new ArrayList>(); + } + return this.egColorTransform; + } + + public boolean isSetEGColorTransform() { + return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); + } + + public void unsetEGColorTransform() { + this.egColorTransform = null; + } + + /** + * Gets the value of the hue property. + * + */ + public int getHue() { + return hue; + } + + /** + * Sets the value of the hue property. + * + */ + public void setHue(int value) { + this.hue = value; + } + + public boolean isSetHue() { + return true; + } + + /** + * Gets the value of the sat property. + * + */ + public int getSat() { + return sat; + } + + /** + * Sets the value of the sat property. + * + */ + public void setSat(int value) { + this.sat = value; + } + + public boolean isSetSat() { + return true; + } + + /** + * Gets the value of the lum property. + * + */ + public int getLum() { + return lum; + } + + /** + * Sets the value of the lum property. + * + */ + public void setLum(int value) { + this.lum = value; + } + + public boolean isSetLum() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTHyperlink.java b/src/java/org/apache/poi/sl/draw/binding/CTHyperlink.java index 03e486af5d..26450ba045 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTHyperlink.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTHyperlink.java @@ -1,403 +1,403 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Hyperlink complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Hyperlink">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="snd" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_EmbeddedWAVAudioFile" minOccurs="0"/>
- *         <element name="extLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_OfficeArtExtensionList" minOccurs="0"/>
- *       </sequence>
- *       <attribute ref="{http://schemas.openxmlformats.org/officeDocument/2006/relationships}id"/>
- *       <attribute name="invalidUrl" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
- *       <attribute name="action" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
- *       <attribute name="tgtFrame" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
- *       <attribute name="tooltip" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
- *       <attribute name="history" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" />
- *       <attribute name="highlightClick" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
- *       <attribute name="endSnd" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Hyperlink", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "snd", - "extLst" -}) -public class CTHyperlink { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTEmbeddedWAVAudioFile snd; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTOfficeArtExtensionList extLst; - @XmlAttribute(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships") - protected String id; - @XmlAttribute - protected String invalidUrl; - @XmlAttribute - protected String action; - @XmlAttribute - protected String tgtFrame; - @XmlAttribute - protected String tooltip; - @XmlAttribute - protected Boolean history; - @XmlAttribute - protected Boolean highlightClick; - @XmlAttribute - protected Boolean endSnd; - - /** - * Gets the value of the snd property. - * - * @return - * possible object is - * {@link CTEmbeddedWAVAudioFile } - * - */ - public CTEmbeddedWAVAudioFile getSnd() { - return snd; - } - - /** - * Sets the value of the snd property. - * - * @param value - * allowed object is - * {@link CTEmbeddedWAVAudioFile } - * - */ - public void setSnd(CTEmbeddedWAVAudioFile value) { - this.snd = value; - } - - public boolean isSetSnd() { - return (this.snd!= null); - } - - /** - * Gets the value of the extLst property. - * - * @return - * possible object is - * {@link CTOfficeArtExtensionList } - * - */ - public CTOfficeArtExtensionList getExtLst() { - return extLst; - } - - /** - * Sets the value of the extLst property. - * - * @param value - * allowed object is - * {@link CTOfficeArtExtensionList } - * - */ - public void setExtLst(CTOfficeArtExtensionList value) { - this.extLst = value; - } - - public boolean isSetExtLst() { - return (this.extLst!= null); - } - - /** - * Drawing Object Hyperlink Target - * - * @return - * possible object is - * {@link String } - * - */ - public String getId() { - return id; - } - - /** - * Sets the value of the id property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setId(String value) { - this.id = value; - } - - public boolean isSetId() { - return (this.id!= null); - } - - /** - * Gets the value of the invalidUrl property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getInvalidUrl() { - if (invalidUrl == null) { - return ""; - } else { - return invalidUrl; - } - } - - /** - * Sets the value of the invalidUrl property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setInvalidUrl(String value) { - this.invalidUrl = value; - } - - public boolean isSetInvalidUrl() { - return (this.invalidUrl!= null); - } - - /** - * Gets the value of the action property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getAction() { - if (action == null) { - return ""; - } else { - return action; - } - } - - /** - * Sets the value of the action property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setAction(String value) { - this.action = value; - } - - public boolean isSetAction() { - return (this.action!= null); - } - - /** - * Gets the value of the tgtFrame property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getTgtFrame() { - if (tgtFrame == null) { - return ""; - } else { - return tgtFrame; - } - } - - /** - * Sets the value of the tgtFrame property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setTgtFrame(String value) { - this.tgtFrame = value; - } - - public boolean isSetTgtFrame() { - return (this.tgtFrame!= null); - } - - /** - * Gets the value of the tooltip property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getTooltip() { - if (tooltip == null) { - return ""; - } else { - return tooltip; - } - } - - /** - * Sets the value of the tooltip property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setTooltip(String value) { - this.tooltip = value; - } - - public boolean isSetTooltip() { - return (this.tooltip!= null); - } - - /** - * Gets the value of the history property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isHistory() { - if (history == null) { - return true; - } else { - return history; - } - } - - /** - * Sets the value of the history property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setHistory(boolean value) { - this.history = value; - } - - public boolean isSetHistory() { - return (this.history!= null); - } - - public void unsetHistory() { - this.history = null; - } - - /** - * Gets the value of the highlightClick property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isHighlightClick() { - if (highlightClick == null) { - return false; - } else { - return highlightClick; - } - } - - /** - * Sets the value of the highlightClick property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setHighlightClick(boolean value) { - this.highlightClick = value; - } - - public boolean isSetHighlightClick() { - return (this.highlightClick!= null); - } - - public void unsetHighlightClick() { - this.highlightClick = null; - } - - /** - * Gets the value of the endSnd property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isEndSnd() { - if (endSnd == null) { - return false; - } else { - return endSnd; - } - } - - /** - * Sets the value of the endSnd property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setEndSnd(boolean value) { - this.endSnd = value; - } - - public boolean isSetEndSnd() { - return (this.endSnd!= null); - } - - public void unsetEndSnd() { - this.endSnd = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Hyperlink complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Hyperlink">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="snd" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_EmbeddedWAVAudioFile" minOccurs="0"/>
+ *         <element name="extLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_OfficeArtExtensionList" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute ref="{http://schemas.openxmlformats.org/officeDocument/2006/relationships}id"/>
+ *       <attribute name="invalidUrl" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
+ *       <attribute name="action" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
+ *       <attribute name="tgtFrame" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
+ *       <attribute name="tooltip" type="{http://www.w3.org/2001/XMLSchema}string" default="" />
+ *       <attribute name="history" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" />
+ *       <attribute name="highlightClick" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *       <attribute name="endSnd" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Hyperlink", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "snd", + "extLst" +}) +public class CTHyperlink { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTEmbeddedWAVAudioFile snd; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTOfficeArtExtensionList extLst; + @XmlAttribute(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships") + protected String id; + @XmlAttribute + protected String invalidUrl; + @XmlAttribute + protected String action; + @XmlAttribute + protected String tgtFrame; + @XmlAttribute + protected String tooltip; + @XmlAttribute + protected Boolean history; + @XmlAttribute + protected Boolean highlightClick; + @XmlAttribute + protected Boolean endSnd; + + /** + * Gets the value of the snd property. + * + * @return + * possible object is + * {@link CTEmbeddedWAVAudioFile } + * + */ + public CTEmbeddedWAVAudioFile getSnd() { + return snd; + } + + /** + * Sets the value of the snd property. + * + * @param value + * allowed object is + * {@link CTEmbeddedWAVAudioFile } + * + */ + public void setSnd(CTEmbeddedWAVAudioFile value) { + this.snd = value; + } + + public boolean isSetSnd() { + return (this.snd!= null); + } + + /** + * Gets the value of the extLst property. + * + * @return + * possible object is + * {@link CTOfficeArtExtensionList } + * + */ + public CTOfficeArtExtensionList getExtLst() { + return extLst; + } + + /** + * Sets the value of the extLst property. + * + * @param value + * allowed object is + * {@link CTOfficeArtExtensionList } + * + */ + public void setExtLst(CTOfficeArtExtensionList value) { + this.extLst = value; + } + + public boolean isSetExtLst() { + return (this.extLst!= null); + } + + /** + * Drawing Object Hyperlink Target + * + * @return + * possible object is + * {@link String } + * + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setId(String value) { + this.id = value; + } + + public boolean isSetId() { + return (this.id!= null); + } + + /** + * Gets the value of the invalidUrl property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getInvalidUrl() { + if (invalidUrl == null) { + return ""; + } else { + return invalidUrl; + } + } + + /** + * Sets the value of the invalidUrl property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setInvalidUrl(String value) { + this.invalidUrl = value; + } + + public boolean isSetInvalidUrl() { + return (this.invalidUrl!= null); + } + + /** + * Gets the value of the action property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAction() { + if (action == null) { + return ""; + } else { + return action; + } + } + + /** + * Sets the value of the action property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAction(String value) { + this.action = value; + } + + public boolean isSetAction() { + return (this.action!= null); + } + + /** + * Gets the value of the tgtFrame property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getTgtFrame() { + if (tgtFrame == null) { + return ""; + } else { + return tgtFrame; + } + } + + /** + * Sets the value of the tgtFrame property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setTgtFrame(String value) { + this.tgtFrame = value; + } + + public boolean isSetTgtFrame() { + return (this.tgtFrame!= null); + } + + /** + * Gets the value of the tooltip property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getTooltip() { + if (tooltip == null) { + return ""; + } else { + return tooltip; + } + } + + /** + * Sets the value of the tooltip property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setTooltip(String value) { + this.tooltip = value; + } + + public boolean isSetTooltip() { + return (this.tooltip!= null); + } + + /** + * Gets the value of the history property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isHistory() { + if (history == null) { + return true; + } else { + return history; + } + } + + /** + * Sets the value of the history property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setHistory(boolean value) { + this.history = value; + } + + public boolean isSetHistory() { + return (this.history!= null); + } + + public void unsetHistory() { + this.history = null; + } + + /** + * Gets the value of the highlightClick property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isHighlightClick() { + if (highlightClick == null) { + return false; + } else { + return highlightClick; + } + } + + /** + * Sets the value of the highlightClick property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setHighlightClick(boolean value) { + this.highlightClick = value; + } + + public boolean isSetHighlightClick() { + return (this.highlightClick!= null); + } + + public void unsetHighlightClick() { + this.highlightClick = null; + } + + /** + * Gets the value of the endSnd property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isEndSnd() { + if (endSnd == null) { + return false; + } else { + return endSnd; + } + } + + /** + * Sets the value of the endSnd property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setEndSnd(boolean value) { + this.endSnd = value; + } + + public boolean isSetEndSnd() { + return (this.endSnd!= null); + } + + public void unsetEndSnd() { + this.endSnd = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java index eaff064d70..32c9c7a6d2 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java @@ -1,46 +1,46 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_InverseGammaTransform complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_InverseGammaTransform">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_InverseGammaTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTInverseGammaTransform { - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_InverseGammaTransform complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_InverseGammaTransform">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_InverseGammaTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTInverseGammaTransform { + + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTInverseTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTInverseTransform.java index 84af625337..a4bbc8f882 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTInverseTransform.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTInverseTransform.java @@ -1,46 +1,46 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_InverseTransform complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_InverseTransform">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_InverseTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTInverseTransform { - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_InverseTransform complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_InverseTransform">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_InverseTransform", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTInverseTransform { + + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java b/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java index 62edc57b93..6b65ddd6c0 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java @@ -1,122 +1,122 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAnyElement; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import org.w3c.dom.Element; - - -/** - *

Java class for CT_OfficeArtExtension complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_OfficeArtExtension">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <any processContents='lax'/>
- *       </sequence>
- *       <attribute name="uri" type="{http://www.w3.org/2001/XMLSchema}token" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_OfficeArtExtension", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "any" -}) -public class CTOfficeArtExtension { - - @XmlAnyElement(lax = true) - protected Object any; - @XmlAttribute - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - @XmlSchemaType(name = "token") - protected String uri; - - /** - * Gets the value of the any property. - * - * @return - * possible object is - * {@link Object } - * {@link Element } - * - */ - public Object getAny() { - return any; - } - - /** - * Sets the value of the any property. - * - * @param value - * allowed object is - * {@link Object } - * {@link Element } - * - */ - public void setAny(Object value) { - this.any = value; - } - - public boolean isSetAny() { - return (this.any!= null); - } - - /** - * Gets the value of the uri property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getUri() { - return uri; - } - - /** - * Sets the value of the uri property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setUri(String value) { - this.uri = value; - } - - public boolean isSetUri() { - return (this.uri!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import org.w3c.dom.Element; + + +/** + *

Java class for CT_OfficeArtExtension complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_OfficeArtExtension">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <any processContents='lax'/>
+ *       </sequence>
+ *       <attribute name="uri" type="{http://www.w3.org/2001/XMLSchema}token" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_OfficeArtExtension", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "any" +}) +public class CTOfficeArtExtension { + + @XmlAnyElement(lax = true) + protected Object any; + @XmlAttribute + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + @XmlSchemaType(name = "token") + protected String uri; + + /** + * Gets the value of the any property. + * + * @return + * possible object is + * {@link Object } + * {@link Element } + * + */ + public Object getAny() { + return any; + } + + /** + * Sets the value of the any property. + * + * @param value + * allowed object is + * {@link Object } + * {@link Element } + * + */ + public void setAny(Object value) { + this.any = value; + } + + public boolean isSetAny() { + return (this.any!= null); + } + + /** + * Gets the value of the uri property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getUri() { + return uri; + } + + /** + * Sets the value of the uri property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setUri(String value) { + this.uri = value; + } + + public boolean isSetUri() { + return (this.uri!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java b/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java index f0b54cb180..4dd5021adc 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_OfficeArtExtensionList complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_OfficeArtExtensionList">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_OfficeArtExtensionList"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_OfficeArtExtensionList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "ext" -}) -public class CTOfficeArtExtensionList { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected List ext; - - /** - * Gets the value of the ext property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the ext property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getExt().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTOfficeArtExtension } - * - * - */ - public List getExt() { - if (ext == null) { - ext = new ArrayList(); - } - return this.ext; - } - - public boolean isSetExt() { - return ((this.ext!= null)&&(!this.ext.isEmpty())); - } - - public void unsetExt() { - this.ext = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_OfficeArtExtensionList complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_OfficeArtExtensionList">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_OfficeArtExtensionList"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_OfficeArtExtensionList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "ext" +}) +public class CTOfficeArtExtensionList { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected List ext; + + /** + * Gets the value of the ext property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ext property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getExt().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTOfficeArtExtension } + * + * + */ + public List getExt() { + if (ext == null) { + ext = new ArrayList(); + } + return this.ext; + } + + public boolean isSetExt() { + return ((this.ext!= null)&&(!this.ext.isEmpty())); + } + + public void unsetExt() { + this.ext = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2D.java index 25fcd49235..6b1ba02729 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2D.java @@ -1,303 +1,303 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElements; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <choice maxOccurs="unbounded" minOccurs="0">
- *         <element name="close" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DClose"/>
- *         <element name="moveTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DMoveTo"/>
- *         <element name="lnTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DLineTo"/>
- *         <element name="arcTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DArcTo"/>
- *         <element name="quadBezTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DQuadBezierTo"/>
- *         <element name="cubicBezTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DCubicBezierTo"/>
- *       </choice>
- *       <attribute name="w" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" default="0" />
- *       <attribute name="h" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" default="0" />
- *       <attribute name="fill" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PathFillMode" default="norm" />
- *       <attribute name="stroke" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" />
- *       <attribute name="extrusionOk" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "closeOrMoveToOrLnTo" -}) -public class CTPath2D { - - @XmlElements({ - @XmlElement(name = "lnTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DLineTo.class), - @XmlElement(name = "close", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DClose.class), - @XmlElement(name = "cubicBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DCubicBezierTo.class), - @XmlElement(name = "quadBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DQuadBezierTo.class), - @XmlElement(name = "arcTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DArcTo.class), - @XmlElement(name = "moveTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DMoveTo.class) - }) - protected List closeOrMoveToOrLnTo; - @XmlAttribute - protected Long w; - @XmlAttribute - protected Long h; - @XmlAttribute - protected STPathFillMode fill; - @XmlAttribute - protected Boolean stroke; - @XmlAttribute - protected Boolean extrusionOk; - - /** - * Gets the value of the closeOrMoveToOrLnTo property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the closeOrMoveToOrLnTo property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getCloseOrMoveToOrLnTo().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTPath2DLineTo } - * {@link CTPath2DClose } - * {@link CTPath2DCubicBezierTo } - * {@link CTPath2DQuadBezierTo } - * {@link CTPath2DArcTo } - * {@link CTPath2DMoveTo } - * - * - */ - public List getCloseOrMoveToOrLnTo() { - if (closeOrMoveToOrLnTo == null) { - closeOrMoveToOrLnTo = new ArrayList(); - } - return this.closeOrMoveToOrLnTo; - } - - public boolean isSetCloseOrMoveToOrLnTo() { - return ((this.closeOrMoveToOrLnTo!= null)&&(!this.closeOrMoveToOrLnTo.isEmpty())); - } - - public void unsetCloseOrMoveToOrLnTo() { - this.closeOrMoveToOrLnTo = null; - } - - /** - * Gets the value of the w property. - * - * @return - * possible object is - * {@link Long } - * - */ - public long getW() { - if (w == null) { - return 0L; - } else { - return w; - } - } - - /** - * Sets the value of the w property. - * - * @param value - * allowed object is - * {@link Long } - * - */ - public void setW(long value) { - this.w = value; - } - - public boolean isSetW() { - return (this.w!= null); - } - - public void unsetW() { - this.w = null; - } - - /** - * Gets the value of the h property. - * - * @return - * possible object is - * {@link Long } - * - */ - public long getH() { - if (h == null) { - return 0L; - } else { - return h; - } - } - - /** - * Sets the value of the h property. - * - * @param value - * allowed object is - * {@link Long } - * - */ - public void setH(long value) { - this.h = value; - } - - public boolean isSetH() { - return (this.h!= null); - } - - public void unsetH() { - this.h = null; - } - - /** - * Gets the value of the fill property. - * - * @return - * possible object is - * {@link STPathFillMode } - * - */ - public STPathFillMode getFill() { - if (fill == null) { - return STPathFillMode.NORM; - } else { - return fill; - } - } - - /** - * Sets the value of the fill property. - * - * @param value - * allowed object is - * {@link STPathFillMode } - * - */ - public void setFill(STPathFillMode value) { - this.fill = value; - } - - public boolean isSetFill() { - return (this.fill!= null); - } - - /** - * Gets the value of the stroke property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isStroke() { - if (stroke == null) { - return true; - } else { - return stroke; - } - } - - /** - * Sets the value of the stroke property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setStroke(boolean value) { - this.stroke = value; - } - - public boolean isSetStroke() { - return (this.stroke!= null); - } - - public void unsetStroke() { - this.stroke = null; - } - - /** - * Gets the value of the extrusionOk property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isExtrusionOk() { - if (extrusionOk == null) { - return true; - } else { - return extrusionOk; - } - } - - /** - * Sets the value of the extrusionOk property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setExtrusionOk(boolean value) { - this.extrusionOk = value; - } - - public boolean isSetExtrusionOk() { - return (this.extrusionOk!= null); - } - - public void unsetExtrusionOk() { - this.extrusionOk = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <choice maxOccurs="unbounded" minOccurs="0">
+ *         <element name="close" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DClose"/>
+ *         <element name="moveTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DMoveTo"/>
+ *         <element name="lnTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DLineTo"/>
+ *         <element name="arcTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DArcTo"/>
+ *         <element name="quadBezTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DQuadBezierTo"/>
+ *         <element name="cubicBezTo" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2DCubicBezierTo"/>
+ *       </choice>
+ *       <attribute name="w" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" default="0" />
+ *       <attribute name="h" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" default="0" />
+ *       <attribute name="fill" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PathFillMode" default="norm" />
+ *       <attribute name="stroke" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" />
+ *       <attribute name="extrusionOk" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "closeOrMoveToOrLnTo" +}) +public class CTPath2D { + + @XmlElements({ + @XmlElement(name = "lnTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DLineTo.class), + @XmlElement(name = "close", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DClose.class), + @XmlElement(name = "cubicBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DCubicBezierTo.class), + @XmlElement(name = "quadBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DQuadBezierTo.class), + @XmlElement(name = "arcTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DArcTo.class), + @XmlElement(name = "moveTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DMoveTo.class) + }) + protected List closeOrMoveToOrLnTo; + @XmlAttribute + protected Long w; + @XmlAttribute + protected Long h; + @XmlAttribute + protected STPathFillMode fill; + @XmlAttribute + protected Boolean stroke; + @XmlAttribute + protected Boolean extrusionOk; + + /** + * Gets the value of the closeOrMoveToOrLnTo property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the closeOrMoveToOrLnTo property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getCloseOrMoveToOrLnTo().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTPath2DLineTo } + * {@link CTPath2DClose } + * {@link CTPath2DCubicBezierTo } + * {@link CTPath2DQuadBezierTo } + * {@link CTPath2DArcTo } + * {@link CTPath2DMoveTo } + * + * + */ + public List getCloseOrMoveToOrLnTo() { + if (closeOrMoveToOrLnTo == null) { + closeOrMoveToOrLnTo = new ArrayList(); + } + return this.closeOrMoveToOrLnTo; + } + + public boolean isSetCloseOrMoveToOrLnTo() { + return ((this.closeOrMoveToOrLnTo!= null)&&(!this.closeOrMoveToOrLnTo.isEmpty())); + } + + public void unsetCloseOrMoveToOrLnTo() { + this.closeOrMoveToOrLnTo = null; + } + + /** + * Gets the value of the w property. + * + * @return + * possible object is + * {@link Long } + * + */ + public long getW() { + if (w == null) { + return 0L; + } else { + return w; + } + } + + /** + * Sets the value of the w property. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setW(long value) { + this.w = value; + } + + public boolean isSetW() { + return (this.w!= null); + } + + public void unsetW() { + this.w = null; + } + + /** + * Gets the value of the h property. + * + * @return + * possible object is + * {@link Long } + * + */ + public long getH() { + if (h == null) { + return 0L; + } else { + return h; + } + } + + /** + * Sets the value of the h property. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setH(long value) { + this.h = value; + } + + public boolean isSetH() { + return (this.h!= null); + } + + public void unsetH() { + this.h = null; + } + + /** + * Gets the value of the fill property. + * + * @return + * possible object is + * {@link STPathFillMode } + * + */ + public STPathFillMode getFill() { + if (fill == null) { + return STPathFillMode.NORM; + } else { + return fill; + } + } + + /** + * Sets the value of the fill property. + * + * @param value + * allowed object is + * {@link STPathFillMode } + * + */ + public void setFill(STPathFillMode value) { + this.fill = value; + } + + public boolean isSetFill() { + return (this.fill!= null); + } + + /** + * Gets the value of the stroke property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isStroke() { + if (stroke == null) { + return true; + } else { + return stroke; + } + } + + /** + * Sets the value of the stroke property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setStroke(boolean value) { + this.stroke = value; + } + + public boolean isSetStroke() { + return (this.stroke!= null); + } + + public void unsetStroke() { + this.stroke = null; + } + + /** + * Gets the value of the extrusionOk property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isExtrusionOk() { + if (extrusionOk == null) { + return true; + } else { + return extrusionOk; + } + } + + /** + * Sets the value of the extrusionOk property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setExtrusionOk(boolean value) { + this.extrusionOk = value; + } + + public boolean isSetExtrusionOk() { + return (this.extrusionOk!= null); + } + + public void unsetExtrusionOk() { + this.extrusionOk = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java index a4c325aa1f..1b12259df5 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java @@ -1,171 +1,171 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2DArcTo complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2DArcTo">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="wR" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="hR" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="stAng" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
- *       <attribute name="swAng" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2DArcTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPath2DArcTo { - - @XmlAttribute(name = "wR", required = true) - protected String wr; - @XmlAttribute(name = "hR", required = true) - protected String hr; - @XmlAttribute(required = true) - protected String stAng; - @XmlAttribute(required = true) - protected String swAng; - - /** - * Gets the value of the wr property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getWR() { - return wr; - } - - /** - * Sets the value of the wr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setWR(String value) { - this.wr = value; - } - - public boolean isSetWR() { - return (this.wr!= null); - } - - /** - * Gets the value of the hr property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getHR() { - return hr; - } - - /** - * Sets the value of the hr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setHR(String value) { - this.hr = value; - } - - public boolean isSetHR() { - return (this.hr!= null); - } - - /** - * Gets the value of the stAng property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getStAng() { - return stAng; - } - - /** - * Sets the value of the stAng property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setStAng(String value) { - this.stAng = value; - } - - public boolean isSetStAng() { - return (this.stAng!= null); - } - - /** - * Gets the value of the swAng property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSwAng() { - return swAng; - } - - /** - * Sets the value of the swAng property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSwAng(String value) { - this.swAng = value; - } - - public boolean isSetSwAng() { - return (this.swAng!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2DArcTo complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2DArcTo">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="wR" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="hR" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="stAng" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
+ *       <attribute name="swAng" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2DArcTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPath2DArcTo { + + @XmlAttribute(name = "wR", required = true) + protected String wr; + @XmlAttribute(name = "hR", required = true) + protected String hr; + @XmlAttribute(required = true) + protected String stAng; + @XmlAttribute(required = true) + protected String swAng; + + /** + * Gets the value of the wr property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getWR() { + return wr; + } + + /** + * Sets the value of the wr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setWR(String value) { + this.wr = value; + } + + public boolean isSetWR() { + return (this.wr!= null); + } + + /** + * Gets the value of the hr property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getHR() { + return hr; + } + + /** + * Sets the value of the hr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setHR(String value) { + this.hr = value; + } + + public boolean isSetHR() { + return (this.hr!= null); + } + + /** + * Gets the value of the stAng property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getStAng() { + return stAng; + } + + /** + * Sets the value of the stAng property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setStAng(String value) { + this.stAng = value; + } + + public boolean isSetStAng() { + return (this.stAng!= null); + } + + /** + * Gets the value of the swAng property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSwAng() { + return swAng; + } + + /** + * Sets the value of the swAng property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSwAng(String value) { + this.swAng = value; + } + + public boolean isSetSwAng() { + return (this.swAng!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2DClose.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DClose.java index a60f98bb67..ca9dfebdfb 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2DClose.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DClose.java @@ -1,46 +1,46 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2DClose complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2DClose">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2DClose", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPath2DClose { - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2DClose complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2DClose">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2DClose", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPath2DClose { + + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java index e1818fa5db..b6042366fb 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2DCubicBezierTo complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2DCubicBezierTo">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D" maxOccurs="3" minOccurs="3"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2DCubicBezierTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "pt" -}) -public class CTPath2DCubicBezierTo { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected List pt; - - /** - * Gets the value of the pt property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the pt property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getPt().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTAdjPoint2D } - * - * - */ - public List getPt() { - if (pt == null) { - pt = new ArrayList(); - } - return this.pt; - } - - public boolean isSetPt() { - return ((this.pt!= null)&&(!this.pt.isEmpty())); - } - - public void unsetPt() { - this.pt = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2DCubicBezierTo complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2DCubicBezierTo">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D" maxOccurs="3" minOccurs="3"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2DCubicBezierTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "pt" +}) +public class CTPath2DCubicBezierTo { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected List pt; + + /** + * Gets the value of the pt property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the pt property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPt().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTAdjPoint2D } + * + * + */ + public List getPt() { + if (pt == null) { + pt = new ArrayList(); + } + return this.pt; + } + + public boolean isSetPt() { + return ((this.pt!= null)&&(!this.pt.isEmpty())); + } + + public void unsetPt() { + this.pt = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java index 9c6d1b39a8..3512cef7cf 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java @@ -1,82 +1,82 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2DLineTo complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2DLineTo">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2DLineTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "pt" -}) -public class CTPath2DLineTo { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTAdjPoint2D pt; - - /** - * Gets the value of the pt property. - * - * @return - * possible object is - * {@link CTAdjPoint2D } - * - */ - public CTAdjPoint2D getPt() { - return pt; - } - - /** - * Sets the value of the pt property. - * - * @param value - * allowed object is - * {@link CTAdjPoint2D } - * - */ - public void setPt(CTAdjPoint2D value) { - this.pt = value; - } - - public boolean isSetPt() { - return (this.pt!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2DLineTo complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2DLineTo">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2DLineTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "pt" +}) +public class CTPath2DLineTo { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTAdjPoint2D pt; + + /** + * Gets the value of the pt property. + * + * @return + * possible object is + * {@link CTAdjPoint2D } + * + */ + public CTAdjPoint2D getPt() { + return pt; + } + + /** + * Sets the value of the pt property. + * + * @param value + * allowed object is + * {@link CTAdjPoint2D } + * + */ + public void setPt(CTAdjPoint2D value) { + this.pt = value; + } + + public boolean isSetPt() { + return (this.pt!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2DList.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DList.java index cd31a0ba57..4abc906eb0 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2DList.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DList.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2DList complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2DList">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="path" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2D" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2DList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "path" -}) -public class CTPath2DList { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected List path; - - /** - * Gets the value of the path property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the path property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getPath().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTPath2D } - * - * - */ - public List getPath() { - if (path == null) { - path = new ArrayList(); - } - return this.path; - } - - public boolean isSetPath() { - return ((this.path!= null)&&(!this.path.isEmpty())); - } - - public void unsetPath() { - this.path = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2DList complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2DList">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="path" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Path2D" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2DList", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "path" +}) +public class CTPath2DList { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected List path; + + /** + * Gets the value of the path property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the path property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPath().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTPath2D } + * + * + */ + public List getPath() { + if (path == null) { + path = new ArrayList(); + } + return this.path; + } + + public boolean isSetPath() { + return ((this.path!= null)&&(!this.path.isEmpty())); + } + + public void unsetPath() { + this.path = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java index f5e210f768..25685e7104 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java @@ -1,82 +1,82 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2DMoveTo complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2DMoveTo">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2DMoveTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "pt" -}) -public class CTPath2DMoveTo { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTAdjPoint2D pt; - - /** - * Gets the value of the pt property. - * - * @return - * possible object is - * {@link CTAdjPoint2D } - * - */ - public CTAdjPoint2D getPt() { - return pt; - } - - /** - * Sets the value of the pt property. - * - * @param value - * allowed object is - * {@link CTAdjPoint2D } - * - */ - public void setPt(CTAdjPoint2D value) { - this.pt = value; - } - - public boolean isSetPt() { - return (this.pt!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2DMoveTo complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2DMoveTo">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2DMoveTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "pt" +}) +public class CTPath2DMoveTo { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTAdjPoint2D pt; + + /** + * Gets the value of the pt property. + * + * @return + * possible object is + * {@link CTAdjPoint2D } + * + */ + public CTAdjPoint2D getPt() { + return pt; + } + + /** + * Sets the value of the pt property. + * + * @param value + * allowed object is + * {@link CTAdjPoint2D } + * + */ + public void setPt(CTAdjPoint2D value) { + this.pt = value; + } + + public boolean isSetPt() { + return (this.pt!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java index b588775245..06f3082047 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Path2DQuadBezierTo complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Path2DQuadBezierTo">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D" maxOccurs="2" minOccurs="2"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Path2DQuadBezierTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "pt" -}) -public class CTPath2DQuadBezierTo { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected List pt; - - /** - * Gets the value of the pt property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the pt property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getPt().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link CTAdjPoint2D } - * - * - */ - public List getPt() { - if (pt == null) { - pt = new ArrayList(); - } - return this.pt; - } - - public boolean isSetPt() { - return ((this.pt!= null)&&(!this.pt.isEmpty())); - } - - public void unsetPt() { - this.pt = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Path2DQuadBezierTo complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Path2DQuadBezierTo">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pt" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D" maxOccurs="2" minOccurs="2"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Path2DQuadBezierTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "pt" +}) +public class CTPath2DQuadBezierTo { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected List pt; + + /** + * Gets the value of the pt property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the pt property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPt().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link CTAdjPoint2D } + * + * + */ + public List getPt() { + if (pt == null) { + pt = new ArrayList(); + } + return this.pt; + } + + public boolean isSetPt() { + return ((this.pt!= null)&&(!this.pt.isEmpty())); + } + + public void unsetPt() { + this.pt = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTPercentage.java index 7ca8c1fec5..b343f30968 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPercentage.java @@ -1,70 +1,70 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Percentage complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Percentage">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Percentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPercentage { - - @XmlAttribute(required = true) - protected int val; - - /** - * Gets the value of the val property. - * - */ - public int getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - */ - public void setVal(int value) { - this.val = value; - } - - public boolean isSetVal() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Percentage complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Percentage">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Percentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPercentage { + + @XmlAttribute(required = true) + protected int val; + + /** + * Gets the value of the val property. + * + */ + public int getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + */ + public void setVal(int value) { + this.val = value; + } + + public boolean isSetVal() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPoint2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPoint2D.java index ae87986035..947685ea4c 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPoint2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPoint2D.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Point2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Point2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="x" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *       <attribute name="y" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Point2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPoint2D { - - @XmlAttribute(required = true) - protected long x; - @XmlAttribute(required = true) - protected long y; - - /** - * Gets the value of the x property. - * - */ - public long getX() { - return x; - } - - /** - * Sets the value of the x property. - * - */ - public void setX(long value) { - this.x = value; - } - - public boolean isSetX() { - return true; - } - - /** - * Gets the value of the y property. - * - */ - public long getY() { - return y; - } - - /** - * Sets the value of the y property. - * - */ - public void setY(long value) { - this.y = value; - } - - public boolean isSetY() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Point2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Point2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="x" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *       <attribute name="y" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Point2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPoint2D { + + @XmlAttribute(required = true) + protected long x; + @XmlAttribute(required = true) + protected long y; + + /** + * Gets the value of the x property. + * + */ + public long getX() { + return x; + } + + /** + * Sets the value of the x property. + * + */ + public void setX(long value) { + this.x = value; + } + + public boolean isSetX() { + return true; + } + + /** + * Gets the value of the y property. + * + */ + public long getY() { + return y; + } + + /** + * Sets the value of the y property. + * + */ + public void setY(long value) { + this.y = value; + } + + public boolean isSetY() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPoint3D.java b/src/java/org/apache/poi/sl/draw/binding/CTPoint3D.java index e14c6ba4f2..853bcd375b 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPoint3D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPoint3D.java @@ -1,116 +1,116 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Point3D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Point3D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="x" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *       <attribute name="y" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *       <attribute name="z" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Point3D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPoint3D { - - @XmlAttribute(required = true) - protected long x; - @XmlAttribute(required = true) - protected long y; - @XmlAttribute(required = true) - protected long z; - - /** - * Gets the value of the x property. - * - */ - public long getX() { - return x; - } - - /** - * Sets the value of the x property. - * - */ - public void setX(long value) { - this.x = value; - } - - public boolean isSetX() { - return true; - } - - /** - * Gets the value of the y property. - * - */ - public long getY() { - return y; - } - - /** - * Sets the value of the y property. - * - */ - public void setY(long value) { - this.y = value; - } - - public boolean isSetY() { - return true; - } - - /** - * Gets the value of the z property. - * - */ - public long getZ() { - return z; - } - - /** - * Sets the value of the z property. - * - */ - public void setZ(long value) { - this.z = value; - } - - public boolean isSetZ() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Point3D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Point3D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="x" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *       <attribute name="y" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *       <attribute name="z" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Point3D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPoint3D { + + @XmlAttribute(required = true) + protected long x; + @XmlAttribute(required = true) + protected long y; + @XmlAttribute(required = true) + protected long z; + + /** + * Gets the value of the x property. + * + */ + public long getX() { + return x; + } + + /** + * Sets the value of the x property. + * + */ + public void setX(long value) { + this.x = value; + } + + public boolean isSetX() { + return true; + } + + /** + * Gets the value of the y property. + * + */ + public long getY() { + return y; + } + + /** + * Sets the value of the y property. + * + */ + public void setY(long value) { + this.y = value; + } + + public boolean isSetY() { + return true; + } + + /** + * Gets the value of the z property. + * + */ + public long getZ() { + return z; + } + + /** + * Sets the value of the z property. + * + */ + public void setZ(long value) { + this.z = value; + } + + public boolean isSetZ() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java b/src/java/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java index 9547ca9881..661fe48749 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java @@ -1,273 +1,273 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; - - -/** - *

Java class for CT_PolarAdjustHandle complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PolarAdjustHandle">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="pos" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
- *       </sequence>
- *       <attribute name="gdRefR" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
- *       <attribute name="minR" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="maxR" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="gdRefAng" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
- *       <attribute name="minAng" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
- *       <attribute name="maxAng" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PolarAdjustHandle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "pos" -}) -public class CTPolarAdjustHandle { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTAdjPoint2D pos; - @XmlAttribute - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - protected String gdRefR; - @XmlAttribute - protected String minR; - @XmlAttribute - protected String maxR; - @XmlAttribute - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - protected String gdRefAng; - @XmlAttribute - protected String minAng; - @XmlAttribute - protected String maxAng; - - /** - * Gets the value of the pos property. - * - * @return - * possible object is - * {@link CTAdjPoint2D } - * - */ - public CTAdjPoint2D getPos() { - return pos; - } - - /** - * Sets the value of the pos property. - * - * @param value - * allowed object is - * {@link CTAdjPoint2D } - * - */ - public void setPos(CTAdjPoint2D value) { - this.pos = value; - } - - public boolean isSetPos() { - return (this.pos!= null); - } - - /** - * Gets the value of the gdRefR property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGdRefR() { - return gdRefR; - } - - /** - * Sets the value of the gdRefR property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGdRefR(String value) { - this.gdRefR = value; - } - - public boolean isSetGdRefR() { - return (this.gdRefR!= null); - } - - /** - * Gets the value of the minR property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMinR() { - return minR; - } - - /** - * Sets the value of the minR property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMinR(String value) { - this.minR = value; - } - - public boolean isSetMinR() { - return (this.minR!= null); - } - - /** - * Gets the value of the maxR property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMaxR() { - return maxR; - } - - /** - * Sets the value of the maxR property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMaxR(String value) { - this.maxR = value; - } - - public boolean isSetMaxR() { - return (this.maxR!= null); - } - - /** - * Gets the value of the gdRefAng property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGdRefAng() { - return gdRefAng; - } - - /** - * Sets the value of the gdRefAng property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGdRefAng(String value) { - this.gdRefAng = value; - } - - public boolean isSetGdRefAng() { - return (this.gdRefAng!= null); - } - - /** - * Gets the value of the minAng property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMinAng() { - return minAng; - } - - /** - * Sets the value of the minAng property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMinAng(String value) { - this.minAng = value; - } - - public boolean isSetMinAng() { - return (this.minAng!= null); - } - - /** - * Gets the value of the maxAng property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMaxAng() { - return maxAng; - } - - /** - * Sets the value of the maxAng property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMaxAng(String value) { - this.maxAng = value; - } - - public boolean isSetMaxAng() { - return (this.maxAng!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + +/** + *

Java class for CT_PolarAdjustHandle complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PolarAdjustHandle">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pos" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
+ *       </sequence>
+ *       <attribute name="gdRefR" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
+ *       <attribute name="minR" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="maxR" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="gdRefAng" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
+ *       <attribute name="minAng" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
+ *       <attribute name="maxAng" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjAngle" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PolarAdjustHandle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "pos" +}) +public class CTPolarAdjustHandle { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTAdjPoint2D pos; + @XmlAttribute + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + protected String gdRefR; + @XmlAttribute + protected String minR; + @XmlAttribute + protected String maxR; + @XmlAttribute + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + protected String gdRefAng; + @XmlAttribute + protected String minAng; + @XmlAttribute + protected String maxAng; + + /** + * Gets the value of the pos property. + * + * @return + * possible object is + * {@link CTAdjPoint2D } + * + */ + public CTAdjPoint2D getPos() { + return pos; + } + + /** + * Sets the value of the pos property. + * + * @param value + * allowed object is + * {@link CTAdjPoint2D } + * + */ + public void setPos(CTAdjPoint2D value) { + this.pos = value; + } + + public boolean isSetPos() { + return (this.pos!= null); + } + + /** + * Gets the value of the gdRefR property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getGdRefR() { + return gdRefR; + } + + /** + * Sets the value of the gdRefR property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setGdRefR(String value) { + this.gdRefR = value; + } + + public boolean isSetGdRefR() { + return (this.gdRefR!= null); + } + + /** + * Gets the value of the minR property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMinR() { + return minR; + } + + /** + * Sets the value of the minR property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMinR(String value) { + this.minR = value; + } + + public boolean isSetMinR() { + return (this.minR!= null); + } + + /** + * Gets the value of the maxR property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMaxR() { + return maxR; + } + + /** + * Sets the value of the maxR property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMaxR(String value) { + this.maxR = value; + } + + public boolean isSetMaxR() { + return (this.maxR!= null); + } + + /** + * Gets the value of the gdRefAng property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getGdRefAng() { + return gdRefAng; + } + + /** + * Sets the value of the gdRefAng property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setGdRefAng(String value) { + this.gdRefAng = value; + } + + public boolean isSetGdRefAng() { + return (this.gdRefAng!= null); + } + + /** + * Gets the value of the minAng property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMinAng() { + return minAng; + } + + /** + * Sets the value of the minAng property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMinAng(String value) { + this.minAng = value; + } + + public boolean isSetMinAng() { + return (this.minAng!= null); + } + + /** + * Gets the value of the maxAng property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMaxAng() { + return maxAng; + } + + /** + * Sets the value of the maxAng property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMaxAng(String value) { + this.maxAng = value; + } + + public boolean isSetMaxAng() { + return (this.maxAng!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java index 94348d9bff..5c181ced02 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java @@ -1,70 +1,70 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_PositiveFixedAngle complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PositiveFixedAngle">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PositiveFixedAngle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPositiveFixedAngle { - - @XmlAttribute(required = true) - protected int val; - - /** - * Gets the value of the val property. - * - */ - public int getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - */ - public void setVal(int value) { - this.val = value; - } - - public boolean isSetVal() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_PositiveFixedAngle complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PositiveFixedAngle">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PositiveFixedAngle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPositiveFixedAngle { + + @XmlAttribute(required = true) + protected int val; + + /** + * Gets the value of the val property. + * + */ + public int getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + */ + public void setVal(int value) { + this.val = value; + } + + public boolean isSetVal() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java index de659159e1..3c60d7f1dc 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java @@ -1,70 +1,70 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_PositiveFixedPercentage complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PositiveFixedPercentage">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedPercentage" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PositiveFixedPercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPositiveFixedPercentage { - - @XmlAttribute(required = true) - protected int val; - - /** - * Gets the value of the val property. - * - */ - public int getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - */ - public void setVal(int value) { - this.val = value; - } - - public boolean isSetVal() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_PositiveFixedPercentage complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PositiveFixedPercentage">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedPercentage" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PositiveFixedPercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPositiveFixedPercentage { + + @XmlAttribute(required = true) + protected int val; + + /** + * Gets the value of the val property. + * + */ + public int getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + */ + public void setVal(int value) { + this.val = value; + } + + public boolean isSetVal() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPositivePercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTPositivePercentage.java index 7b377e1444..60961f6ac6 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPositivePercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositivePercentage.java @@ -1,70 +1,70 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_PositivePercentage complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PositivePercentage">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositivePercentage" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PositivePercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPositivePercentage { - - @XmlAttribute(required = true) - protected int val; - - /** - * Gets the value of the val property. - * - */ - public int getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - */ - public void setVal(int value) { - this.val = value; - } - - public boolean isSetVal() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_PositivePercentage complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PositivePercentage">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositivePercentage" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PositivePercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPositivePercentage { + + @XmlAttribute(required = true) + protected int val; + + /** + * Gets the value of the val property. + * + */ + public int getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + */ + public void setVal(int value) { + this.val = value; + } + + public boolean isSetVal() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java index 210fd925a5..7ee53eb307 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_PositiveSize2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PositiveSize2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="cx" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" />
- *       <attribute name="cy" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PositiveSize2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTPositiveSize2D { - - @XmlAttribute(required = true) - protected long cx; - @XmlAttribute(required = true) - protected long cy; - - /** - * Gets the value of the cx property. - * - */ - public long getCx() { - return cx; - } - - /** - * Sets the value of the cx property. - * - */ - public void setCx(long value) { - this.cx = value; - } - - public boolean isSetCx() { - return true; - } - - /** - * Gets the value of the cy property. - * - */ - public long getCy() { - return cy; - } - - /** - * Sets the value of the cy property. - * - */ - public void setCy(long value) { - this.cy = value; - } - - public boolean isSetCy() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_PositiveSize2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PositiveSize2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="cx" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" />
+ *       <attribute name="cy" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveCoordinate" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PositiveSize2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTPositiveSize2D { + + @XmlAttribute(required = true) + protected long cx; + @XmlAttribute(required = true) + protected long cy; + + /** + * Gets the value of the cx property. + * + */ + public long getCx() { + return cx; + } + + /** + * Sets the value of the cx property. + * + */ + public void setCx(long value) { + this.cx = value; + } + + public boolean isSetCx() { + return true; + } + + /** + * Gets the value of the cy property. + * + */ + public long getCy() { + return cy; + } + + /** + * Sets the value of the cy property. + * + */ + public void setCy(long value) { + this.cy = value; + } + + public boolean isSetCy() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPresetColor.java b/src/java/org/apache/poi/sl/draw/binding/CTPresetColor.java index 595d1c5968..b1bc857f53 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPresetColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPresetColor.java @@ -1,183 +1,183 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlElementRefs; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_PresetColor complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PresetColor">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="val" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PresetColorVal" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PresetColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "egColorTransform" -}) -public class CTPresetColor { - - @XmlElementRefs({ - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) - }) - protected List> egColorTransform; - @XmlAttribute - protected STPresetColorVal val; - - /** - * Gets the value of the egColorTransform property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the egColorTransform property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getEGColorTransform().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * - * - */ - public List> getEGColorTransform() { - if (egColorTransform == null) { - egColorTransform = new ArrayList>(); - } - return this.egColorTransform; - } - - public boolean isSetEGColorTransform() { - return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); - } - - public void unsetEGColorTransform() { - this.egColorTransform = null; - } - - /** - * Gets the value of the val property. - * - * @return - * possible object is - * {@link STPresetColorVal } - * - */ - public STPresetColorVal getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - * @param value - * allowed object is - * {@link STPresetColorVal } - * - */ - public void setVal(STPresetColorVal value) { - this.val = value; - } - - public boolean isSetVal() { - return (this.val!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_PresetColor complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PresetColor">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="val" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PresetColorVal" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PresetColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "egColorTransform" +}) +public class CTPresetColor { + + @XmlElementRefs({ + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + }) + protected List> egColorTransform; + @XmlAttribute + protected STPresetColorVal val; + + /** + * Gets the value of the egColorTransform property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egColorTransform property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEGColorTransform().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * + * + */ + public List> getEGColorTransform() { + if (egColorTransform == null) { + egColorTransform = new ArrayList>(); + } + return this.egColorTransform; + } + + public boolean isSetEGColorTransform() { + return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); + } + + public void unsetEGColorTransform() { + this.egColorTransform = null; + } + + /** + * Gets the value of the val property. + * + * @return + * possible object is + * {@link STPresetColorVal } + * + */ + public STPresetColorVal getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + * @param value + * allowed object is + * {@link STPresetColorVal } + * + */ + public void setVal(STPresetColorVal value) { + this.val = value; + } + + public boolean isSetVal() { + return (this.val!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java index 234bbd95f9..a560e640c2 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java @@ -1,114 +1,114 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_PresetGeometry2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PresetGeometry2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="avLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="prst" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_ShapeType" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PresetGeometry2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "avLst" -}) -public class CTPresetGeometry2D { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTGeomGuideList avLst; - @XmlAttribute(required = true) - protected STShapeType prst; - - /** - * Gets the value of the avLst property. - * - * @return - * possible object is - * {@link CTGeomGuideList } - * - */ - public CTGeomGuideList getAvLst() { - return avLst; - } - - /** - * Sets the value of the avLst property. - * - * @param value - * allowed object is - * {@link CTGeomGuideList } - * - */ - public void setAvLst(CTGeomGuideList value) { - this.avLst = value; - } - - public boolean isSetAvLst() { - return (this.avLst!= null); - } - - /** - * Gets the value of the prst property. - * - * @return - * possible object is - * {@link STShapeType } - * - */ - public STShapeType getPrst() { - return prst; - } - - /** - * Sets the value of the prst property. - * - * @param value - * allowed object is - * {@link STShapeType } - * - */ - public void setPrst(STShapeType value) { - this.prst = value; - } - - public boolean isSetPrst() { - return (this.prst!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_PresetGeometry2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PresetGeometry2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="avLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="prst" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_ShapeType" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PresetGeometry2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "avLst" +}) +public class CTPresetGeometry2D { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTGeomGuideList avLst; + @XmlAttribute(required = true) + protected STShapeType prst; + + /** + * Gets the value of the avLst property. + * + * @return + * possible object is + * {@link CTGeomGuideList } + * + */ + public CTGeomGuideList getAvLst() { + return avLst; + } + + /** + * Sets the value of the avLst property. + * + * @param value + * allowed object is + * {@link CTGeomGuideList } + * + */ + public void setAvLst(CTGeomGuideList value) { + this.avLst = value; + } + + public boolean isSetAvLst() { + return (this.avLst!= null); + } + + /** + * Gets the value of the prst property. + * + * @return + * possible object is + * {@link STShapeType } + * + */ + public STShapeType getPrst() { + return prst; + } + + /** + * Sets the value of the prst property. + * + * @param value + * allowed object is + * {@link STShapeType } + * + */ + public void setPrst(STShapeType value) { + this.prst = value; + } + + public boolean isSetPrst() { + return (this.prst!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTPresetTextShape.java b/src/java/org/apache/poi/sl/draw/binding/CTPresetTextShape.java index 0a6135fc90..052a765d9d 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTPresetTextShape.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPresetTextShape.java @@ -1,114 +1,114 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_PresetTextShape complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_PresetTextShape">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="avLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="prst" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_TextShapeType" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_PresetTextShape", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "avLst" -}) -public class CTPresetTextShape { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTGeomGuideList avLst; - @XmlAttribute(required = true) - protected STTextShapeType prst; - - /** - * Gets the value of the avLst property. - * - * @return - * possible object is - * {@link CTGeomGuideList } - * - */ - public CTGeomGuideList getAvLst() { - return avLst; - } - - /** - * Sets the value of the avLst property. - * - * @param value - * allowed object is - * {@link CTGeomGuideList } - * - */ - public void setAvLst(CTGeomGuideList value) { - this.avLst = value; - } - - public boolean isSetAvLst() { - return (this.avLst!= null); - } - - /** - * Gets the value of the prst property. - * - * @return - * possible object is - * {@link STTextShapeType } - * - */ - public STTextShapeType getPrst() { - return prst; - } - - /** - * Sets the value of the prst property. - * - * @param value - * allowed object is - * {@link STTextShapeType } - * - */ - public void setPrst(STTextShapeType value) { - this.prst = value; - } - - public boolean isSetPrst() { - return (this.prst!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_PresetTextShape complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_PresetTextShape">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="avLst" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_GeomGuideList" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="prst" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_TextShapeType" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_PresetTextShape", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "avLst" +}) +public class CTPresetTextShape { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTGeomGuideList avLst; + @XmlAttribute(required = true) + protected STTextShapeType prst; + + /** + * Gets the value of the avLst property. + * + * @return + * possible object is + * {@link CTGeomGuideList } + * + */ + public CTGeomGuideList getAvLst() { + return avLst; + } + + /** + * Sets the value of the avLst property. + * + * @param value + * allowed object is + * {@link CTGeomGuideList } + * + */ + public void setAvLst(CTGeomGuideList value) { + this.avLst = value; + } + + public boolean isSetAvLst() { + return (this.avLst!= null); + } + + /** + * Gets the value of the prst property. + * + * @return + * possible object is + * {@link STTextShapeType } + * + */ + public STTextShapeType getPrst() { + return prst; + } + + /** + * Sets the value of the prst property. + * + * @param value + * allowed object is + * {@link STTextShapeType } + * + */ + public void setPrst(STTextShapeType value) { + this.prst = value; + } + + public boolean isSetPrst() { + return (this.prst!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTRatio.java b/src/java/org/apache/poi/sl/draw/binding/CTRatio.java index 4a61b88cb9..05df06b7ae 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTRatio.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTRatio.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Ratio complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Ratio">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="n" use="required" type="{http://www.w3.org/2001/XMLSchema}long" />
- *       <attribute name="d" use="required" type="{http://www.w3.org/2001/XMLSchema}long" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Ratio", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTRatio { - - @XmlAttribute(required = true) - protected long n; - @XmlAttribute(required = true) - protected long d; - - /** - * Gets the value of the n property. - * - */ - public long getN() { - return n; - } - - /** - * Sets the value of the n property. - * - */ - public void setN(long value) { - this.n = value; - } - - public boolean isSetN() { - return true; - } - - /** - * Gets the value of the d property. - * - */ - public long getD() { - return d; - } - - /** - * Sets the value of the d property. - * - */ - public void setD(long value) { - this.d = value; - } - - public boolean isSetD() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Ratio complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Ratio">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="n" use="required" type="{http://www.w3.org/2001/XMLSchema}long" />
+ *       <attribute name="d" use="required" type="{http://www.w3.org/2001/XMLSchema}long" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Ratio", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTRatio { + + @XmlAttribute(required = true) + protected long n; + @XmlAttribute(required = true) + protected long d; + + /** + * Gets the value of the n property. + * + */ + public long getN() { + return n; + } + + /** + * Sets the value of the n property. + * + */ + public void setN(long value) { + this.n = value; + } + + public boolean isSetN() { + return true; + } + + /** + * Gets the value of the d property. + * + */ + public long getD() { + return d; + } + + /** + * Sets the value of the d property. + * + */ + public void setD(long value) { + this.d = value; + } + + public boolean isSetD() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTRelativeRect.java b/src/java/org/apache/poi/sl/draw/binding/CTRelativeRect.java index a8b82c4744..ed340ed2d4 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTRelativeRect.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTRelativeRect.java @@ -1,203 +1,203 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_RelativeRect complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_RelativeRect">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="l" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
- *       <attribute name="t" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
- *       <attribute name="r" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
- *       <attribute name="b" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_RelativeRect", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTRelativeRect { - - @XmlAttribute - protected Integer l; - @XmlAttribute - protected Integer t; - @XmlAttribute - protected Integer r; - @XmlAttribute - protected Integer b; - - /** - * Gets the value of the l property. - * - * @return - * possible object is - * {@link Integer } - * - */ - public int getL() { - if (l == null) { - return 0; - } else { - return l; - } - } - - /** - * Sets the value of the l property. - * - * @param value - * allowed object is - * {@link Integer } - * - */ - public void setL(int value) { - this.l = value; - } - - public boolean isSetL() { - return (this.l!= null); - } - - public void unsetL() { - this.l = null; - } - - /** - * Gets the value of the t property. - * - * @return - * possible object is - * {@link Integer } - * - */ - public int getT() { - if (t == null) { - return 0; - } else { - return t; - } - } - - /** - * Sets the value of the t property. - * - * @param value - * allowed object is - * {@link Integer } - * - */ - public void setT(int value) { - this.t = value; - } - - public boolean isSetT() { - return (this.t!= null); - } - - public void unsetT() { - this.t = null; - } - - /** - * Gets the value of the r property. - * - * @return - * possible object is - * {@link Integer } - * - */ - public int getR() { - if (r == null) { - return 0; - } else { - return r; - } - } - - /** - * Sets the value of the r property. - * - * @param value - * allowed object is - * {@link Integer } - * - */ - public void setR(int value) { - this.r = value; - } - - public boolean isSetR() { - return (this.r!= null); - } - - public void unsetR() { - this.r = null; - } - - /** - * Gets the value of the b property. - * - * @return - * possible object is - * {@link Integer } - * - */ - public int getB() { - if (b == null) { - return 0; - } else { - return b; - } - } - - /** - * Sets the value of the b property. - * - * @param value - * allowed object is - * {@link Integer } - * - */ - public void setB(int value) { - this.b = value; - } - - public boolean isSetB() { - return (this.b!= null); - } - - public void unsetB() { - this.b = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_RelativeRect complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_RelativeRect">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="l" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
+ *       <attribute name="t" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
+ *       <attribute name="r" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
+ *       <attribute name="b" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" default="0" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_RelativeRect", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTRelativeRect { + + @XmlAttribute + protected Integer l; + @XmlAttribute + protected Integer t; + @XmlAttribute + protected Integer r; + @XmlAttribute + protected Integer b; + + /** + * Gets the value of the l property. + * + * @return + * possible object is + * {@link Integer } + * + */ + public int getL() { + if (l == null) { + return 0; + } else { + return l; + } + } + + /** + * Sets the value of the l property. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setL(int value) { + this.l = value; + } + + public boolean isSetL() { + return (this.l!= null); + } + + public void unsetL() { + this.l = null; + } + + /** + * Gets the value of the t property. + * + * @return + * possible object is + * {@link Integer } + * + */ + public int getT() { + if (t == null) { + return 0; + } else { + return t; + } + } + + /** + * Sets the value of the t property. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setT(int value) { + this.t = value; + } + + public boolean isSetT() { + return (this.t!= null); + } + + public void unsetT() { + this.t = null; + } + + /** + * Gets the value of the r property. + * + * @return + * possible object is + * {@link Integer } + * + */ + public int getR() { + if (r == null) { + return 0; + } else { + return r; + } + } + + /** + * Sets the value of the r property. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setR(int value) { + this.r = value; + } + + public boolean isSetR() { + return (this.r!= null); + } + + public void unsetR() { + this.r = null; + } + + /** + * Gets the value of the b property. + * + * @return + * possible object is + * {@link Integer } + * + */ + public int getB() { + if (b == null) { + return 0; + } else { + return b; + } + } + + /** + * Sets the value of the b property. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setB(int value) { + this.b = value; + } + + public boolean isSetB() { + return (this.b!= null); + } + + public void unsetB() { + this.b = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTSRgbColor.java b/src/java/org/apache/poi/sl/draw/binding/CTSRgbColor.java index 36cefe532a..be4d49b276 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTSRgbColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSRgbColor.java @@ -1,186 +1,186 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlElementRefs; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.HexBinaryAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; - - -/** - *

Java class for CT_SRgbColor complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_SRgbColor">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_HexBinary3" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_SRgbColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "egColorTransform" -}) -public class CTSRgbColor { - - @XmlElementRefs({ - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) - }) - protected List> egColorTransform; - @XmlAttribute(required = true) - @XmlJavaTypeAdapter(HexBinaryAdapter.class) - protected byte[] val; - - /** - * Gets the value of the egColorTransform property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the egColorTransform property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getEGColorTransform().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * - * - */ - public List> getEGColorTransform() { - if (egColorTransform == null) { - egColorTransform = new ArrayList>(); - } - return this.egColorTransform; - } - - public boolean isSetEGColorTransform() { - return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); - } - - public void unsetEGColorTransform() { - this.egColorTransform = null; - } - - /** - * Gets the value of the val property. - * - * @return - * possible object is - * {@link String } - * - */ - public byte[] getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setVal(byte[] value) { - this.val = (value != null) ? value.clone() : null; - } - - public boolean isSetVal() { - return (this.val!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.HexBinaryAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + +/** + *

Java class for CT_SRgbColor complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_SRgbColor">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_HexBinary3" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_SRgbColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "egColorTransform" +}) +public class CTSRgbColor { + + @XmlElementRefs({ + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + }) + protected List> egColorTransform; + @XmlAttribute(required = true) + @XmlJavaTypeAdapter(HexBinaryAdapter.class) + protected byte[] val; + + /** + * Gets the value of the egColorTransform property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egColorTransform property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEGColorTransform().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * + * + */ + public List> getEGColorTransform() { + if (egColorTransform == null) { + egColorTransform = new ArrayList>(); + } + return this.egColorTransform; + } + + public boolean isSetEGColorTransform() { + return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); + } + + public void unsetEGColorTransform() { + this.egColorTransform = null; + } + + /** + * Gets the value of the val property. + * + * @return + * possible object is + * {@link String } + * + */ + public byte[] getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVal(byte[] value) { + this.val = (value != null) ? value.clone() : null; + } + + public boolean isSetVal() { + return (this.val!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTScRgbColor.java b/src/java/org/apache/poi/sl/draw/binding/CTScRgbColor.java index 2cb3986eb1..7e8292149f 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTScRgbColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTScRgbColor.java @@ -1,221 +1,221 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlElementRefs; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_ScRgbColor complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_ScRgbColor">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="r" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
- *       <attribute name="g" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
- *       <attribute name="b" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_ScRgbColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "egColorTransform" -}) -public class CTScRgbColor { - - @XmlElementRefs({ - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) - }) - protected List> egColorTransform; - @XmlAttribute(required = true) - protected int r; - @XmlAttribute(required = true) - protected int g; - @XmlAttribute(required = true) - protected int b; - - /** - * Gets the value of the egColorTransform property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the egColorTransform property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getEGColorTransform().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * - * - */ - public List> getEGColorTransform() { - if (egColorTransform == null) { - egColorTransform = new ArrayList>(); - } - return this.egColorTransform; - } - - public boolean isSetEGColorTransform() { - return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); - } - - public void unsetEGColorTransform() { - this.egColorTransform = null; - } - - /** - * Gets the value of the r property. - * - */ - public int getR() { - return r; - } - - /** - * Sets the value of the r property. - * - */ - public void setR(int value) { - this.r = value; - } - - public boolean isSetR() { - return true; - } - - /** - * Gets the value of the g property. - * - */ - public int getG() { - return g; - } - - /** - * Sets the value of the g property. - * - */ - public void setG(int value) { - this.g = value; - } - - public boolean isSetG() { - return true; - } - - /** - * Gets the value of the b property. - * - */ - public int getB() { - return b; - } - - /** - * Sets the value of the b property. - * - */ - public void setB(int value) { - this.b = value; - } - - public boolean isSetB() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_ScRgbColor complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_ScRgbColor">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="r" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
+ *       <attribute name="g" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
+ *       <attribute name="b" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Percentage" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_ScRgbColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "egColorTransform" +}) +public class CTScRgbColor { + + @XmlElementRefs({ + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + }) + protected List> egColorTransform; + @XmlAttribute(required = true) + protected int r; + @XmlAttribute(required = true) + protected int g; + @XmlAttribute(required = true) + protected int b; + + /** + * Gets the value of the egColorTransform property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egColorTransform property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEGColorTransform().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * + * + */ + public List> getEGColorTransform() { + if (egColorTransform == null) { + egColorTransform = new ArrayList>(); + } + return this.egColorTransform; + } + + public boolean isSetEGColorTransform() { + return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); + } + + public void unsetEGColorTransform() { + this.egColorTransform = null; + } + + /** + * Gets the value of the r property. + * + */ + public int getR() { + return r; + } + + /** + * Sets the value of the r property. + * + */ + public void setR(int value) { + this.r = value; + } + + public boolean isSetR() { + return true; + } + + /** + * Gets the value of the g property. + * + */ + public int getG() { + return g; + } + + /** + * Sets the value of the g property. + * + */ + public void setG(int value) { + this.g = value; + } + + public boolean isSetG() { + return true; + } + + /** + * Gets the value of the b property. + * + */ + public int getB() { + return b; + } + + /** + * Sets the value of the b property. + * + */ + public void setB(int value) { + this.b = value; + } + + public boolean isSetB() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTScale2D.java b/src/java/org/apache/poi/sl/draw/binding/CTScale2D.java index 2e8eba1940..ed94b74adc 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTScale2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTScale2D.java @@ -1,114 +1,114 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Scale2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Scale2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="sx" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Ratio"/>
- *         <element name="sy" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Ratio"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Scale2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "sx", - "sy" -}) -public class CTScale2D { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTRatio sx; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTRatio sy; - - /** - * Gets the value of the sx property. - * - * @return - * possible object is - * {@link CTRatio } - * - */ - public CTRatio getSx() { - return sx; - } - - /** - * Sets the value of the sx property. - * - * @param value - * allowed object is - * {@link CTRatio } - * - */ - public void setSx(CTRatio value) { - this.sx = value; - } - - public boolean isSetSx() { - return (this.sx!= null); - } - - /** - * Gets the value of the sy property. - * - * @return - * possible object is - * {@link CTRatio } - * - */ - public CTRatio getSy() { - return sy; - } - - /** - * Sets the value of the sy property. - * - * @param value - * allowed object is - * {@link CTRatio } - * - */ - public void setSy(CTRatio value) { - this.sy = value; - } - - public boolean isSetSy() { - return (this.sy!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Scale2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Scale2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="sx" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Ratio"/>
+ *         <element name="sy" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Ratio"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Scale2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "sx", + "sy" +}) +public class CTScale2D { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTRatio sx; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTRatio sy; + + /** + * Gets the value of the sx property. + * + * @return + * possible object is + * {@link CTRatio } + * + */ + public CTRatio getSx() { + return sx; + } + + /** + * Sets the value of the sx property. + * + * @param value + * allowed object is + * {@link CTRatio } + * + */ + public void setSx(CTRatio value) { + this.sx = value; + } + + public boolean isSetSx() { + return (this.sx!= null); + } + + /** + * Gets the value of the sy property. + * + * @return + * possible object is + * {@link CTRatio } + * + */ + public CTRatio getSy() { + return sy; + } + + /** + * Sets the value of the sy property. + * + * @param value + * allowed object is + * {@link CTRatio } + * + */ + public void setSy(CTRatio value) { + this.sy = value; + } + + public boolean isSetSy() { + return (this.sy!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTSchemeColor.java b/src/java/org/apache/poi/sl/draw/binding/CTSchemeColor.java index ac8fb5c27d..fcafd606fc 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTSchemeColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSchemeColor.java @@ -1,183 +1,183 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlElementRefs; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_SchemeColor complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_SchemeColor">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_SchemeColorVal" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_SchemeColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "egColorTransform" -}) -public class CTSchemeColor { - - @XmlElementRefs({ - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) - }) - protected List> egColorTransform; - @XmlAttribute(required = true) - protected STSchemeColorVal val; - - /** - * Gets the value of the egColorTransform property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the egColorTransform property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getEGColorTransform().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * - * - */ - public List> getEGColorTransform() { - if (egColorTransform == null) { - egColorTransform = new ArrayList>(); - } - return this.egColorTransform; - } - - public boolean isSetEGColorTransform() { - return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); - } - - public void unsetEGColorTransform() { - this.egColorTransform = null; - } - - /** - * Gets the value of the val property. - * - * @return - * possible object is - * {@link STSchemeColorVal } - * - */ - public STSchemeColorVal getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - * @param value - * allowed object is - * {@link STSchemeColorVal } - * - */ - public void setVal(STSchemeColorVal value) { - this.val = value; - } - - public boolean isSetVal() { - return (this.val!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_SchemeColor complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_SchemeColor">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_SchemeColorVal" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_SchemeColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "egColorTransform" +}) +public class CTSchemeColor { + + @XmlElementRefs({ + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + }) + protected List> egColorTransform; + @XmlAttribute(required = true) + protected STSchemeColorVal val; + + /** + * Gets the value of the egColorTransform property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egColorTransform property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEGColorTransform().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * + * + */ + public List> getEGColorTransform() { + if (egColorTransform == null) { + egColorTransform = new ArrayList>(); + } + return this.egColorTransform; + } + + public boolean isSetEGColorTransform() { + return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); + } + + public void unsetEGColorTransform() { + this.egColorTransform = null; + } + + /** + * Gets the value of the val property. + * + * @return + * possible object is + * {@link STSchemeColorVal } + * + */ + public STSchemeColorVal getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + * @param value + * allowed object is + * {@link STSchemeColorVal } + * + */ + public void setVal(STSchemeColorVal value) { + this.val = value; + } + + public boolean isSetVal() { + return (this.val!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTSphereCoords.java b/src/java/org/apache/poi/sl/draw/binding/CTSphereCoords.java index 7f03d0dac2..4921935abc 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTSphereCoords.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSphereCoords.java @@ -1,116 +1,116 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_SphereCoords complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_SphereCoords">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="lat" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
- *       <attribute name="lon" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
- *       <attribute name="rev" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_SphereCoords", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTSphereCoords { - - @XmlAttribute(required = true) - protected int lat; - @XmlAttribute(required = true) - protected int lon; - @XmlAttribute(required = true) - protected int rev; - - /** - * Gets the value of the lat property. - * - */ - public int getLat() { - return lat; - } - - /** - * Sets the value of the lat property. - * - */ - public void setLat(int value) { - this.lat = value; - } - - public boolean isSetLat() { - return true; - } - - /** - * Gets the value of the lon property. - * - */ - public int getLon() { - return lon; - } - - /** - * Sets the value of the lon property. - * - */ - public void setLon(int value) { - this.lon = value; - } - - public boolean isSetLon() { - return true; - } - - /** - * Gets the value of the rev property. - * - */ - public int getRev() { - return rev; - } - - /** - * Sets the value of the rev property. - * - */ - public void setRev(int value) { - this.rev = value; - } - - public boolean isSetRev() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_SphereCoords complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_SphereCoords">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="lat" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
+ *       <attribute name="lon" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
+ *       <attribute name="rev" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_PositiveFixedAngle" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_SphereCoords", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTSphereCoords { + + @XmlAttribute(required = true) + protected int lat; + @XmlAttribute(required = true) + protected int lon; + @XmlAttribute(required = true) + protected int rev; + + /** + * Gets the value of the lat property. + * + */ + public int getLat() { + return lat; + } + + /** + * Sets the value of the lat property. + * + */ + public void setLat(int value) { + this.lat = value; + } + + public boolean isSetLat() { + return true; + } + + /** + * Gets the value of the lon property. + * + */ + public int getLon() { + return lon; + } + + /** + * Sets the value of the lon property. + * + */ + public void setLon(int value) { + this.lon = value; + } + + public boolean isSetLon() { + return true; + } + + /** + * Gets the value of the rev property. + * + */ + public int getRev() { + return rev; + } + + /** + * Sets the value of the rev property. + * + */ + public void setRev(int value) { + this.rev = value; + } + + public boolean isSetRev() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTSystemColor.java b/src/java/org/apache/poi/sl/draw/binding/CTSystemColor.java index 1300f87f56..b5657ff21b 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTSystemColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSystemColor.java @@ -1,219 +1,219 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlElementRefs; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.HexBinaryAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; - - -/** - *

Java class for CT_SystemColor complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_SystemColor">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_SystemColorVal" />
- *       <attribute name="lastClr" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_HexBinary3" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_SystemColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "egColorTransform" -}) -public class CTSystemColor { - - @XmlElementRefs({ - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) - }) - protected List> egColorTransform; - @XmlAttribute(required = true) - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - protected String val; - @XmlAttribute - @XmlJavaTypeAdapter(HexBinaryAdapter.class) - protected byte[] lastClr; - - /** - * Gets the value of the egColorTransform property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the egColorTransform property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getEGColorTransform().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * - * - */ - public List> getEGColorTransform() { - if (egColorTransform == null) { - egColorTransform = new ArrayList>(); - } - return this.egColorTransform; - } - - public boolean isSetEGColorTransform() { - return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); - } - - public void unsetEGColorTransform() { - this.egColorTransform = null; - } - - /** - * Gets the value of the val property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getVal() { - return val; - } - - /** - * Sets the value of the val property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setVal(String value) { - this.val = value; - } - - public boolean isSetVal() { - return (this.val!= null); - } - - /** - * Gets the value of the lastClr property. - * - * @return - * possible object is - * {@link String } - * - */ - public byte[] getLastClr() { - return lastClr; - } - - /** - * Sets the value of the lastClr property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setLastClr(byte[] value) { - this.lastClr = (value != null) ? value.clone() : null; - } - - public boolean isSetLastClr() { - return (this.lastClr!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlElementRefs; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.HexBinaryAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + +/** + *

Java class for CT_SystemColor complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_SystemColor">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <group ref="{http://schemas.openxmlformats.org/drawingml/2006/main}EG_ColorTransform" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="val" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_SystemColorVal" />
+ *       <attribute name="lastClr" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_HexBinary3" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_SystemColor", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "egColorTransform" +}) +public class CTSystemColor { + + @XmlElementRefs({ + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + }) + protected List> egColorTransform; + @XmlAttribute(required = true) + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + protected String val; + @XmlAttribute + @XmlJavaTypeAdapter(HexBinaryAdapter.class) + protected byte[] lastClr; + + /** + * Gets the value of the egColorTransform property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egColorTransform property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEGColorTransform().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * + * + */ + public List> getEGColorTransform() { + if (egColorTransform == null) { + egColorTransform = new ArrayList>(); + } + return this.egColorTransform; + } + + public boolean isSetEGColorTransform() { + return ((this.egColorTransform!= null)&&(!this.egColorTransform.isEmpty())); + } + + public void unsetEGColorTransform() { + this.egColorTransform = null; + } + + /** + * Gets the value of the val property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVal() { + return val; + } + + /** + * Sets the value of the val property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVal(String value) { + this.val = value; + } + + public boolean isSetVal() { + return (this.val!= null); + } + + /** + * Gets the value of the lastClr property. + * + * @return + * possible object is + * {@link String } + * + */ + public byte[] getLastClr() { + return lastClr; + } + + /** + * Sets the value of the lastClr property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setLastClr(byte[] value) { + this.lastClr = (value != null) ? value.clone() : null; + } + + public boolean isSetLastClr() { + return (this.lastClr!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTTransform2D.java b/src/java/org/apache/poi/sl/draw/binding/CTTransform2D.java index dd1dcb501e..efe57bc087 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTTransform2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTTransform2D.java @@ -1,232 +1,232 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Transform2D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Transform2D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="off" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Point2D" minOccurs="0"/>
- *         <element name="ext" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PositiveSize2D" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="rot" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Angle" default="0" />
- *       <attribute name="flipH" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
- *       <attribute name="flipV" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Transform2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "off", - "ext" -}) -public class CTTransform2D { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTPoint2D off; - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") - protected CTPositiveSize2D ext; - @XmlAttribute - protected Integer rot; - @XmlAttribute - protected Boolean flipH; - @XmlAttribute - protected Boolean flipV; - - /** - * Gets the value of the off property. - * - * @return - * possible object is - * {@link CTPoint2D } - * - */ - public CTPoint2D getOff() { - return off; - } - - /** - * Sets the value of the off property. - * - * @param value - * allowed object is - * {@link CTPoint2D } - * - */ - public void setOff(CTPoint2D value) { - this.off = value; - } - - public boolean isSetOff() { - return (this.off!= null); - } - - /** - * Gets the value of the ext property. - * - * @return - * possible object is - * {@link CTPositiveSize2D } - * - */ - public CTPositiveSize2D getExt() { - return ext; - } - - /** - * Sets the value of the ext property. - * - * @param value - * allowed object is - * {@link CTPositiveSize2D } - * - */ - public void setExt(CTPositiveSize2D value) { - this.ext = value; - } - - public boolean isSetExt() { - return (this.ext!= null); - } - - /** - * Gets the value of the rot property. - * - * @return - * possible object is - * {@link Integer } - * - */ - public int getRot() { - if (rot == null) { - return 0; - } else { - return rot; - } - } - - /** - * Sets the value of the rot property. - * - * @param value - * allowed object is - * {@link Integer } - * - */ - public void setRot(int value) { - this.rot = value; - } - - public boolean isSetRot() { - return (this.rot!= null); - } - - public void unsetRot() { - this.rot = null; - } - - /** - * Gets the value of the flipH property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isFlipH() { - if (flipH == null) { - return false; - } else { - return flipH; - } - } - - /** - * Sets the value of the flipH property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setFlipH(boolean value) { - this.flipH = value; - } - - public boolean isSetFlipH() { - return (this.flipH!= null); - } - - public void unsetFlipH() { - this.flipH = null; - } - - /** - * Gets the value of the flipV property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public boolean isFlipV() { - if (flipV == null) { - return false; - } else { - return flipV; - } - } - - /** - * Sets the value of the flipV property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setFlipV(boolean value) { - this.flipV = value; - } - - public boolean isSetFlipV() { - return (this.flipV!= null); - } - - public void unsetFlipV() { - this.flipV = null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Transform2D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Transform2D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="off" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_Point2D" minOccurs="0"/>
+ *         <element name="ext" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_PositiveSize2D" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="rot" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Angle" default="0" />
+ *       <attribute name="flipH" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *       <attribute name="flipV" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Transform2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "off", + "ext" +}) +public class CTTransform2D { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTPoint2D off; + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") + protected CTPositiveSize2D ext; + @XmlAttribute + protected Integer rot; + @XmlAttribute + protected Boolean flipH; + @XmlAttribute + protected Boolean flipV; + + /** + * Gets the value of the off property. + * + * @return + * possible object is + * {@link CTPoint2D } + * + */ + public CTPoint2D getOff() { + return off; + } + + /** + * Sets the value of the off property. + * + * @param value + * allowed object is + * {@link CTPoint2D } + * + */ + public void setOff(CTPoint2D value) { + this.off = value; + } + + public boolean isSetOff() { + return (this.off!= null); + } + + /** + * Gets the value of the ext property. + * + * @return + * possible object is + * {@link CTPositiveSize2D } + * + */ + public CTPositiveSize2D getExt() { + return ext; + } + + /** + * Sets the value of the ext property. + * + * @param value + * allowed object is + * {@link CTPositiveSize2D } + * + */ + public void setExt(CTPositiveSize2D value) { + this.ext = value; + } + + public boolean isSetExt() { + return (this.ext!= null); + } + + /** + * Gets the value of the rot property. + * + * @return + * possible object is + * {@link Integer } + * + */ + public int getRot() { + if (rot == null) { + return 0; + } else { + return rot; + } + } + + /** + * Sets the value of the rot property. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setRot(int value) { + this.rot = value; + } + + public boolean isSetRot() { + return (this.rot!= null); + } + + public void unsetRot() { + this.rot = null; + } + + /** + * Gets the value of the flipH property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isFlipH() { + if (flipH == null) { + return false; + } else { + return flipH; + } + } + + /** + * Sets the value of the flipH property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setFlipH(boolean value) { + this.flipH = value; + } + + public boolean isSetFlipH() { + return (this.flipH!= null); + } + + public void unsetFlipH() { + this.flipH = null; + } + + /** + * Gets the value of the flipV property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public boolean isFlipV() { + if (flipV == null) { + return false; + } else { + return flipV; + } + } + + /** + * Sets the value of the flipV property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setFlipV(boolean value) { + this.flipV = value; + } + + public boolean isSetFlipV() { + return (this.flipV!= null); + } + + public void unsetFlipV() { + this.flipV = null; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTVector3D.java b/src/java/org/apache/poi/sl/draw/binding/CTVector3D.java index d7f744ba6c..cd97d6bc94 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTVector3D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTVector3D.java @@ -1,116 +1,116 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for CT_Vector3D complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_Vector3D">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <attribute name="dx" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *       <attribute name="dy" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *       <attribute name="dz" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_Vector3D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -public class CTVector3D { - - @XmlAttribute(required = true) - protected long dx; - @XmlAttribute(required = true) - protected long dy; - @XmlAttribute(required = true) - protected long dz; - - /** - * Gets the value of the dx property. - * - */ - public long getDx() { - return dx; - } - - /** - * Sets the value of the dx property. - * - */ - public void setDx(long value) { - this.dx = value; - } - - public boolean isSetDx() { - return true; - } - - /** - * Gets the value of the dy property. - * - */ - public long getDy() { - return dy; - } - - /** - * Sets the value of the dy property. - * - */ - public void setDy(long value) { - this.dy = value; - } - - public boolean isSetDy() { - return true; - } - - /** - * Gets the value of the dz property. - * - */ - public long getDz() { - return dz; - } - - /** - * Sets the value of the dz property. - * - */ - public void setDz(long value) { - this.dz = value; - } - - public boolean isSetDz() { - return true; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for CT_Vector3D complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_Vector3D">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="dx" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *       <attribute name="dy" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *       <attribute name="dz" use="required" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_Coordinate" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_Vector3D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +public class CTVector3D { + + @XmlAttribute(required = true) + protected long dx; + @XmlAttribute(required = true) + protected long dy; + @XmlAttribute(required = true) + protected long dz; + + /** + * Gets the value of the dx property. + * + */ + public long getDx() { + return dx; + } + + /** + * Sets the value of the dx property. + * + */ + public void setDx(long value) { + this.dx = value; + } + + public boolean isSetDx() { + return true; + } + + /** + * Gets the value of the dy property. + * + */ + public long getDy() { + return dy; + } + + /** + * Sets the value of the dy property. + * + */ + public void setDy(long value) { + this.dy = value; + } + + public boolean isSetDy() { + return true; + } + + /** + * Gets the value of the dz property. + * + */ + public long getDz() { + return dz; + } + + /** + * Sets the value of the dz property. + * + */ + public void setDz(long value) { + this.dz = value; + } + + public boolean isSetDz() { + return true; + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java b/src/java/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java index 2b22a58814..2942bb9ee0 100644 --- a/src/java/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java @@ -1,273 +1,273 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; - - -/** - *

Java class for CT_XYAdjustHandle complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="CT_XYAdjustHandle">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="pos" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
- *       </sequence>
- *       <attribute name="gdRefX" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
- *       <attribute name="minX" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="maxX" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="gdRefY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
- *       <attribute name="minY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *       <attribute name="maxY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "CT_XYAdjustHandle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { - "pos" -}) -public class CTXYAdjustHandle { - - @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) - protected CTAdjPoint2D pos; - @XmlAttribute - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - protected String gdRefX; - @XmlAttribute - protected String minX; - @XmlAttribute - protected String maxX; - @XmlAttribute - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - protected String gdRefY; - @XmlAttribute - protected String minY; - @XmlAttribute - protected String maxY; - - /** - * Gets the value of the pos property. - * - * @return - * possible object is - * {@link CTAdjPoint2D } - * - */ - public CTAdjPoint2D getPos() { - return pos; - } - - /** - * Sets the value of the pos property. - * - * @param value - * allowed object is - * {@link CTAdjPoint2D } - * - */ - public void setPos(CTAdjPoint2D value) { - this.pos = value; - } - - public boolean isSetPos() { - return (this.pos!= null); - } - - /** - * Gets the value of the gdRefX property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGdRefX() { - return gdRefX; - } - - /** - * Sets the value of the gdRefX property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGdRefX(String value) { - this.gdRefX = value; - } - - public boolean isSetGdRefX() { - return (this.gdRefX!= null); - } - - /** - * Gets the value of the minX property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMinX() { - return minX; - } - - /** - * Sets the value of the minX property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMinX(String value) { - this.minX = value; - } - - public boolean isSetMinX() { - return (this.minX!= null); - } - - /** - * Gets the value of the maxX property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMaxX() { - return maxX; - } - - /** - * Sets the value of the maxX property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMaxX(String value) { - this.maxX = value; - } - - public boolean isSetMaxX() { - return (this.maxX!= null); - } - - /** - * Gets the value of the gdRefY property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGdRefY() { - return gdRefY; - } - - /** - * Sets the value of the gdRefY property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGdRefY(String value) { - this.gdRefY = value; - } - - public boolean isSetGdRefY() { - return (this.gdRefY!= null); - } - - /** - * Gets the value of the minY property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMinY() { - return minY; - } - - /** - * Sets the value of the minY property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMinY(String value) { - this.minY = value; - } - - public boolean isSetMinY() { - return (this.minY!= null); - } - - /** - * Gets the value of the maxY property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMaxY() { - return maxY; - } - - /** - * Sets the value of the maxY property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMaxY(String value) { - this.maxY = value; - } - - public boolean isSetMaxY() { - return (this.maxY!= null); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + +/** + *

Java class for CT_XYAdjustHandle complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="CT_XYAdjustHandle">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pos" type="{http://schemas.openxmlformats.org/drawingml/2006/main}CT_AdjPoint2D"/>
+ *       </sequence>
+ *       <attribute name="gdRefX" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
+ *       <attribute name="minX" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="maxX" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="gdRefY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_GeomGuideName" />
+ *       <attribute name="minY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *       <attribute name="maxY" type="{http://schemas.openxmlformats.org/drawingml/2006/main}ST_AdjCoordinate" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CT_XYAdjustHandle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", propOrder = { + "pos" +}) +public class CTXYAdjustHandle { + + @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) + protected CTAdjPoint2D pos; + @XmlAttribute + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + protected String gdRefX; + @XmlAttribute + protected String minX; + @XmlAttribute + protected String maxX; + @XmlAttribute + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + protected String gdRefY; + @XmlAttribute + protected String minY; + @XmlAttribute + protected String maxY; + + /** + * Gets the value of the pos property. + * + * @return + * possible object is + * {@link CTAdjPoint2D } + * + */ + public CTAdjPoint2D getPos() { + return pos; + } + + /** + * Sets the value of the pos property. + * + * @param value + * allowed object is + * {@link CTAdjPoint2D } + * + */ + public void setPos(CTAdjPoint2D value) { + this.pos = value; + } + + public boolean isSetPos() { + return (this.pos!= null); + } + + /** + * Gets the value of the gdRefX property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getGdRefX() { + return gdRefX; + } + + /** + * Sets the value of the gdRefX property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setGdRefX(String value) { + this.gdRefX = value; + } + + public boolean isSetGdRefX() { + return (this.gdRefX!= null); + } + + /** + * Gets the value of the minX property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMinX() { + return minX; + } + + /** + * Sets the value of the minX property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMinX(String value) { + this.minX = value; + } + + public boolean isSetMinX() { + return (this.minX!= null); + } + + /** + * Gets the value of the maxX property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMaxX() { + return maxX; + } + + /** + * Sets the value of the maxX property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMaxX(String value) { + this.maxX = value; + } + + public boolean isSetMaxX() { + return (this.maxX!= null); + } + + /** + * Gets the value of the gdRefY property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getGdRefY() { + return gdRefY; + } + + /** + * Sets the value of the gdRefY property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setGdRefY(String value) { + this.gdRefY = value; + } + + public boolean isSetGdRefY() { + return (this.gdRefY!= null); + } + + /** + * Gets the value of the minY property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMinY() { + return minY; + } + + /** + * Sets the value of the minY property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMinY(String value) { + this.minY = value; + } + + public boolean isSetMinY() { + return (this.minY!= null); + } + + /** + * Gets the value of the maxY property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMaxY() { + return maxY; + } + + /** + * Sets the value of the maxY property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMaxY(String value) { + this.maxY = value; + } + + public boolean isSetMaxY() { + return (this.maxY!= null); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/ObjectFactory.java b/src/java/org/apache/poi/sl/draw/binding/ObjectFactory.java index 896fb24761..1a2e14db3a 100644 --- a/src/java/org/apache/poi/sl/draw/binding/ObjectFactory.java +++ b/src/java/org/apache/poi/sl/draw/binding/ObjectFactory.java @@ -1,2023 +1,2023 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlElementDecl; -import javax.xml.bind.annotation.XmlRegistry; -import javax.xml.namespace.QName; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the org.apache.poi.sl.draw.binding package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - private final static QName _CTSRgbColorAlpha_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alpha"); - private final static QName _CTSRgbColorLum_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lum"); - private final static QName _CTSRgbColorGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gamma"); - private final static QName _CTSRgbColorInvGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "invGamma"); - private final static QName _CTSRgbColorRedOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redOff"); - private final static QName _CTSRgbColorAlphaMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaMod"); - private final static QName _CTSRgbColorAlphaOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaOff"); - private final static QName _CTSRgbColorGreenOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenOff"); - private final static QName _CTSRgbColorRedMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redMod"); - private final static QName _CTSRgbColorHue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hue"); - private final static QName _CTSRgbColorSatOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satOff"); - private final static QName _CTSRgbColorGreenMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenMod"); - private final static QName _CTSRgbColorSat_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "sat"); - private final static QName _CTSRgbColorBlue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blue"); - private final static QName _CTSRgbColorRed_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "red"); - private final static QName _CTSRgbColorSatMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satMod"); - private final static QName _CTSRgbColorHueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueOff"); - private final static QName _CTSRgbColorBlueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueMod"); - private final static QName _CTSRgbColorShade_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "shade"); - private final static QName _CTSRgbColorLumMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumMod"); - private final static QName _CTSRgbColorInv_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "inv"); - private final static QName _CTSRgbColorLumOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumOff"); - private final static QName _CTSRgbColorTint_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tint"); - private final static QName _CTSRgbColorGreen_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "green"); - private final static QName _CTSRgbColorComp_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "comp"); - private final static QName _CTSRgbColorBlueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueOff"); - private final static QName _CTSRgbColorHueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueMod"); - private final static QName _CTSRgbColorGray_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gray"); - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.poi.sl.draw.binding - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link CTPositiveSize2D } - * - */ - public CTPositiveSize2D createCTPositiveSize2D() { - return new CTPositiveSize2D(); - } - - /** - * Create an instance of {@link CTSphereCoords } - * - */ - public CTSphereCoords createCTSphereCoords() { - return new CTSphereCoords(); - } - - /** - * Create an instance of {@link CTPositivePercentage } - * - */ - public CTPositivePercentage createCTPositivePercentage() { - return new CTPositivePercentage(); - } - - /** - * Create an instance of {@link CTAdjPoint2D } - * - */ - public CTAdjPoint2D createCTAdjPoint2D() { - return new CTAdjPoint2D(); - } - - /** - * Create an instance of {@link CTPath2DCubicBezierTo } - * - */ - public CTPath2DCubicBezierTo createCTPath2DCubicBezierTo() { - return new CTPath2DCubicBezierTo(); - } - - /** - * Create an instance of {@link CTEmbeddedWAVAudioFile } - * - */ - public CTEmbeddedWAVAudioFile createCTEmbeddedWAVAudioFile() { - return new CTEmbeddedWAVAudioFile(); - } - - /** - * Create an instance of {@link CTPresetGeometry2D } - * - */ - public CTPresetGeometry2D createCTPresetGeometry2D() { - return new CTPresetGeometry2D(); - } - - /** - * Create an instance of {@link CTSchemeColor } - * - */ - public CTSchemeColor createCTSchemeColor() { - return new CTSchemeColor(); - } - - /** - * Create an instance of {@link CTInverseTransform } - * - */ - public CTInverseTransform createCTInverseTransform() { - return new CTInverseTransform(); - } - - /** - * Create an instance of {@link CTScRgbColor } - * - */ - public CTScRgbColor createCTScRgbColor() { - return new CTScRgbColor(); - } - - /** - * Create an instance of {@link CTPositiveFixedAngle } - * - */ - public CTPositiveFixedAngle createCTPositiveFixedAngle() { - return new CTPositiveFixedAngle(); - } - - /** - * Create an instance of {@link CTInverseGammaTransform } - * - */ - public CTInverseGammaTransform createCTInverseGammaTransform() { - return new CTInverseGammaTransform(); - } - - /** - * Create an instance of {@link CTColorMRU } - * - */ - public CTColorMRU createCTColorMRU() { - return new CTColorMRU(); - } - - /** - * Create an instance of {@link CTPath2DArcTo } - * - */ - public CTPath2DArcTo createCTPath2DArcTo() { - return new CTPath2DArcTo(); - } - - /** - * Create an instance of {@link CTSystemColor } - * - */ - public CTSystemColor createCTSystemColor() { - return new CTSystemColor(); - } - - /** - * Create an instance of {@link CTGroupTransform2D } - * - */ - public CTGroupTransform2D createCTGroupTransform2D() { - return new CTGroupTransform2D(); - } - - /** - * Create an instance of {@link CTPoint2D } - * - */ - public CTPoint2D createCTPoint2D() { - return new CTPoint2D(); - } - - /** - * Create an instance of {@link CTGeomRect } - * - */ - public CTGeomRect createCTGeomRect() { - return new CTGeomRect(); - } - - /** - * Create an instance of {@link CTScale2D } - * - */ - public CTScale2D createCTScale2D() { - return new CTScale2D(); - } - - /** - * Create an instance of {@link CTGeomGuide } - * - */ - public CTGeomGuide createCTGeomGuide() { - return new CTGeomGuide(); - } - - /** - * Create an instance of {@link CTXYAdjustHandle } - * - */ - public CTXYAdjustHandle createCTXYAdjustHandle() { - return new CTXYAdjustHandle(); - } - - /** - * Create an instance of {@link CTCustomGeometry2D } - * - */ - public CTCustomGeometry2D createCTCustomGeometry2D() { - return new CTCustomGeometry2D(); - } - - /** - * Create an instance of {@link CTOfficeArtExtension } - * - */ - public CTOfficeArtExtension createCTOfficeArtExtension() { - return new CTOfficeArtExtension(); - } - - /** - * Create an instance of {@link CTGrayscaleTransform } - * - */ - public CTGrayscaleTransform createCTGrayscaleTransform() { - return new CTGrayscaleTransform(); - } - - /** - * Create an instance of {@link CTPath2DClose } - * - */ - public CTPath2DClose createCTPath2DClose() { - return new CTPath2DClose(); - } - - /** - * Create an instance of {@link CTComplementTransform } - * - */ - public CTComplementTransform createCTComplementTransform() { - return new CTComplementTransform(); - } - - /** - * Create an instance of {@link CTPoint3D } - * - */ - public CTPoint3D createCTPoint3D() { - return new CTPoint3D(); - } - - /** - * Create an instance of {@link CTPositiveFixedPercentage } - * - */ - public CTPositiveFixedPercentage createCTPositiveFixedPercentage() { - return new CTPositiveFixedPercentage(); - } - - /** - * Create an instance of {@link CTPath2D } - * - */ - public CTPath2D createCTPath2D() { - return new CTPath2D(); - } - - /** - * Create an instance of {@link CTAdjustHandleList } - * - */ - public CTAdjustHandleList createCTAdjustHandleList() { - return new CTAdjustHandleList(); - } - - /** - * Create an instance of {@link CTConnectionSiteList } - * - */ - public CTConnectionSiteList createCTConnectionSiteList() { - return new CTConnectionSiteList(); - } - - /** - * Create an instance of {@link CTPresetTextShape } - * - */ - public CTPresetTextShape createCTPresetTextShape() { - return new CTPresetTextShape(); - } - - /** - * Create an instance of {@link CTSRgbColor } - * - */ - public CTSRgbColor createCTSRgbColor() { - return new CTSRgbColor(); - } - - /** - * Create an instance of {@link CTPath2DMoveTo } - * - */ - public CTPath2DMoveTo createCTPath2DMoveTo() { - return new CTPath2DMoveTo(); - } - - /** - * Create an instance of {@link CTRelativeRect } - * - */ - public CTRelativeRect createCTRelativeRect() { - return new CTRelativeRect(); - } - - /** - * Create an instance of {@link CTPath2DList } - * - */ - public CTPath2DList createCTPath2DList() { - return new CTPath2DList(); - } - - /** - * Create an instance of {@link CTPolarAdjustHandle } - * - */ - public CTPolarAdjustHandle createCTPolarAdjustHandle() { - return new CTPolarAdjustHandle(); - } - - /** - * Create an instance of {@link CTPercentage } - * - */ - public CTPercentage createCTPercentage() { - return new CTPercentage(); - } - - /** - * Create an instance of {@link CTHslColor } - * - */ - public CTHslColor createCTHslColor() { - return new CTHslColor(); - } - - /** - * Create an instance of {@link CTRatio } - * - */ - public CTRatio createCTRatio() { - return new CTRatio(); - } - - /** - * Create an instance of {@link CTGeomGuideList } - * - */ - public CTGeomGuideList createCTGeomGuideList() { - return new CTGeomGuideList(); - } - - /** - * Create an instance of {@link CTTransform2D } - * - */ - public CTTransform2D createCTTransform2D() { - return new CTTransform2D(); - } - - /** - * Create an instance of {@link CTGammaTransform } - * - */ - public CTGammaTransform createCTGammaTransform() { - return new CTGammaTransform(); - } - - /** - * Create an instance of {@link CTPath2DQuadBezierTo } - * - */ - public CTPath2DQuadBezierTo createCTPath2DQuadBezierTo() { - return new CTPath2DQuadBezierTo(); - } - - /** - * Create an instance of {@link CTAngle } - * - */ - public CTAngle createCTAngle() { - return new CTAngle(); - } - - /** - * Create an instance of {@link CTConnectionSite } - * - */ - public CTConnectionSite createCTConnectionSite() { - return new CTConnectionSite(); - } - - /** - * Create an instance of {@link CTHyperlink } - * - */ - public CTHyperlink createCTHyperlink() { - return new CTHyperlink(); - } - - /** - * Create an instance of {@link CTFixedPercentage } - * - */ - public CTFixedPercentage createCTFixedPercentage() { - return new CTFixedPercentage(); - } - - /** - * Create an instance of {@link CTPath2DLineTo } - * - */ - public CTPath2DLineTo createCTPath2DLineTo() { - return new CTPath2DLineTo(); - } - - /** - * Create an instance of {@link CTColor } - * - */ - public CTColor createCTColor() { - return new CTColor(); - } - - /** - * Create an instance of {@link CTPresetColor } - * - */ - public CTPresetColor createCTPresetColor() { - return new CTPresetColor(); - } - - /** - * Create an instance of {@link CTVector3D } - * - */ - public CTVector3D createCTVector3D() { - return new CTVector3D(); - } - - /** - * Create an instance of {@link CTOfficeArtExtensionList } - * - */ - public CTOfficeArtExtensionList createCTOfficeArtExtensionList() { - return new CTOfficeArtExtensionList(); - } - - /** - * Create an instance of {@link CTConnection } - * - */ - public CTConnection createCTConnection() { - return new CTConnection(); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorLum(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorRedOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorRedMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorSatOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorSat(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorBlue(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorRed(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorSatMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorHueOff(CTAngle value) { - return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorLumMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorInv(CTInverseTransform value) { - return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorLumOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorGreen(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorComp(CTComplementTransform value) { - return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorLum(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorRedOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorRedMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorSatOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorBlue(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorSat(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorRed(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorSatMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorHueOff(CTAngle value) { - return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorLumMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorInv(CTInverseTransform value) { - return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorLumOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGreen(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorComp(CTComplementTransform value) { - return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorLum(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorRedOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorRedMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorSatOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorBlue(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorSat(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorRed(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorSatMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorHueOff(CTAngle value) { - return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorLumMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorInv(CTInverseTransform value) { - return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorLumOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorGreen(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorComp(CTComplementTransform value) { - return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorLum(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorRedOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorRedMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorSatOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorSat(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorBlue(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorRed(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorSatMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorHueOff(CTAngle value) { - return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorLumMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorInv(CTInverseTransform value) { - return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorLumOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGreen(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorComp(CTComplementTransform value) { - return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTHslColor.class) - public JAXBElement createCTHslColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTHslColor.class) - public JAXBElement createCTHslColorLum(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTHslColor.class) - public JAXBElement createCTHslColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTHslColor.class) - public JAXBElement createCTHslColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorRedOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTHslColor.class) - public JAXBElement createCTHslColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorRedMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorSatOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTHslColor.class) - public JAXBElement createCTHslColorBlue(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTHslColor.class) - public JAXBElement createCTHslColorSat(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTHslColor.class) - public JAXBElement createCTHslColorRed(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorSatMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorHueOff(CTAngle value) { - return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTHslColor.class) - public JAXBElement createCTHslColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorLumMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTHslColor.class) - public JAXBElement createCTHslColorInv(CTInverseTransform value) { - return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorLumOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTHslColor.class) - public JAXBElement createCTHslColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTHslColor.class) - public JAXBElement createCTHslColorGreen(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTHslColor.class) - public JAXBElement createCTHslColorComp(CTComplementTransform value) { - return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTHslColor.class) - public JAXBElement createCTHslColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorLum(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorRedOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorRedMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorSatOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorBlue(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorSat(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorRed(CTPercentage value) { - return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorSatMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorHueOff(CTAngle value) { - return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorLumMod(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorInv(CTInverseTransform value) { - return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorLumOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGreen(CTPercentage value) { - return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorComp(CTComplementTransform value) { - return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTPresetColor.class, value); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the org.apache.poi.sl.draw.binding package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _CTSRgbColorAlpha_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alpha"); + private final static QName _CTSRgbColorLum_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lum"); + private final static QName _CTSRgbColorGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gamma"); + private final static QName _CTSRgbColorInvGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "invGamma"); + private final static QName _CTSRgbColorRedOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redOff"); + private final static QName _CTSRgbColorAlphaMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaMod"); + private final static QName _CTSRgbColorAlphaOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaOff"); + private final static QName _CTSRgbColorGreenOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenOff"); + private final static QName _CTSRgbColorRedMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redMod"); + private final static QName _CTSRgbColorHue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hue"); + private final static QName _CTSRgbColorSatOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satOff"); + private final static QName _CTSRgbColorGreenMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenMod"); + private final static QName _CTSRgbColorSat_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "sat"); + private final static QName _CTSRgbColorBlue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blue"); + private final static QName _CTSRgbColorRed_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "red"); + private final static QName _CTSRgbColorSatMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satMod"); + private final static QName _CTSRgbColorHueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueOff"); + private final static QName _CTSRgbColorBlueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueMod"); + private final static QName _CTSRgbColorShade_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "shade"); + private final static QName _CTSRgbColorLumMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumMod"); + private final static QName _CTSRgbColorInv_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "inv"); + private final static QName _CTSRgbColorLumOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumOff"); + private final static QName _CTSRgbColorTint_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tint"); + private final static QName _CTSRgbColorGreen_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "green"); + private final static QName _CTSRgbColorComp_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "comp"); + private final static QName _CTSRgbColorBlueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueOff"); + private final static QName _CTSRgbColorHueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueMod"); + private final static QName _CTSRgbColorGray_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gray"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.poi.sl.draw.binding + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link CTPositiveSize2D } + * + */ + public CTPositiveSize2D createCTPositiveSize2D() { + return new CTPositiveSize2D(); + } + + /** + * Create an instance of {@link CTSphereCoords } + * + */ + public CTSphereCoords createCTSphereCoords() { + return new CTSphereCoords(); + } + + /** + * Create an instance of {@link CTPositivePercentage } + * + */ + public CTPositivePercentage createCTPositivePercentage() { + return new CTPositivePercentage(); + } + + /** + * Create an instance of {@link CTAdjPoint2D } + * + */ + public CTAdjPoint2D createCTAdjPoint2D() { + return new CTAdjPoint2D(); + } + + /** + * Create an instance of {@link CTPath2DCubicBezierTo } + * + */ + public CTPath2DCubicBezierTo createCTPath2DCubicBezierTo() { + return new CTPath2DCubicBezierTo(); + } + + /** + * Create an instance of {@link CTEmbeddedWAVAudioFile } + * + */ + public CTEmbeddedWAVAudioFile createCTEmbeddedWAVAudioFile() { + return new CTEmbeddedWAVAudioFile(); + } + + /** + * Create an instance of {@link CTPresetGeometry2D } + * + */ + public CTPresetGeometry2D createCTPresetGeometry2D() { + return new CTPresetGeometry2D(); + } + + /** + * Create an instance of {@link CTSchemeColor } + * + */ + public CTSchemeColor createCTSchemeColor() { + return new CTSchemeColor(); + } + + /** + * Create an instance of {@link CTInverseTransform } + * + */ + public CTInverseTransform createCTInverseTransform() { + return new CTInverseTransform(); + } + + /** + * Create an instance of {@link CTScRgbColor } + * + */ + public CTScRgbColor createCTScRgbColor() { + return new CTScRgbColor(); + } + + /** + * Create an instance of {@link CTPositiveFixedAngle } + * + */ + public CTPositiveFixedAngle createCTPositiveFixedAngle() { + return new CTPositiveFixedAngle(); + } + + /** + * Create an instance of {@link CTInverseGammaTransform } + * + */ + public CTInverseGammaTransform createCTInverseGammaTransform() { + return new CTInverseGammaTransform(); + } + + /** + * Create an instance of {@link CTColorMRU } + * + */ + public CTColorMRU createCTColorMRU() { + return new CTColorMRU(); + } + + /** + * Create an instance of {@link CTPath2DArcTo } + * + */ + public CTPath2DArcTo createCTPath2DArcTo() { + return new CTPath2DArcTo(); + } + + /** + * Create an instance of {@link CTSystemColor } + * + */ + public CTSystemColor createCTSystemColor() { + return new CTSystemColor(); + } + + /** + * Create an instance of {@link CTGroupTransform2D } + * + */ + public CTGroupTransform2D createCTGroupTransform2D() { + return new CTGroupTransform2D(); + } + + /** + * Create an instance of {@link CTPoint2D } + * + */ + public CTPoint2D createCTPoint2D() { + return new CTPoint2D(); + } + + /** + * Create an instance of {@link CTGeomRect } + * + */ + public CTGeomRect createCTGeomRect() { + return new CTGeomRect(); + } + + /** + * Create an instance of {@link CTScale2D } + * + */ + public CTScale2D createCTScale2D() { + return new CTScale2D(); + } + + /** + * Create an instance of {@link CTGeomGuide } + * + */ + public CTGeomGuide createCTGeomGuide() { + return new CTGeomGuide(); + } + + /** + * Create an instance of {@link CTXYAdjustHandle } + * + */ + public CTXYAdjustHandle createCTXYAdjustHandle() { + return new CTXYAdjustHandle(); + } + + /** + * Create an instance of {@link CTCustomGeometry2D } + * + */ + public CTCustomGeometry2D createCTCustomGeometry2D() { + return new CTCustomGeometry2D(); + } + + /** + * Create an instance of {@link CTOfficeArtExtension } + * + */ + public CTOfficeArtExtension createCTOfficeArtExtension() { + return new CTOfficeArtExtension(); + } + + /** + * Create an instance of {@link CTGrayscaleTransform } + * + */ + public CTGrayscaleTransform createCTGrayscaleTransform() { + return new CTGrayscaleTransform(); + } + + /** + * Create an instance of {@link CTPath2DClose } + * + */ + public CTPath2DClose createCTPath2DClose() { + return new CTPath2DClose(); + } + + /** + * Create an instance of {@link CTComplementTransform } + * + */ + public CTComplementTransform createCTComplementTransform() { + return new CTComplementTransform(); + } + + /** + * Create an instance of {@link CTPoint3D } + * + */ + public CTPoint3D createCTPoint3D() { + return new CTPoint3D(); + } + + /** + * Create an instance of {@link CTPositiveFixedPercentage } + * + */ + public CTPositiveFixedPercentage createCTPositiveFixedPercentage() { + return new CTPositiveFixedPercentage(); + } + + /** + * Create an instance of {@link CTPath2D } + * + */ + public CTPath2D createCTPath2D() { + return new CTPath2D(); + } + + /** + * Create an instance of {@link CTAdjustHandleList } + * + */ + public CTAdjustHandleList createCTAdjustHandleList() { + return new CTAdjustHandleList(); + } + + /** + * Create an instance of {@link CTConnectionSiteList } + * + */ + public CTConnectionSiteList createCTConnectionSiteList() { + return new CTConnectionSiteList(); + } + + /** + * Create an instance of {@link CTPresetTextShape } + * + */ + public CTPresetTextShape createCTPresetTextShape() { + return new CTPresetTextShape(); + } + + /** + * Create an instance of {@link CTSRgbColor } + * + */ + public CTSRgbColor createCTSRgbColor() { + return new CTSRgbColor(); + } + + /** + * Create an instance of {@link CTPath2DMoveTo } + * + */ + public CTPath2DMoveTo createCTPath2DMoveTo() { + return new CTPath2DMoveTo(); + } + + /** + * Create an instance of {@link CTRelativeRect } + * + */ + public CTRelativeRect createCTRelativeRect() { + return new CTRelativeRect(); + } + + /** + * Create an instance of {@link CTPath2DList } + * + */ + public CTPath2DList createCTPath2DList() { + return new CTPath2DList(); + } + + /** + * Create an instance of {@link CTPolarAdjustHandle } + * + */ + public CTPolarAdjustHandle createCTPolarAdjustHandle() { + return new CTPolarAdjustHandle(); + } + + /** + * Create an instance of {@link CTPercentage } + * + */ + public CTPercentage createCTPercentage() { + return new CTPercentage(); + } + + /** + * Create an instance of {@link CTHslColor } + * + */ + public CTHslColor createCTHslColor() { + return new CTHslColor(); + } + + /** + * Create an instance of {@link CTRatio } + * + */ + public CTRatio createCTRatio() { + return new CTRatio(); + } + + /** + * Create an instance of {@link CTGeomGuideList } + * + */ + public CTGeomGuideList createCTGeomGuideList() { + return new CTGeomGuideList(); + } + + /** + * Create an instance of {@link CTTransform2D } + * + */ + public CTTransform2D createCTTransform2D() { + return new CTTransform2D(); + } + + /** + * Create an instance of {@link CTGammaTransform } + * + */ + public CTGammaTransform createCTGammaTransform() { + return new CTGammaTransform(); + } + + /** + * Create an instance of {@link CTPath2DQuadBezierTo } + * + */ + public CTPath2DQuadBezierTo createCTPath2DQuadBezierTo() { + return new CTPath2DQuadBezierTo(); + } + + /** + * Create an instance of {@link CTAngle } + * + */ + public CTAngle createCTAngle() { + return new CTAngle(); + } + + /** + * Create an instance of {@link CTConnectionSite } + * + */ + public CTConnectionSite createCTConnectionSite() { + return new CTConnectionSite(); + } + + /** + * Create an instance of {@link CTHyperlink } + * + */ + public CTHyperlink createCTHyperlink() { + return new CTHyperlink(); + } + + /** + * Create an instance of {@link CTFixedPercentage } + * + */ + public CTFixedPercentage createCTFixedPercentage() { + return new CTFixedPercentage(); + } + + /** + * Create an instance of {@link CTPath2DLineTo } + * + */ + public CTPath2DLineTo createCTPath2DLineTo() { + return new CTPath2DLineTo(); + } + + /** + * Create an instance of {@link CTColor } + * + */ + public CTColor createCTColor() { + return new CTColor(); + } + + /** + * Create an instance of {@link CTPresetColor } + * + */ + public CTPresetColor createCTPresetColor() { + return new CTPresetColor(); + } + + /** + * Create an instance of {@link CTVector3D } + * + */ + public CTVector3D createCTVector3D() { + return new CTVector3D(); + } + + /** + * Create an instance of {@link CTOfficeArtExtensionList } + * + */ + public CTOfficeArtExtensionList createCTOfficeArtExtensionList() { + return new CTOfficeArtExtensionList(); + } + + /** + * Create an instance of {@link CTConnection } + * + */ + public CTConnection createCTConnection() { + return new CTConnection(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTHslColor.class) + public JAXBElement createCTHslColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTHslColor.class) + public JAXBElement createCTHslColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTHslColor.class) + public JAXBElement createCTHslColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTHslColor.class) + public JAXBElement createCTHslColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTHslColor.class) + public JAXBElement createCTHslColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTHslColor.class) + public JAXBElement createCTHslColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTHslColor.class) + public JAXBElement createCTHslColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTHslColor.class) + public JAXBElement createCTHslColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTHslColor.class) + public JAXBElement createCTHslColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTHslColor.class) + public JAXBElement createCTHslColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTHslColor.class) + public JAXBElement createCTHslColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTHslColor.class) + public JAXBElement createCTHslColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTHslColor.class) + public JAXBElement createCTHslColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTHslColor.class) + public JAXBElement createCTHslColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTPresetColor.class, value); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java b/src/java/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java index 27262d6060..033fe442fe 100644 --- a/src/java/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java +++ b/src/java/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java @@ -1,149 +1,149 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for ST_BlackWhiteMode. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="ST_BlackWhiteMode">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
- *     <enumeration value="clr"/>
- *     <enumeration value="auto"/>
- *     <enumeration value="gray"/>
- *     <enumeration value="ltGray"/>
- *     <enumeration value="invGray"/>
- *     <enumeration value="grayWhite"/>
- *     <enumeration value="blackGray"/>
- *     <enumeration value="blackWhite"/>
- *     <enumeration value="black"/>
- *     <enumeration value="white"/>
- *     <enumeration value="hidden"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "ST_BlackWhiteMode", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -@XmlEnum -public enum STBlackWhiteMode { - - - /** - * Color - * - */ - @XmlEnumValue("clr") - CLR("clr"), - - /** - * Automatic - * - */ - @XmlEnumValue("auto") - AUTO("auto"), - - /** - * Gray - * - */ - @XmlEnumValue("gray") - GRAY("gray"), - - /** - * Light Gray - * - */ - @XmlEnumValue("ltGray") - LT_GRAY("ltGray"), - - /** - * Inverse Gray - * - */ - @XmlEnumValue("invGray") - INV_GRAY("invGray"), - - /** - * Gray and White - * - */ - @XmlEnumValue("grayWhite") - GRAY_WHITE("grayWhite"), - - /** - * Black and Gray - * - */ - @XmlEnumValue("blackGray") - BLACK_GRAY("blackGray"), - - /** - * Black and White - * - */ - @XmlEnumValue("blackWhite") - BLACK_WHITE("blackWhite"), - - /** - * Black - * - */ - @XmlEnumValue("black") - BLACK("black"), - - /** - * White - * - */ - @XmlEnumValue("white") - WHITE("white"), - - /** - * Hidden - * - */ - @XmlEnumValue("hidden") - HIDDEN("hidden"); - private final String value; - - STBlackWhiteMode(String v) { - value = v; - } - - public String value() { - return value; - } - - public static STBlackWhiteMode fromValue(String v) { - for (STBlackWhiteMode c: STBlackWhiteMode.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ST_BlackWhiteMode. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="ST_BlackWhiteMode">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
+ *     <enumeration value="clr"/>
+ *     <enumeration value="auto"/>
+ *     <enumeration value="gray"/>
+ *     <enumeration value="ltGray"/>
+ *     <enumeration value="invGray"/>
+ *     <enumeration value="grayWhite"/>
+ *     <enumeration value="blackGray"/>
+ *     <enumeration value="blackWhite"/>
+ *     <enumeration value="black"/>
+ *     <enumeration value="white"/>
+ *     <enumeration value="hidden"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "ST_BlackWhiteMode", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +@XmlEnum +public enum STBlackWhiteMode { + + + /** + * Color + * + */ + @XmlEnumValue("clr") + CLR("clr"), + + /** + * Automatic + * + */ + @XmlEnumValue("auto") + AUTO("auto"), + + /** + * Gray + * + */ + @XmlEnumValue("gray") + GRAY("gray"), + + /** + * Light Gray + * + */ + @XmlEnumValue("ltGray") + LT_GRAY("ltGray"), + + /** + * Inverse Gray + * + */ + @XmlEnumValue("invGray") + INV_GRAY("invGray"), + + /** + * Gray and White + * + */ + @XmlEnumValue("grayWhite") + GRAY_WHITE("grayWhite"), + + /** + * Black and Gray + * + */ + @XmlEnumValue("blackGray") + BLACK_GRAY("blackGray"), + + /** + * Black and White + * + */ + @XmlEnumValue("blackWhite") + BLACK_WHITE("blackWhite"), + + /** + * Black + * + */ + @XmlEnumValue("black") + BLACK("black"), + + /** + * White + * + */ + @XmlEnumValue("white") + WHITE("white"), + + /** + * Hidden + * + */ + @XmlEnumValue("hidden") + HIDDEN("hidden"); + private final String value; + + STBlackWhiteMode(String v) { + value = v; + } + + public String value() { + return value; + } + + public static STBlackWhiteMode fromValue(String v) { + for (STBlackWhiteMode c: STBlackWhiteMode.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/STPathFillMode.java b/src/java/org/apache/poi/sl/draw/binding/STPathFillMode.java index 8a26458f02..ad610f1972 100644 --- a/src/java/org/apache/poi/sl/draw/binding/STPathFillMode.java +++ b/src/java/org/apache/poi/sl/draw/binding/STPathFillMode.java @@ -1,109 +1,109 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for ST_PathFillMode. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="ST_PathFillMode">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
- *     <enumeration value="none"/>
- *     <enumeration value="norm"/>
- *     <enumeration value="lighten"/>
- *     <enumeration value="lightenLess"/>
- *     <enumeration value="darken"/>
- *     <enumeration value="darkenLess"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "ST_PathFillMode", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -@XmlEnum -public enum STPathFillMode { - - - /** - * No Path Fill - * - */ - @XmlEnumValue("none") - NONE("none"), - - /** - * Normal Path Fill - * - */ - @XmlEnumValue("norm") - NORM("norm"), - - /** - * Lighten Path Fill - * - */ - @XmlEnumValue("lighten") - LIGHTEN("lighten"), - - /** - * Lighten Path Fill Less - * - */ - @XmlEnumValue("lightenLess") - LIGHTEN_LESS("lightenLess"), - - /** - * Darken Path Fill - * - */ - @XmlEnumValue("darken") - DARKEN("darken"), - - /** - * Darken Path Fill Less - * - */ - @XmlEnumValue("darkenLess") - DARKEN_LESS("darkenLess"); - private final String value; - - STPathFillMode(String v) { - value = v; - } - - public String value() { - return value; - } - - public static STPathFillMode fromValue(String v) { - for (STPathFillMode c: STPathFillMode.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ST_PathFillMode. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="ST_PathFillMode">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
+ *     <enumeration value="none"/>
+ *     <enumeration value="norm"/>
+ *     <enumeration value="lighten"/>
+ *     <enumeration value="lightenLess"/>
+ *     <enumeration value="darken"/>
+ *     <enumeration value="darkenLess"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "ST_PathFillMode", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +@XmlEnum +public enum STPathFillMode { + + + /** + * No Path Fill + * + */ + @XmlEnumValue("none") + NONE("none"), + + /** + * Normal Path Fill + * + */ + @XmlEnumValue("norm") + NORM("norm"), + + /** + * Lighten Path Fill + * + */ + @XmlEnumValue("lighten") + LIGHTEN("lighten"), + + /** + * Lighten Path Fill Less + * + */ + @XmlEnumValue("lightenLess") + LIGHTEN_LESS("lightenLess"), + + /** + * Darken Path Fill + * + */ + @XmlEnumValue("darken") + DARKEN("darken"), + + /** + * Darken Path Fill Less + * + */ + @XmlEnumValue("darkenLess") + DARKEN_LESS("darkenLess"); + private final String value; + + STPathFillMode(String v) { + value = v; + } + + public String value() { + return value; + } + + public static STPathFillMode fromValue(String v) { + for (STPathFillMode c: STPathFillMode.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/STPresetColorVal.java b/src/java/org/apache/poi/sl/draw/binding/STPresetColorVal.java index 7450ac656c..c4b3f84dd8 100644 --- a/src/java/org/apache/poi/sl/draw/binding/STPresetColorVal.java +++ b/src/java/org/apache/poi/sl/draw/binding/STPresetColorVal.java @@ -1,1181 +1,1181 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for ST_PresetColorVal. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="ST_PresetColorVal">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
- *     <enumeration value="aliceBlue"/>
- *     <enumeration value="antiqueWhite"/>
- *     <enumeration value="aqua"/>
- *     <enumeration value="aquamarine"/>
- *     <enumeration value="azure"/>
- *     <enumeration value="beige"/>
- *     <enumeration value="bisque"/>
- *     <enumeration value="black"/>
- *     <enumeration value="blanchedAlmond"/>
- *     <enumeration value="blue"/>
- *     <enumeration value="blueViolet"/>
- *     <enumeration value="brown"/>
- *     <enumeration value="burlyWood"/>
- *     <enumeration value="cadetBlue"/>
- *     <enumeration value="chartreuse"/>
- *     <enumeration value="chocolate"/>
- *     <enumeration value="coral"/>
- *     <enumeration value="cornflowerBlue"/>
- *     <enumeration value="cornsilk"/>
- *     <enumeration value="crimson"/>
- *     <enumeration value="cyan"/>
- *     <enumeration value="dkBlue"/>
- *     <enumeration value="dkCyan"/>
- *     <enumeration value="dkGoldenrod"/>
- *     <enumeration value="dkGray"/>
- *     <enumeration value="dkGreen"/>
- *     <enumeration value="dkKhaki"/>
- *     <enumeration value="dkMagenta"/>
- *     <enumeration value="dkOliveGreen"/>
- *     <enumeration value="dkOrange"/>
- *     <enumeration value="dkOrchid"/>
- *     <enumeration value="dkRed"/>
- *     <enumeration value="dkSalmon"/>
- *     <enumeration value="dkSeaGreen"/>
- *     <enumeration value="dkSlateBlue"/>
- *     <enumeration value="dkSlateGray"/>
- *     <enumeration value="dkTurquoise"/>
- *     <enumeration value="dkViolet"/>
- *     <enumeration value="deepPink"/>
- *     <enumeration value="deepSkyBlue"/>
- *     <enumeration value="dimGray"/>
- *     <enumeration value="dodgerBlue"/>
- *     <enumeration value="firebrick"/>
- *     <enumeration value="floralWhite"/>
- *     <enumeration value="forestGreen"/>
- *     <enumeration value="fuchsia"/>
- *     <enumeration value="gainsboro"/>
- *     <enumeration value="ghostWhite"/>
- *     <enumeration value="gold"/>
- *     <enumeration value="goldenrod"/>
- *     <enumeration value="gray"/>
- *     <enumeration value="green"/>
- *     <enumeration value="greenYellow"/>
- *     <enumeration value="honeydew"/>
- *     <enumeration value="hotPink"/>
- *     <enumeration value="indianRed"/>
- *     <enumeration value="indigo"/>
- *     <enumeration value="ivory"/>
- *     <enumeration value="khaki"/>
- *     <enumeration value="lavender"/>
- *     <enumeration value="lavenderBlush"/>
- *     <enumeration value="lawnGreen"/>
- *     <enumeration value="lemonChiffon"/>
- *     <enumeration value="ltBlue"/>
- *     <enumeration value="ltCoral"/>
- *     <enumeration value="ltCyan"/>
- *     <enumeration value="ltGoldenrodYellow"/>
- *     <enumeration value="ltGray"/>
- *     <enumeration value="ltGreen"/>
- *     <enumeration value="ltPink"/>
- *     <enumeration value="ltSalmon"/>
- *     <enumeration value="ltSeaGreen"/>
- *     <enumeration value="ltSkyBlue"/>
- *     <enumeration value="ltSlateGray"/>
- *     <enumeration value="ltSteelBlue"/>
- *     <enumeration value="ltYellow"/>
- *     <enumeration value="lime"/>
- *     <enumeration value="limeGreen"/>
- *     <enumeration value="linen"/>
- *     <enumeration value="magenta"/>
- *     <enumeration value="maroon"/>
- *     <enumeration value="medAquamarine"/>
- *     <enumeration value="medBlue"/>
- *     <enumeration value="medOrchid"/>
- *     <enumeration value="medPurple"/>
- *     <enumeration value="medSeaGreen"/>
- *     <enumeration value="medSlateBlue"/>
- *     <enumeration value="medSpringGreen"/>
- *     <enumeration value="medTurquoise"/>
- *     <enumeration value="medVioletRed"/>
- *     <enumeration value="midnightBlue"/>
- *     <enumeration value="mintCream"/>
- *     <enumeration value="mistyRose"/>
- *     <enumeration value="moccasin"/>
- *     <enumeration value="navajoWhite"/>
- *     <enumeration value="navy"/>
- *     <enumeration value="oldLace"/>
- *     <enumeration value="olive"/>
- *     <enumeration value="oliveDrab"/>
- *     <enumeration value="orange"/>
- *     <enumeration value="orangeRed"/>
- *     <enumeration value="orchid"/>
- *     <enumeration value="paleGoldenrod"/>
- *     <enumeration value="paleGreen"/>
- *     <enumeration value="paleTurquoise"/>
- *     <enumeration value="paleVioletRed"/>
- *     <enumeration value="papayaWhip"/>
- *     <enumeration value="peachPuff"/>
- *     <enumeration value="peru"/>
- *     <enumeration value="pink"/>
- *     <enumeration value="plum"/>
- *     <enumeration value="powderBlue"/>
- *     <enumeration value="purple"/>
- *     <enumeration value="red"/>
- *     <enumeration value="rosyBrown"/>
- *     <enumeration value="royalBlue"/>
- *     <enumeration value="saddleBrown"/>
- *     <enumeration value="salmon"/>
- *     <enumeration value="sandyBrown"/>
- *     <enumeration value="seaGreen"/>
- *     <enumeration value="seaShell"/>
- *     <enumeration value="sienna"/>
- *     <enumeration value="silver"/>
- *     <enumeration value="skyBlue"/>
- *     <enumeration value="slateBlue"/>
- *     <enumeration value="slateGray"/>
- *     <enumeration value="snow"/>
- *     <enumeration value="springGreen"/>
- *     <enumeration value="steelBlue"/>
- *     <enumeration value="tan"/>
- *     <enumeration value="teal"/>
- *     <enumeration value="thistle"/>
- *     <enumeration value="tomato"/>
- *     <enumeration value="turquoise"/>
- *     <enumeration value="violet"/>
- *     <enumeration value="wheat"/>
- *     <enumeration value="white"/>
- *     <enumeration value="whiteSmoke"/>
- *     <enumeration value="yellow"/>
- *     <enumeration value="yellowGreen"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "ST_PresetColorVal", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -@XmlEnum -public enum STPresetColorVal { - - - /** - * Alice Blue Preset Color - * - */ - @XmlEnumValue("aliceBlue") - ALICE_BLUE("aliceBlue"), - - /** - * Antique White Preset Color - * - */ - @XmlEnumValue("antiqueWhite") - ANTIQUE_WHITE("antiqueWhite"), - - /** - * Aqua Preset Color - * - */ - @XmlEnumValue("aqua") - AQUA("aqua"), - - /** - * Aquamarine Preset Color - * - */ - @XmlEnumValue("aquamarine") - AQUAMARINE("aquamarine"), - - /** - * Azure Preset Color - * - */ - @XmlEnumValue("azure") - AZURE("azure"), - - /** - * Beige Preset Color - * - */ - @XmlEnumValue("beige") - BEIGE("beige"), - - /** - * Bisque Preset Color - * - */ - @XmlEnumValue("bisque") - BISQUE("bisque"), - - /** - * Black Preset Color - * - */ - @XmlEnumValue("black") - BLACK("black"), - - /** - * Blanched Almond Preset Color - * - */ - @XmlEnumValue("blanchedAlmond") - BLANCHED_ALMOND("blanchedAlmond"), - - /** - * Blue Preset Color - * - */ - @XmlEnumValue("blue") - BLUE("blue"), - - /** - * Blue Violet Preset Color - * - */ - @XmlEnumValue("blueViolet") - BLUE_VIOLET("blueViolet"), - - /** - * Brown Preset Color - * - */ - @XmlEnumValue("brown") - BROWN("brown"), - - /** - * Burly Wood Preset Color - * - */ - @XmlEnumValue("burlyWood") - BURLY_WOOD("burlyWood"), - - /** - * Cadet Blue Preset Color - * - */ - @XmlEnumValue("cadetBlue") - CADET_BLUE("cadetBlue"), - - /** - * Chartreuse Preset Color - * - */ - @XmlEnumValue("chartreuse") - CHARTREUSE("chartreuse"), - - /** - * Chocolate Preset Color - * - */ - @XmlEnumValue("chocolate") - CHOCOLATE("chocolate"), - - /** - * Coral Preset Color - * - */ - @XmlEnumValue("coral") - CORAL("coral"), - - /** - * Cornflower Blue Preset Color - * - */ - @XmlEnumValue("cornflowerBlue") - CORNFLOWER_BLUE("cornflowerBlue"), - - /** - * Cornsilk Preset Color - * - */ - @XmlEnumValue("cornsilk") - CORNSILK("cornsilk"), - - /** - * Crimson Preset Color - * - */ - @XmlEnumValue("crimson") - CRIMSON("crimson"), - - /** - * Cyan Preset Color - * - */ - @XmlEnumValue("cyan") - CYAN("cyan"), - - /** - * Dark Blue Preset Color - * - */ - @XmlEnumValue("dkBlue") - DK_BLUE("dkBlue"), - - /** - * Dark Cyan Preset Color - * - */ - @XmlEnumValue("dkCyan") - DK_CYAN("dkCyan"), - - /** - * Dark Goldenrod Preset Color - * - */ - @XmlEnumValue("dkGoldenrod") - DK_GOLDENROD("dkGoldenrod"), - - /** - * Dark Gray Preset Color - * - */ - @XmlEnumValue("dkGray") - DK_GRAY("dkGray"), - - /** - * Dark Green Preset Color - * - */ - @XmlEnumValue("dkGreen") - DK_GREEN("dkGreen"), - - /** - * Dark Khaki Preset Color - * - */ - @XmlEnumValue("dkKhaki") - DK_KHAKI("dkKhaki"), - - /** - * Dark Magenta Preset Color - * - */ - @XmlEnumValue("dkMagenta") - DK_MAGENTA("dkMagenta"), - - /** - * Dark Olive Green Preset Color - * - */ - @XmlEnumValue("dkOliveGreen") - DK_OLIVE_GREEN("dkOliveGreen"), - - /** - * Dark Orange Preset Color - * - */ - @XmlEnumValue("dkOrange") - DK_ORANGE("dkOrange"), - - /** - * Dark Orchid Preset Color - * - */ - @XmlEnumValue("dkOrchid") - DK_ORCHID("dkOrchid"), - - /** - * Dark Red Preset Color - * - */ - @XmlEnumValue("dkRed") - DK_RED("dkRed"), - - /** - * Dark Salmon Preset Color - * - */ - @XmlEnumValue("dkSalmon") - DK_SALMON("dkSalmon"), - - /** - * Dark Sea Green Preset Color - * - */ - @XmlEnumValue("dkSeaGreen") - DK_SEA_GREEN("dkSeaGreen"), - - /** - * Dark Slate Blue Preset Color - * - */ - @XmlEnumValue("dkSlateBlue") - DK_SLATE_BLUE("dkSlateBlue"), - - /** - * Dark Slate Gray Preset Color - * - */ - @XmlEnumValue("dkSlateGray") - DK_SLATE_GRAY("dkSlateGray"), - - /** - * Dark Turquoise Preset Color - * - */ - @XmlEnumValue("dkTurquoise") - DK_TURQUOISE("dkTurquoise"), - - /** - * Dark Violet Preset Color - * - */ - @XmlEnumValue("dkViolet") - DK_VIOLET("dkViolet"), - - /** - * Deep Pink Preset Color - * - */ - @XmlEnumValue("deepPink") - DEEP_PINK("deepPink"), - - /** - * Deep Sky Blue Preset Color - * - */ - @XmlEnumValue("deepSkyBlue") - DEEP_SKY_BLUE("deepSkyBlue"), - - /** - * Dim Gray Preset Color - * - */ - @XmlEnumValue("dimGray") - DIM_GRAY("dimGray"), - - /** - * Dodger Blue Preset Color - * - */ - @XmlEnumValue("dodgerBlue") - DODGER_BLUE("dodgerBlue"), - - /** - * Firebrick Preset Color - * - */ - @XmlEnumValue("firebrick") - FIREBRICK("firebrick"), - - /** - * Floral White Preset Color - * - */ - @XmlEnumValue("floralWhite") - FLORAL_WHITE("floralWhite"), - - /** - * Forest Green Preset Color - * - */ - @XmlEnumValue("forestGreen") - FOREST_GREEN("forestGreen"), - - /** - * Fuchsia Preset Color - * - */ - @XmlEnumValue("fuchsia") - FUCHSIA("fuchsia"), - - /** - * Gainsboro Preset Color - * - */ - @XmlEnumValue("gainsboro") - GAINSBORO("gainsboro"), - - /** - * Ghost White Preset Color - * - */ - @XmlEnumValue("ghostWhite") - GHOST_WHITE("ghostWhite"), - - /** - * Gold Preset Color - * - */ - @XmlEnumValue("gold") - GOLD("gold"), - - /** - * Goldenrod Preset Color - * - */ - @XmlEnumValue("goldenrod") - GOLDENROD("goldenrod"), - - /** - * Gray Preset Color - * - */ - @XmlEnumValue("gray") - GRAY("gray"), - - /** - * Green Preset Color - * - */ - @XmlEnumValue("green") - GREEN("green"), - - /** - * Green Yellow Preset Color - * - */ - @XmlEnumValue("greenYellow") - GREEN_YELLOW("greenYellow"), - - /** - * Honeydew Preset Color - * - */ - @XmlEnumValue("honeydew") - HONEYDEW("honeydew"), - - /** - * Hot Pink Preset Color - * - */ - @XmlEnumValue("hotPink") - HOT_PINK("hotPink"), - - /** - * Indian Red Preset Color - * - */ - @XmlEnumValue("indianRed") - INDIAN_RED("indianRed"), - - /** - * Indigo Preset Color - * - */ - @XmlEnumValue("indigo") - INDIGO("indigo"), - - /** - * Ivory Preset Color - * - */ - @XmlEnumValue("ivory") - IVORY("ivory"), - - /** - * Khaki Preset Color - * - */ - @XmlEnumValue("khaki") - KHAKI("khaki"), - - /** - * Lavender Preset Color - * - */ - @XmlEnumValue("lavender") - LAVENDER("lavender"), - - /** - * Lavender Blush Preset Color - * - */ - @XmlEnumValue("lavenderBlush") - LAVENDER_BLUSH("lavenderBlush"), - - /** - * Lawn Green Preset Color - * - */ - @XmlEnumValue("lawnGreen") - LAWN_GREEN("lawnGreen"), - - /** - * Lemon Chiffon Preset Color - * - */ - @XmlEnumValue("lemonChiffon") - LEMON_CHIFFON("lemonChiffon"), - - /** - * Light Blue Preset Color - * - */ - @XmlEnumValue("ltBlue") - LT_BLUE("ltBlue"), - - /** - * Light Coral Preset Color - * - */ - @XmlEnumValue("ltCoral") - LT_CORAL("ltCoral"), - - /** - * Light Cyan Preset Color - * - */ - @XmlEnumValue("ltCyan") - LT_CYAN("ltCyan"), - - /** - * Light Goldenrod Yellow Preset Color - * - */ - @XmlEnumValue("ltGoldenrodYellow") - LT_GOLDENROD_YELLOW("ltGoldenrodYellow"), - - /** - * Light Gray Preset Color - * - */ - @XmlEnumValue("ltGray") - LT_GRAY("ltGray"), - - /** - * Light Green Preset Color - * - */ - @XmlEnumValue("ltGreen") - LT_GREEN("ltGreen"), - - /** - * Light Pink Preset Color - * - */ - @XmlEnumValue("ltPink") - LT_PINK("ltPink"), - - /** - * Light Salmon Preset Color - * - */ - @XmlEnumValue("ltSalmon") - LT_SALMON("ltSalmon"), - - /** - * Light Sea Green Preset Color - * - */ - @XmlEnumValue("ltSeaGreen") - LT_SEA_GREEN("ltSeaGreen"), - - /** - * Light Sky Blue Preset Color - * - */ - @XmlEnumValue("ltSkyBlue") - LT_SKY_BLUE("ltSkyBlue"), - - /** - * Light Slate Gray Preset Color - * - */ - @XmlEnumValue("ltSlateGray") - LT_SLATE_GRAY("ltSlateGray"), - - /** - * Light Steel Blue Preset Color - * - */ - @XmlEnumValue("ltSteelBlue") - LT_STEEL_BLUE("ltSteelBlue"), - - /** - * Light Yellow Preset Color - * - */ - @XmlEnumValue("ltYellow") - LT_YELLOW("ltYellow"), - - /** - * Lime Preset Color - * - */ - @XmlEnumValue("lime") - LIME("lime"), - - /** - * Lime Green Preset Color - * - */ - @XmlEnumValue("limeGreen") - LIME_GREEN("limeGreen"), - - /** - * Linen Preset Color - * - */ - @XmlEnumValue("linen") - LINEN("linen"), - - /** - * Magenta Preset Color - * - */ - @XmlEnumValue("magenta") - MAGENTA("magenta"), - - /** - * Maroon Preset Color - * - */ - @XmlEnumValue("maroon") - MAROON("maroon"), - - /** - * Medium Aquamarine Preset Color - * - */ - @XmlEnumValue("medAquamarine") - MED_AQUAMARINE("medAquamarine"), - - /** - * Medium Blue Preset Color - * - */ - @XmlEnumValue("medBlue") - MED_BLUE("medBlue"), - - /** - * Medium Orchid Preset Color - * - */ - @XmlEnumValue("medOrchid") - MED_ORCHID("medOrchid"), - - /** - * Medium Purple Preset Color - * - */ - @XmlEnumValue("medPurple") - MED_PURPLE("medPurple"), - - /** - * Medium Sea Green Preset Color - * - */ - @XmlEnumValue("medSeaGreen") - MED_SEA_GREEN("medSeaGreen"), - - /** - * Medium Slate Blue Preset Color - * - */ - @XmlEnumValue("medSlateBlue") - MED_SLATE_BLUE("medSlateBlue"), - - /** - * Medium Spring Green Preset Color - * - */ - @XmlEnumValue("medSpringGreen") - MED_SPRING_GREEN("medSpringGreen"), - - /** - * Medium Turquoise Preset Color - * - */ - @XmlEnumValue("medTurquoise") - MED_TURQUOISE("medTurquoise"), - - /** - * Medium Violet Red Preset Color - * - */ - @XmlEnumValue("medVioletRed") - MED_VIOLET_RED("medVioletRed"), - - /** - * Midnight Blue Preset Color - * - */ - @XmlEnumValue("midnightBlue") - MIDNIGHT_BLUE("midnightBlue"), - - /** - * Mint Cream Preset Color - * - */ - @XmlEnumValue("mintCream") - MINT_CREAM("mintCream"), - - /** - * Misty Rose Preset Color - * - */ - @XmlEnumValue("mistyRose") - MISTY_ROSE("mistyRose"), - - /** - * Moccasin Preset Color - * - */ - @XmlEnumValue("moccasin") - MOCCASIN("moccasin"), - - /** - * Navajo White Preset Color - * - */ - @XmlEnumValue("navajoWhite") - NAVAJO_WHITE("navajoWhite"), - - /** - * Navy Preset Color - * - */ - @XmlEnumValue("navy") - NAVY("navy"), - - /** - * Old Lace Preset Color - * - */ - @XmlEnumValue("oldLace") - OLD_LACE("oldLace"), - - /** - * Olive Preset Color - * - */ - @XmlEnumValue("olive") - OLIVE("olive"), - - /** - * Olive Drab Preset Color - * - */ - @XmlEnumValue("oliveDrab") - OLIVE_DRAB("oliveDrab"), - - /** - * Orange Preset Color - * - */ - @XmlEnumValue("orange") - ORANGE("orange"), - - /** - * Orange Red Preset Color - * - */ - @XmlEnumValue("orangeRed") - ORANGE_RED("orangeRed"), - - /** - * Orchid Preset Color - * - */ - @XmlEnumValue("orchid") - ORCHID("orchid"), - - /** - * Pale Goldenrod Preset Color - * - */ - @XmlEnumValue("paleGoldenrod") - PALE_GOLDENROD("paleGoldenrod"), - - /** - * Pale Green Preset Color - * - */ - @XmlEnumValue("paleGreen") - PALE_GREEN("paleGreen"), - - /** - * Pale Turquoise Preset Color - * - */ - @XmlEnumValue("paleTurquoise") - PALE_TURQUOISE("paleTurquoise"), - - /** - * Pale Violet Red Preset Color - * - */ - @XmlEnumValue("paleVioletRed") - PALE_VIOLET_RED("paleVioletRed"), - - /** - * Papaya Whip Preset Color - * - */ - @XmlEnumValue("papayaWhip") - PAPAYA_WHIP("papayaWhip"), - - /** - * Peach Puff Preset Color - * - */ - @XmlEnumValue("peachPuff") - PEACH_PUFF("peachPuff"), - - /** - * Peru Preset Color - * - */ - @XmlEnumValue("peru") - PERU("peru"), - - /** - * Pink Preset Color - * - */ - @XmlEnumValue("pink") - PINK("pink"), - - /** - * Plum Preset Color - * - */ - @XmlEnumValue("plum") - PLUM("plum"), - - /** - * Powder Blue Preset Color - * - */ - @XmlEnumValue("powderBlue") - POWDER_BLUE("powderBlue"), - - /** - * Purple Preset Color - * - */ - @XmlEnumValue("purple") - PURPLE("purple"), - - /** - * Red Preset Color - * - */ - @XmlEnumValue("red") - RED("red"), - - /** - * Rosy Brown Preset Color - * - */ - @XmlEnumValue("rosyBrown") - ROSY_BROWN("rosyBrown"), - - /** - * Royal Blue Preset Color - * - */ - @XmlEnumValue("royalBlue") - ROYAL_BLUE("royalBlue"), - - /** - * Saddle Brown Preset Color - * - */ - @XmlEnumValue("saddleBrown") - SADDLE_BROWN("saddleBrown"), - - /** - * Salmon Preset Color - * - */ - @XmlEnumValue("salmon") - SALMON("salmon"), - - /** - * Sandy Brown Preset Color - * - */ - @XmlEnumValue("sandyBrown") - SANDY_BROWN("sandyBrown"), - - /** - * Sea Green Preset Color - * - */ - @XmlEnumValue("seaGreen") - SEA_GREEN("seaGreen"), - - /** - * Sea Shell Preset Color - * - */ - @XmlEnumValue("seaShell") - SEA_SHELL("seaShell"), - - /** - * Sienna Preset Color - * - */ - @XmlEnumValue("sienna") - SIENNA("sienna"), - - /** - * Silver Preset Color - * - */ - @XmlEnumValue("silver") - SILVER("silver"), - - /** - * Sky Blue Preset Color - * - */ - @XmlEnumValue("skyBlue") - SKY_BLUE("skyBlue"), - - /** - * Slate Blue Preset Color - * - */ - @XmlEnumValue("slateBlue") - SLATE_BLUE("slateBlue"), - - /** - * Slate Gray Preset Color - * - */ - @XmlEnumValue("slateGray") - SLATE_GRAY("slateGray"), - - /** - * Snow Preset Color - * - */ - @XmlEnumValue("snow") - SNOW("snow"), - - /** - * Spring Green Preset Color - * - */ - @XmlEnumValue("springGreen") - SPRING_GREEN("springGreen"), - - /** - * Steel Blue Preset Color - * - */ - @XmlEnumValue("steelBlue") - STEEL_BLUE("steelBlue"), - - /** - * Tan Preset Color - * - */ - @XmlEnumValue("tan") - TAN("tan"), - - /** - * Teal Preset Color - * - */ - @XmlEnumValue("teal") - TEAL("teal"), - - /** - * Thistle Preset Color - * - */ - @XmlEnumValue("thistle") - THISTLE("thistle"), - - /** - * Tomato Preset Color - * - */ - @XmlEnumValue("tomato") - TOMATO("tomato"), - - /** - * Turquoise Preset Color - * - */ - @XmlEnumValue("turquoise") - TURQUOISE("turquoise"), - - /** - * Violet Preset Color - * - */ - @XmlEnumValue("violet") - VIOLET("violet"), - - /** - * Wheat Preset Color - * - */ - @XmlEnumValue("wheat") - WHEAT("wheat"), - - /** - * White Preset Color - * - */ - @XmlEnumValue("white") - WHITE("white"), - - /** - * White Smoke Preset Color - * - */ - @XmlEnumValue("whiteSmoke") - WHITE_SMOKE("whiteSmoke"), - - /** - * Yellow Preset Color - * - */ - @XmlEnumValue("yellow") - YELLOW("yellow"), - - /** - * Yellow Green Preset Color - * - */ - @XmlEnumValue("yellowGreen") - YELLOW_GREEN("yellowGreen"); - private final String value; - - STPresetColorVal(String v) { - value = v; - } - - public String value() { - return value; - } - - public static STPresetColorVal fromValue(String v) { - for (STPresetColorVal c: STPresetColorVal.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ST_PresetColorVal. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="ST_PresetColorVal">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
+ *     <enumeration value="aliceBlue"/>
+ *     <enumeration value="antiqueWhite"/>
+ *     <enumeration value="aqua"/>
+ *     <enumeration value="aquamarine"/>
+ *     <enumeration value="azure"/>
+ *     <enumeration value="beige"/>
+ *     <enumeration value="bisque"/>
+ *     <enumeration value="black"/>
+ *     <enumeration value="blanchedAlmond"/>
+ *     <enumeration value="blue"/>
+ *     <enumeration value="blueViolet"/>
+ *     <enumeration value="brown"/>
+ *     <enumeration value="burlyWood"/>
+ *     <enumeration value="cadetBlue"/>
+ *     <enumeration value="chartreuse"/>
+ *     <enumeration value="chocolate"/>
+ *     <enumeration value="coral"/>
+ *     <enumeration value="cornflowerBlue"/>
+ *     <enumeration value="cornsilk"/>
+ *     <enumeration value="crimson"/>
+ *     <enumeration value="cyan"/>
+ *     <enumeration value="dkBlue"/>
+ *     <enumeration value="dkCyan"/>
+ *     <enumeration value="dkGoldenrod"/>
+ *     <enumeration value="dkGray"/>
+ *     <enumeration value="dkGreen"/>
+ *     <enumeration value="dkKhaki"/>
+ *     <enumeration value="dkMagenta"/>
+ *     <enumeration value="dkOliveGreen"/>
+ *     <enumeration value="dkOrange"/>
+ *     <enumeration value="dkOrchid"/>
+ *     <enumeration value="dkRed"/>
+ *     <enumeration value="dkSalmon"/>
+ *     <enumeration value="dkSeaGreen"/>
+ *     <enumeration value="dkSlateBlue"/>
+ *     <enumeration value="dkSlateGray"/>
+ *     <enumeration value="dkTurquoise"/>
+ *     <enumeration value="dkViolet"/>
+ *     <enumeration value="deepPink"/>
+ *     <enumeration value="deepSkyBlue"/>
+ *     <enumeration value="dimGray"/>
+ *     <enumeration value="dodgerBlue"/>
+ *     <enumeration value="firebrick"/>
+ *     <enumeration value="floralWhite"/>
+ *     <enumeration value="forestGreen"/>
+ *     <enumeration value="fuchsia"/>
+ *     <enumeration value="gainsboro"/>
+ *     <enumeration value="ghostWhite"/>
+ *     <enumeration value="gold"/>
+ *     <enumeration value="goldenrod"/>
+ *     <enumeration value="gray"/>
+ *     <enumeration value="green"/>
+ *     <enumeration value="greenYellow"/>
+ *     <enumeration value="honeydew"/>
+ *     <enumeration value="hotPink"/>
+ *     <enumeration value="indianRed"/>
+ *     <enumeration value="indigo"/>
+ *     <enumeration value="ivory"/>
+ *     <enumeration value="khaki"/>
+ *     <enumeration value="lavender"/>
+ *     <enumeration value="lavenderBlush"/>
+ *     <enumeration value="lawnGreen"/>
+ *     <enumeration value="lemonChiffon"/>
+ *     <enumeration value="ltBlue"/>
+ *     <enumeration value="ltCoral"/>
+ *     <enumeration value="ltCyan"/>
+ *     <enumeration value="ltGoldenrodYellow"/>
+ *     <enumeration value="ltGray"/>
+ *     <enumeration value="ltGreen"/>
+ *     <enumeration value="ltPink"/>
+ *     <enumeration value="ltSalmon"/>
+ *     <enumeration value="ltSeaGreen"/>
+ *     <enumeration value="ltSkyBlue"/>
+ *     <enumeration value="ltSlateGray"/>
+ *     <enumeration value="ltSteelBlue"/>
+ *     <enumeration value="ltYellow"/>
+ *     <enumeration value="lime"/>
+ *     <enumeration value="limeGreen"/>
+ *     <enumeration value="linen"/>
+ *     <enumeration value="magenta"/>
+ *     <enumeration value="maroon"/>
+ *     <enumeration value="medAquamarine"/>
+ *     <enumeration value="medBlue"/>
+ *     <enumeration value="medOrchid"/>
+ *     <enumeration value="medPurple"/>
+ *     <enumeration value="medSeaGreen"/>
+ *     <enumeration value="medSlateBlue"/>
+ *     <enumeration value="medSpringGreen"/>
+ *     <enumeration value="medTurquoise"/>
+ *     <enumeration value="medVioletRed"/>
+ *     <enumeration value="midnightBlue"/>
+ *     <enumeration value="mintCream"/>
+ *     <enumeration value="mistyRose"/>
+ *     <enumeration value="moccasin"/>
+ *     <enumeration value="navajoWhite"/>
+ *     <enumeration value="navy"/>
+ *     <enumeration value="oldLace"/>
+ *     <enumeration value="olive"/>
+ *     <enumeration value="oliveDrab"/>
+ *     <enumeration value="orange"/>
+ *     <enumeration value="orangeRed"/>
+ *     <enumeration value="orchid"/>
+ *     <enumeration value="paleGoldenrod"/>
+ *     <enumeration value="paleGreen"/>
+ *     <enumeration value="paleTurquoise"/>
+ *     <enumeration value="paleVioletRed"/>
+ *     <enumeration value="papayaWhip"/>
+ *     <enumeration value="peachPuff"/>
+ *     <enumeration value="peru"/>
+ *     <enumeration value="pink"/>
+ *     <enumeration value="plum"/>
+ *     <enumeration value="powderBlue"/>
+ *     <enumeration value="purple"/>
+ *     <enumeration value="red"/>
+ *     <enumeration value="rosyBrown"/>
+ *     <enumeration value="royalBlue"/>
+ *     <enumeration value="saddleBrown"/>
+ *     <enumeration value="salmon"/>
+ *     <enumeration value="sandyBrown"/>
+ *     <enumeration value="seaGreen"/>
+ *     <enumeration value="seaShell"/>
+ *     <enumeration value="sienna"/>
+ *     <enumeration value="silver"/>
+ *     <enumeration value="skyBlue"/>
+ *     <enumeration value="slateBlue"/>
+ *     <enumeration value="slateGray"/>
+ *     <enumeration value="snow"/>
+ *     <enumeration value="springGreen"/>
+ *     <enumeration value="steelBlue"/>
+ *     <enumeration value="tan"/>
+ *     <enumeration value="teal"/>
+ *     <enumeration value="thistle"/>
+ *     <enumeration value="tomato"/>
+ *     <enumeration value="turquoise"/>
+ *     <enumeration value="violet"/>
+ *     <enumeration value="wheat"/>
+ *     <enumeration value="white"/>
+ *     <enumeration value="whiteSmoke"/>
+ *     <enumeration value="yellow"/>
+ *     <enumeration value="yellowGreen"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "ST_PresetColorVal", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +@XmlEnum +public enum STPresetColorVal { + + + /** + * Alice Blue Preset Color + * + */ + @XmlEnumValue("aliceBlue") + ALICE_BLUE("aliceBlue"), + + /** + * Antique White Preset Color + * + */ + @XmlEnumValue("antiqueWhite") + ANTIQUE_WHITE("antiqueWhite"), + + /** + * Aqua Preset Color + * + */ + @XmlEnumValue("aqua") + AQUA("aqua"), + + /** + * Aquamarine Preset Color + * + */ + @XmlEnumValue("aquamarine") + AQUAMARINE("aquamarine"), + + /** + * Azure Preset Color + * + */ + @XmlEnumValue("azure") + AZURE("azure"), + + /** + * Beige Preset Color + * + */ + @XmlEnumValue("beige") + BEIGE("beige"), + + /** + * Bisque Preset Color + * + */ + @XmlEnumValue("bisque") + BISQUE("bisque"), + + /** + * Black Preset Color + * + */ + @XmlEnumValue("black") + BLACK("black"), + + /** + * Blanched Almond Preset Color + * + */ + @XmlEnumValue("blanchedAlmond") + BLANCHED_ALMOND("blanchedAlmond"), + + /** + * Blue Preset Color + * + */ + @XmlEnumValue("blue") + BLUE("blue"), + + /** + * Blue Violet Preset Color + * + */ + @XmlEnumValue("blueViolet") + BLUE_VIOLET("blueViolet"), + + /** + * Brown Preset Color + * + */ + @XmlEnumValue("brown") + BROWN("brown"), + + /** + * Burly Wood Preset Color + * + */ + @XmlEnumValue("burlyWood") + BURLY_WOOD("burlyWood"), + + /** + * Cadet Blue Preset Color + * + */ + @XmlEnumValue("cadetBlue") + CADET_BLUE("cadetBlue"), + + /** + * Chartreuse Preset Color + * + */ + @XmlEnumValue("chartreuse") + CHARTREUSE("chartreuse"), + + /** + * Chocolate Preset Color + * + */ + @XmlEnumValue("chocolate") + CHOCOLATE("chocolate"), + + /** + * Coral Preset Color + * + */ + @XmlEnumValue("coral") + CORAL("coral"), + + /** + * Cornflower Blue Preset Color + * + */ + @XmlEnumValue("cornflowerBlue") + CORNFLOWER_BLUE("cornflowerBlue"), + + /** + * Cornsilk Preset Color + * + */ + @XmlEnumValue("cornsilk") + CORNSILK("cornsilk"), + + /** + * Crimson Preset Color + * + */ + @XmlEnumValue("crimson") + CRIMSON("crimson"), + + /** + * Cyan Preset Color + * + */ + @XmlEnumValue("cyan") + CYAN("cyan"), + + /** + * Dark Blue Preset Color + * + */ + @XmlEnumValue("dkBlue") + DK_BLUE("dkBlue"), + + /** + * Dark Cyan Preset Color + * + */ + @XmlEnumValue("dkCyan") + DK_CYAN("dkCyan"), + + /** + * Dark Goldenrod Preset Color + * + */ + @XmlEnumValue("dkGoldenrod") + DK_GOLDENROD("dkGoldenrod"), + + /** + * Dark Gray Preset Color + * + */ + @XmlEnumValue("dkGray") + DK_GRAY("dkGray"), + + /** + * Dark Green Preset Color + * + */ + @XmlEnumValue("dkGreen") + DK_GREEN("dkGreen"), + + /** + * Dark Khaki Preset Color + * + */ + @XmlEnumValue("dkKhaki") + DK_KHAKI("dkKhaki"), + + /** + * Dark Magenta Preset Color + * + */ + @XmlEnumValue("dkMagenta") + DK_MAGENTA("dkMagenta"), + + /** + * Dark Olive Green Preset Color + * + */ + @XmlEnumValue("dkOliveGreen") + DK_OLIVE_GREEN("dkOliveGreen"), + + /** + * Dark Orange Preset Color + * + */ + @XmlEnumValue("dkOrange") + DK_ORANGE("dkOrange"), + + /** + * Dark Orchid Preset Color + * + */ + @XmlEnumValue("dkOrchid") + DK_ORCHID("dkOrchid"), + + /** + * Dark Red Preset Color + * + */ + @XmlEnumValue("dkRed") + DK_RED("dkRed"), + + /** + * Dark Salmon Preset Color + * + */ + @XmlEnumValue("dkSalmon") + DK_SALMON("dkSalmon"), + + /** + * Dark Sea Green Preset Color + * + */ + @XmlEnumValue("dkSeaGreen") + DK_SEA_GREEN("dkSeaGreen"), + + /** + * Dark Slate Blue Preset Color + * + */ + @XmlEnumValue("dkSlateBlue") + DK_SLATE_BLUE("dkSlateBlue"), + + /** + * Dark Slate Gray Preset Color + * + */ + @XmlEnumValue("dkSlateGray") + DK_SLATE_GRAY("dkSlateGray"), + + /** + * Dark Turquoise Preset Color + * + */ + @XmlEnumValue("dkTurquoise") + DK_TURQUOISE("dkTurquoise"), + + /** + * Dark Violet Preset Color + * + */ + @XmlEnumValue("dkViolet") + DK_VIOLET("dkViolet"), + + /** + * Deep Pink Preset Color + * + */ + @XmlEnumValue("deepPink") + DEEP_PINK("deepPink"), + + /** + * Deep Sky Blue Preset Color + * + */ + @XmlEnumValue("deepSkyBlue") + DEEP_SKY_BLUE("deepSkyBlue"), + + /** + * Dim Gray Preset Color + * + */ + @XmlEnumValue("dimGray") + DIM_GRAY("dimGray"), + + /** + * Dodger Blue Preset Color + * + */ + @XmlEnumValue("dodgerBlue") + DODGER_BLUE("dodgerBlue"), + + /** + * Firebrick Preset Color + * + */ + @XmlEnumValue("firebrick") + FIREBRICK("firebrick"), + + /** + * Floral White Preset Color + * + */ + @XmlEnumValue("floralWhite") + FLORAL_WHITE("floralWhite"), + + /** + * Forest Green Preset Color + * + */ + @XmlEnumValue("forestGreen") + FOREST_GREEN("forestGreen"), + + /** + * Fuchsia Preset Color + * + */ + @XmlEnumValue("fuchsia") + FUCHSIA("fuchsia"), + + /** + * Gainsboro Preset Color + * + */ + @XmlEnumValue("gainsboro") + GAINSBORO("gainsboro"), + + /** + * Ghost White Preset Color + * + */ + @XmlEnumValue("ghostWhite") + GHOST_WHITE("ghostWhite"), + + /** + * Gold Preset Color + * + */ + @XmlEnumValue("gold") + GOLD("gold"), + + /** + * Goldenrod Preset Color + * + */ + @XmlEnumValue("goldenrod") + GOLDENROD("goldenrod"), + + /** + * Gray Preset Color + * + */ + @XmlEnumValue("gray") + GRAY("gray"), + + /** + * Green Preset Color + * + */ + @XmlEnumValue("green") + GREEN("green"), + + /** + * Green Yellow Preset Color + * + */ + @XmlEnumValue("greenYellow") + GREEN_YELLOW("greenYellow"), + + /** + * Honeydew Preset Color + * + */ + @XmlEnumValue("honeydew") + HONEYDEW("honeydew"), + + /** + * Hot Pink Preset Color + * + */ + @XmlEnumValue("hotPink") + HOT_PINK("hotPink"), + + /** + * Indian Red Preset Color + * + */ + @XmlEnumValue("indianRed") + INDIAN_RED("indianRed"), + + /** + * Indigo Preset Color + * + */ + @XmlEnumValue("indigo") + INDIGO("indigo"), + + /** + * Ivory Preset Color + * + */ + @XmlEnumValue("ivory") + IVORY("ivory"), + + /** + * Khaki Preset Color + * + */ + @XmlEnumValue("khaki") + KHAKI("khaki"), + + /** + * Lavender Preset Color + * + */ + @XmlEnumValue("lavender") + LAVENDER("lavender"), + + /** + * Lavender Blush Preset Color + * + */ + @XmlEnumValue("lavenderBlush") + LAVENDER_BLUSH("lavenderBlush"), + + /** + * Lawn Green Preset Color + * + */ + @XmlEnumValue("lawnGreen") + LAWN_GREEN("lawnGreen"), + + /** + * Lemon Chiffon Preset Color + * + */ + @XmlEnumValue("lemonChiffon") + LEMON_CHIFFON("lemonChiffon"), + + /** + * Light Blue Preset Color + * + */ + @XmlEnumValue("ltBlue") + LT_BLUE("ltBlue"), + + /** + * Light Coral Preset Color + * + */ + @XmlEnumValue("ltCoral") + LT_CORAL("ltCoral"), + + /** + * Light Cyan Preset Color + * + */ + @XmlEnumValue("ltCyan") + LT_CYAN("ltCyan"), + + /** + * Light Goldenrod Yellow Preset Color + * + */ + @XmlEnumValue("ltGoldenrodYellow") + LT_GOLDENROD_YELLOW("ltGoldenrodYellow"), + + /** + * Light Gray Preset Color + * + */ + @XmlEnumValue("ltGray") + LT_GRAY("ltGray"), + + /** + * Light Green Preset Color + * + */ + @XmlEnumValue("ltGreen") + LT_GREEN("ltGreen"), + + /** + * Light Pink Preset Color + * + */ + @XmlEnumValue("ltPink") + LT_PINK("ltPink"), + + /** + * Light Salmon Preset Color + * + */ + @XmlEnumValue("ltSalmon") + LT_SALMON("ltSalmon"), + + /** + * Light Sea Green Preset Color + * + */ + @XmlEnumValue("ltSeaGreen") + LT_SEA_GREEN("ltSeaGreen"), + + /** + * Light Sky Blue Preset Color + * + */ + @XmlEnumValue("ltSkyBlue") + LT_SKY_BLUE("ltSkyBlue"), + + /** + * Light Slate Gray Preset Color + * + */ + @XmlEnumValue("ltSlateGray") + LT_SLATE_GRAY("ltSlateGray"), + + /** + * Light Steel Blue Preset Color + * + */ + @XmlEnumValue("ltSteelBlue") + LT_STEEL_BLUE("ltSteelBlue"), + + /** + * Light Yellow Preset Color + * + */ + @XmlEnumValue("ltYellow") + LT_YELLOW("ltYellow"), + + /** + * Lime Preset Color + * + */ + @XmlEnumValue("lime") + LIME("lime"), + + /** + * Lime Green Preset Color + * + */ + @XmlEnumValue("limeGreen") + LIME_GREEN("limeGreen"), + + /** + * Linen Preset Color + * + */ + @XmlEnumValue("linen") + LINEN("linen"), + + /** + * Magenta Preset Color + * + */ + @XmlEnumValue("magenta") + MAGENTA("magenta"), + + /** + * Maroon Preset Color + * + */ + @XmlEnumValue("maroon") + MAROON("maroon"), + + /** + * Medium Aquamarine Preset Color + * + */ + @XmlEnumValue("medAquamarine") + MED_AQUAMARINE("medAquamarine"), + + /** + * Medium Blue Preset Color + * + */ + @XmlEnumValue("medBlue") + MED_BLUE("medBlue"), + + /** + * Medium Orchid Preset Color + * + */ + @XmlEnumValue("medOrchid") + MED_ORCHID("medOrchid"), + + /** + * Medium Purple Preset Color + * + */ + @XmlEnumValue("medPurple") + MED_PURPLE("medPurple"), + + /** + * Medium Sea Green Preset Color + * + */ + @XmlEnumValue("medSeaGreen") + MED_SEA_GREEN("medSeaGreen"), + + /** + * Medium Slate Blue Preset Color + * + */ + @XmlEnumValue("medSlateBlue") + MED_SLATE_BLUE("medSlateBlue"), + + /** + * Medium Spring Green Preset Color + * + */ + @XmlEnumValue("medSpringGreen") + MED_SPRING_GREEN("medSpringGreen"), + + /** + * Medium Turquoise Preset Color + * + */ + @XmlEnumValue("medTurquoise") + MED_TURQUOISE("medTurquoise"), + + /** + * Medium Violet Red Preset Color + * + */ + @XmlEnumValue("medVioletRed") + MED_VIOLET_RED("medVioletRed"), + + /** + * Midnight Blue Preset Color + * + */ + @XmlEnumValue("midnightBlue") + MIDNIGHT_BLUE("midnightBlue"), + + /** + * Mint Cream Preset Color + * + */ + @XmlEnumValue("mintCream") + MINT_CREAM("mintCream"), + + /** + * Misty Rose Preset Color + * + */ + @XmlEnumValue("mistyRose") + MISTY_ROSE("mistyRose"), + + /** + * Moccasin Preset Color + * + */ + @XmlEnumValue("moccasin") + MOCCASIN("moccasin"), + + /** + * Navajo White Preset Color + * + */ + @XmlEnumValue("navajoWhite") + NAVAJO_WHITE("navajoWhite"), + + /** + * Navy Preset Color + * + */ + @XmlEnumValue("navy") + NAVY("navy"), + + /** + * Old Lace Preset Color + * + */ + @XmlEnumValue("oldLace") + OLD_LACE("oldLace"), + + /** + * Olive Preset Color + * + */ + @XmlEnumValue("olive") + OLIVE("olive"), + + /** + * Olive Drab Preset Color + * + */ + @XmlEnumValue("oliveDrab") + OLIVE_DRAB("oliveDrab"), + + /** + * Orange Preset Color + * + */ + @XmlEnumValue("orange") + ORANGE("orange"), + + /** + * Orange Red Preset Color + * + */ + @XmlEnumValue("orangeRed") + ORANGE_RED("orangeRed"), + + /** + * Orchid Preset Color + * + */ + @XmlEnumValue("orchid") + ORCHID("orchid"), + + /** + * Pale Goldenrod Preset Color + * + */ + @XmlEnumValue("paleGoldenrod") + PALE_GOLDENROD("paleGoldenrod"), + + /** + * Pale Green Preset Color + * + */ + @XmlEnumValue("paleGreen") + PALE_GREEN("paleGreen"), + + /** + * Pale Turquoise Preset Color + * + */ + @XmlEnumValue("paleTurquoise") + PALE_TURQUOISE("paleTurquoise"), + + /** + * Pale Violet Red Preset Color + * + */ + @XmlEnumValue("paleVioletRed") + PALE_VIOLET_RED("paleVioletRed"), + + /** + * Papaya Whip Preset Color + * + */ + @XmlEnumValue("papayaWhip") + PAPAYA_WHIP("papayaWhip"), + + /** + * Peach Puff Preset Color + * + */ + @XmlEnumValue("peachPuff") + PEACH_PUFF("peachPuff"), + + /** + * Peru Preset Color + * + */ + @XmlEnumValue("peru") + PERU("peru"), + + /** + * Pink Preset Color + * + */ + @XmlEnumValue("pink") + PINK("pink"), + + /** + * Plum Preset Color + * + */ + @XmlEnumValue("plum") + PLUM("plum"), + + /** + * Powder Blue Preset Color + * + */ + @XmlEnumValue("powderBlue") + POWDER_BLUE("powderBlue"), + + /** + * Purple Preset Color + * + */ + @XmlEnumValue("purple") + PURPLE("purple"), + + /** + * Red Preset Color + * + */ + @XmlEnumValue("red") + RED("red"), + + /** + * Rosy Brown Preset Color + * + */ + @XmlEnumValue("rosyBrown") + ROSY_BROWN("rosyBrown"), + + /** + * Royal Blue Preset Color + * + */ + @XmlEnumValue("royalBlue") + ROYAL_BLUE("royalBlue"), + + /** + * Saddle Brown Preset Color + * + */ + @XmlEnumValue("saddleBrown") + SADDLE_BROWN("saddleBrown"), + + /** + * Salmon Preset Color + * + */ + @XmlEnumValue("salmon") + SALMON("salmon"), + + /** + * Sandy Brown Preset Color + * + */ + @XmlEnumValue("sandyBrown") + SANDY_BROWN("sandyBrown"), + + /** + * Sea Green Preset Color + * + */ + @XmlEnumValue("seaGreen") + SEA_GREEN("seaGreen"), + + /** + * Sea Shell Preset Color + * + */ + @XmlEnumValue("seaShell") + SEA_SHELL("seaShell"), + + /** + * Sienna Preset Color + * + */ + @XmlEnumValue("sienna") + SIENNA("sienna"), + + /** + * Silver Preset Color + * + */ + @XmlEnumValue("silver") + SILVER("silver"), + + /** + * Sky Blue Preset Color + * + */ + @XmlEnumValue("skyBlue") + SKY_BLUE("skyBlue"), + + /** + * Slate Blue Preset Color + * + */ + @XmlEnumValue("slateBlue") + SLATE_BLUE("slateBlue"), + + /** + * Slate Gray Preset Color + * + */ + @XmlEnumValue("slateGray") + SLATE_GRAY("slateGray"), + + /** + * Snow Preset Color + * + */ + @XmlEnumValue("snow") + SNOW("snow"), + + /** + * Spring Green Preset Color + * + */ + @XmlEnumValue("springGreen") + SPRING_GREEN("springGreen"), + + /** + * Steel Blue Preset Color + * + */ + @XmlEnumValue("steelBlue") + STEEL_BLUE("steelBlue"), + + /** + * Tan Preset Color + * + */ + @XmlEnumValue("tan") + TAN("tan"), + + /** + * Teal Preset Color + * + */ + @XmlEnumValue("teal") + TEAL("teal"), + + /** + * Thistle Preset Color + * + */ + @XmlEnumValue("thistle") + THISTLE("thistle"), + + /** + * Tomato Preset Color + * + */ + @XmlEnumValue("tomato") + TOMATO("tomato"), + + /** + * Turquoise Preset Color + * + */ + @XmlEnumValue("turquoise") + TURQUOISE("turquoise"), + + /** + * Violet Preset Color + * + */ + @XmlEnumValue("violet") + VIOLET("violet"), + + /** + * Wheat Preset Color + * + */ + @XmlEnumValue("wheat") + WHEAT("wheat"), + + /** + * White Preset Color + * + */ + @XmlEnumValue("white") + WHITE("white"), + + /** + * White Smoke Preset Color + * + */ + @XmlEnumValue("whiteSmoke") + WHITE_SMOKE("whiteSmoke"), + + /** + * Yellow Preset Color + * + */ + @XmlEnumValue("yellow") + YELLOW("yellow"), + + /** + * Yellow Green Preset Color + * + */ + @XmlEnumValue("yellowGreen") + YELLOW_GREEN("yellowGreen"); + private final String value; + + STPresetColorVal(String v) { + value = v; + } + + public String value() { + return value; + } + + public static STPresetColorVal fromValue(String v) { + for (STPresetColorVal c: STPresetColorVal.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/STRectAlignment.java b/src/java/org/apache/poi/sl/draw/binding/STRectAlignment.java index 688a166baf..4a95ae6ab9 100644 --- a/src/java/org/apache/poi/sl/draw/binding/STRectAlignment.java +++ b/src/java/org/apache/poi/sl/draw/binding/STRectAlignment.java @@ -1,133 +1,133 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for ST_RectAlignment. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="ST_RectAlignment">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
- *     <enumeration value="tl"/>
- *     <enumeration value="t"/>
- *     <enumeration value="tr"/>
- *     <enumeration value="l"/>
- *     <enumeration value="ctr"/>
- *     <enumeration value="r"/>
- *     <enumeration value="bl"/>
- *     <enumeration value="b"/>
- *     <enumeration value="br"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "ST_RectAlignment", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -@XmlEnum -public enum STRectAlignment { - - - /** - * Rectangle Alignment Enum ( Top Left ) - * - */ - @XmlEnumValue("tl") - TL("tl"), - - /** - * Rectangle Alignment Enum ( Top ) - * - */ - @XmlEnumValue("t") - T("t"), - - /** - * Rectangle Alignment Enum ( Top Right ) - * - */ - @XmlEnumValue("tr") - TR("tr"), - - /** - * Rectangle Alignment Enum ( Left ) - * - */ - @XmlEnumValue("l") - L("l"), - - /** - * Rectangle Alignment Enum ( Center ) - * - */ - @XmlEnumValue("ctr") - CTR("ctr"), - - /** - * Rectangle Alignment Enum ( Right ) - * - */ - @XmlEnumValue("r") - R("r"), - - /** - * Rectangle Alignment Enum ( Bottom Left ) - * - */ - @XmlEnumValue("bl") - BL("bl"), - - /** - * Rectangle Alignment Enum ( Bottom ) - * - */ - @XmlEnumValue("b") - B("b"), - - /** - * Rectangle Alignment Enum ( Bottom Right ) - * - */ - @XmlEnumValue("br") - BR("br"); - private final String value; - - STRectAlignment(String v) { - value = v; - } - - public String value() { - return value; - } - - public static STRectAlignment fromValue(String v) { - for (STRectAlignment c: STRectAlignment.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ST_RectAlignment. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="ST_RectAlignment">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
+ *     <enumeration value="tl"/>
+ *     <enumeration value="t"/>
+ *     <enumeration value="tr"/>
+ *     <enumeration value="l"/>
+ *     <enumeration value="ctr"/>
+ *     <enumeration value="r"/>
+ *     <enumeration value="bl"/>
+ *     <enumeration value="b"/>
+ *     <enumeration value="br"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "ST_RectAlignment", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +@XmlEnum +public enum STRectAlignment { + + + /** + * Rectangle Alignment Enum ( Top Left ) + * + */ + @XmlEnumValue("tl") + TL("tl"), + + /** + * Rectangle Alignment Enum ( Top ) + * + */ + @XmlEnumValue("t") + T("t"), + + /** + * Rectangle Alignment Enum ( Top Right ) + * + */ + @XmlEnumValue("tr") + TR("tr"), + + /** + * Rectangle Alignment Enum ( Left ) + * + */ + @XmlEnumValue("l") + L("l"), + + /** + * Rectangle Alignment Enum ( Center ) + * + */ + @XmlEnumValue("ctr") + CTR("ctr"), + + /** + * Rectangle Alignment Enum ( Right ) + * + */ + @XmlEnumValue("r") + R("r"), + + /** + * Rectangle Alignment Enum ( Bottom Left ) + * + */ + @XmlEnumValue("bl") + BL("bl"), + + /** + * Rectangle Alignment Enum ( Bottom ) + * + */ + @XmlEnumValue("b") + B("b"), + + /** + * Rectangle Alignment Enum ( Bottom Right ) + * + */ + @XmlEnumValue("br") + BR("br"); + private final String value; + + STRectAlignment(String v) { + value = v; + } + + public String value() { + return value; + } + + public static STRectAlignment fromValue(String v) { + for (STRectAlignment c: STRectAlignment.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/STSchemeColorVal.java b/src/java/org/apache/poi/sl/draw/binding/STSchemeColorVal.java index 84b88075f1..d7b50ec732 100644 --- a/src/java/org/apache/poi/sl/draw/binding/STSchemeColorVal.java +++ b/src/java/org/apache/poi/sl/draw/binding/STSchemeColorVal.java @@ -1,197 +1,197 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for ST_SchemeColorVal. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="ST_SchemeColorVal">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
- *     <enumeration value="bg1"/>
- *     <enumeration value="tx1"/>
- *     <enumeration value="bg2"/>
- *     <enumeration value="tx2"/>
- *     <enumeration value="accent1"/>
- *     <enumeration value="accent2"/>
- *     <enumeration value="accent3"/>
- *     <enumeration value="accent4"/>
- *     <enumeration value="accent5"/>
- *     <enumeration value="accent6"/>
- *     <enumeration value="hlink"/>
- *     <enumeration value="folHlink"/>
- *     <enumeration value="phClr"/>
- *     <enumeration value="dk1"/>
- *     <enumeration value="lt1"/>
- *     <enumeration value="dk2"/>
- *     <enumeration value="lt2"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "ST_SchemeColorVal", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -@XmlEnum -public enum STSchemeColorVal { - - - /** - * Background Color 1 - * - */ - @XmlEnumValue("bg1") - BG_1("bg1"), - - /** - * Text Color 1 - * - */ - @XmlEnumValue("tx1") - TX_1("tx1"), - - /** - * Background Color 2 - * - */ - @XmlEnumValue("bg2") - BG_2("bg2"), - - /** - * Text Color 2 - * - */ - @XmlEnumValue("tx2") - TX_2("tx2"), - - /** - * Accent Color 1 - * - */ - @XmlEnumValue("accent1") - ACCENT_1("accent1"), - - /** - * Accent Color 2 - * - */ - @XmlEnumValue("accent2") - ACCENT_2("accent2"), - - /** - * Accent Color 3 - * - */ - @XmlEnumValue("accent3") - ACCENT_3("accent3"), - - /** - * Accent Color 4 - * - */ - @XmlEnumValue("accent4") - ACCENT_4("accent4"), - - /** - * Accent Color 5 - * - */ - @XmlEnumValue("accent5") - ACCENT_5("accent5"), - - /** - * Accent Color 6 - * - */ - @XmlEnumValue("accent6") - ACCENT_6("accent6"), - - /** - * Hyperlink Color - * - */ - @XmlEnumValue("hlink") - HLINK("hlink"), - - /** - * Followed Hyperlink Color - * - */ - @XmlEnumValue("folHlink") - FOL_HLINK("folHlink"), - - /** - * Style Color - * - */ - @XmlEnumValue("phClr") - PH_CLR("phClr"), - - /** - * Dark Color 1 - * - */ - @XmlEnumValue("dk1") - DK_1("dk1"), - - /** - * Light Color 1 - * - */ - @XmlEnumValue("lt1") - LT_1("lt1"), - - /** - * Dark Color 2 - * - */ - @XmlEnumValue("dk2") - DK_2("dk2"), - - /** - * Light Color 2 - * - */ - @XmlEnumValue("lt2") - LT_2("lt2"); - private final String value; - - STSchemeColorVal(String v) { - value = v; - } - - public String value() { - return value; - } - - public static STSchemeColorVal fromValue(String v) { - for (STSchemeColorVal c: STSchemeColorVal.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ST_SchemeColorVal. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="ST_SchemeColorVal">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
+ *     <enumeration value="bg1"/>
+ *     <enumeration value="tx1"/>
+ *     <enumeration value="bg2"/>
+ *     <enumeration value="tx2"/>
+ *     <enumeration value="accent1"/>
+ *     <enumeration value="accent2"/>
+ *     <enumeration value="accent3"/>
+ *     <enumeration value="accent4"/>
+ *     <enumeration value="accent5"/>
+ *     <enumeration value="accent6"/>
+ *     <enumeration value="hlink"/>
+ *     <enumeration value="folHlink"/>
+ *     <enumeration value="phClr"/>
+ *     <enumeration value="dk1"/>
+ *     <enumeration value="lt1"/>
+ *     <enumeration value="dk2"/>
+ *     <enumeration value="lt2"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "ST_SchemeColorVal", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +@XmlEnum +public enum STSchemeColorVal { + + + /** + * Background Color 1 + * + */ + @XmlEnumValue("bg1") + BG_1("bg1"), + + /** + * Text Color 1 + * + */ + @XmlEnumValue("tx1") + TX_1("tx1"), + + /** + * Background Color 2 + * + */ + @XmlEnumValue("bg2") + BG_2("bg2"), + + /** + * Text Color 2 + * + */ + @XmlEnumValue("tx2") + TX_2("tx2"), + + /** + * Accent Color 1 + * + */ + @XmlEnumValue("accent1") + ACCENT_1("accent1"), + + /** + * Accent Color 2 + * + */ + @XmlEnumValue("accent2") + ACCENT_2("accent2"), + + /** + * Accent Color 3 + * + */ + @XmlEnumValue("accent3") + ACCENT_3("accent3"), + + /** + * Accent Color 4 + * + */ + @XmlEnumValue("accent4") + ACCENT_4("accent4"), + + /** + * Accent Color 5 + * + */ + @XmlEnumValue("accent5") + ACCENT_5("accent5"), + + /** + * Accent Color 6 + * + */ + @XmlEnumValue("accent6") + ACCENT_6("accent6"), + + /** + * Hyperlink Color + * + */ + @XmlEnumValue("hlink") + HLINK("hlink"), + + /** + * Followed Hyperlink Color + * + */ + @XmlEnumValue("folHlink") + FOL_HLINK("folHlink"), + + /** + * Style Color + * + */ + @XmlEnumValue("phClr") + PH_CLR("phClr"), + + /** + * Dark Color 1 + * + */ + @XmlEnumValue("dk1") + DK_1("dk1"), + + /** + * Light Color 1 + * + */ + @XmlEnumValue("lt1") + LT_1("lt1"), + + /** + * Dark Color 2 + * + */ + @XmlEnumValue("dk2") + DK_2("dk2"), + + /** + * Light Color 2 + * + */ + @XmlEnumValue("lt2") + LT_2("lt2"); + private final String value; + + STSchemeColorVal(String v) { + value = v; + } + + public String value() { + return value; + } + + public static STSchemeColorVal fromValue(String v) { + for (STSchemeColorVal c: STSchemeColorVal.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/STShapeType.java b/src/java/org/apache/poi/sl/draw/binding/STShapeType.java index 559b0a1591..f160ec560b 100644 --- a/src/java/org/apache/poi/sl/draw/binding/STShapeType.java +++ b/src/java/org/apache/poi/sl/draw/binding/STShapeType.java @@ -1,1557 +1,1557 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for ST_ShapeType. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="ST_ShapeType">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
- *     <enumeration value="line"/>
- *     <enumeration value="lineInv"/>
- *     <enumeration value="triangle"/>
- *     <enumeration value="rtTriangle"/>
- *     <enumeration value="rect"/>
- *     <enumeration value="diamond"/>
- *     <enumeration value="parallelogram"/>
- *     <enumeration value="trapezoid"/>
- *     <enumeration value="nonIsoscelesTrapezoid"/>
- *     <enumeration value="pentagon"/>
- *     <enumeration value="hexagon"/>
- *     <enumeration value="heptagon"/>
- *     <enumeration value="octagon"/>
- *     <enumeration value="decagon"/>
- *     <enumeration value="dodecagon"/>
- *     <enumeration value="star4"/>
- *     <enumeration value="star5"/>
- *     <enumeration value="star6"/>
- *     <enumeration value="star7"/>
- *     <enumeration value="star8"/>
- *     <enumeration value="star10"/>
- *     <enumeration value="star12"/>
- *     <enumeration value="star16"/>
- *     <enumeration value="star24"/>
- *     <enumeration value="star32"/>
- *     <enumeration value="roundRect"/>
- *     <enumeration value="round1Rect"/>
- *     <enumeration value="round2SameRect"/>
- *     <enumeration value="round2DiagRect"/>
- *     <enumeration value="snipRoundRect"/>
- *     <enumeration value="snip1Rect"/>
- *     <enumeration value="snip2SameRect"/>
- *     <enumeration value="snip2DiagRect"/>
- *     <enumeration value="plaque"/>
- *     <enumeration value="ellipse"/>
- *     <enumeration value="teardrop"/>
- *     <enumeration value="homePlate"/>
- *     <enumeration value="chevron"/>
- *     <enumeration value="pieWedge"/>
- *     <enumeration value="pie"/>
- *     <enumeration value="blockArc"/>
- *     <enumeration value="donut"/>
- *     <enumeration value="noSmoking"/>
- *     <enumeration value="rightArrow"/>
- *     <enumeration value="leftArrow"/>
- *     <enumeration value="upArrow"/>
- *     <enumeration value="downArrow"/>
- *     <enumeration value="stripedRightArrow"/>
- *     <enumeration value="notchedRightArrow"/>
- *     <enumeration value="bentUpArrow"/>
- *     <enumeration value="leftRightArrow"/>
- *     <enumeration value="upDownArrow"/>
- *     <enumeration value="leftUpArrow"/>
- *     <enumeration value="leftRightUpArrow"/>
- *     <enumeration value="quadArrow"/>
- *     <enumeration value="leftArrowCallout"/>
- *     <enumeration value="rightArrowCallout"/>
- *     <enumeration value="upArrowCallout"/>
- *     <enumeration value="downArrowCallout"/>
- *     <enumeration value="leftRightArrowCallout"/>
- *     <enumeration value="upDownArrowCallout"/>
- *     <enumeration value="quadArrowCallout"/>
- *     <enumeration value="bentArrow"/>
- *     <enumeration value="uturnArrow"/>
- *     <enumeration value="circularArrow"/>
- *     <enumeration value="leftCircularArrow"/>
- *     <enumeration value="leftRightCircularArrow"/>
- *     <enumeration value="curvedRightArrow"/>
- *     <enumeration value="curvedLeftArrow"/>
- *     <enumeration value="curvedUpArrow"/>
- *     <enumeration value="curvedDownArrow"/>
- *     <enumeration value="swooshArrow"/>
- *     <enumeration value="cube"/>
- *     <enumeration value="can"/>
- *     <enumeration value="lightningBolt"/>
- *     <enumeration value="heart"/>
- *     <enumeration value="sun"/>
- *     <enumeration value="moon"/>
- *     <enumeration value="smileyFace"/>
- *     <enumeration value="irregularSeal1"/>
- *     <enumeration value="irregularSeal2"/>
- *     <enumeration value="foldedCorner"/>
- *     <enumeration value="bevel"/>
- *     <enumeration value="frame"/>
- *     <enumeration value="halfFrame"/>
- *     <enumeration value="corner"/>
- *     <enumeration value="diagStripe"/>
- *     <enumeration value="chord"/>
- *     <enumeration value="arc"/>
- *     <enumeration value="leftBracket"/>
- *     <enumeration value="rightBracket"/>
- *     <enumeration value="leftBrace"/>
- *     <enumeration value="rightBrace"/>
- *     <enumeration value="bracketPair"/>
- *     <enumeration value="bracePair"/>
- *     <enumeration value="straightConnector1"/>
- *     <enumeration value="bentConnector2"/>
- *     <enumeration value="bentConnector3"/>
- *     <enumeration value="bentConnector4"/>
- *     <enumeration value="bentConnector5"/>
- *     <enumeration value="curvedConnector2"/>
- *     <enumeration value="curvedConnector3"/>
- *     <enumeration value="curvedConnector4"/>
- *     <enumeration value="curvedConnector5"/>
- *     <enumeration value="callout1"/>
- *     <enumeration value="callout2"/>
- *     <enumeration value="callout3"/>
- *     <enumeration value="accentCallout1"/>
- *     <enumeration value="accentCallout2"/>
- *     <enumeration value="accentCallout3"/>
- *     <enumeration value="borderCallout1"/>
- *     <enumeration value="borderCallout2"/>
- *     <enumeration value="borderCallout3"/>
- *     <enumeration value="accentBorderCallout1"/>
- *     <enumeration value="accentBorderCallout2"/>
- *     <enumeration value="accentBorderCallout3"/>
- *     <enumeration value="wedgeRectCallout"/>
- *     <enumeration value="wedgeRoundRectCallout"/>
- *     <enumeration value="wedgeEllipseCallout"/>
- *     <enumeration value="cloudCallout"/>
- *     <enumeration value="cloud"/>
- *     <enumeration value="ribbon"/>
- *     <enumeration value="ribbon2"/>
- *     <enumeration value="ellipseRibbon"/>
- *     <enumeration value="ellipseRibbon2"/>
- *     <enumeration value="leftRightRibbon"/>
- *     <enumeration value="verticalScroll"/>
- *     <enumeration value="horizontalScroll"/>
- *     <enumeration value="wave"/>
- *     <enumeration value="doubleWave"/>
- *     <enumeration value="plus"/>
- *     <enumeration value="flowChartProcess"/>
- *     <enumeration value="flowChartDecision"/>
- *     <enumeration value="flowChartInputOutput"/>
- *     <enumeration value="flowChartPredefinedProcess"/>
- *     <enumeration value="flowChartInternalStorage"/>
- *     <enumeration value="flowChartDocument"/>
- *     <enumeration value="flowChartMultidocument"/>
- *     <enumeration value="flowChartTerminator"/>
- *     <enumeration value="flowChartPreparation"/>
- *     <enumeration value="flowChartManualInput"/>
- *     <enumeration value="flowChartManualOperation"/>
- *     <enumeration value="flowChartConnector"/>
- *     <enumeration value="flowChartPunchedCard"/>
- *     <enumeration value="flowChartPunchedTape"/>
- *     <enumeration value="flowChartSummingJunction"/>
- *     <enumeration value="flowChartOr"/>
- *     <enumeration value="flowChartCollate"/>
- *     <enumeration value="flowChartSort"/>
- *     <enumeration value="flowChartExtract"/>
- *     <enumeration value="flowChartMerge"/>
- *     <enumeration value="flowChartOfflineStorage"/>
- *     <enumeration value="flowChartOnlineStorage"/>
- *     <enumeration value="flowChartMagneticTape"/>
- *     <enumeration value="flowChartMagneticDisk"/>
- *     <enumeration value="flowChartMagneticDrum"/>
- *     <enumeration value="flowChartDisplay"/>
- *     <enumeration value="flowChartDelay"/>
- *     <enumeration value="flowChartAlternateProcess"/>
- *     <enumeration value="flowChartOffpageConnector"/>
- *     <enumeration value="actionButtonBlank"/>
- *     <enumeration value="actionButtonHome"/>
- *     <enumeration value="actionButtonHelp"/>
- *     <enumeration value="actionButtonInformation"/>
- *     <enumeration value="actionButtonForwardNext"/>
- *     <enumeration value="actionButtonBackPrevious"/>
- *     <enumeration value="actionButtonEnd"/>
- *     <enumeration value="actionButtonBeginning"/>
- *     <enumeration value="actionButtonReturn"/>
- *     <enumeration value="actionButtonDocument"/>
- *     <enumeration value="actionButtonSound"/>
- *     <enumeration value="actionButtonMovie"/>
- *     <enumeration value="gear6"/>
- *     <enumeration value="gear9"/>
- *     <enumeration value="funnel"/>
- *     <enumeration value="mathPlus"/>
- *     <enumeration value="mathMinus"/>
- *     <enumeration value="mathMultiply"/>
- *     <enumeration value="mathDivide"/>
- *     <enumeration value="mathEqual"/>
- *     <enumeration value="mathNotEqual"/>
- *     <enumeration value="cornerTabs"/>
- *     <enumeration value="squareTabs"/>
- *     <enumeration value="plaqueTabs"/>
- *     <enumeration value="chartX"/>
- *     <enumeration value="chartStar"/>
- *     <enumeration value="chartPlus"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "ST_ShapeType", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -@XmlEnum -public enum STShapeType { - - - /** - * Line Shape - * - */ - @XmlEnumValue("line") - LINE("line"), - - /** - * Line Inverse Shape - * - */ - @XmlEnumValue("lineInv") - LINE_INV("lineInv"), - - /** - * Triangle Shape - * - */ - @XmlEnumValue("triangle") - TRIANGLE("triangle"), - - /** - * Right Triangle Shape - * - */ - @XmlEnumValue("rtTriangle") - RT_TRIANGLE("rtTriangle"), - - /** - * Rectangle Shape - * - */ - @XmlEnumValue("rect") - RECT("rect"), - - /** - * Diamond Shape - * - */ - @XmlEnumValue("diamond") - DIAMOND("diamond"), - - /** - * Parallelogram Shape - * - */ - @XmlEnumValue("parallelogram") - PARALLELOGRAM("parallelogram"), - - /** - * Trapezoid Shape - * - */ - @XmlEnumValue("trapezoid") - TRAPEZOID("trapezoid"), - - /** - * Non-Isosceles Trapezoid Shape - * - */ - @XmlEnumValue("nonIsoscelesTrapezoid") - NON_ISOSCELES_TRAPEZOID("nonIsoscelesTrapezoid"), - - /** - * Pentagon Shape - * - */ - @XmlEnumValue("pentagon") - PENTAGON("pentagon"), - - /** - * Hexagon Shape - * - */ - @XmlEnumValue("hexagon") - HEXAGON("hexagon"), - - /** - * Heptagon Shape - * - */ - @XmlEnumValue("heptagon") - HEPTAGON("heptagon"), - - /** - * Octagon Shape - * - */ - @XmlEnumValue("octagon") - OCTAGON("octagon"), - - /** - * Decagon Shape - * - */ - @XmlEnumValue("decagon") - DECAGON("decagon"), - - /** - * Dodecagon Shape - * - */ - @XmlEnumValue("dodecagon") - DODECAGON("dodecagon"), - - /** - * Four Pointed Star Shape - * - */ - @XmlEnumValue("star4") - STAR_4("star4"), - - /** - * Five Pointed Star Shape - * - */ - @XmlEnumValue("star5") - STAR_5("star5"), - - /** - * Six Pointed Star Shape - * - */ - @XmlEnumValue("star6") - STAR_6("star6"), - - /** - * Seven Pointed Star Shape - * - */ - @XmlEnumValue("star7") - STAR_7("star7"), - - /** - * Eight Pointed Star Shape - * - */ - @XmlEnumValue("star8") - STAR_8("star8"), - - /** - * Ten Pointed Star Shape - * - */ - @XmlEnumValue("star10") - STAR_10("star10"), - - /** - * Twelve Pointed Star Shape - * - */ - @XmlEnumValue("star12") - STAR_12("star12"), - - /** - * Sixteen Pointed Star Shape - * - */ - @XmlEnumValue("star16") - STAR_16("star16"), - - /** - * Twenty Four Pointed Star Shape - * - */ - @XmlEnumValue("star24") - STAR_24("star24"), - - /** - * Thirty Two Pointed Star Shape - * - */ - @XmlEnumValue("star32") - STAR_32("star32"), - - /** - * Round Corner Rectangle Shape - * - */ - @XmlEnumValue("roundRect") - ROUND_RECT("roundRect"), - - /** - * One Round Corner Rectangle Shape - * - */ - @XmlEnumValue("round1Rect") - ROUND_1_RECT("round1Rect"), - - /** - * Two Same-side Round Corner Rectangle Shape - * - */ - @XmlEnumValue("round2SameRect") - ROUND_2_SAME_RECT("round2SameRect"), - - /** - * Two Diagonal Round Corner Rectangle Shape - * - */ - @XmlEnumValue("round2DiagRect") - ROUND_2_DIAG_RECT("round2DiagRect"), - - /** - * One Snip One Round Corner Rectangle Shape - * - */ - @XmlEnumValue("snipRoundRect") - SNIP_ROUND_RECT("snipRoundRect"), - - /** - * One Snip Corner Rectangle Shape - * - */ - @XmlEnumValue("snip1Rect") - SNIP_1_RECT("snip1Rect"), - - /** - * Two Same-side Snip Corner Rectangle Shape - * - */ - @XmlEnumValue("snip2SameRect") - SNIP_2_SAME_RECT("snip2SameRect"), - - /** - * Two Diagonal Snip Corner Rectangle Shape - * - */ - @XmlEnumValue("snip2DiagRect") - SNIP_2_DIAG_RECT("snip2DiagRect"), - - /** - * Plaque Shape - * - */ - @XmlEnumValue("plaque") - PLAQUE("plaque"), - - /** - * Ellipse Shape - * - */ - @XmlEnumValue("ellipse") - ELLIPSE("ellipse"), - - /** - * Teardrop Shape - * - */ - @XmlEnumValue("teardrop") - TEARDROP("teardrop"), - - /** - * Home Plate Shape - * - */ - @XmlEnumValue("homePlate") - HOME_PLATE("homePlate"), - - /** - * Chevron Shape - * - */ - @XmlEnumValue("chevron") - CHEVRON("chevron"), - - /** - * Pie Wedge Shape - * - */ - @XmlEnumValue("pieWedge") - PIE_WEDGE("pieWedge"), - - /** - * Pie Shape - * - */ - @XmlEnumValue("pie") - PIE("pie"), - - /** - * Block Arc Shape - * - */ - @XmlEnumValue("blockArc") - BLOCK_ARC("blockArc"), - - /** - * Donut Shape - * - */ - @XmlEnumValue("donut") - DONUT("donut"), - - /** - * No Smoking Shape - * - */ - @XmlEnumValue("noSmoking") - NO_SMOKING("noSmoking"), - - /** - * Right Arrow Shape - * - */ - @XmlEnumValue("rightArrow") - RIGHT_ARROW("rightArrow"), - - /** - * Left Arrow Shape - * - */ - @XmlEnumValue("leftArrow") - LEFT_ARROW("leftArrow"), - - /** - * Up Arrow Shape - * - */ - @XmlEnumValue("upArrow") - UP_ARROW("upArrow"), - - /** - * Down Arrow Shape - * - */ - @XmlEnumValue("downArrow") - DOWN_ARROW("downArrow"), - - /** - * Striped Right Arrow Shape - * - */ - @XmlEnumValue("stripedRightArrow") - STRIPED_RIGHT_ARROW("stripedRightArrow"), - - /** - * Notched Right Arrow Shape - * - */ - @XmlEnumValue("notchedRightArrow") - NOTCHED_RIGHT_ARROW("notchedRightArrow"), - - /** - * Bent Up Arrow Shape - * - */ - @XmlEnumValue("bentUpArrow") - BENT_UP_ARROW("bentUpArrow"), - - /** - * Left Right Arrow Shape - * - */ - @XmlEnumValue("leftRightArrow") - LEFT_RIGHT_ARROW("leftRightArrow"), - - /** - * Up Down Arrow Shape - * - */ - @XmlEnumValue("upDownArrow") - UP_DOWN_ARROW("upDownArrow"), - - /** - * Left Up Arrow Shape - * - */ - @XmlEnumValue("leftUpArrow") - LEFT_UP_ARROW("leftUpArrow"), - - /** - * Left Right Up Arrow Shape - * - */ - @XmlEnumValue("leftRightUpArrow") - LEFT_RIGHT_UP_ARROW("leftRightUpArrow"), - - /** - * Quad-Arrow Shape - * - */ - @XmlEnumValue("quadArrow") - QUAD_ARROW("quadArrow"), - - /** - * Callout Left Arrow Shape - * - */ - @XmlEnumValue("leftArrowCallout") - LEFT_ARROW_CALLOUT("leftArrowCallout"), - - /** - * Callout Right Arrow Shape - * - */ - @XmlEnumValue("rightArrowCallout") - RIGHT_ARROW_CALLOUT("rightArrowCallout"), - - /** - * Callout Up Arrow Shape - * - */ - @XmlEnumValue("upArrowCallout") - UP_ARROW_CALLOUT("upArrowCallout"), - - /** - * Callout Down Arrow Shape - * - */ - @XmlEnumValue("downArrowCallout") - DOWN_ARROW_CALLOUT("downArrowCallout"), - - /** - * Callout Left Right Arrow Shape - * - */ - @XmlEnumValue("leftRightArrowCallout") - LEFT_RIGHT_ARROW_CALLOUT("leftRightArrowCallout"), - - /** - * Callout Up Down Arrow Shape - * - */ - @XmlEnumValue("upDownArrowCallout") - UP_DOWN_ARROW_CALLOUT("upDownArrowCallout"), - - /** - * Callout Quad-Arrow Shape - * - */ - @XmlEnumValue("quadArrowCallout") - QUAD_ARROW_CALLOUT("quadArrowCallout"), - - /** - * Bent Arrow Shape - * - */ - @XmlEnumValue("bentArrow") - BENT_ARROW("bentArrow"), - - /** - * U-Turn Arrow Shape - * - */ - @XmlEnumValue("uturnArrow") - UTURN_ARROW("uturnArrow"), - - /** - * Circular Arrow Shape - * - */ - @XmlEnumValue("circularArrow") - CIRCULAR_ARROW("circularArrow"), - - /** - * Left Circular Arrow Shape - * - */ - @XmlEnumValue("leftCircularArrow") - LEFT_CIRCULAR_ARROW("leftCircularArrow"), - - /** - * Left Right Circular Arrow Shape - * - */ - @XmlEnumValue("leftRightCircularArrow") - LEFT_RIGHT_CIRCULAR_ARROW("leftRightCircularArrow"), - - /** - * Curved Right Arrow Shape - * - */ - @XmlEnumValue("curvedRightArrow") - CURVED_RIGHT_ARROW("curvedRightArrow"), - - /** - * Curved Left Arrow Shape - * - */ - @XmlEnumValue("curvedLeftArrow") - CURVED_LEFT_ARROW("curvedLeftArrow"), - - /** - * Curved Up Arrow Shape - * - */ - @XmlEnumValue("curvedUpArrow") - CURVED_UP_ARROW("curvedUpArrow"), - - /** - * Curved Down Arrow Shape - * - */ - @XmlEnumValue("curvedDownArrow") - CURVED_DOWN_ARROW("curvedDownArrow"), - - /** - * Swoosh Arrow Shape - * - */ - @XmlEnumValue("swooshArrow") - SWOOSH_ARROW("swooshArrow"), - - /** - * Cube Shape - * - */ - @XmlEnumValue("cube") - CUBE("cube"), - - /** - * Can Shape - * - */ - @XmlEnumValue("can") - CAN("can"), - - /** - * Lightning Bolt Shape - * - */ - @XmlEnumValue("lightningBolt") - LIGHTNING_BOLT("lightningBolt"), - - /** - * Heart Shape - * - */ - @XmlEnumValue("heart") - HEART("heart"), - - /** - * Sun Shape - * - */ - @XmlEnumValue("sun") - SUN("sun"), - - /** - * Moon Shape - * - */ - @XmlEnumValue("moon") - MOON("moon"), - - /** - * Smiley Face Shape - * - */ - @XmlEnumValue("smileyFace") - SMILEY_FACE("smileyFace"), - - /** - * Irregular Seal 1 Shape - * - */ - @XmlEnumValue("irregularSeal1") - IRREGULAR_SEAL_1("irregularSeal1"), - - /** - * Irregular Seal 2 Shape - * - */ - @XmlEnumValue("irregularSeal2") - IRREGULAR_SEAL_2("irregularSeal2"), - - /** - * Folded Corner Shape - * - */ - @XmlEnumValue("foldedCorner") - FOLDED_CORNER("foldedCorner"), - - /** - * Bevel Shape - * - */ - @XmlEnumValue("bevel") - BEVEL("bevel"), - - /** - * Frame Shape - * - */ - @XmlEnumValue("frame") - FRAME("frame"), - - /** - * Half Frame Shape - * - */ - @XmlEnumValue("halfFrame") - HALF_FRAME("halfFrame"), - - /** - * Corner Shape - * - */ - @XmlEnumValue("corner") - CORNER("corner"), - - /** - * Diagonal Stripe Shape - * - */ - @XmlEnumValue("diagStripe") - DIAG_STRIPE("diagStripe"), - - /** - * Chord Shape - * - */ - @XmlEnumValue("chord") - CHORD("chord"), - - /** - * Curved Arc Shape - * - */ - @XmlEnumValue("arc") - ARC("arc"), - - /** - * Left Bracket Shape - * - */ - @XmlEnumValue("leftBracket") - LEFT_BRACKET("leftBracket"), - - /** - * Right Bracket Shape - * - */ - @XmlEnumValue("rightBracket") - RIGHT_BRACKET("rightBracket"), - - /** - * Left Brace Shape - * - */ - @XmlEnumValue("leftBrace") - LEFT_BRACE("leftBrace"), - - /** - * Right Brace Shape - * - */ - @XmlEnumValue("rightBrace") - RIGHT_BRACE("rightBrace"), - - /** - * Bracket Pair Shape - * - */ - @XmlEnumValue("bracketPair") - BRACKET_PAIR("bracketPair"), - - /** - * Brace Pair Shape - * - */ - @XmlEnumValue("bracePair") - BRACE_PAIR("bracePair"), - - /** - * Straight Connector 1 Shape - * - */ - @XmlEnumValue("straightConnector1") - STRAIGHT_CONNECTOR_1("straightConnector1"), - - /** - * Bent Connector 2 Shape - * - */ - @XmlEnumValue("bentConnector2") - BENT_CONNECTOR_2("bentConnector2"), - - /** - * Bent Connector 3 Shape - * - */ - @XmlEnumValue("bentConnector3") - BENT_CONNECTOR_3("bentConnector3"), - - /** - * Bent Connector 4 Shape - * - */ - @XmlEnumValue("bentConnector4") - BENT_CONNECTOR_4("bentConnector4"), - - /** - * Bent Connector 5 Shape - * - */ - @XmlEnumValue("bentConnector5") - BENT_CONNECTOR_5("bentConnector5"), - - /** - * Curved Connector 2 Shape - * - */ - @XmlEnumValue("curvedConnector2") - CURVED_CONNECTOR_2("curvedConnector2"), - - /** - * Curved Connector 3 Shape - * - */ - @XmlEnumValue("curvedConnector3") - CURVED_CONNECTOR_3("curvedConnector3"), - - /** - * Curved Connector 4 Shape - * - */ - @XmlEnumValue("curvedConnector4") - CURVED_CONNECTOR_4("curvedConnector4"), - - /** - * Curved Connector 5 Shape - * - */ - @XmlEnumValue("curvedConnector5") - CURVED_CONNECTOR_5("curvedConnector5"), - - /** - * Callout 1 Shape - * - */ - @XmlEnumValue("callout1") - CALLOUT_1("callout1"), - - /** - * Callout 2 Shape - * - */ - @XmlEnumValue("callout2") - CALLOUT_2("callout2"), - - /** - * Callout 3 Shape - * - */ - @XmlEnumValue("callout3") - CALLOUT_3("callout3"), - - /** - * Callout 1 Shape - * - */ - @XmlEnumValue("accentCallout1") - ACCENT_CALLOUT_1("accentCallout1"), - - /** - * Callout 2 Shape - * - */ - @XmlEnumValue("accentCallout2") - ACCENT_CALLOUT_2("accentCallout2"), - - /** - * Callout 3 Shape - * - */ - @XmlEnumValue("accentCallout3") - ACCENT_CALLOUT_3("accentCallout3"), - - /** - * Callout 1 with Border Shape - * - */ - @XmlEnumValue("borderCallout1") - BORDER_CALLOUT_1("borderCallout1"), - - /** - * Callout 2 with Border Shape - * - */ - @XmlEnumValue("borderCallout2") - BORDER_CALLOUT_2("borderCallout2"), - - /** - * Callout 3 with Border Shape - * - */ - @XmlEnumValue("borderCallout3") - BORDER_CALLOUT_3("borderCallout3"), - - /** - * Callout 1 with Border and Accent Shape - * - */ - @XmlEnumValue("accentBorderCallout1") - ACCENT_BORDER_CALLOUT_1("accentBorderCallout1"), - - /** - * Callout 2 with Border and Accent Shape - * - */ - @XmlEnumValue("accentBorderCallout2") - ACCENT_BORDER_CALLOUT_2("accentBorderCallout2"), - - /** - * Callout 3 with Border and Accent Shape - * - */ - @XmlEnumValue("accentBorderCallout3") - ACCENT_BORDER_CALLOUT_3("accentBorderCallout3"), - - /** - * Callout Wedge Rectangle Shape - * - */ - @XmlEnumValue("wedgeRectCallout") - WEDGE_RECT_CALLOUT("wedgeRectCallout"), - - /** - * Callout Wedge Round Rectangle Shape - * - */ - @XmlEnumValue("wedgeRoundRectCallout") - WEDGE_ROUND_RECT_CALLOUT("wedgeRoundRectCallout"), - - /** - * Callout Wedge Ellipse Shape - * - */ - @XmlEnumValue("wedgeEllipseCallout") - WEDGE_ELLIPSE_CALLOUT("wedgeEllipseCallout"), - - /** - * Callout Cloud Shape - * - */ - @XmlEnumValue("cloudCallout") - CLOUD_CALLOUT("cloudCallout"), - - /** - * Cloud Shape - * - */ - @XmlEnumValue("cloud") - CLOUD("cloud"), - - /** - * Ribbon Shape - * - */ - @XmlEnumValue("ribbon") - RIBBON("ribbon"), - - /** - * Ribbon 2 Shape - * - */ - @XmlEnumValue("ribbon2") - RIBBON_2("ribbon2"), - - /** - * Ellipse Ribbon Shape - * - */ - @XmlEnumValue("ellipseRibbon") - ELLIPSE_RIBBON("ellipseRibbon"), - - /** - * Ellipse Ribbon 2 Shape - * - */ - @XmlEnumValue("ellipseRibbon2") - ELLIPSE_RIBBON_2("ellipseRibbon2"), - - /** - * Left Right Ribbon Shape - * - */ - @XmlEnumValue("leftRightRibbon") - LEFT_RIGHT_RIBBON("leftRightRibbon"), - - /** - * Vertical Scroll Shape - * - */ - @XmlEnumValue("verticalScroll") - VERTICAL_SCROLL("verticalScroll"), - - /** - * Horizontal Scroll Shape - * - */ - @XmlEnumValue("horizontalScroll") - HORIZONTAL_SCROLL("horizontalScroll"), - - /** - * Wave Shape - * - */ - @XmlEnumValue("wave") - WAVE("wave"), - - /** - * Double Wave Shape - * - */ - @XmlEnumValue("doubleWave") - DOUBLE_WAVE("doubleWave"), - - /** - * Plus Shape - * - */ - @XmlEnumValue("plus") - PLUS("plus"), - - /** - * Process Flow Shape - * - */ - @XmlEnumValue("flowChartProcess") - FLOW_CHART_PROCESS("flowChartProcess"), - - /** - * Decision Flow Shape - * - */ - @XmlEnumValue("flowChartDecision") - FLOW_CHART_DECISION("flowChartDecision"), - - /** - * Input Output Flow Shape - * - */ - @XmlEnumValue("flowChartInputOutput") - FLOW_CHART_INPUT_OUTPUT("flowChartInputOutput"), - - /** - * Predefined Process Flow Shape - * - */ - @XmlEnumValue("flowChartPredefinedProcess") - FLOW_CHART_PREDEFINED_PROCESS("flowChartPredefinedProcess"), - - /** - * Internal Storage Flow Shape - * - */ - @XmlEnumValue("flowChartInternalStorage") - FLOW_CHART_INTERNAL_STORAGE("flowChartInternalStorage"), - - /** - * Document Flow Shape - * - */ - @XmlEnumValue("flowChartDocument") - FLOW_CHART_DOCUMENT("flowChartDocument"), - - /** - * Multi-Document Flow Shape - * - */ - @XmlEnumValue("flowChartMultidocument") - FLOW_CHART_MULTIDOCUMENT("flowChartMultidocument"), - - /** - * Terminator Flow Shape - * - */ - @XmlEnumValue("flowChartTerminator") - FLOW_CHART_TERMINATOR("flowChartTerminator"), - - /** - * Preparation Flow Shape - * - */ - @XmlEnumValue("flowChartPreparation") - FLOW_CHART_PREPARATION("flowChartPreparation"), - - /** - * Manual Input Flow Shape - * - */ - @XmlEnumValue("flowChartManualInput") - FLOW_CHART_MANUAL_INPUT("flowChartManualInput"), - - /** - * Manual Operation Flow Shape - * - */ - @XmlEnumValue("flowChartManualOperation") - FLOW_CHART_MANUAL_OPERATION("flowChartManualOperation"), - - /** - * Connector Flow Shape - * - */ - @XmlEnumValue("flowChartConnector") - FLOW_CHART_CONNECTOR("flowChartConnector"), - - /** - * Punched Card Flow Shape - * - */ - @XmlEnumValue("flowChartPunchedCard") - FLOW_CHART_PUNCHED_CARD("flowChartPunchedCard"), - - /** - * Punched Tape Flow Shape - * - */ - @XmlEnumValue("flowChartPunchedTape") - FLOW_CHART_PUNCHED_TAPE("flowChartPunchedTape"), - - /** - * Summing Junction Flow Shape - * - */ - @XmlEnumValue("flowChartSummingJunction") - FLOW_CHART_SUMMING_JUNCTION("flowChartSummingJunction"), - - /** - * Or Flow Shape - * - */ - @XmlEnumValue("flowChartOr") - FLOW_CHART_OR("flowChartOr"), - - /** - * Collate Flow Shape - * - */ - @XmlEnumValue("flowChartCollate") - FLOW_CHART_COLLATE("flowChartCollate"), - - /** - * Sort Flow Shape - * - */ - @XmlEnumValue("flowChartSort") - FLOW_CHART_SORT("flowChartSort"), - - /** - * Extract Flow Shape - * - */ - @XmlEnumValue("flowChartExtract") - FLOW_CHART_EXTRACT("flowChartExtract"), - - /** - * Merge Flow Shape - * - */ - @XmlEnumValue("flowChartMerge") - FLOW_CHART_MERGE("flowChartMerge"), - - /** - * Offline Storage Flow Shape - * - */ - @XmlEnumValue("flowChartOfflineStorage") - FLOW_CHART_OFFLINE_STORAGE("flowChartOfflineStorage"), - - /** - * Online Storage Flow Shape - * - */ - @XmlEnumValue("flowChartOnlineStorage") - FLOW_CHART_ONLINE_STORAGE("flowChartOnlineStorage"), - - /** - * Magnetic Tape Flow Shape - * - */ - @XmlEnumValue("flowChartMagneticTape") - FLOW_CHART_MAGNETIC_TAPE("flowChartMagneticTape"), - - /** - * Magnetic Disk Flow Shape - * - */ - @XmlEnumValue("flowChartMagneticDisk") - FLOW_CHART_MAGNETIC_DISK("flowChartMagneticDisk"), - - /** - * Magnetic Drum Flow Shape - * - */ - @XmlEnumValue("flowChartMagneticDrum") - FLOW_CHART_MAGNETIC_DRUM("flowChartMagneticDrum"), - - /** - * Display Flow Shape - * - */ - @XmlEnumValue("flowChartDisplay") - FLOW_CHART_DISPLAY("flowChartDisplay"), - - /** - * Delay Flow Shape - * - */ - @XmlEnumValue("flowChartDelay") - FLOW_CHART_DELAY("flowChartDelay"), - - /** - * Alternate Process Flow Shape - * - */ - @XmlEnumValue("flowChartAlternateProcess") - FLOW_CHART_ALTERNATE_PROCESS("flowChartAlternateProcess"), - - /** - * Off-Page Connector Flow Shape - * - */ - @XmlEnumValue("flowChartOffpageConnector") - FLOW_CHART_OFFPAGE_CONNECTOR("flowChartOffpageConnector"), - - /** - * Blank Button Shape - * - */ - @XmlEnumValue("actionButtonBlank") - ACTION_BUTTON_BLANK("actionButtonBlank"), - - /** - * Home Button Shape - * - */ - @XmlEnumValue("actionButtonHome") - ACTION_BUTTON_HOME("actionButtonHome"), - - /** - * Help Button Shape - * - */ - @XmlEnumValue("actionButtonHelp") - ACTION_BUTTON_HELP("actionButtonHelp"), - - /** - * Information Button Shape - * - */ - @XmlEnumValue("actionButtonInformation") - ACTION_BUTTON_INFORMATION("actionButtonInformation"), - - /** - * Forward or Next Button Shape - * - */ - @XmlEnumValue("actionButtonForwardNext") - ACTION_BUTTON_FORWARD_NEXT("actionButtonForwardNext"), - - /** - * Back or Previous Button Shape - * - */ - @XmlEnumValue("actionButtonBackPrevious") - ACTION_BUTTON_BACK_PREVIOUS("actionButtonBackPrevious"), - - /** - * End Button Shape - * - */ - @XmlEnumValue("actionButtonEnd") - ACTION_BUTTON_END("actionButtonEnd"), - - /** - * Beginning Button Shape - * - */ - @XmlEnumValue("actionButtonBeginning") - ACTION_BUTTON_BEGINNING("actionButtonBeginning"), - - /** - * Return Button Shape - * - */ - @XmlEnumValue("actionButtonReturn") - ACTION_BUTTON_RETURN("actionButtonReturn"), - - /** - * Document Button Shape - * - */ - @XmlEnumValue("actionButtonDocument") - ACTION_BUTTON_DOCUMENT("actionButtonDocument"), - - /** - * Sound Button Shape - * - */ - @XmlEnumValue("actionButtonSound") - ACTION_BUTTON_SOUND("actionButtonSound"), - - /** - * Movie Button Shape - * - */ - @XmlEnumValue("actionButtonMovie") - ACTION_BUTTON_MOVIE("actionButtonMovie"), - - /** - * Gear 6 Shape - * - */ - @XmlEnumValue("gear6") - GEAR_6("gear6"), - - /** - * Gear 9 Shape - * - */ - @XmlEnumValue("gear9") - GEAR_9("gear9"), - - /** - * Funnel Shape - * - */ - @XmlEnumValue("funnel") - FUNNEL("funnel"), - - /** - * Plus Math Shape - * - */ - @XmlEnumValue("mathPlus") - MATH_PLUS("mathPlus"), - - /** - * Minus Math Shape - * - */ - @XmlEnumValue("mathMinus") - MATH_MINUS("mathMinus"), - - /** - * Multiply Math Shape - * - */ - @XmlEnumValue("mathMultiply") - MATH_MULTIPLY("mathMultiply"), - - /** - * Divide Math Shape - * - */ - @XmlEnumValue("mathDivide") - MATH_DIVIDE("mathDivide"), - - /** - * Equal Math Shape - * - */ - @XmlEnumValue("mathEqual") - MATH_EQUAL("mathEqual"), - - /** - * Not Equal Math Shape - * - */ - @XmlEnumValue("mathNotEqual") - MATH_NOT_EQUAL("mathNotEqual"), - - /** - * Corner Tabs Shape - * - */ - @XmlEnumValue("cornerTabs") - CORNER_TABS("cornerTabs"), - - /** - * Square Tabs Shape - * - */ - @XmlEnumValue("squareTabs") - SQUARE_TABS("squareTabs"), - - /** - * Plaque Tabs Shape - * - */ - @XmlEnumValue("plaqueTabs") - PLAQUE_TABS("plaqueTabs"), - - /** - * Chart X Shape - * - */ - @XmlEnumValue("chartX") - CHART_X("chartX"), - - /** - * Chart Star Shape - * - */ - @XmlEnumValue("chartStar") - CHART_STAR("chartStar"), - - /** - * Chart Plus Shape - * - */ - @XmlEnumValue("chartPlus") - CHART_PLUS("chartPlus"); - private final String value; - - STShapeType(String v) { - value = v; - } - - public String value() { - return value; - } - - public static STShapeType fromValue(String v) { - for (STShapeType c: STShapeType.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ST_ShapeType. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="ST_ShapeType">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
+ *     <enumeration value="line"/>
+ *     <enumeration value="lineInv"/>
+ *     <enumeration value="triangle"/>
+ *     <enumeration value="rtTriangle"/>
+ *     <enumeration value="rect"/>
+ *     <enumeration value="diamond"/>
+ *     <enumeration value="parallelogram"/>
+ *     <enumeration value="trapezoid"/>
+ *     <enumeration value="nonIsoscelesTrapezoid"/>
+ *     <enumeration value="pentagon"/>
+ *     <enumeration value="hexagon"/>
+ *     <enumeration value="heptagon"/>
+ *     <enumeration value="octagon"/>
+ *     <enumeration value="decagon"/>
+ *     <enumeration value="dodecagon"/>
+ *     <enumeration value="star4"/>
+ *     <enumeration value="star5"/>
+ *     <enumeration value="star6"/>
+ *     <enumeration value="star7"/>
+ *     <enumeration value="star8"/>
+ *     <enumeration value="star10"/>
+ *     <enumeration value="star12"/>
+ *     <enumeration value="star16"/>
+ *     <enumeration value="star24"/>
+ *     <enumeration value="star32"/>
+ *     <enumeration value="roundRect"/>
+ *     <enumeration value="round1Rect"/>
+ *     <enumeration value="round2SameRect"/>
+ *     <enumeration value="round2DiagRect"/>
+ *     <enumeration value="snipRoundRect"/>
+ *     <enumeration value="snip1Rect"/>
+ *     <enumeration value="snip2SameRect"/>
+ *     <enumeration value="snip2DiagRect"/>
+ *     <enumeration value="plaque"/>
+ *     <enumeration value="ellipse"/>
+ *     <enumeration value="teardrop"/>
+ *     <enumeration value="homePlate"/>
+ *     <enumeration value="chevron"/>
+ *     <enumeration value="pieWedge"/>
+ *     <enumeration value="pie"/>
+ *     <enumeration value="blockArc"/>
+ *     <enumeration value="donut"/>
+ *     <enumeration value="noSmoking"/>
+ *     <enumeration value="rightArrow"/>
+ *     <enumeration value="leftArrow"/>
+ *     <enumeration value="upArrow"/>
+ *     <enumeration value="downArrow"/>
+ *     <enumeration value="stripedRightArrow"/>
+ *     <enumeration value="notchedRightArrow"/>
+ *     <enumeration value="bentUpArrow"/>
+ *     <enumeration value="leftRightArrow"/>
+ *     <enumeration value="upDownArrow"/>
+ *     <enumeration value="leftUpArrow"/>
+ *     <enumeration value="leftRightUpArrow"/>
+ *     <enumeration value="quadArrow"/>
+ *     <enumeration value="leftArrowCallout"/>
+ *     <enumeration value="rightArrowCallout"/>
+ *     <enumeration value="upArrowCallout"/>
+ *     <enumeration value="downArrowCallout"/>
+ *     <enumeration value="leftRightArrowCallout"/>
+ *     <enumeration value="upDownArrowCallout"/>
+ *     <enumeration value="quadArrowCallout"/>
+ *     <enumeration value="bentArrow"/>
+ *     <enumeration value="uturnArrow"/>
+ *     <enumeration value="circularArrow"/>
+ *     <enumeration value="leftCircularArrow"/>
+ *     <enumeration value="leftRightCircularArrow"/>
+ *     <enumeration value="curvedRightArrow"/>
+ *     <enumeration value="curvedLeftArrow"/>
+ *     <enumeration value="curvedUpArrow"/>
+ *     <enumeration value="curvedDownArrow"/>
+ *     <enumeration value="swooshArrow"/>
+ *     <enumeration value="cube"/>
+ *     <enumeration value="can"/>
+ *     <enumeration value="lightningBolt"/>
+ *     <enumeration value="heart"/>
+ *     <enumeration value="sun"/>
+ *     <enumeration value="moon"/>
+ *     <enumeration value="smileyFace"/>
+ *     <enumeration value="irregularSeal1"/>
+ *     <enumeration value="irregularSeal2"/>
+ *     <enumeration value="foldedCorner"/>
+ *     <enumeration value="bevel"/>
+ *     <enumeration value="frame"/>
+ *     <enumeration value="halfFrame"/>
+ *     <enumeration value="corner"/>
+ *     <enumeration value="diagStripe"/>
+ *     <enumeration value="chord"/>
+ *     <enumeration value="arc"/>
+ *     <enumeration value="leftBracket"/>
+ *     <enumeration value="rightBracket"/>
+ *     <enumeration value="leftBrace"/>
+ *     <enumeration value="rightBrace"/>
+ *     <enumeration value="bracketPair"/>
+ *     <enumeration value="bracePair"/>
+ *     <enumeration value="straightConnector1"/>
+ *     <enumeration value="bentConnector2"/>
+ *     <enumeration value="bentConnector3"/>
+ *     <enumeration value="bentConnector4"/>
+ *     <enumeration value="bentConnector5"/>
+ *     <enumeration value="curvedConnector2"/>
+ *     <enumeration value="curvedConnector3"/>
+ *     <enumeration value="curvedConnector4"/>
+ *     <enumeration value="curvedConnector5"/>
+ *     <enumeration value="callout1"/>
+ *     <enumeration value="callout2"/>
+ *     <enumeration value="callout3"/>
+ *     <enumeration value="accentCallout1"/>
+ *     <enumeration value="accentCallout2"/>
+ *     <enumeration value="accentCallout3"/>
+ *     <enumeration value="borderCallout1"/>
+ *     <enumeration value="borderCallout2"/>
+ *     <enumeration value="borderCallout3"/>
+ *     <enumeration value="accentBorderCallout1"/>
+ *     <enumeration value="accentBorderCallout2"/>
+ *     <enumeration value="accentBorderCallout3"/>
+ *     <enumeration value="wedgeRectCallout"/>
+ *     <enumeration value="wedgeRoundRectCallout"/>
+ *     <enumeration value="wedgeEllipseCallout"/>
+ *     <enumeration value="cloudCallout"/>
+ *     <enumeration value="cloud"/>
+ *     <enumeration value="ribbon"/>
+ *     <enumeration value="ribbon2"/>
+ *     <enumeration value="ellipseRibbon"/>
+ *     <enumeration value="ellipseRibbon2"/>
+ *     <enumeration value="leftRightRibbon"/>
+ *     <enumeration value="verticalScroll"/>
+ *     <enumeration value="horizontalScroll"/>
+ *     <enumeration value="wave"/>
+ *     <enumeration value="doubleWave"/>
+ *     <enumeration value="plus"/>
+ *     <enumeration value="flowChartProcess"/>
+ *     <enumeration value="flowChartDecision"/>
+ *     <enumeration value="flowChartInputOutput"/>
+ *     <enumeration value="flowChartPredefinedProcess"/>
+ *     <enumeration value="flowChartInternalStorage"/>
+ *     <enumeration value="flowChartDocument"/>
+ *     <enumeration value="flowChartMultidocument"/>
+ *     <enumeration value="flowChartTerminator"/>
+ *     <enumeration value="flowChartPreparation"/>
+ *     <enumeration value="flowChartManualInput"/>
+ *     <enumeration value="flowChartManualOperation"/>
+ *     <enumeration value="flowChartConnector"/>
+ *     <enumeration value="flowChartPunchedCard"/>
+ *     <enumeration value="flowChartPunchedTape"/>
+ *     <enumeration value="flowChartSummingJunction"/>
+ *     <enumeration value="flowChartOr"/>
+ *     <enumeration value="flowChartCollate"/>
+ *     <enumeration value="flowChartSort"/>
+ *     <enumeration value="flowChartExtract"/>
+ *     <enumeration value="flowChartMerge"/>
+ *     <enumeration value="flowChartOfflineStorage"/>
+ *     <enumeration value="flowChartOnlineStorage"/>
+ *     <enumeration value="flowChartMagneticTape"/>
+ *     <enumeration value="flowChartMagneticDisk"/>
+ *     <enumeration value="flowChartMagneticDrum"/>
+ *     <enumeration value="flowChartDisplay"/>
+ *     <enumeration value="flowChartDelay"/>
+ *     <enumeration value="flowChartAlternateProcess"/>
+ *     <enumeration value="flowChartOffpageConnector"/>
+ *     <enumeration value="actionButtonBlank"/>
+ *     <enumeration value="actionButtonHome"/>
+ *     <enumeration value="actionButtonHelp"/>
+ *     <enumeration value="actionButtonInformation"/>
+ *     <enumeration value="actionButtonForwardNext"/>
+ *     <enumeration value="actionButtonBackPrevious"/>
+ *     <enumeration value="actionButtonEnd"/>
+ *     <enumeration value="actionButtonBeginning"/>
+ *     <enumeration value="actionButtonReturn"/>
+ *     <enumeration value="actionButtonDocument"/>
+ *     <enumeration value="actionButtonSound"/>
+ *     <enumeration value="actionButtonMovie"/>
+ *     <enumeration value="gear6"/>
+ *     <enumeration value="gear9"/>
+ *     <enumeration value="funnel"/>
+ *     <enumeration value="mathPlus"/>
+ *     <enumeration value="mathMinus"/>
+ *     <enumeration value="mathMultiply"/>
+ *     <enumeration value="mathDivide"/>
+ *     <enumeration value="mathEqual"/>
+ *     <enumeration value="mathNotEqual"/>
+ *     <enumeration value="cornerTabs"/>
+ *     <enumeration value="squareTabs"/>
+ *     <enumeration value="plaqueTabs"/>
+ *     <enumeration value="chartX"/>
+ *     <enumeration value="chartStar"/>
+ *     <enumeration value="chartPlus"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "ST_ShapeType", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +@XmlEnum +public enum STShapeType { + + + /** + * Line Shape + * + */ + @XmlEnumValue("line") + LINE("line"), + + /** + * Line Inverse Shape + * + */ + @XmlEnumValue("lineInv") + LINE_INV("lineInv"), + + /** + * Triangle Shape + * + */ + @XmlEnumValue("triangle") + TRIANGLE("triangle"), + + /** + * Right Triangle Shape + * + */ + @XmlEnumValue("rtTriangle") + RT_TRIANGLE("rtTriangle"), + + /** + * Rectangle Shape + * + */ + @XmlEnumValue("rect") + RECT("rect"), + + /** + * Diamond Shape + * + */ + @XmlEnumValue("diamond") + DIAMOND("diamond"), + + /** + * Parallelogram Shape + * + */ + @XmlEnumValue("parallelogram") + PARALLELOGRAM("parallelogram"), + + /** + * Trapezoid Shape + * + */ + @XmlEnumValue("trapezoid") + TRAPEZOID("trapezoid"), + + /** + * Non-Isosceles Trapezoid Shape + * + */ + @XmlEnumValue("nonIsoscelesTrapezoid") + NON_ISOSCELES_TRAPEZOID("nonIsoscelesTrapezoid"), + + /** + * Pentagon Shape + * + */ + @XmlEnumValue("pentagon") + PENTAGON("pentagon"), + + /** + * Hexagon Shape + * + */ + @XmlEnumValue("hexagon") + HEXAGON("hexagon"), + + /** + * Heptagon Shape + * + */ + @XmlEnumValue("heptagon") + HEPTAGON("heptagon"), + + /** + * Octagon Shape + * + */ + @XmlEnumValue("octagon") + OCTAGON("octagon"), + + /** + * Decagon Shape + * + */ + @XmlEnumValue("decagon") + DECAGON("decagon"), + + /** + * Dodecagon Shape + * + */ + @XmlEnumValue("dodecagon") + DODECAGON("dodecagon"), + + /** + * Four Pointed Star Shape + * + */ + @XmlEnumValue("star4") + STAR_4("star4"), + + /** + * Five Pointed Star Shape + * + */ + @XmlEnumValue("star5") + STAR_5("star5"), + + /** + * Six Pointed Star Shape + * + */ + @XmlEnumValue("star6") + STAR_6("star6"), + + /** + * Seven Pointed Star Shape + * + */ + @XmlEnumValue("star7") + STAR_7("star7"), + + /** + * Eight Pointed Star Shape + * + */ + @XmlEnumValue("star8") + STAR_8("star8"), + + /** + * Ten Pointed Star Shape + * + */ + @XmlEnumValue("star10") + STAR_10("star10"), + + /** + * Twelve Pointed Star Shape + * + */ + @XmlEnumValue("star12") + STAR_12("star12"), + + /** + * Sixteen Pointed Star Shape + * + */ + @XmlEnumValue("star16") + STAR_16("star16"), + + /** + * Twenty Four Pointed Star Shape + * + */ + @XmlEnumValue("star24") + STAR_24("star24"), + + /** + * Thirty Two Pointed Star Shape + * + */ + @XmlEnumValue("star32") + STAR_32("star32"), + + /** + * Round Corner Rectangle Shape + * + */ + @XmlEnumValue("roundRect") + ROUND_RECT("roundRect"), + + /** + * One Round Corner Rectangle Shape + * + */ + @XmlEnumValue("round1Rect") + ROUND_1_RECT("round1Rect"), + + /** + * Two Same-side Round Corner Rectangle Shape + * + */ + @XmlEnumValue("round2SameRect") + ROUND_2_SAME_RECT("round2SameRect"), + + /** + * Two Diagonal Round Corner Rectangle Shape + * + */ + @XmlEnumValue("round2DiagRect") + ROUND_2_DIAG_RECT("round2DiagRect"), + + /** + * One Snip One Round Corner Rectangle Shape + * + */ + @XmlEnumValue("snipRoundRect") + SNIP_ROUND_RECT("snipRoundRect"), + + /** + * One Snip Corner Rectangle Shape + * + */ + @XmlEnumValue("snip1Rect") + SNIP_1_RECT("snip1Rect"), + + /** + * Two Same-side Snip Corner Rectangle Shape + * + */ + @XmlEnumValue("snip2SameRect") + SNIP_2_SAME_RECT("snip2SameRect"), + + /** + * Two Diagonal Snip Corner Rectangle Shape + * + */ + @XmlEnumValue("snip2DiagRect") + SNIP_2_DIAG_RECT("snip2DiagRect"), + + /** + * Plaque Shape + * + */ + @XmlEnumValue("plaque") + PLAQUE("plaque"), + + /** + * Ellipse Shape + * + */ + @XmlEnumValue("ellipse") + ELLIPSE("ellipse"), + + /** + * Teardrop Shape + * + */ + @XmlEnumValue("teardrop") + TEARDROP("teardrop"), + + /** + * Home Plate Shape + * + */ + @XmlEnumValue("homePlate") + HOME_PLATE("homePlate"), + + /** + * Chevron Shape + * + */ + @XmlEnumValue("chevron") + CHEVRON("chevron"), + + /** + * Pie Wedge Shape + * + */ + @XmlEnumValue("pieWedge") + PIE_WEDGE("pieWedge"), + + /** + * Pie Shape + * + */ + @XmlEnumValue("pie") + PIE("pie"), + + /** + * Block Arc Shape + * + */ + @XmlEnumValue("blockArc") + BLOCK_ARC("blockArc"), + + /** + * Donut Shape + * + */ + @XmlEnumValue("donut") + DONUT("donut"), + + /** + * No Smoking Shape + * + */ + @XmlEnumValue("noSmoking") + NO_SMOKING("noSmoking"), + + /** + * Right Arrow Shape + * + */ + @XmlEnumValue("rightArrow") + RIGHT_ARROW("rightArrow"), + + /** + * Left Arrow Shape + * + */ + @XmlEnumValue("leftArrow") + LEFT_ARROW("leftArrow"), + + /** + * Up Arrow Shape + * + */ + @XmlEnumValue("upArrow") + UP_ARROW("upArrow"), + + /** + * Down Arrow Shape + * + */ + @XmlEnumValue("downArrow") + DOWN_ARROW("downArrow"), + + /** + * Striped Right Arrow Shape + * + */ + @XmlEnumValue("stripedRightArrow") + STRIPED_RIGHT_ARROW("stripedRightArrow"), + + /** + * Notched Right Arrow Shape + * + */ + @XmlEnumValue("notchedRightArrow") + NOTCHED_RIGHT_ARROW("notchedRightArrow"), + + /** + * Bent Up Arrow Shape + * + */ + @XmlEnumValue("bentUpArrow") + BENT_UP_ARROW("bentUpArrow"), + + /** + * Left Right Arrow Shape + * + */ + @XmlEnumValue("leftRightArrow") + LEFT_RIGHT_ARROW("leftRightArrow"), + + /** + * Up Down Arrow Shape + * + */ + @XmlEnumValue("upDownArrow") + UP_DOWN_ARROW("upDownArrow"), + + /** + * Left Up Arrow Shape + * + */ + @XmlEnumValue("leftUpArrow") + LEFT_UP_ARROW("leftUpArrow"), + + /** + * Left Right Up Arrow Shape + * + */ + @XmlEnumValue("leftRightUpArrow") + LEFT_RIGHT_UP_ARROW("leftRightUpArrow"), + + /** + * Quad-Arrow Shape + * + */ + @XmlEnumValue("quadArrow") + QUAD_ARROW("quadArrow"), + + /** + * Callout Left Arrow Shape + * + */ + @XmlEnumValue("leftArrowCallout") + LEFT_ARROW_CALLOUT("leftArrowCallout"), + + /** + * Callout Right Arrow Shape + * + */ + @XmlEnumValue("rightArrowCallout") + RIGHT_ARROW_CALLOUT("rightArrowCallout"), + + /** + * Callout Up Arrow Shape + * + */ + @XmlEnumValue("upArrowCallout") + UP_ARROW_CALLOUT("upArrowCallout"), + + /** + * Callout Down Arrow Shape + * + */ + @XmlEnumValue("downArrowCallout") + DOWN_ARROW_CALLOUT("downArrowCallout"), + + /** + * Callout Left Right Arrow Shape + * + */ + @XmlEnumValue("leftRightArrowCallout") + LEFT_RIGHT_ARROW_CALLOUT("leftRightArrowCallout"), + + /** + * Callout Up Down Arrow Shape + * + */ + @XmlEnumValue("upDownArrowCallout") + UP_DOWN_ARROW_CALLOUT("upDownArrowCallout"), + + /** + * Callout Quad-Arrow Shape + * + */ + @XmlEnumValue("quadArrowCallout") + QUAD_ARROW_CALLOUT("quadArrowCallout"), + + /** + * Bent Arrow Shape + * + */ + @XmlEnumValue("bentArrow") + BENT_ARROW("bentArrow"), + + /** + * U-Turn Arrow Shape + * + */ + @XmlEnumValue("uturnArrow") + UTURN_ARROW("uturnArrow"), + + /** + * Circular Arrow Shape + * + */ + @XmlEnumValue("circularArrow") + CIRCULAR_ARROW("circularArrow"), + + /** + * Left Circular Arrow Shape + * + */ + @XmlEnumValue("leftCircularArrow") + LEFT_CIRCULAR_ARROW("leftCircularArrow"), + + /** + * Left Right Circular Arrow Shape + * + */ + @XmlEnumValue("leftRightCircularArrow") + LEFT_RIGHT_CIRCULAR_ARROW("leftRightCircularArrow"), + + /** + * Curved Right Arrow Shape + * + */ + @XmlEnumValue("curvedRightArrow") + CURVED_RIGHT_ARROW("curvedRightArrow"), + + /** + * Curved Left Arrow Shape + * + */ + @XmlEnumValue("curvedLeftArrow") + CURVED_LEFT_ARROW("curvedLeftArrow"), + + /** + * Curved Up Arrow Shape + * + */ + @XmlEnumValue("curvedUpArrow") + CURVED_UP_ARROW("curvedUpArrow"), + + /** + * Curved Down Arrow Shape + * + */ + @XmlEnumValue("curvedDownArrow") + CURVED_DOWN_ARROW("curvedDownArrow"), + + /** + * Swoosh Arrow Shape + * + */ + @XmlEnumValue("swooshArrow") + SWOOSH_ARROW("swooshArrow"), + + /** + * Cube Shape + * + */ + @XmlEnumValue("cube") + CUBE("cube"), + + /** + * Can Shape + * + */ + @XmlEnumValue("can") + CAN("can"), + + /** + * Lightning Bolt Shape + * + */ + @XmlEnumValue("lightningBolt") + LIGHTNING_BOLT("lightningBolt"), + + /** + * Heart Shape + * + */ + @XmlEnumValue("heart") + HEART("heart"), + + /** + * Sun Shape + * + */ + @XmlEnumValue("sun") + SUN("sun"), + + /** + * Moon Shape + * + */ + @XmlEnumValue("moon") + MOON("moon"), + + /** + * Smiley Face Shape + * + */ + @XmlEnumValue("smileyFace") + SMILEY_FACE("smileyFace"), + + /** + * Irregular Seal 1 Shape + * + */ + @XmlEnumValue("irregularSeal1") + IRREGULAR_SEAL_1("irregularSeal1"), + + /** + * Irregular Seal 2 Shape + * + */ + @XmlEnumValue("irregularSeal2") + IRREGULAR_SEAL_2("irregularSeal2"), + + /** + * Folded Corner Shape + * + */ + @XmlEnumValue("foldedCorner") + FOLDED_CORNER("foldedCorner"), + + /** + * Bevel Shape + * + */ + @XmlEnumValue("bevel") + BEVEL("bevel"), + + /** + * Frame Shape + * + */ + @XmlEnumValue("frame") + FRAME("frame"), + + /** + * Half Frame Shape + * + */ + @XmlEnumValue("halfFrame") + HALF_FRAME("halfFrame"), + + /** + * Corner Shape + * + */ + @XmlEnumValue("corner") + CORNER("corner"), + + /** + * Diagonal Stripe Shape + * + */ + @XmlEnumValue("diagStripe") + DIAG_STRIPE("diagStripe"), + + /** + * Chord Shape + * + */ + @XmlEnumValue("chord") + CHORD("chord"), + + /** + * Curved Arc Shape + * + */ + @XmlEnumValue("arc") + ARC("arc"), + + /** + * Left Bracket Shape + * + */ + @XmlEnumValue("leftBracket") + LEFT_BRACKET("leftBracket"), + + /** + * Right Bracket Shape + * + */ + @XmlEnumValue("rightBracket") + RIGHT_BRACKET("rightBracket"), + + /** + * Left Brace Shape + * + */ + @XmlEnumValue("leftBrace") + LEFT_BRACE("leftBrace"), + + /** + * Right Brace Shape + * + */ + @XmlEnumValue("rightBrace") + RIGHT_BRACE("rightBrace"), + + /** + * Bracket Pair Shape + * + */ + @XmlEnumValue("bracketPair") + BRACKET_PAIR("bracketPair"), + + /** + * Brace Pair Shape + * + */ + @XmlEnumValue("bracePair") + BRACE_PAIR("bracePair"), + + /** + * Straight Connector 1 Shape + * + */ + @XmlEnumValue("straightConnector1") + STRAIGHT_CONNECTOR_1("straightConnector1"), + + /** + * Bent Connector 2 Shape + * + */ + @XmlEnumValue("bentConnector2") + BENT_CONNECTOR_2("bentConnector2"), + + /** + * Bent Connector 3 Shape + * + */ + @XmlEnumValue("bentConnector3") + BENT_CONNECTOR_3("bentConnector3"), + + /** + * Bent Connector 4 Shape + * + */ + @XmlEnumValue("bentConnector4") + BENT_CONNECTOR_4("bentConnector4"), + + /** + * Bent Connector 5 Shape + * + */ + @XmlEnumValue("bentConnector5") + BENT_CONNECTOR_5("bentConnector5"), + + /** + * Curved Connector 2 Shape + * + */ + @XmlEnumValue("curvedConnector2") + CURVED_CONNECTOR_2("curvedConnector2"), + + /** + * Curved Connector 3 Shape + * + */ + @XmlEnumValue("curvedConnector3") + CURVED_CONNECTOR_3("curvedConnector3"), + + /** + * Curved Connector 4 Shape + * + */ + @XmlEnumValue("curvedConnector4") + CURVED_CONNECTOR_4("curvedConnector4"), + + /** + * Curved Connector 5 Shape + * + */ + @XmlEnumValue("curvedConnector5") + CURVED_CONNECTOR_5("curvedConnector5"), + + /** + * Callout 1 Shape + * + */ + @XmlEnumValue("callout1") + CALLOUT_1("callout1"), + + /** + * Callout 2 Shape + * + */ + @XmlEnumValue("callout2") + CALLOUT_2("callout2"), + + /** + * Callout 3 Shape + * + */ + @XmlEnumValue("callout3") + CALLOUT_3("callout3"), + + /** + * Callout 1 Shape + * + */ + @XmlEnumValue("accentCallout1") + ACCENT_CALLOUT_1("accentCallout1"), + + /** + * Callout 2 Shape + * + */ + @XmlEnumValue("accentCallout2") + ACCENT_CALLOUT_2("accentCallout2"), + + /** + * Callout 3 Shape + * + */ + @XmlEnumValue("accentCallout3") + ACCENT_CALLOUT_3("accentCallout3"), + + /** + * Callout 1 with Border Shape + * + */ + @XmlEnumValue("borderCallout1") + BORDER_CALLOUT_1("borderCallout1"), + + /** + * Callout 2 with Border Shape + * + */ + @XmlEnumValue("borderCallout2") + BORDER_CALLOUT_2("borderCallout2"), + + /** + * Callout 3 with Border Shape + * + */ + @XmlEnumValue("borderCallout3") + BORDER_CALLOUT_3("borderCallout3"), + + /** + * Callout 1 with Border and Accent Shape + * + */ + @XmlEnumValue("accentBorderCallout1") + ACCENT_BORDER_CALLOUT_1("accentBorderCallout1"), + + /** + * Callout 2 with Border and Accent Shape + * + */ + @XmlEnumValue("accentBorderCallout2") + ACCENT_BORDER_CALLOUT_2("accentBorderCallout2"), + + /** + * Callout 3 with Border and Accent Shape + * + */ + @XmlEnumValue("accentBorderCallout3") + ACCENT_BORDER_CALLOUT_3("accentBorderCallout3"), + + /** + * Callout Wedge Rectangle Shape + * + */ + @XmlEnumValue("wedgeRectCallout") + WEDGE_RECT_CALLOUT("wedgeRectCallout"), + + /** + * Callout Wedge Round Rectangle Shape + * + */ + @XmlEnumValue("wedgeRoundRectCallout") + WEDGE_ROUND_RECT_CALLOUT("wedgeRoundRectCallout"), + + /** + * Callout Wedge Ellipse Shape + * + */ + @XmlEnumValue("wedgeEllipseCallout") + WEDGE_ELLIPSE_CALLOUT("wedgeEllipseCallout"), + + /** + * Callout Cloud Shape + * + */ + @XmlEnumValue("cloudCallout") + CLOUD_CALLOUT("cloudCallout"), + + /** + * Cloud Shape + * + */ + @XmlEnumValue("cloud") + CLOUD("cloud"), + + /** + * Ribbon Shape + * + */ + @XmlEnumValue("ribbon") + RIBBON("ribbon"), + + /** + * Ribbon 2 Shape + * + */ + @XmlEnumValue("ribbon2") + RIBBON_2("ribbon2"), + + /** + * Ellipse Ribbon Shape + * + */ + @XmlEnumValue("ellipseRibbon") + ELLIPSE_RIBBON("ellipseRibbon"), + + /** + * Ellipse Ribbon 2 Shape + * + */ + @XmlEnumValue("ellipseRibbon2") + ELLIPSE_RIBBON_2("ellipseRibbon2"), + + /** + * Left Right Ribbon Shape + * + */ + @XmlEnumValue("leftRightRibbon") + LEFT_RIGHT_RIBBON("leftRightRibbon"), + + /** + * Vertical Scroll Shape + * + */ + @XmlEnumValue("verticalScroll") + VERTICAL_SCROLL("verticalScroll"), + + /** + * Horizontal Scroll Shape + * + */ + @XmlEnumValue("horizontalScroll") + HORIZONTAL_SCROLL("horizontalScroll"), + + /** + * Wave Shape + * + */ + @XmlEnumValue("wave") + WAVE("wave"), + + /** + * Double Wave Shape + * + */ + @XmlEnumValue("doubleWave") + DOUBLE_WAVE("doubleWave"), + + /** + * Plus Shape + * + */ + @XmlEnumValue("plus") + PLUS("plus"), + + /** + * Process Flow Shape + * + */ + @XmlEnumValue("flowChartProcess") + FLOW_CHART_PROCESS("flowChartProcess"), + + /** + * Decision Flow Shape + * + */ + @XmlEnumValue("flowChartDecision") + FLOW_CHART_DECISION("flowChartDecision"), + + /** + * Input Output Flow Shape + * + */ + @XmlEnumValue("flowChartInputOutput") + FLOW_CHART_INPUT_OUTPUT("flowChartInputOutput"), + + /** + * Predefined Process Flow Shape + * + */ + @XmlEnumValue("flowChartPredefinedProcess") + FLOW_CHART_PREDEFINED_PROCESS("flowChartPredefinedProcess"), + + /** + * Internal Storage Flow Shape + * + */ + @XmlEnumValue("flowChartInternalStorage") + FLOW_CHART_INTERNAL_STORAGE("flowChartInternalStorage"), + + /** + * Document Flow Shape + * + */ + @XmlEnumValue("flowChartDocument") + FLOW_CHART_DOCUMENT("flowChartDocument"), + + /** + * Multi-Document Flow Shape + * + */ + @XmlEnumValue("flowChartMultidocument") + FLOW_CHART_MULTIDOCUMENT("flowChartMultidocument"), + + /** + * Terminator Flow Shape + * + */ + @XmlEnumValue("flowChartTerminator") + FLOW_CHART_TERMINATOR("flowChartTerminator"), + + /** + * Preparation Flow Shape + * + */ + @XmlEnumValue("flowChartPreparation") + FLOW_CHART_PREPARATION("flowChartPreparation"), + + /** + * Manual Input Flow Shape + * + */ + @XmlEnumValue("flowChartManualInput") + FLOW_CHART_MANUAL_INPUT("flowChartManualInput"), + + /** + * Manual Operation Flow Shape + * + */ + @XmlEnumValue("flowChartManualOperation") + FLOW_CHART_MANUAL_OPERATION("flowChartManualOperation"), + + /** + * Connector Flow Shape + * + */ + @XmlEnumValue("flowChartConnector") + FLOW_CHART_CONNECTOR("flowChartConnector"), + + /** + * Punched Card Flow Shape + * + */ + @XmlEnumValue("flowChartPunchedCard") + FLOW_CHART_PUNCHED_CARD("flowChartPunchedCard"), + + /** + * Punched Tape Flow Shape + * + */ + @XmlEnumValue("flowChartPunchedTape") + FLOW_CHART_PUNCHED_TAPE("flowChartPunchedTape"), + + /** + * Summing Junction Flow Shape + * + */ + @XmlEnumValue("flowChartSummingJunction") + FLOW_CHART_SUMMING_JUNCTION("flowChartSummingJunction"), + + /** + * Or Flow Shape + * + */ + @XmlEnumValue("flowChartOr") + FLOW_CHART_OR("flowChartOr"), + + /** + * Collate Flow Shape + * + */ + @XmlEnumValue("flowChartCollate") + FLOW_CHART_COLLATE("flowChartCollate"), + + /** + * Sort Flow Shape + * + */ + @XmlEnumValue("flowChartSort") + FLOW_CHART_SORT("flowChartSort"), + + /** + * Extract Flow Shape + * + */ + @XmlEnumValue("flowChartExtract") + FLOW_CHART_EXTRACT("flowChartExtract"), + + /** + * Merge Flow Shape + * + */ + @XmlEnumValue("flowChartMerge") + FLOW_CHART_MERGE("flowChartMerge"), + + /** + * Offline Storage Flow Shape + * + */ + @XmlEnumValue("flowChartOfflineStorage") + FLOW_CHART_OFFLINE_STORAGE("flowChartOfflineStorage"), + + /** + * Online Storage Flow Shape + * + */ + @XmlEnumValue("flowChartOnlineStorage") + FLOW_CHART_ONLINE_STORAGE("flowChartOnlineStorage"), + + /** + * Magnetic Tape Flow Shape + * + */ + @XmlEnumValue("flowChartMagneticTape") + FLOW_CHART_MAGNETIC_TAPE("flowChartMagneticTape"), + + /** + * Magnetic Disk Flow Shape + * + */ + @XmlEnumValue("flowChartMagneticDisk") + FLOW_CHART_MAGNETIC_DISK("flowChartMagneticDisk"), + + /** + * Magnetic Drum Flow Shape + * + */ + @XmlEnumValue("flowChartMagneticDrum") + FLOW_CHART_MAGNETIC_DRUM("flowChartMagneticDrum"), + + /** + * Display Flow Shape + * + */ + @XmlEnumValue("flowChartDisplay") + FLOW_CHART_DISPLAY("flowChartDisplay"), + + /** + * Delay Flow Shape + * + */ + @XmlEnumValue("flowChartDelay") + FLOW_CHART_DELAY("flowChartDelay"), + + /** + * Alternate Process Flow Shape + * + */ + @XmlEnumValue("flowChartAlternateProcess") + FLOW_CHART_ALTERNATE_PROCESS("flowChartAlternateProcess"), + + /** + * Off-Page Connector Flow Shape + * + */ + @XmlEnumValue("flowChartOffpageConnector") + FLOW_CHART_OFFPAGE_CONNECTOR("flowChartOffpageConnector"), + + /** + * Blank Button Shape + * + */ + @XmlEnumValue("actionButtonBlank") + ACTION_BUTTON_BLANK("actionButtonBlank"), + + /** + * Home Button Shape + * + */ + @XmlEnumValue("actionButtonHome") + ACTION_BUTTON_HOME("actionButtonHome"), + + /** + * Help Button Shape + * + */ + @XmlEnumValue("actionButtonHelp") + ACTION_BUTTON_HELP("actionButtonHelp"), + + /** + * Information Button Shape + * + */ + @XmlEnumValue("actionButtonInformation") + ACTION_BUTTON_INFORMATION("actionButtonInformation"), + + /** + * Forward or Next Button Shape + * + */ + @XmlEnumValue("actionButtonForwardNext") + ACTION_BUTTON_FORWARD_NEXT("actionButtonForwardNext"), + + /** + * Back or Previous Button Shape + * + */ + @XmlEnumValue("actionButtonBackPrevious") + ACTION_BUTTON_BACK_PREVIOUS("actionButtonBackPrevious"), + + /** + * End Button Shape + * + */ + @XmlEnumValue("actionButtonEnd") + ACTION_BUTTON_END("actionButtonEnd"), + + /** + * Beginning Button Shape + * + */ + @XmlEnumValue("actionButtonBeginning") + ACTION_BUTTON_BEGINNING("actionButtonBeginning"), + + /** + * Return Button Shape + * + */ + @XmlEnumValue("actionButtonReturn") + ACTION_BUTTON_RETURN("actionButtonReturn"), + + /** + * Document Button Shape + * + */ + @XmlEnumValue("actionButtonDocument") + ACTION_BUTTON_DOCUMENT("actionButtonDocument"), + + /** + * Sound Button Shape + * + */ + @XmlEnumValue("actionButtonSound") + ACTION_BUTTON_SOUND("actionButtonSound"), + + /** + * Movie Button Shape + * + */ + @XmlEnumValue("actionButtonMovie") + ACTION_BUTTON_MOVIE("actionButtonMovie"), + + /** + * Gear 6 Shape + * + */ + @XmlEnumValue("gear6") + GEAR_6("gear6"), + + /** + * Gear 9 Shape + * + */ + @XmlEnumValue("gear9") + GEAR_9("gear9"), + + /** + * Funnel Shape + * + */ + @XmlEnumValue("funnel") + FUNNEL("funnel"), + + /** + * Plus Math Shape + * + */ + @XmlEnumValue("mathPlus") + MATH_PLUS("mathPlus"), + + /** + * Minus Math Shape + * + */ + @XmlEnumValue("mathMinus") + MATH_MINUS("mathMinus"), + + /** + * Multiply Math Shape + * + */ + @XmlEnumValue("mathMultiply") + MATH_MULTIPLY("mathMultiply"), + + /** + * Divide Math Shape + * + */ + @XmlEnumValue("mathDivide") + MATH_DIVIDE("mathDivide"), + + /** + * Equal Math Shape + * + */ + @XmlEnumValue("mathEqual") + MATH_EQUAL("mathEqual"), + + /** + * Not Equal Math Shape + * + */ + @XmlEnumValue("mathNotEqual") + MATH_NOT_EQUAL("mathNotEqual"), + + /** + * Corner Tabs Shape + * + */ + @XmlEnumValue("cornerTabs") + CORNER_TABS("cornerTabs"), + + /** + * Square Tabs Shape + * + */ + @XmlEnumValue("squareTabs") + SQUARE_TABS("squareTabs"), + + /** + * Plaque Tabs Shape + * + */ + @XmlEnumValue("plaqueTabs") + PLAQUE_TABS("plaqueTabs"), + + /** + * Chart X Shape + * + */ + @XmlEnumValue("chartX") + CHART_X("chartX"), + + /** + * Chart Star Shape + * + */ + @XmlEnumValue("chartStar") + CHART_STAR("chartStar"), + + /** + * Chart Plus Shape + * + */ + @XmlEnumValue("chartPlus") + CHART_PLUS("chartPlus"); + private final String value; + + STShapeType(String v) { + value = v; + } + + public String value() { + return value; + } + + public static STShapeType fromValue(String v) { + for (STShapeType c: STShapeType.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/src/java/org/apache/poi/sl/draw/binding/STTextShapeType.java b/src/java/org/apache/poi/sl/draw/binding/STTextShapeType.java index f3ed4b0cf7..584d971a51 100644 --- a/src/java/org/apache/poi/sl/draw/binding/STTextShapeType.java +++ b/src/java/org/apache/poi/sl/draw/binding/STTextShapeType.java @@ -1,389 +1,389 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.draw.binding; - -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for ST_TextShapeType. - * - *

The following schema fragment specifies the expected content contained within this class. - *

- *

- * <simpleType name="ST_TextShapeType">
- *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
- *     <enumeration value="textNoShape"/>
- *     <enumeration value="textPlain"/>
- *     <enumeration value="textStop"/>
- *     <enumeration value="textTriangle"/>
- *     <enumeration value="textTriangleInverted"/>
- *     <enumeration value="textChevron"/>
- *     <enumeration value="textChevronInverted"/>
- *     <enumeration value="textRingInside"/>
- *     <enumeration value="textRingOutside"/>
- *     <enumeration value="textArchUp"/>
- *     <enumeration value="textArchDown"/>
- *     <enumeration value="textCircle"/>
- *     <enumeration value="textButton"/>
- *     <enumeration value="textArchUpPour"/>
- *     <enumeration value="textArchDownPour"/>
- *     <enumeration value="textCirclePour"/>
- *     <enumeration value="textButtonPour"/>
- *     <enumeration value="textCurveUp"/>
- *     <enumeration value="textCurveDown"/>
- *     <enumeration value="textCanUp"/>
- *     <enumeration value="textCanDown"/>
- *     <enumeration value="textWave1"/>
- *     <enumeration value="textWave2"/>
- *     <enumeration value="textDoubleWave1"/>
- *     <enumeration value="textWave4"/>
- *     <enumeration value="textInflate"/>
- *     <enumeration value="textDeflate"/>
- *     <enumeration value="textInflateBottom"/>
- *     <enumeration value="textDeflateBottom"/>
- *     <enumeration value="textInflateTop"/>
- *     <enumeration value="textDeflateTop"/>
- *     <enumeration value="textDeflateInflate"/>
- *     <enumeration value="textDeflateInflateDeflate"/>
- *     <enumeration value="textFadeRight"/>
- *     <enumeration value="textFadeLeft"/>
- *     <enumeration value="textFadeUp"/>
- *     <enumeration value="textFadeDown"/>
- *     <enumeration value="textSlantUp"/>
- *     <enumeration value="textSlantDown"/>
- *     <enumeration value="textCascadeUp"/>
- *     <enumeration value="textCascadeDown"/>
- *   </restriction>
- * </simpleType>
- * 
- * - */ -@XmlType(name = "ST_TextShapeType", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") -@XmlEnum -public enum STTextShapeType { - - - /** - * No Text Shape - * - */ - @XmlEnumValue("textNoShape") - TEXT_NO_SHAPE("textNoShape"), - - /** - * Plain Text Shape - * - */ - @XmlEnumValue("textPlain") - TEXT_PLAIN("textPlain"), - - /** - * Stop Sign Text Shape - * - */ - @XmlEnumValue("textStop") - TEXT_STOP("textStop"), - - /** - * Triangle Text Shape - * - */ - @XmlEnumValue("textTriangle") - TEXT_TRIANGLE("textTriangle"), - - /** - * Inverted Triangle Text Shape - * - */ - @XmlEnumValue("textTriangleInverted") - TEXT_TRIANGLE_INVERTED("textTriangleInverted"), - - /** - * Chevron Text Shape - * - */ - @XmlEnumValue("textChevron") - TEXT_CHEVRON("textChevron"), - - /** - * Inverted Chevron Text Shape - * - */ - @XmlEnumValue("textChevronInverted") - TEXT_CHEVRON_INVERTED("textChevronInverted"), - - /** - * Inside Ring Text Shape - * - */ - @XmlEnumValue("textRingInside") - TEXT_RING_INSIDE("textRingInside"), - - /** - * Outside Ring Text Shape - * - */ - @XmlEnumValue("textRingOutside") - TEXT_RING_OUTSIDE("textRingOutside"), - - /** - * Upward Arch Text Shape - * - */ - @XmlEnumValue("textArchUp") - TEXT_ARCH_UP("textArchUp"), - - /** - * Downward Arch Text Shape - * - */ - @XmlEnumValue("textArchDown") - TEXT_ARCH_DOWN("textArchDown"), - - /** - * Circle Text Shape - * - */ - @XmlEnumValue("textCircle") - TEXT_CIRCLE("textCircle"), - - /** - * Button Text Shape - * - */ - @XmlEnumValue("textButton") - TEXT_BUTTON("textButton"), - - /** - * Upward Pour Arch Text Shape - * - */ - @XmlEnumValue("textArchUpPour") - TEXT_ARCH_UP_POUR("textArchUpPour"), - - /** - * Downward Pour Arch Text Shape - * - */ - @XmlEnumValue("textArchDownPour") - TEXT_ARCH_DOWN_POUR("textArchDownPour"), - - /** - * Circle Pour Text Shape - * - */ - @XmlEnumValue("textCirclePour") - TEXT_CIRCLE_POUR("textCirclePour"), - - /** - * Button Pour Text Shape - * - */ - @XmlEnumValue("textButtonPour") - TEXT_BUTTON_POUR("textButtonPour"), - - /** - * Upward Curve Text Shape - * - */ - @XmlEnumValue("textCurveUp") - TEXT_CURVE_UP("textCurveUp"), - - /** - * Downward Curve Text Shape - * - */ - @XmlEnumValue("textCurveDown") - TEXT_CURVE_DOWN("textCurveDown"), - - /** - * Upward Can Text Shape - * - */ - @XmlEnumValue("textCanUp") - TEXT_CAN_UP("textCanUp"), - - /** - * Downward Can Text Shape - * - */ - @XmlEnumValue("textCanDown") - TEXT_CAN_DOWN("textCanDown"), - - /** - * Wave 1 Text Shape - * - */ - @XmlEnumValue("textWave1") - TEXT_WAVE_1("textWave1"), - - /** - * Wave 2 Text Shape - * - */ - @XmlEnumValue("textWave2") - TEXT_WAVE_2("textWave2"), - - /** - * Double Wave 1 Text Shape - * - */ - @XmlEnumValue("textDoubleWave1") - TEXT_DOUBLE_WAVE_1("textDoubleWave1"), - - /** - * Wave 4 Text Shape - * - */ - @XmlEnumValue("textWave4") - TEXT_WAVE_4("textWave4"), - - /** - * Inflate Text Shape - * - */ - @XmlEnumValue("textInflate") - TEXT_INFLATE("textInflate"), - - /** - * Deflate Text Shape - * - */ - @XmlEnumValue("textDeflate") - TEXT_DEFLATE("textDeflate"), - - /** - * Bottom Inflate Text Shape - * - */ - @XmlEnumValue("textInflateBottom") - TEXT_INFLATE_BOTTOM("textInflateBottom"), - - /** - * Bottom Deflate Text Shape - * - */ - @XmlEnumValue("textDeflateBottom") - TEXT_DEFLATE_BOTTOM("textDeflateBottom"), - - /** - * Top Inflate Text Shape - * - */ - @XmlEnumValue("textInflateTop") - TEXT_INFLATE_TOP("textInflateTop"), - - /** - * Top Deflate Text Shape - * - */ - @XmlEnumValue("textDeflateTop") - TEXT_DEFLATE_TOP("textDeflateTop"), - - /** - * Deflate-Inflate Text Shape - * - */ - @XmlEnumValue("textDeflateInflate") - TEXT_DEFLATE_INFLATE("textDeflateInflate"), - - /** - * Deflate-Inflate-Deflate Text Shape - * - */ - @XmlEnumValue("textDeflateInflateDeflate") - TEXT_DEFLATE_INFLATE_DEFLATE("textDeflateInflateDeflate"), - - /** - * Right Fade Text Shape - * - */ - @XmlEnumValue("textFadeRight") - TEXT_FADE_RIGHT("textFadeRight"), - - /** - * Left Fade Text Shape - * - */ - @XmlEnumValue("textFadeLeft") - TEXT_FADE_LEFT("textFadeLeft"), - - /** - * Upward Fade Text Shape - * - */ - @XmlEnumValue("textFadeUp") - TEXT_FADE_UP("textFadeUp"), - - /** - * Downward Fade Text Shape - * - */ - @XmlEnumValue("textFadeDown") - TEXT_FADE_DOWN("textFadeDown"), - - /** - * Upward Slant Text Shape - * - */ - @XmlEnumValue("textSlantUp") - TEXT_SLANT_UP("textSlantUp"), - - /** - * Downward Slant Text Shape - * - */ - @XmlEnumValue("textSlantDown") - TEXT_SLANT_DOWN("textSlantDown"), - - /** - * Upward Cascade Text Shape - * - */ - @XmlEnumValue("textCascadeUp") - TEXT_CASCADE_UP("textCascadeUp"), - - /** - * Downward Cascade Text Shape - * - */ - @XmlEnumValue("textCascadeDown") - TEXT_CASCADE_DOWN("textCascadeDown"); - private final String value; - - STTextShapeType(String v) { - value = v; - } - - public String value() { - return value; - } - - public static STTextShapeType fromValue(String v) { - for (STTextShapeType c: STTextShapeType.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.draw.binding; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ST_TextShapeType. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="ST_TextShapeType">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}token">
+ *     <enumeration value="textNoShape"/>
+ *     <enumeration value="textPlain"/>
+ *     <enumeration value="textStop"/>
+ *     <enumeration value="textTriangle"/>
+ *     <enumeration value="textTriangleInverted"/>
+ *     <enumeration value="textChevron"/>
+ *     <enumeration value="textChevronInverted"/>
+ *     <enumeration value="textRingInside"/>
+ *     <enumeration value="textRingOutside"/>
+ *     <enumeration value="textArchUp"/>
+ *     <enumeration value="textArchDown"/>
+ *     <enumeration value="textCircle"/>
+ *     <enumeration value="textButton"/>
+ *     <enumeration value="textArchUpPour"/>
+ *     <enumeration value="textArchDownPour"/>
+ *     <enumeration value="textCirclePour"/>
+ *     <enumeration value="textButtonPour"/>
+ *     <enumeration value="textCurveUp"/>
+ *     <enumeration value="textCurveDown"/>
+ *     <enumeration value="textCanUp"/>
+ *     <enumeration value="textCanDown"/>
+ *     <enumeration value="textWave1"/>
+ *     <enumeration value="textWave2"/>
+ *     <enumeration value="textDoubleWave1"/>
+ *     <enumeration value="textWave4"/>
+ *     <enumeration value="textInflate"/>
+ *     <enumeration value="textDeflate"/>
+ *     <enumeration value="textInflateBottom"/>
+ *     <enumeration value="textDeflateBottom"/>
+ *     <enumeration value="textInflateTop"/>
+ *     <enumeration value="textDeflateTop"/>
+ *     <enumeration value="textDeflateInflate"/>
+ *     <enumeration value="textDeflateInflateDeflate"/>
+ *     <enumeration value="textFadeRight"/>
+ *     <enumeration value="textFadeLeft"/>
+ *     <enumeration value="textFadeUp"/>
+ *     <enumeration value="textFadeDown"/>
+ *     <enumeration value="textSlantUp"/>
+ *     <enumeration value="textSlantDown"/>
+ *     <enumeration value="textCascadeUp"/>
+ *     <enumeration value="textCascadeDown"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "ST_TextShapeType", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") +@XmlEnum +public enum STTextShapeType { + + + /** + * No Text Shape + * + */ + @XmlEnumValue("textNoShape") + TEXT_NO_SHAPE("textNoShape"), + + /** + * Plain Text Shape + * + */ + @XmlEnumValue("textPlain") + TEXT_PLAIN("textPlain"), + + /** + * Stop Sign Text Shape + * + */ + @XmlEnumValue("textStop") + TEXT_STOP("textStop"), + + /** + * Triangle Text Shape + * + */ + @XmlEnumValue("textTriangle") + TEXT_TRIANGLE("textTriangle"), + + /** + * Inverted Triangle Text Shape + * + */ + @XmlEnumValue("textTriangleInverted") + TEXT_TRIANGLE_INVERTED("textTriangleInverted"), + + /** + * Chevron Text Shape + * + */ + @XmlEnumValue("textChevron") + TEXT_CHEVRON("textChevron"), + + /** + * Inverted Chevron Text Shape + * + */ + @XmlEnumValue("textChevronInverted") + TEXT_CHEVRON_INVERTED("textChevronInverted"), + + /** + * Inside Ring Text Shape + * + */ + @XmlEnumValue("textRingInside") + TEXT_RING_INSIDE("textRingInside"), + + /** + * Outside Ring Text Shape + * + */ + @XmlEnumValue("textRingOutside") + TEXT_RING_OUTSIDE("textRingOutside"), + + /** + * Upward Arch Text Shape + * + */ + @XmlEnumValue("textArchUp") + TEXT_ARCH_UP("textArchUp"), + + /** + * Downward Arch Text Shape + * + */ + @XmlEnumValue("textArchDown") + TEXT_ARCH_DOWN("textArchDown"), + + /** + * Circle Text Shape + * + */ + @XmlEnumValue("textCircle") + TEXT_CIRCLE("textCircle"), + + /** + * Button Text Shape + * + */ + @XmlEnumValue("textButton") + TEXT_BUTTON("textButton"), + + /** + * Upward Pour Arch Text Shape + * + */ + @XmlEnumValue("textArchUpPour") + TEXT_ARCH_UP_POUR("textArchUpPour"), + + /** + * Downward Pour Arch Text Shape + * + */ + @XmlEnumValue("textArchDownPour") + TEXT_ARCH_DOWN_POUR("textArchDownPour"), + + /** + * Circle Pour Text Shape + * + */ + @XmlEnumValue("textCirclePour") + TEXT_CIRCLE_POUR("textCirclePour"), + + /** + * Button Pour Text Shape + * + */ + @XmlEnumValue("textButtonPour") + TEXT_BUTTON_POUR("textButtonPour"), + + /** + * Upward Curve Text Shape + * + */ + @XmlEnumValue("textCurveUp") + TEXT_CURVE_UP("textCurveUp"), + + /** + * Downward Curve Text Shape + * + */ + @XmlEnumValue("textCurveDown") + TEXT_CURVE_DOWN("textCurveDown"), + + /** + * Upward Can Text Shape + * + */ + @XmlEnumValue("textCanUp") + TEXT_CAN_UP("textCanUp"), + + /** + * Downward Can Text Shape + * + */ + @XmlEnumValue("textCanDown") + TEXT_CAN_DOWN("textCanDown"), + + /** + * Wave 1 Text Shape + * + */ + @XmlEnumValue("textWave1") + TEXT_WAVE_1("textWave1"), + + /** + * Wave 2 Text Shape + * + */ + @XmlEnumValue("textWave2") + TEXT_WAVE_2("textWave2"), + + /** + * Double Wave 1 Text Shape + * + */ + @XmlEnumValue("textDoubleWave1") + TEXT_DOUBLE_WAVE_1("textDoubleWave1"), + + /** + * Wave 4 Text Shape + * + */ + @XmlEnumValue("textWave4") + TEXT_WAVE_4("textWave4"), + + /** + * Inflate Text Shape + * + */ + @XmlEnumValue("textInflate") + TEXT_INFLATE("textInflate"), + + /** + * Deflate Text Shape + * + */ + @XmlEnumValue("textDeflate") + TEXT_DEFLATE("textDeflate"), + + /** + * Bottom Inflate Text Shape + * + */ + @XmlEnumValue("textInflateBottom") + TEXT_INFLATE_BOTTOM("textInflateBottom"), + + /** + * Bottom Deflate Text Shape + * + */ + @XmlEnumValue("textDeflateBottom") + TEXT_DEFLATE_BOTTOM("textDeflateBottom"), + + /** + * Top Inflate Text Shape + * + */ + @XmlEnumValue("textInflateTop") + TEXT_INFLATE_TOP("textInflateTop"), + + /** + * Top Deflate Text Shape + * + */ + @XmlEnumValue("textDeflateTop") + TEXT_DEFLATE_TOP("textDeflateTop"), + + /** + * Deflate-Inflate Text Shape + * + */ + @XmlEnumValue("textDeflateInflate") + TEXT_DEFLATE_INFLATE("textDeflateInflate"), + + /** + * Deflate-Inflate-Deflate Text Shape + * + */ + @XmlEnumValue("textDeflateInflateDeflate") + TEXT_DEFLATE_INFLATE_DEFLATE("textDeflateInflateDeflate"), + + /** + * Right Fade Text Shape + * + */ + @XmlEnumValue("textFadeRight") + TEXT_FADE_RIGHT("textFadeRight"), + + /** + * Left Fade Text Shape + * + */ + @XmlEnumValue("textFadeLeft") + TEXT_FADE_LEFT("textFadeLeft"), + + /** + * Upward Fade Text Shape + * + */ + @XmlEnumValue("textFadeUp") + TEXT_FADE_UP("textFadeUp"), + + /** + * Downward Fade Text Shape + * + */ + @XmlEnumValue("textFadeDown") + TEXT_FADE_DOWN("textFadeDown"), + + /** + * Upward Slant Text Shape + * + */ + @XmlEnumValue("textSlantUp") + TEXT_SLANT_UP("textSlantUp"), + + /** + * Downward Slant Text Shape + * + */ + @XmlEnumValue("textSlantDown") + TEXT_SLANT_DOWN("textSlantDown"), + + /** + * Upward Cascade Text Shape + * + */ + @XmlEnumValue("textCascadeUp") + TEXT_CASCADE_UP("textCascadeUp"), + + /** + * Downward Cascade Text Shape + * + */ + @XmlEnumValue("textCascadeDown") + TEXT_CASCADE_DOWN("textCascadeDown"); + private final String value; + + STTextShapeType(String v) { + value = v; + } + + public String value() { + return value; + } + + public static STTextShapeType fromValue(String v) { + for (STTextShapeType c: STTextShapeType.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/src/java/org/apache/poi/sl/usermodel/AutoNumberingScheme.java b/src/java/org/apache/poi/sl/usermodel/AutoNumberingScheme.java index 1ba4f13e25..1006134d5f 100644 --- a/src/java/org/apache/poi/sl/usermodel/AutoNumberingScheme.java +++ b/src/java/org/apache/poi/sl/usermodel/AutoNumberingScheme.java @@ -1,289 +1,289 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import java.util.Locale; - -public enum AutoNumberingScheme { - /** Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ... */ - alphaLcParenBoth(0x0008, 1), - /** Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ... */ - alphaUcParenBoth(0x000A, 2), - /** Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ... */ - alphaLcParenRight(0x0009, 3), - /** Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ... */ - alphaUcParenRight(0x000B, 4), - /** Lowercase Latin character followed by a period. Example: a., b., c., ... */ - alphaLcPeriod(0x0000, 5), - /** Uppercase Latin character followed by a period. Example: A., B., C., ... */ - alphaUcPeriod(0x0001, 6), - /** Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ... */ - arabicParenBoth(0x000C, 7), - /** Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ... */ - arabicParenRight(0x0002, 8), - /** Arabic numeral followed by a period. Example: 1., 2., 3., ... */ - arabicPeriod(0x0003, 9), - /** Arabic numeral. Example: 1, 2, 3, ... */ - arabicPlain(0x000D, 10), - /** Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ... */ - romanLcParenBoth(0x0004, 11), - /** Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ... */ - romanUcParenBoth(0x000E, 12), - /** Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ... */ - romanLcParenRight(0x0005, 13), - /** Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), .... */ - romanUcParenRight(0x000F, 14), - /** Lowercase Roman numeral followed by a period. Example: i., ii., iii., ... */ - romanLcPeriod(0x0006, 15), - /** Uppercase Roman numeral followed by a period. Example: I., II., III., ... */ - romanUcPeriod(0x0007, 16), - /** Double byte circle numbers. */ - circleNumDbPlain(0x0012, 17), - /** Wingdings black circle numbers. */ - circleNumWdBlackPlain(0x0014, 18), - /** Wingdings white circle numbers. */ - circleNumWdWhitePlain(0x0013, 19), - /** Double-byte Arabic numbers with double-byte period. */ - arabicDbPeriod(0x001D, 20), - /** Double-byte Arabic numbers. */ - arabicDbPlain(0x001C, 21), - /** Simplified Chinese with single-byte period. */ - ea1ChsPeriod(0x0011, 22), - /** Simplified Chinese. */ - ea1ChsPlain(0x0010, 23), - /** Traditional Chinese with single-byte period. */ - ea1ChtPeriod(0x0015, 24), - /** Traditional Chinese. */ - ea1ChtPlain(0x0014, 25), - /** Japanese with double-byte period. */ - ea1JpnChsDbPeriod(0x0026, 26), - /** Japanese/Korean. */ - ea1JpnKorPlain(0x001A, 27), - /** Japanese/Korean with single-byte period. */ - ea1JpnKorPeriod(0x001B, 28), - /** Bidi Arabic 1 (AraAlpha) with ANSI minus symbol. */ - arabic1Minus(0x0017, 29), - /** Bidi Arabic 2 (AraAbjad) with ANSI minus symbol. */ - arabic2Minus(0x0018, 30), - /** Bidi Hebrew 2 with ANSI minus symbol. */ - hebrew2Minus(0x0019, 31), - /** Thai alphabetic character followed by a period. */ - thaiAlphaPeriod(0x001E, 32), - /** Thai alphabetic character followed by a closing parenthesis. */ - thaiAlphaParenRight(0x001F, 33), - /** Thai alphabetic character enclosed by parentheses. */ - thaiAlphaParenBoth(0x0020, 34), - /** Thai numeral followed by a period. */ - thaiNumPeriod(0x0021, 35), - /** Thai numeral followed by a closing parenthesis. */ - thaiNumParenRight(0x0022, 36), - /** Thai numeral enclosed in parentheses. */ - thaiNumParenBoth(0x0023, 37), - /** Hindi alphabetic character followed by a period. */ - hindiAlphaPeriod(0x0024, 38), - /** Hindi numeric character followed by a period. */ - hindiNumPeriod(0x0025, 39), - /** Hindi numeric character followed by a closing parenthesis. */ - hindiNumParenRight(0x0027, 40), - /** Hindi alphabetic character followed by a period. */ - hindiAlpha1Period(0x0027, 41); - - public final int nativeId, ooxmlId; - - AutoNumberingScheme(int nativeId, int ooxmlId) { - this.nativeId = nativeId; - this.ooxmlId = ooxmlId; - } - - public static AutoNumberingScheme forNativeID(int nativeId) { - for (AutoNumberingScheme ans : values()) { - if (ans.nativeId == nativeId) return ans; - } - return null; - } - - public static AutoNumberingScheme forOoxmlID(int ooxmlId) { - for (AutoNumberingScheme ans : values()) { - if (ans.ooxmlId == ooxmlId) return ans; - } - return null; - } - - public String getDescription() { - switch (this) { - case alphaLcPeriod : return "Lowercase Latin character followed by a period. Example: a., b., c., ..."; - case alphaUcPeriod : return "Uppercase Latin character followed by a period. Example: A., B., C., ..."; - case arabicParenRight : return "Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ..."; - case arabicPeriod : return "Arabic numeral followed by a period. Example: 1., 2., 3., ..."; - case romanLcParenBoth : return "Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ..."; - case romanLcParenRight : return "Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ..."; - case romanLcPeriod : return "Lowercase Roman numeral followed by a period. Example: i., ii., iii., ..."; - case romanUcPeriod : return "Uppercase Roman numeral followed by a period. Example: I., II., III., ..."; - case alphaLcParenBoth : return "Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ..."; - case alphaLcParenRight : return "Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ..."; - case alphaUcParenBoth : return "Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ..."; - case alphaUcParenRight : return "Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ..."; - case arabicParenBoth : return "Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ..."; - case arabicPlain : return "Arabic numeral. Example: 1, 2, 3, ..."; - case romanUcParenBoth : return "Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ..."; - case romanUcParenRight : return "Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), ..."; - case ea1ChsPlain : return "Simplified Chinese."; - case ea1ChsPeriod : return "Simplified Chinese with single-byte period."; - case circleNumDbPlain : return "Double byte circle numbers."; - case circleNumWdWhitePlain : return "Wingdings white circle numbers."; - case circleNumWdBlackPlain : return "Wingdings black circle numbers."; - case ea1ChtPlain : return "Traditional Chinese."; - case ea1ChtPeriod : return "Traditional Chinese with single-byte period."; - case arabic1Minus : return "Bidi Arabic 1 (AraAlpha) with ANSI minus symbol."; - case arabic2Minus : return "Bidi Arabic 2 (AraAbjad) with ANSI minus symbol."; - case hebrew2Minus : return "Bidi Hebrew 2 with ANSI minus symbol."; - case ea1JpnKorPlain : return "Japanese/Korean."; - case ea1JpnKorPeriod : return "Japanese/Korean with single-byte period."; - case arabicDbPlain : return "Double-byte Arabic numbers."; - case arabicDbPeriod : return "Double-byte Arabic numbers with double-byte period."; - case thaiAlphaPeriod : return "Thai alphabetic character followed by a period."; - case thaiAlphaParenRight : return "Thai alphabetic character followed by a closing parenthesis."; - case thaiAlphaParenBoth : return "Thai alphabetic character enclosed by parentheses."; - case thaiNumPeriod : return "Thai numeral followed by a period."; - case thaiNumParenRight : return "Thai numeral followed by a closing parenthesis."; - case thaiNumParenBoth : return "Thai numeral enclosed in parentheses."; - case hindiAlphaPeriod : return "Hindi alphabetic character followed by a period."; - case hindiNumPeriod : return "Hindi numeric character followed by a period."; - case ea1JpnChsDbPeriod : return "Japanese with double-byte period."; - case hindiNumParenRight : return "Hindi numeric character followed by a closing parenthesis."; - case hindiAlpha1Period : return "Hindi alphabetic character followed by a period."; - default : return "Unknown Numbered Scheme"; - } - } - - public String format(int value) { - String index = formatIndex(value); - String cased = formatCase(index); - String seperated = formatSeperator(cased); - return seperated; - } - - private String formatSeperator(String cased) { - String name = name().toLowerCase(Locale.ROOT); - if (name.contains("plain")) return cased; - if (name.contains("parenright")) return cased+")"; - if (name.contains("parenboth")) return "("+cased+")"; - if (name.contains("period")) return cased+"."; - if (name.contains("minus")) return cased+"-"; // ??? - return cased; - } - - private String formatCase(String index) { - String name = name().toLowerCase(Locale.ROOT); - if (name.contains("lc")) return index.toLowerCase(Locale.ROOT); - if (name.contains("uc")) return index.toUpperCase(Locale.ROOT); - return index; - } - - private static final String ARABIC_LIST = "0123456789"; - private static final String ALPHA_LIST = "abcdefghijklmnopqrstuvwxyz"; - private static final String WINGDINGS_WHITE_LIST = - "\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089"; - private static final String WINGDINGS_BLACK_LIST = - "\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094"; - private static final String CIRCLE_DB_LIST = - "\u2776\u2777\u2778\u2779\u277A\u277B\u277C\u277D\u277E"; - - private String formatIndex(int value) { - String name = name().toLowerCase(Locale.ROOT); - if (name.startsWith("roman")) { - return formatRomanIndex(value); - } else if (name.startsWith("arabic") && !name.contains("db")) { - return getIndexedList(value, ARABIC_LIST, false); - } else if (name.startsWith("alpha")) { - return getIndexedList(value, ALPHA_LIST, true); - } else if (name.contains("WdWhite")) { - return (value == 10) ? "\u008A" - : getIndexedList(value, WINGDINGS_WHITE_LIST, false); - } else if (name.contains("WdBlack")) { - return (value == 10) ? "\u0095" - : getIndexedList(value, WINGDINGS_BLACK_LIST, false); - } else if (name.contains("NumDb")) { - return (value == 10) ? "\u277F" - : getIndexedList(value, CIRCLE_DB_LIST, true); - } else { - return "?"; - } - } - - private static String getIndexedList(int val, String list, boolean oneBased) { - StringBuilder sb = new StringBuilder(); - addIndexedChar(val, list, oneBased, sb); - return sb.toString(); - } - - private static void addIndexedChar(int val, String list, boolean oneBased, StringBuilder sb) { - if (oneBased) val -= 1; - final int len = list.length(); - if (val >= len) { - addIndexedChar(val/len, list, oneBased, sb); - } - sb.append(list.charAt(val%len)); - } - - - private String formatRomanIndex(int value) { - //M (1000), CM (900), D (500), CD (400), C (100), XC (90), L (50), XL (40), X (10), IX (9), V (5), IV (4) and I (1). - final int[] VALUES = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; - final String[] ROMAN = new String[]{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; - final String conciseList[][] = { - {"XLV", "VL"}, //45 - {"XCV", "VC"}, //95 - {"CDL", "LD"}, //450 - {"CML", "LM"}, //950 - {"CMVC", "LMVL"}, //995 - {"CDXC", "LDXL"}, //490 - {"CDVC", "LDVL"}, //495 - {"CMXC", "LMXL"}, //990 - {"XCIX", "VCIV"}, //99 - {"XLIX", "VLIV"}, //49 - {"XLIX", "IL"}, //49 - {"XCIX", "IC"}, //99 - {"CDXC", "XD"}, //490 - {"CDVC", "XDV"}, //495 - {"CDIC", "XDIX"}, //499 - {"LMVL", "XMV"}, //995 - {"CMIC", "XMIX"}, //999 - {"CMXC", "XM"}, // 990 - {"XDV", "VD"}, //495 - {"XDIX", "VDIV"}, //499 - {"XMV", "VM"}, // 995 - {"XMIX", "VMIV"}, //999 - {"VDIV", "ID"}, //499 - {"VMIV", "IM"} //999 - }; - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 13; i++) { - while (value >= VALUES[i]) { - value -= VALUES[i]; - sb.append(ROMAN[i]); - } - } - String result = sb.toString(); - for (String cc[] : conciseList) { - result = result.replace(cc[0], cc[1]); - } - return result; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.util.Locale; + +public enum AutoNumberingScheme { + /** Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ... */ + alphaLcParenBoth(0x0008, 1), + /** Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ... */ + alphaUcParenBoth(0x000A, 2), + /** Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ... */ + alphaLcParenRight(0x0009, 3), + /** Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ... */ + alphaUcParenRight(0x000B, 4), + /** Lowercase Latin character followed by a period. Example: a., b., c., ... */ + alphaLcPeriod(0x0000, 5), + /** Uppercase Latin character followed by a period. Example: A., B., C., ... */ + alphaUcPeriod(0x0001, 6), + /** Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ... */ + arabicParenBoth(0x000C, 7), + /** Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ... */ + arabicParenRight(0x0002, 8), + /** Arabic numeral followed by a period. Example: 1., 2., 3., ... */ + arabicPeriod(0x0003, 9), + /** Arabic numeral. Example: 1, 2, 3, ... */ + arabicPlain(0x000D, 10), + /** Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ... */ + romanLcParenBoth(0x0004, 11), + /** Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ... */ + romanUcParenBoth(0x000E, 12), + /** Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ... */ + romanLcParenRight(0x0005, 13), + /** Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), .... */ + romanUcParenRight(0x000F, 14), + /** Lowercase Roman numeral followed by a period. Example: i., ii., iii., ... */ + romanLcPeriod(0x0006, 15), + /** Uppercase Roman numeral followed by a period. Example: I., II., III., ... */ + romanUcPeriod(0x0007, 16), + /** Double byte circle numbers. */ + circleNumDbPlain(0x0012, 17), + /** Wingdings black circle numbers. */ + circleNumWdBlackPlain(0x0014, 18), + /** Wingdings white circle numbers. */ + circleNumWdWhitePlain(0x0013, 19), + /** Double-byte Arabic numbers with double-byte period. */ + arabicDbPeriod(0x001D, 20), + /** Double-byte Arabic numbers. */ + arabicDbPlain(0x001C, 21), + /** Simplified Chinese with single-byte period. */ + ea1ChsPeriod(0x0011, 22), + /** Simplified Chinese. */ + ea1ChsPlain(0x0010, 23), + /** Traditional Chinese with single-byte period. */ + ea1ChtPeriod(0x0015, 24), + /** Traditional Chinese. */ + ea1ChtPlain(0x0014, 25), + /** Japanese with double-byte period. */ + ea1JpnChsDbPeriod(0x0026, 26), + /** Japanese/Korean. */ + ea1JpnKorPlain(0x001A, 27), + /** Japanese/Korean with single-byte period. */ + ea1JpnKorPeriod(0x001B, 28), + /** Bidi Arabic 1 (AraAlpha) with ANSI minus symbol. */ + arabic1Minus(0x0017, 29), + /** Bidi Arabic 2 (AraAbjad) with ANSI minus symbol. */ + arabic2Minus(0x0018, 30), + /** Bidi Hebrew 2 with ANSI minus symbol. */ + hebrew2Minus(0x0019, 31), + /** Thai alphabetic character followed by a period. */ + thaiAlphaPeriod(0x001E, 32), + /** Thai alphabetic character followed by a closing parenthesis. */ + thaiAlphaParenRight(0x001F, 33), + /** Thai alphabetic character enclosed by parentheses. */ + thaiAlphaParenBoth(0x0020, 34), + /** Thai numeral followed by a period. */ + thaiNumPeriod(0x0021, 35), + /** Thai numeral followed by a closing parenthesis. */ + thaiNumParenRight(0x0022, 36), + /** Thai numeral enclosed in parentheses. */ + thaiNumParenBoth(0x0023, 37), + /** Hindi alphabetic character followed by a period. */ + hindiAlphaPeriod(0x0024, 38), + /** Hindi numeric character followed by a period. */ + hindiNumPeriod(0x0025, 39), + /** Hindi numeric character followed by a closing parenthesis. */ + hindiNumParenRight(0x0027, 40), + /** Hindi alphabetic character followed by a period. */ + hindiAlpha1Period(0x0027, 41); + + public final int nativeId, ooxmlId; + + AutoNumberingScheme(int nativeId, int ooxmlId) { + this.nativeId = nativeId; + this.ooxmlId = ooxmlId; + } + + public static AutoNumberingScheme forNativeID(int nativeId) { + for (AutoNumberingScheme ans : values()) { + if (ans.nativeId == nativeId) return ans; + } + return null; + } + + public static AutoNumberingScheme forOoxmlID(int ooxmlId) { + for (AutoNumberingScheme ans : values()) { + if (ans.ooxmlId == ooxmlId) return ans; + } + return null; + } + + public String getDescription() { + switch (this) { + case alphaLcPeriod : return "Lowercase Latin character followed by a period. Example: a., b., c., ..."; + case alphaUcPeriod : return "Uppercase Latin character followed by a period. Example: A., B., C., ..."; + case arabicParenRight : return "Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ..."; + case arabicPeriod : return "Arabic numeral followed by a period. Example: 1., 2., 3., ..."; + case romanLcParenBoth : return "Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ..."; + case romanLcParenRight : return "Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ..."; + case romanLcPeriod : return "Lowercase Roman numeral followed by a period. Example: i., ii., iii., ..."; + case romanUcPeriod : return "Uppercase Roman numeral followed by a period. Example: I., II., III., ..."; + case alphaLcParenBoth : return "Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ..."; + case alphaLcParenRight : return "Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ..."; + case alphaUcParenBoth : return "Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ..."; + case alphaUcParenRight : return "Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ..."; + case arabicParenBoth : return "Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ..."; + case arabicPlain : return "Arabic numeral. Example: 1, 2, 3, ..."; + case romanUcParenBoth : return "Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ..."; + case romanUcParenRight : return "Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), ..."; + case ea1ChsPlain : return "Simplified Chinese."; + case ea1ChsPeriod : return "Simplified Chinese with single-byte period."; + case circleNumDbPlain : return "Double byte circle numbers."; + case circleNumWdWhitePlain : return "Wingdings white circle numbers."; + case circleNumWdBlackPlain : return "Wingdings black circle numbers."; + case ea1ChtPlain : return "Traditional Chinese."; + case ea1ChtPeriod : return "Traditional Chinese with single-byte period."; + case arabic1Minus : return "Bidi Arabic 1 (AraAlpha) with ANSI minus symbol."; + case arabic2Minus : return "Bidi Arabic 2 (AraAbjad) with ANSI minus symbol."; + case hebrew2Minus : return "Bidi Hebrew 2 with ANSI minus symbol."; + case ea1JpnKorPlain : return "Japanese/Korean."; + case ea1JpnKorPeriod : return "Japanese/Korean with single-byte period."; + case arabicDbPlain : return "Double-byte Arabic numbers."; + case arabicDbPeriod : return "Double-byte Arabic numbers with double-byte period."; + case thaiAlphaPeriod : return "Thai alphabetic character followed by a period."; + case thaiAlphaParenRight : return "Thai alphabetic character followed by a closing parenthesis."; + case thaiAlphaParenBoth : return "Thai alphabetic character enclosed by parentheses."; + case thaiNumPeriod : return "Thai numeral followed by a period."; + case thaiNumParenRight : return "Thai numeral followed by a closing parenthesis."; + case thaiNumParenBoth : return "Thai numeral enclosed in parentheses."; + case hindiAlphaPeriod : return "Hindi alphabetic character followed by a period."; + case hindiNumPeriod : return "Hindi numeric character followed by a period."; + case ea1JpnChsDbPeriod : return "Japanese with double-byte period."; + case hindiNumParenRight : return "Hindi numeric character followed by a closing parenthesis."; + case hindiAlpha1Period : return "Hindi alphabetic character followed by a period."; + default : return "Unknown Numbered Scheme"; + } + } + + public String format(int value) { + String index = formatIndex(value); + String cased = formatCase(index); + String seperated = formatSeperator(cased); + return seperated; + } + + private String formatSeperator(String cased) { + String name = name().toLowerCase(Locale.ROOT); + if (name.contains("plain")) return cased; + if (name.contains("parenright")) return cased+")"; + if (name.contains("parenboth")) return "("+cased+")"; + if (name.contains("period")) return cased+"."; + if (name.contains("minus")) return cased+"-"; // ??? + return cased; + } + + private String formatCase(String index) { + String name = name().toLowerCase(Locale.ROOT); + if (name.contains("lc")) return index.toLowerCase(Locale.ROOT); + if (name.contains("uc")) return index.toUpperCase(Locale.ROOT); + return index; + } + + private static final String ARABIC_LIST = "0123456789"; + private static final String ALPHA_LIST = "abcdefghijklmnopqrstuvwxyz"; + private static final String WINGDINGS_WHITE_LIST = + "\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089"; + private static final String WINGDINGS_BLACK_LIST = + "\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094"; + private static final String CIRCLE_DB_LIST = + "\u2776\u2777\u2778\u2779\u277A\u277B\u277C\u277D\u277E"; + + private String formatIndex(int value) { + String name = name().toLowerCase(Locale.ROOT); + if (name.startsWith("roman")) { + return formatRomanIndex(value); + } else if (name.startsWith("arabic") && !name.contains("db")) { + return getIndexedList(value, ARABIC_LIST, false); + } else if (name.startsWith("alpha")) { + return getIndexedList(value, ALPHA_LIST, true); + } else if (name.contains("WdWhite")) { + return (value == 10) ? "\u008A" + : getIndexedList(value, WINGDINGS_WHITE_LIST, false); + } else if (name.contains("WdBlack")) { + return (value == 10) ? "\u0095" + : getIndexedList(value, WINGDINGS_BLACK_LIST, false); + } else if (name.contains("NumDb")) { + return (value == 10) ? "\u277F" + : getIndexedList(value, CIRCLE_DB_LIST, true); + } else { + return "?"; + } + } + + private static String getIndexedList(int val, String list, boolean oneBased) { + StringBuilder sb = new StringBuilder(); + addIndexedChar(val, list, oneBased, sb); + return sb.toString(); + } + + private static void addIndexedChar(int val, String list, boolean oneBased, StringBuilder sb) { + if (oneBased) val -= 1; + final int len = list.length(); + if (val >= len) { + addIndexedChar(val/len, list, oneBased, sb); + } + sb.append(list.charAt(val%len)); + } + + + private String formatRomanIndex(int value) { + //M (1000), CM (900), D (500), CD (400), C (100), XC (90), L (50), XL (40), X (10), IX (9), V (5), IV (4) and I (1). + final int[] VALUES = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + final String[] ROMAN = new String[]{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + final String conciseList[][] = { + {"XLV", "VL"}, //45 + {"XCV", "VC"}, //95 + {"CDL", "LD"}, //450 + {"CML", "LM"}, //950 + {"CMVC", "LMVL"}, //995 + {"CDXC", "LDXL"}, //490 + {"CDVC", "LDVL"}, //495 + {"CMXC", "LMXL"}, //990 + {"XCIX", "VCIV"}, //99 + {"XLIX", "VLIV"}, //49 + {"XLIX", "IL"}, //49 + {"XCIX", "IC"}, //99 + {"CDXC", "XD"}, //490 + {"CDVC", "XDV"}, //495 + {"CDIC", "XDIX"}, //499 + {"LMVL", "XMV"}, //995 + {"CMIC", "XMIX"}, //999 + {"CMXC", "XM"}, // 990 + {"XDV", "VD"}, //495 + {"XDIX", "VDIV"}, //499 + {"XMV", "VM"}, // 995 + {"XMIX", "VMIV"}, //999 + {"VDIV", "ID"}, //499 + {"VMIV", "IM"} //999 + }; + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 13; i++) { + while (value >= VALUES[i]) { + value -= VALUES[i]; + sb.append(ROMAN[i]); + } + } + String result = sb.toString(); + for (String cc[] : conciseList) { + result = result.replace(cc[0], cc[1]); + } + return result; + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/sl/usermodel/ColorStyle.java b/src/java/org/apache/poi/sl/usermodel/ColorStyle.java index fba7f5eae0..da24d16583 100644 --- a/src/java/org/apache/poi/sl/usermodel/ColorStyle.java +++ b/src/java/org/apache/poi/sl/usermodel/ColorStyle.java @@ -1,109 +1,109 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import java.awt.Color; - - -public interface ColorStyle { - Color getColor(); - - /** - * the opacity as expressed by a percentage value - * - * @return opacity in percents in the range [0..100000] - * or -1 if the value is not set - */ - int getAlpha(); - - /** - * the hue shift as expressed by a percentage relative to the input color. - * Be aware that OOXML also returns values greater than 100% - * - * @return hue shift in percents in the range [0..100000] (usually ...) - * or -1 if the value is not set - */ - int getHueOff(); - - /** - * the hue as expressed by a percentage relative to the input color. - * Be aware that OOXML also returns values greater than 100% - * - * @return hue in percents in the range [0..100000] (usually ...) - * or -1 if the value is not set - */ - int getHueMod(); - - /** - * the saturation shift as expressed by a percentage relative to the input color. - * Be aware that OOXML also returns values greater than 100% - * - * @return saturation shift in percents in the range [0..100000] (usually ...) - * or -1 if the value is not set - */ - int getSatOff(); - - /** - * the saturation as expressed by a percentage relative to the input color. - * Be aware that OOXML also returns values greater than 100% - * - * @return saturation in percents in the range [0..100000] (usually ...) - * or -1 if the value is not set - */ - int getSatMod(); - - /** - * the luminance shift as expressed by a percentage relative to the input color. - * Be aware that OOXML also returns values greater than 100% - * - * @return luminance shift in percents in the range [0..100000] (usually ...) - * or -1 if the value is not set - */ - int getLumOff(); - - /** - * the luminance as expressed by a percentage relative to the input color. - * Be aware that OOXML also returns values greater than 100%. - * - * @return luminance in percents in the range [0..100000] (usually ...) - * or -1 if the value is not set - */ - int getLumMod(); - - /** - * specifies a darker version of its input color. - * A 10% shade is 10% of the input color combined with 90% black. - * Be aware that OOXML also returns values greater than 100%. - * - * @return the value of the shade specified as percents in the range [0..100000] (usually ...) - * with 0% indicating minimal shade and 100% indicating maximum - * or -1 if the value is not set - */ - int getShade(); - - /** - * specifies a lighter version of its input color. - * A 10% tint is 10% of the input color combined with 90% white. - * Be aware that OOXML also returns values greater than 100% - * - * @return the value of the tint specified as percents in the range [0..100000] (usually ...) - * with 0% indicating minimal tint and 100% indicating maximum - * or -1 if the value is not set - */ - int getTint(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.awt.Color; + + +public interface ColorStyle { + Color getColor(); + + /** + * the opacity as expressed by a percentage value + * + * @return opacity in percents in the range [0..100000] + * or -1 if the value is not set + */ + int getAlpha(); + + /** + * the hue shift as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return hue shift in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getHueOff(); + + /** + * the hue as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return hue in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getHueMod(); + + /** + * the saturation shift as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return saturation shift in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getSatOff(); + + /** + * the saturation as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return saturation in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getSatMod(); + + /** + * the luminance shift as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return luminance shift in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getLumOff(); + + /** + * the luminance as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100%. + * + * @return luminance in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getLumMod(); + + /** + * specifies a darker version of its input color. + * A 10% shade is 10% of the input color combined with 90% black. + * Be aware that OOXML also returns values greater than 100%. + * + * @return the value of the shade specified as percents in the range [0..100000] (usually ...) + * with 0% indicating minimal shade and 100% indicating maximum + * or -1 if the value is not set + */ + int getShade(); + + /** + * specifies a lighter version of its input color. + * A 10% tint is 10% of the input color combined with 90% white. + * Be aware that OOXML also returns values greater than 100% + * + * @return the value of the tint specified as percents in the range [0..100000] (usually ...) + * with 0% indicating minimal tint and 100% indicating maximum + * or -1 if the value is not set + */ + int getTint(); +} diff --git a/src/java/org/apache/poi/sl/usermodel/ConnectorShape.java b/src/java/org/apache/poi/sl/usermodel/ConnectorShape.java index 39e34d29e3..e10c7507dd 100644 --- a/src/java/org/apache/poi/sl/usermodel/ConnectorShape.java +++ b/src/java/org/apache/poi/sl/usermodel/ConnectorShape.java @@ -1,25 +1,25 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -public interface ConnectorShape< - S extends Shape, - P extends TextParagraph -> extends SimpleShape { - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +public interface ConnectorShape< + S extends Shape, + P extends TextParagraph +> extends SimpleShape { + +} diff --git a/src/java/org/apache/poi/sl/usermodel/FillStyle.java b/src/java/org/apache/poi/sl/usermodel/FillStyle.java index 8414000b8b..59cff8dd47 100644 --- a/src/java/org/apache/poi/sl/usermodel/FillStyle.java +++ b/src/java/org/apache/poi/sl/usermodel/FillStyle.java @@ -1,22 +1,22 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -public interface FillStyle { - PaintStyle getPaint(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +public interface FillStyle { + PaintStyle getPaint(); +} diff --git a/src/java/org/apache/poi/sl/usermodel/FreeformShape.java b/src/java/org/apache/poi/sl/usermodel/FreeformShape.java index 9536065ef0..c8ada26f22 100644 --- a/src/java/org/apache/poi/sl/usermodel/FreeformShape.java +++ b/src/java/org/apache/poi/sl/usermodel/FreeformShape.java @@ -1,45 +1,45 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import java.awt.geom.Path2D; - -public interface FreeformShape< - S extends Shape, - P extends TextParagraph -> extends AutoShape { - /** - * Gets the shape path. - *

- * The path is translated in the shape's coordinate system, i.e. - * freeform.getPath().getBounds2D() equals to freeform.getAnchor() - * (small discrepancies are possible due to rounding errors) - *

- * - * @return the path - */ - Path2D.Double getPath(); - - /** - * Set the shape path - * - * @param path shape outline - * @return the number of points written - */ - int setPath(Path2D.Double path); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.awt.geom.Path2D; + +public interface FreeformShape< + S extends Shape, + P extends TextParagraph +> extends AutoShape { + /** + * Gets the shape path. + *

+ * The path is translated in the shape's coordinate system, i.e. + * freeform.getPath().getBounds2D() equals to freeform.getAnchor() + * (small discrepancies are possible due to rounding errors) + *

+ * + * @return the path + */ + Path2D.Double getPath(); + + /** + * Set the shape path + * + * @param path shape outline + * @return the number of points written + */ + int setPath(Path2D.Double path); +} diff --git a/src/java/org/apache/poi/sl/usermodel/GraphicalFrame.java b/src/java/org/apache/poi/sl/usermodel/GraphicalFrame.java index 20621efedf..f8ba1e2c9d 100644 --- a/src/java/org/apache/poi/sl/usermodel/GraphicalFrame.java +++ b/src/java/org/apache/poi/sl/usermodel/GraphicalFrame.java @@ -1,29 +1,29 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -public interface GraphicalFrame< - S extends Shape, - P extends TextParagraph -> extends Shape, PlaceableShape { - - /** - * @return a fallback representation as picture shape - */ - PictureShape getFallbackPicture(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +public interface GraphicalFrame< + S extends Shape, + P extends TextParagraph +> extends Shape, PlaceableShape { + + /** + * @return a fallback representation as picture shape + */ + PictureShape getFallbackPicture(); +} diff --git a/src/java/org/apache/poi/sl/usermodel/Insets2D.java b/src/java/org/apache/poi/sl/usermodel/Insets2D.java index c7e59c27f5..205e4053a2 100644 --- a/src/java/org/apache/poi/sl/usermodel/Insets2D.java +++ b/src/java/org/apache/poi/sl/usermodel/Insets2D.java @@ -1,140 +1,140 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -/** - * This is a replacement for {@link java.awt.Insets} which works on doubles - * instead of ints - */ -public final class Insets2D implements Cloneable { - - /** - * The inset from the top. - * This value is added to the Top of the rectangle - * to yield a new location for the Top. - */ - public double top; - - /** - * The inset from the left. - * This value is added to the Left of the rectangle - * to yield a new location for the Left edge. - */ - public double left; - - /** - * The inset from the bottom. - * This value is subtracted from the Bottom of the rectangle - * to yield a new location for the Bottom. - */ - public double bottom; - - /** - * The inset from the right. - * This value is subtracted from the Right of the rectangle - * to yield a new location for the Right edge. - */ - public double right; - - /** - * Creates and initializes a new Insets object with the - * specified top, left, bottom, and right insets. - * @param top the inset from the top. - * @param left the inset from the left. - * @param bottom the inset from the bottom. - * @param right the inset from the right. - */ - public Insets2D(double top, double left, double bottom, double right) { - this.top = top; - this.left = left; - this.bottom = bottom; - this.right = right; - } - - /** - * Set top, left, bottom, and right to the specified values - * - * @param top the inset from the top. - * @param left the inset from the left. - * @param bottom the inset from the bottom. - * @param right the inset from the right. - * @since 1.5 - */ - public void set(double top, double left, double bottom, double right) { - this.top = top; - this.left = left; - this.bottom = bottom; - this.right = right; - } - - /** - * Checks whether two insets objects are equal. Two instances - * of Insets are equal if the four integer values - * of the fields top, left, - * bottom, and right are all equal. - * @return true if the two insets are equal; - * otherwise false. - * @since JDK1.1 - */ - public boolean equals(Object obj) { - if (obj instanceof Insets2D) { - Insets2D insets = (Insets2D)obj; - return ((top == insets.top) && (left == insets.left) && - (bottom == insets.bottom) && (right == insets.right)); - } - return false; - } - - /** - * Returns the hash code for this Insets. - * - * @return a hash code for this Insets. - */ - public int hashCode() { - double sum1 = left + bottom; - double sum2 = right + top; - double val1 = sum1 * (sum1 + 1)/2 + left; - double val2 = sum2 * (sum2 + 1)/2 + top; - double sum3 = val1 + val2; - return (int)(sum3 * (sum3 + 1)/2 + val2); - } - - /** - * Returns a string representation of this Insets object. - * This method is intended to be used only for debugging purposes, and - * the content and format of the returned string may vary between - * implementations. The returned string may be empty but may not be - * null. - * - * @return a string representation of this Insets object. - */ - public String toString() { - return getClass().getName() + "[top=" + top + ",left=" + left + ",bottom=" + bottom + ",right=" + right + "]"; - } - - /** - * Create a copy of this object. - * @return a copy of this Insets2D object. - */ - @Override - public Insets2D clone() { - return new Insets2D(top, left, bottom, right); - } - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +/** + * This is a replacement for {@link java.awt.Insets} which works on doubles + * instead of ints + */ +public final class Insets2D implements Cloneable { + + /** + * The inset from the top. + * This value is added to the Top of the rectangle + * to yield a new location for the Top. + */ + public double top; + + /** + * The inset from the left. + * This value is added to the Left of the rectangle + * to yield a new location for the Left edge. + */ + public double left; + + /** + * The inset from the bottom. + * This value is subtracted from the Bottom of the rectangle + * to yield a new location for the Bottom. + */ + public double bottom; + + /** + * The inset from the right. + * This value is subtracted from the Right of the rectangle + * to yield a new location for the Right edge. + */ + public double right; + + /** + * Creates and initializes a new Insets object with the + * specified top, left, bottom, and right insets. + * @param top the inset from the top. + * @param left the inset from the left. + * @param bottom the inset from the bottom. + * @param right the inset from the right. + */ + public Insets2D(double top, double left, double bottom, double right) { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + + /** + * Set top, left, bottom, and right to the specified values + * + * @param top the inset from the top. + * @param left the inset from the left. + * @param bottom the inset from the bottom. + * @param right the inset from the right. + * @since 1.5 + */ + public void set(double top, double left, double bottom, double right) { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + + /** + * Checks whether two insets objects are equal. Two instances + * of Insets are equal if the four integer values + * of the fields top, left, + * bottom, and right are all equal. + * @return true if the two insets are equal; + * otherwise false. + * @since JDK1.1 + */ + public boolean equals(Object obj) { + if (obj instanceof Insets2D) { + Insets2D insets = (Insets2D)obj; + return ((top == insets.top) && (left == insets.left) && + (bottom == insets.bottom) && (right == insets.right)); + } + return false; + } + + /** + * Returns the hash code for this Insets. + * + * @return a hash code for this Insets. + */ + public int hashCode() { + double sum1 = left + bottom; + double sum2 = right + top; + double val1 = sum1 * (sum1 + 1)/2 + left; + double val2 = sum2 * (sum2 + 1)/2 + top; + double sum3 = val1 + val2; + return (int)(sum3 * (sum3 + 1)/2 + val2); + } + + /** + * Returns a string representation of this Insets object. + * This method is intended to be used only for debugging purposes, and + * the content and format of the returned string may vary between + * implementations. The returned string may be empty but may not be + * null. + * + * @return a string representation of this Insets object. + */ + public String toString() { + return getClass().getName() + "[top=" + top + ",left=" + left + ",bottom=" + bottom + ",right=" + right + "]"; + } + + /** + * Create a copy of this object. + * @return a copy of this Insets2D object. + */ + @Override + public Insets2D clone() { + return new Insets2D(top, left, bottom, right); + } + + +} diff --git a/src/java/org/apache/poi/sl/usermodel/LineDecoration.java b/src/java/org/apache/poi/sl/usermodel/LineDecoration.java index ad61e413c9..7d78e8040a 100644 --- a/src/java/org/apache/poi/sl/usermodel/LineDecoration.java +++ b/src/java/org/apache/poi/sl/usermodel/LineDecoration.java @@ -1,113 +1,113 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -public interface LineDecoration { - /** - * Represents the shape decoration that appears at the ends of lines. - */ - enum DecorationShape { - NONE(0,1), - TRIANGLE(1,2), - STEALTH(2,3), - DIAMOND(3,4), - OVAL(4,5), - ARROW(5,6); - - public final int nativeId; - public final int ooxmlId; - - DecorationShape(int nativeId, int ooxmlId) { - this.nativeId = nativeId; - this.ooxmlId = ooxmlId; - } - - public static DecorationShape fromNativeId(int nativeId) { - for (DecorationShape ld : values()) { - if (ld.nativeId == nativeId) return ld; - } - return null; - } - - public static DecorationShape fromOoxmlId(int ooxmlId) { - for (DecorationShape ds : values()) { - if (ds.ooxmlId == ooxmlId) return ds; - } - return null; - } - } - - enum DecorationSize { - SMALL(0, 1), - MEDIUM(1, 2), - LARGE(2, 3); - - public final int nativeId; - public final int ooxmlId; - - DecorationSize(int nativeId, int ooxmlId) { - this.nativeId = nativeId; - this.ooxmlId = ooxmlId; - } - - public static DecorationSize fromNativeId(int nativeId) { - for (DecorationSize ld : values()) { - if (ld.nativeId == nativeId) return ld; - } - return null; - } - - public static DecorationSize fromOoxmlId(int ooxmlId) { - for (DecorationSize ds : values()) { - if (ds.ooxmlId == ooxmlId) return ds; - } - return null; - } - } - - /** - * @return the line start shape - */ - DecorationShape getHeadShape(); - - /** - * @return the width of the start shape - */ - DecorationSize getHeadWidth(); - - /** - * @return the length of the start shape - */ - DecorationSize getHeadLength(); - - /** - * @return the line end shape - */ - DecorationShape getTailShape(); - - /** - * @return the width of the end shape - */ - DecorationSize getTailWidth(); - - /** - * @return the length of the end shape - */ - DecorationSize getTailLength(); - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +public interface LineDecoration { + /** + * Represents the shape decoration that appears at the ends of lines. + */ + enum DecorationShape { + NONE(0,1), + TRIANGLE(1,2), + STEALTH(2,3), + DIAMOND(3,4), + OVAL(4,5), + ARROW(5,6); + + public final int nativeId; + public final int ooxmlId; + + DecorationShape(int nativeId, int ooxmlId) { + this.nativeId = nativeId; + this.ooxmlId = ooxmlId; + } + + public static DecorationShape fromNativeId(int nativeId) { + for (DecorationShape ld : values()) { + if (ld.nativeId == nativeId) return ld; + } + return null; + } + + public static DecorationShape fromOoxmlId(int ooxmlId) { + for (DecorationShape ds : values()) { + if (ds.ooxmlId == ooxmlId) return ds; + } + return null; + } + } + + enum DecorationSize { + SMALL(0, 1), + MEDIUM(1, 2), + LARGE(2, 3); + + public final int nativeId; + public final int ooxmlId; + + DecorationSize(int nativeId, int ooxmlId) { + this.nativeId = nativeId; + this.ooxmlId = ooxmlId; + } + + public static DecorationSize fromNativeId(int nativeId) { + for (DecorationSize ld : values()) { + if (ld.nativeId == nativeId) return ld; + } + return null; + } + + public static DecorationSize fromOoxmlId(int ooxmlId) { + for (DecorationSize ds : values()) { + if (ds.ooxmlId == ooxmlId) return ds; + } + return null; + } + } + + /** + * @return the line start shape + */ + DecorationShape getHeadShape(); + + /** + * @return the width of the start shape + */ + DecorationSize getHeadWidth(); + + /** + * @return the length of the start shape + */ + DecorationSize getHeadLength(); + + /** + * @return the line end shape + */ + DecorationShape getTailShape(); + + /** + * @return the width of the end shape + */ + DecorationSize getTailWidth(); + + /** + * @return the length of the end shape + */ + DecorationSize getTailLength(); + +} diff --git a/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java b/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java index 9fdcf91f6b..da1981a04d 100644 --- a/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java +++ b/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java @@ -1,92 +1,92 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import java.awt.geom.Rectangle2D; - -public interface PlaceableShape< - S extends Shape, - P extends TextParagraph -> { - ShapeContainer getParent(); - - /** - * @return the sheet this shape belongs to - */ - Sheet getSheet(); - - /** - * @return the position of this shape within the drawing canvas. - * The coordinates are expressed in points - */ - Rectangle2D getAnchor(); - - /** - * @param anchor the position of this shape within the drawing canvas. - * The coordinates are expressed in points - */ - void setAnchor(Rectangle2D anchor); - - /** - * Rotation angle in degrees - *

- * Positive angles are clockwise (i.e., towards the positive y axis); - * negative angles are counter-clockwise (i.e., towards the negative y axis). - *

- * - * @return rotation angle in degrees - */ - double getRotation(); - - /** - * Rotate this shape. - *

- * Positive angles are clockwise (i.e., towards the positive y axis); - * negative angles are counter-clockwise (i.e., towards the negative y axis). - *

- * - * @param theta the rotation angle in degrees. - */ - void setRotation(double theta); - - /** - * @param flip whether the shape is horizontally flipped - */ - void setFlipHorizontal(boolean flip); - - /** - * Whether the shape is vertically flipped - * - * @param flip whether the shape is vertically flipped - */ - void setFlipVertical(boolean flip); - - /** - * Whether the shape is horizontally flipped - * - * @return whether the shape is horizontally flipped - */ - boolean getFlipHorizontal(); - - /** - * Whether the shape is vertically flipped - * - * @return whether the shape is vertically flipped - */ - boolean getFlipVertical(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.awt.geom.Rectangle2D; + +public interface PlaceableShape< + S extends Shape, + P extends TextParagraph +> { + ShapeContainer getParent(); + + /** + * @return the sheet this shape belongs to + */ + Sheet getSheet(); + + /** + * @return the position of this shape within the drawing canvas. + * The coordinates are expressed in points + */ + Rectangle2D getAnchor(); + + /** + * @param anchor the position of this shape within the drawing canvas. + * The coordinates are expressed in points + */ + void setAnchor(Rectangle2D anchor); + + /** + * Rotation angle in degrees + *

+ * Positive angles are clockwise (i.e., towards the positive y axis); + * negative angles are counter-clockwise (i.e., towards the negative y axis). + *

+ * + * @return rotation angle in degrees + */ + double getRotation(); + + /** + * Rotate this shape. + *

+ * Positive angles are clockwise (i.e., towards the positive y axis); + * negative angles are counter-clockwise (i.e., towards the negative y axis). + *

+ * + * @param theta the rotation angle in degrees. + */ + void setRotation(double theta); + + /** + * @param flip whether the shape is horizontally flipped + */ + void setFlipHorizontal(boolean flip); + + /** + * Whether the shape is vertically flipped + * + * @param flip whether the shape is vertically flipped + */ + void setFlipVertical(boolean flip); + + /** + * Whether the shape is horizontally flipped + * + * @return whether the shape is horizontally flipped + */ + boolean getFlipHorizontal(); + + /** + * Whether the shape is vertically flipped + * + * @return whether the shape is vertically flipped + */ + boolean getFlipVertical(); +} diff --git a/src/java/org/apache/poi/sl/usermodel/Placeholder.java b/src/java/org/apache/poi/sl/usermodel/Placeholder.java index e546e8bee2..1d7e4c421c 100644 --- a/src/java/org/apache/poi/sl/usermodel/Placeholder.java +++ b/src/java/org/apache/poi/sl/usermodel/Placeholder.java @@ -1,156 +1,156 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -public enum Placeholder { - /** - * No placeholder shape. - */ - NONE(0,0,0,0,0), - /** - * Title text placeholder shape. - */ - TITLE(13,1,1,1,1), - /** - * Body text placeholder shape. - */ - BODY(14,2,12,6,2), - /** - * Center title text placeholder shape. - */ - CENTERED_TITLE(15,3,3,3,3), - /** - * Sub-title text placeholder shape. - */ - SUBTITLE(16,4,4,4,4), - /** - * Date placeholder shape. - */ - DATETIME(7,7,7,7,5), - /** - * Slide number placeholder shape. - */ - SLIDE_NUMBER(8,8,8,8,6), - /** - * Footer placeholder shape. - */ - FOOTER(9,9,9,9,7), - /** - * Header placeholder shape. - */ - HEADER(10,10,10,10,8), - /** - * Object placeholder shape. - */ - CONTENT(19,19,19,19,9), - /** - * Graph object placeholder shape. - */ - CHART(20,20,20,20,10), - /** - * Table object placeholder shape. - */ - TABLE(21,21,21,21,11), - /** - * Clipart object placeholder shape. - */ - CLIP_ART(22,22,22,22,12), - /** - * Organization chart object placeholder shape. - */ - DGM(23,23,23,23,13), - /** - * Media object placeholder shape. - */ - MEDIA(24,24,24,24,14), - /** - * Slide image placeholder shape. - */ - SLIDE_IMAGE(11,11,11,5,15), - /** - * Picture object placeholder shape. - */ - PICTURE(26,26,26,26,16), - /** - * Vertical object placeholder shape. - */ - VERTICAL_OBJECT(25,25,25,25,-2), - /** - * Vertical title text placeholder shape. - */ - VERTICAL_TEXT_TITLE(17,17,17,17,-2), - /** - * Vertical body text placeholder shape. - */ - VERTICAL_TEXT_BODY(18,18,18,18,-2) - ; - - public final int nativeSlideId; - public final int nativeSlideMasterId; - public final int nativeNotesId; - public final int nativeNotesMasterId; - public final int ooxmlId; - - Placeholder(int nativeSlideId, int nativeSlideMasterId, int nativeNotesId, int nativeNotesMasterId, int ooxmlId) { - this.nativeSlideId = nativeSlideId; - this.nativeSlideMasterId = nativeSlideMasterId; - this.nativeNotesId = nativeNotesId; - this.nativeNotesMasterId = nativeNotesMasterId; - this.ooxmlId = ooxmlId; - } - - public static Placeholder lookupNativeSlide(int nativeId) { - return lookupNative(nativeId, 0); - } - - public static Placeholder lookupNativeSlideMaster(int nativeId) { - return lookupNative(nativeId, 1); - } - - public static Placeholder lookupNativeNotes(int nativeId) { - return lookupNative(nativeId, 2); - } - - public static Placeholder lookupNativeNotesMaster(int nativeId) { - return lookupNative(nativeId, 3); - } - - - private static Placeholder lookupNative(int nativeId, int type) { - for (Placeholder ph : values()) { - if ( - type == 0 && ph.nativeSlideId == nativeId || - type == 1 && ph.nativeSlideMasterId == nativeId || - type == 2 && ph.nativeNotesId == nativeId || - type == 3 && ph.nativeNotesMasterId == nativeId - ) { - return ph; - } - } - return null; - } - - public static Placeholder lookupOoxml(int ooxmlId) { - for (Placeholder ph : values()) { - if (ph.ooxmlId == ooxmlId) { - return ph; - } - } - return null; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +public enum Placeholder { + /** + * No placeholder shape. + */ + NONE(0,0,0,0,0), + /** + * Title text placeholder shape. + */ + TITLE(13,1,1,1,1), + /** + * Body text placeholder shape. + */ + BODY(14,2,12,6,2), + /** + * Center title text placeholder shape. + */ + CENTERED_TITLE(15,3,3,3,3), + /** + * Sub-title text placeholder shape. + */ + SUBTITLE(16,4,4,4,4), + /** + * Date placeholder shape. + */ + DATETIME(7,7,7,7,5), + /** + * Slide number placeholder shape. + */ + SLIDE_NUMBER(8,8,8,8,6), + /** + * Footer placeholder shape. + */ + FOOTER(9,9,9,9,7), + /** + * Header placeholder shape. + */ + HEADER(10,10,10,10,8), + /** + * Object placeholder shape. + */ + CONTENT(19,19,19,19,9), + /** + * Graph object placeholder shape. + */ + CHART(20,20,20,20,10), + /** + * Table object placeholder shape. + */ + TABLE(21,21,21,21,11), + /** + * Clipart object placeholder shape. + */ + CLIP_ART(22,22,22,22,12), + /** + * Organization chart object placeholder shape. + */ + DGM(23,23,23,23,13), + /** + * Media object placeholder shape. + */ + MEDIA(24,24,24,24,14), + /** + * Slide image placeholder shape. + */ + SLIDE_IMAGE(11,11,11,5,15), + /** + * Picture object placeholder shape. + */ + PICTURE(26,26,26,26,16), + /** + * Vertical object placeholder shape. + */ + VERTICAL_OBJECT(25,25,25,25,-2), + /** + * Vertical title text placeholder shape. + */ + VERTICAL_TEXT_TITLE(17,17,17,17,-2), + /** + * Vertical body text placeholder shape. + */ + VERTICAL_TEXT_BODY(18,18,18,18,-2) + ; + + public final int nativeSlideId; + public final int nativeSlideMasterId; + public final int nativeNotesId; + public final int nativeNotesMasterId; + public final int ooxmlId; + + Placeholder(int nativeSlideId, int nativeSlideMasterId, int nativeNotesId, int nativeNotesMasterId, int ooxmlId) { + this.nativeSlideId = nativeSlideId; + this.nativeSlideMasterId = nativeSlideMasterId; + this.nativeNotesId = nativeNotesId; + this.nativeNotesMasterId = nativeNotesMasterId; + this.ooxmlId = ooxmlId; + } + + public static Placeholder lookupNativeSlide(int nativeId) { + return lookupNative(nativeId, 0); + } + + public static Placeholder lookupNativeSlideMaster(int nativeId) { + return lookupNative(nativeId, 1); + } + + public static Placeholder lookupNativeNotes(int nativeId) { + return lookupNative(nativeId, 2); + } + + public static Placeholder lookupNativeNotesMaster(int nativeId) { + return lookupNative(nativeId, 3); + } + + + private static Placeholder lookupNative(int nativeId, int type) { + for (Placeholder ph : values()) { + if ( + type == 0 && ph.nativeSlideId == nativeId || + type == 1 && ph.nativeSlideMasterId == nativeId || + type == 2 && ph.nativeNotesId == nativeId || + type == 3 && ph.nativeNotesMasterId == nativeId + ) { + return ph; + } + } + return null; + } + + public static Placeholder lookupOoxml(int ooxmlId) { + for (Placeholder ph : values()) { + if (ph.ooxmlId == ooxmlId) { + return ph; + } + } + return null; + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/sl/usermodel/PresetColor.java b/src/java/org/apache/poi/sl/usermodel/PresetColor.java index f78dbca406..b5c8e1ad56 100644 --- a/src/java/org/apache/poi/sl/usermodel/PresetColor.java +++ b/src/java/org/apache/poi/sl/usermodel/PresetColor.java @@ -1,279 +1,279 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.sl.usermodel; - -import java.awt.Color; -import java.util.HashMap; -import java.util.Map; - -/** - * Preset colors defined in DrawingML aka known/system colors - * - * @see KnownColor Enumeration - * @see Colors Class - */ -public enum PresetColor { - // the order of this enum can be found in the definition of .net System.Drawing.KnownColor enumeration - // or by running the the program in the linked documentation - - // default colors for theme-depending colors taken from ... (last post): - // https://social.technet.microsoft.com/Forums/windows/en-US/ac76cc56-6ff2-4778-b260-8141d7170a3b/windows-7-highlight-text-color-or-selected-text-color-in-aero - - // see ST_SystemColorVal for system color names - - /** The system-defined color of the active window's border. */ - ActiveBorder (0xffb4b4b4, 1, "activeBorder"), - /** The system-defined color of the background of the active window's title bar. */ - ActiveCaption (0xff99b4d1, 2, "activeCaption"), - /** The system-defined color of the text in the active window's title bar. */ - ActiveCaptionText (0xff000000, 3, "captionText"), - /** The application workspace is the area in a multiple-document view that is not being occupied by documents. */ - AppWorkspace (0xffababab, 4, "appWorkspace"), - /** The system-defined face color of a 3-D element. */ - Control (0xfff0f0f0, 5, "btnFace"), - /** The system-defined shadow color of a 3-D element. The shadow color is applied to parts of a 3-D element that face away from the light source. */ - ControlDark (0xff696969, 6, "btnShadow"), - /** The system-defined color that is the dark shadow color of a 3-D element. The dark shadow color is applied to the parts of a 3-D element that are the darkest color. */ - ControlDarkDark (0xff000000, 7, "3dDkShadow"), - /** The system-defined color that is the light color of a 3-D element. The light color is applied to parts of a 3-D element that face the light source. */ - ControlLight (0xffe3e3e3, 8, "btnHighlight"), - /** The system-defined highlight color of a 3-D element. The highlight color is applied to the parts of a 3-D element that are the lightest color. */ - ControlLightLight (0xffe3e3e3, 9, "3dLight"), - /** The system-defined color of text in a 3-D element. */ - ControlText (0xff000000, 10, "btnText"), - /** The system-defined color of the desktop. */ - Desktop (0xff000000, 11, "background"), - /** The system-defined color of dimmed text. Items in a list that are disabled are displayed in dimmed text. */ - GrayText (0xff6d6d6d, 12, "grayText"), - /** The system-defined color of the background of selected items. This includes selected menu items as well as selected text. */ - Highlight (0xff3399ff, 13, "highlight"), - /** The system-defined color of the text of selected items. */ - HighlightText (0xffffffff, 14, "highlightText"), - /** The system-defined color used to designate a hot-tracked item. Single-clicking a hot-tracked item executes the item. */ - HotTrack (0xff0066cc, 15, "hotLight"), - /** The system-defined color of an inactive window's border. */ - InactiveBorder (0xfff4f7fc, 16, "inactiveBorder"), - /** The system-defined color of the background of an inactive window's title bar. */ - InactiveCaption (0xffbfcddb, 17, "inactiveCaption"), - /** The system-defined color of the text in an inactive window's title bar. */ - InactiveCaptionText (0xff000000, 18, "inactiveCaptionText"), - /** The system-defined color of the background of a ToolTip. */ - Info (0xffffffe1, 19, "infoBk"), - /** The system-defined color of the text of a ToolTip. */ - InfoText (0xff000000, 20, "infoText"), - /** The system-defined color of a menu's background. */ - Menu (0xfff0f0f0, 21, "menu"), - /** The system-defined color of a menu's text. */ - MenuText (0xff000000, 22, "menuText"), - /** The system-defined color of the background of a scroll bar. */ - ScrollBar (0xffc8c8c8, 23, "scrollBar"), - /** The system-defined color of the background in the client area of a window. */ - Window (0xffffffff, 24, "window"), - /** The system-defined color of a window frame. */ - WindowFrame (0xff646464, 25, "windowFrame"), - /** The system-defined color of the text in the client area of a window. */ - WindowText (0xff000000, 26, "windowText"), - Transparent (0x00ffffff, 27, null), - AliceBlue (0xfff0f8ff, 28, "aliceBlue"), - AntiqueWhite (0xfffaebd7, 29, "antiqueWhite"), - Aqua (0xff00ffff, 30, "aqua"), - Aquamarine (0xff7fffd4, 31, "aquamarine"), - Azure (0xfff0ffff, 32, "azure"), - Beige (0xfff5f5dc, 33, "beige"), - Bisque (0xffffe4c4, 34, "bisque"), - Black (0xff000000, 35, "black"), - BlanchedAlmond (0xffffebcd, 36, "blanchedAlmond"), - Blue (0xff0000ff, 37, "blue"), - BlueViolet (0xff8a2be2, 38, "blueViolet"), - Brown (0xffa52a2a, 39, "brown"), - BurlyWood (0xffdeb887, 40, "burlyWood"), - CadetBlue (0xff5f9ea0, 41, "cadetBlue"), - Chartreuse (0xff7fff00, 42, "chartreuse"), - Chocolate (0xffd2691e, 43, "chocolate"), - Coral (0xffff7f50, 44, "coral"), - CornflowerBlue (0xff6495ed, 45, "cornflowerBlue"), - Cornsilk (0xfffff8dc, 46, "cornsilk"), - Crimson (0xffdc143c, 47, "crimson"), - Cyan (0xff00ffff, 48, "cyan"), - DarkBlue (0xff00008b, 49, "dkBlue"), - DarkCyan (0xff008b8b, 50, "dkCyan"), - DarkGoldenrod (0xffb8860b, 51, "dkGoldenrod"), - DarkGray (0xffa9a9a9, 52, "dkGray"), - DarkGreen (0xff006400, 53, "dkGreen"), - DarkKhaki (0xffbdb76b, 54, "dkKhaki"), - DarkMagenta (0xff8b008b, 55, "dkMagenta"), - DarkOliveGreen (0xff556b2f, 56, "dkOliveGreen"), - DarkOrange (0xffff8c00, 57, "dkOrange"), - DarkOrchid (0xff9932cc, 58, "dkOrchid"), - DarkRed (0xff8b0000, 59, "dkRed"), - DarkSalmon (0xffe9967a, 60, "dkSalmon"), - DarkSeaGreen (0xff8fbc8b, 61, "dkSeaGreen"), - DarkSlateBlue (0xff483d8b, 62, "dkSlateBlue"), - DarkSlateGray (0xff2f4f4f, 63, "dkSlateGray"), - DarkTurquoise (0xff00ced1, 64, "dkTurquoise"), - DarkViolet (0xff9400d3, 65, "dkViolet"), - DeepPink (0xffff1493, 66, "deepPink"), - DeepSkyBlue (0xff00bfff, 67, "deepSkyBlue"), - DimGray (0xff696969, 68, "dimGray"), - DodgerBlue (0xff1e90ff, 69, "dodgerBlue"), - Firebrick (0xffb22222, 70, "firebrick"), - FloralWhite (0xfffffaf0, 71, "floralWhite"), - ForestGreen (0xff228b22, 72, "forestGreen"), - Fuchsia (0xffff00ff, 73, "fuchsia"), - Gainsboro (0xffdcdcdc, 74, "gainsboro"), - GhostWhite (0xfff8f8ff, 75, "ghostWhite"), - Gold (0xffffd700, 76, "gold"), - Goldenrod (0xffdaa520, 77, "goldenrod"), - Gray (0xff808080, 78, "gray"), - Green (0xff008000, 79, "green"), - GreenYellow (0xffadff2f, 80, "greenYellow"), - Honeydew (0xfff0fff0, 81, "honeydew"), - HotPink (0xffff69b4, 82, "hotPink"), - IndianRed (0xffcd5c5c, 83, "indianRed"), - Indigo (0xff4b0082, 84, "indigo"), - Ivory (0xfffffff0, 85, "ivory"), - Khaki (0xfff0e68c, 86, "khaki"), - Lavender (0xffe6e6fa, 87, "lavender"), - LavenderBlush (0xfffff0f5, 88, "lavenderBlush"), - LawnGreen (0xff7cfc00, 89, "lawnGreen"), - LemonChiffon (0xfffffacd, 90, "lemonChiffon"), - LightBlue (0xffadd8e6, 91, "ltBlue"), - LightCoral (0xfff08080, 92, "ltCoral"), - LightCyan (0xffe0ffff, 93, "ltCyan"), - LightGoldenrodYellow (0xfffafa78, 94, "ltGoldenrodYellow"), - LightGray (0xffd3d3d3, 95, "ltGray"), - LightGreen (0xff90ee90, 96, "ltGreen"), - LightPink (0xffffb6c1, 97, "ltPink"), - LightSalmon (0xffffa07a, 98, "ltSalmon"), - LightSeaGreen (0xff20b2aa, 99, "ltSeaGreen"), - LightSkyBlue (0xff87cefa, 100, "ltSkyBlue"), - LightSlateGray (0xff778899, 101, "ltSlateGray"), - LightSteelBlue (0xffb0c4de, 102, "ltSteelBlue"), - LightYellow (0xffffffe0, 103, "ltYellow"), - Lime (0xff00ff00, 104, "lime"), - LimeGreen (0xff32cd32, 105, "limeGreen"), - Linen (0xfffaf0e6, 106, "linen"), - Magenta (0xffff00ff, 107, "magenta"), - Maroon (0xff800000, 108, "maroon"), - MediumAquamarine (0xff66cdaa, 109, "medAquamarine"), - MediumBlue (0xff0000cd, 110, "medBlue"), - MediumOrchid (0xffba55d3, 111, "medOrchid"), - MediumPurple (0xff9370db, 112, "medPurple"), - MediumSeaGreen (0xff3cb371, 113, "medSeaGreen"), - MediumSlateBlue (0xff7b68ee, 114, "medSlateBlue"), - MediumSpringGreen (0xff00fa9a, 115, "medSpringGreen"), - MediumTurquoise (0xff48d1cc, 116, "medTurquoise"), - MediumVioletRed (0xffc71585, 117, "medVioletRed"), - MidnightBlue (0xff191970, 118, "midnightBlue"), - MintCream (0xfff5fffa, 119, "mintCream"), - MistyRose (0xffffe4e1, 120, "mistyRose"), - Moccasin (0xffffe4b5, 121, "moccasin"), - NavajoWhite (0xffffdead, 122, "navajoWhite"), - Navy (0xff000080, 123, "navy"), - OldLace (0xfffdf5e6, 124, "oldLace"), - Olive (0xff808000, 125, "olive"), - OliveDrab (0xff6b8e23, 126, "oliveDrab"), - Orange (0xffffa500, 127, "orange"), - OrangeRed (0xffff4500, 128, "orangeRed"), - Orchid (0xffda70d6, 129, "orchid"), - PaleGoldenrod (0xffeee8aa, 130, "paleGoldenrod"), - PaleGreen (0xff98fb98, 131, "paleGreen"), - PaleTurquoise (0xffafeeee, 132, "paleTurquoise"), - PaleVioletRed (0xffdb7093, 133, "paleVioletRed"), - PapayaWhip (0xffffefd5, 134, "papayaWhip"), - PeachPuff (0xffffdab9, 135, "peachPuff"), - Peru (0xffcd853f, 136, "peru"), - Pink (0xffffc0cb, 137, "pink"), - Plum (0xffdda0dd, 138, "plum"), - PowderBlue (0xffb0e0e6, 139, "powderBlue"), - Purple (0xff800080, 140, "purple"), - Red (0xffff0000, 141, "red"), - RosyBrown (0xffbc8f8f, 142, "rosyBrown"), - RoyalBlue (0xff4169e1, 143, "royalBlue"), - SaddleBrown (0xff8b4513, 144, "saddleBrown"), - Salmon (0xfffa8072, 145, "salmon"), - SandyBrown (0xfff4a460, 146, "sandyBrown"), - SeaGreen (0xff2e8b57, 147, "seaGreen"), - SeaShell (0xfffff5ee, 148, "seaShell"), - Sienna (0xffa0522d, 149, "sienna"), - Silver (0xffc0c0c0, 150, "silver"), - SkyBlue (0xff87ceeb, 151, "skyBlue"), - SlateBlue (0xff6a5acd, 152, "slateBlue"), - SlateGray (0xff708090, 153, "slateGray"), - Snow (0xfffffafa, 154, "snow"), - SpringGreen (0xff00ff7f, 155, "springGreen"), - SteelBlue (0xff4682b4, 156, "steelBlue"), - Tan (0xffd2b48c, 157, "tan"), - Teal (0xff008080, 158, "teal"), - Thistle (0xffd8bfd8, 159, "thistle"), - Tomato (0xffff6347, 160, "tomato"), - Turquoise (0xff40e0d0, 161, "turquoise"), - Violet (0xffee82ee, 162, "violet"), - Wheat (0xfff5deb3, 163, "wheat"), - White (0xffffffff, 164, "white"), - WhiteSmoke (0xfff5f5f5, 165, "whiteSmoke"), - Yellow (0xffffff00, 166, "yellow"), - YellowGreen (0xff9acd32, 167, "yellowGreen"), - /** The system-defined face color of a 3-D element. */ - ButtonFace (0xfff0f0f0, 168, null), - /** The system-defined color that is the highlight color of a 3-D element. This color is applied to parts of a 3-D element that face the light source. */ - ButtonHighlight (0xffffffff, 169, null), - /** The system-defined color that is the shadow color of a 3-D element. This color is applied to parts of a 3-D element that face away from the light source. */ - ButtonShadow (0xffa0a0a0, 170, null), - /** The system-defined color of the lightest color in the color gradient of an active window's title bar. */ - GradientActiveCaption (0xffb9d1ea, 171, "gradientActiveCaption"), - /** The system-defined color of the lightest color in the color gradient of an inactive window's title bar. */ - GradientInactiveCaption (0xffd7e4f2, 172, "gradientInactiveCaption"), - /** The system-defined color of the background of a menu bar. */ - MenuBar (0xfff0f0f0, 173, "menuBar"), - /** The system-defined color used to highlight menu items when the menu appears as a flat menu. */ - MenuHighlight (0xff3399ff, 174, "menuHighlight") - ; - - public final Color color; - public final int nativeId; - public final String ooxmlId; - - PresetColor(Integer rgb, int nativeId, String ooxmlId) { - this.color = (rgb == null) ? null : new Color(rgb, true); - this.nativeId = nativeId; - this.ooxmlId = ooxmlId; - } - - private static final Map lookupOoxmlId; - - static { - lookupOoxmlId = new HashMap(); - for(PresetColor pc : PresetColor.values()) { - if (pc.ooxmlId != null) { - lookupOoxmlId.put(pc.ooxmlId, pc); - } - } - } - - public static PresetColor valueOfOoxmlId(String ooxmlId) { - return lookupOoxmlId.get(ooxmlId); - } - - public static PresetColor valueOfNativeId(int nativeId) { - PresetColor vals[] = values(); - return (0 < nativeId && nativeId <= vals.length) ? vals[nativeId-1] : null; - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.sl.usermodel; + +import java.awt.Color; +import java.util.HashMap; +import java.util.Map; + +/** + * Preset colors defined in DrawingML aka known/system colors + * + * @see KnownColor Enumeration + * @see Colors Class + */ +public enum PresetColor { + // the order of this enum can be found in the definition of .net System.Drawing.KnownColor enumeration + // or by running the the program in the linked documentation + + // default colors for theme-depending colors taken from ... (last post): + // https://social.technet.microsoft.com/Forums/windows/en-US/ac76cc56-6ff2-4778-b260-8141d7170a3b/windows-7-highlight-text-color-or-selected-text-color-in-aero + + // see ST_SystemColorVal for system color names + + /** The system-defined color of the active window's border. */ + ActiveBorder (0xffb4b4b4, 1, "activeBorder"), + /** The system-defined color of the background of the active window's title bar. */ + ActiveCaption (0xff99b4d1, 2, "activeCaption"), + /** The system-defined color of the text in the active window's title bar. */ + ActiveCaptionText (0xff000000, 3, "captionText"), + /** The application workspace is the area in a multiple-document view that is not being occupied by documents. */ + AppWorkspace (0xffababab, 4, "appWorkspace"), + /** The system-defined face color of a 3-D element. */ + Control (0xfff0f0f0, 5, "btnFace"), + /** The system-defined shadow color of a 3-D element. The shadow color is applied to parts of a 3-D element that face away from the light source. */ + ControlDark (0xff696969, 6, "btnShadow"), + /** The system-defined color that is the dark shadow color of a 3-D element. The dark shadow color is applied to the parts of a 3-D element that are the darkest color. */ + ControlDarkDark (0xff000000, 7, "3dDkShadow"), + /** The system-defined color that is the light color of a 3-D element. The light color is applied to parts of a 3-D element that face the light source. */ + ControlLight (0xffe3e3e3, 8, "btnHighlight"), + /** The system-defined highlight color of a 3-D element. The highlight color is applied to the parts of a 3-D element that are the lightest color. */ + ControlLightLight (0xffe3e3e3, 9, "3dLight"), + /** The system-defined color of text in a 3-D element. */ + ControlText (0xff000000, 10, "btnText"), + /** The system-defined color of the desktop. */ + Desktop (0xff000000, 11, "background"), + /** The system-defined color of dimmed text. Items in a list that are disabled are displayed in dimmed text. */ + GrayText (0xff6d6d6d, 12, "grayText"), + /** The system-defined color of the background of selected items. This includes selected menu items as well as selected text. */ + Highlight (0xff3399ff, 13, "highlight"), + /** The system-defined color of the text of selected items. */ + HighlightText (0xffffffff, 14, "highlightText"), + /** The system-defined color used to designate a hot-tracked item. Single-clicking a hot-tracked item executes the item. */ + HotTrack (0xff0066cc, 15, "hotLight"), + /** The system-defined color of an inactive window's border. */ + InactiveBorder (0xfff4f7fc, 16, "inactiveBorder"), + /** The system-defined color of the background of an inactive window's title bar. */ + InactiveCaption (0xffbfcddb, 17, "inactiveCaption"), + /** The system-defined color of the text in an inactive window's title bar. */ + InactiveCaptionText (0xff000000, 18, "inactiveCaptionText"), + /** The system-defined color of the background of a ToolTip. */ + Info (0xffffffe1, 19, "infoBk"), + /** The system-defined color of the text of a ToolTip. */ + InfoText (0xff000000, 20, "infoText"), + /** The system-defined color of a menu's background. */ + Menu (0xfff0f0f0, 21, "menu"), + /** The system-defined color of a menu's text. */ + MenuText (0xff000000, 22, "menuText"), + /** The system-defined color of the background of a scroll bar. */ + ScrollBar (0xffc8c8c8, 23, "scrollBar"), + /** The system-defined color of the background in the client area of a window. */ + Window (0xffffffff, 24, "window"), + /** The system-defined color of a window frame. */ + WindowFrame (0xff646464, 25, "windowFrame"), + /** The system-defined color of the text in the client area of a window. */ + WindowText (0xff000000, 26, "windowText"), + Transparent (0x00ffffff, 27, null), + AliceBlue (0xfff0f8ff, 28, "aliceBlue"), + AntiqueWhite (0xfffaebd7, 29, "antiqueWhite"), + Aqua (0xff00ffff, 30, "aqua"), + Aquamarine (0xff7fffd4, 31, "aquamarine"), + Azure (0xfff0ffff, 32, "azure"), + Beige (0xfff5f5dc, 33, "beige"), + Bisque (0xffffe4c4, 34, "bisque"), + Black (0xff000000, 35, "black"), + BlanchedAlmond (0xffffebcd, 36, "blanchedAlmond"), + Blue (0xff0000ff, 37, "blue"), + BlueViolet (0xff8a2be2, 38, "blueViolet"), + Brown (0xffa52a2a, 39, "brown"), + BurlyWood (0xffdeb887, 40, "burlyWood"), + CadetBlue (0xff5f9ea0, 41, "cadetBlue"), + Chartreuse (0xff7fff00, 42, "chartreuse"), + Chocolate (0xffd2691e, 43, "chocolate"), + Coral (0xffff7f50, 44, "coral"), + CornflowerBlue (0xff6495ed, 45, "cornflowerBlue"), + Cornsilk (0xfffff8dc, 46, "cornsilk"), + Crimson (0xffdc143c, 47, "crimson"), + Cyan (0xff00ffff, 48, "cyan"), + DarkBlue (0xff00008b, 49, "dkBlue"), + DarkCyan (0xff008b8b, 50, "dkCyan"), + DarkGoldenrod (0xffb8860b, 51, "dkGoldenrod"), + DarkGray (0xffa9a9a9, 52, "dkGray"), + DarkGreen (0xff006400, 53, "dkGreen"), + DarkKhaki (0xffbdb76b, 54, "dkKhaki"), + DarkMagenta (0xff8b008b, 55, "dkMagenta"), + DarkOliveGreen (0xff556b2f, 56, "dkOliveGreen"), + DarkOrange (0xffff8c00, 57, "dkOrange"), + DarkOrchid (0xff9932cc, 58, "dkOrchid"), + DarkRed (0xff8b0000, 59, "dkRed"), + DarkSalmon (0xffe9967a, 60, "dkSalmon"), + DarkSeaGreen (0xff8fbc8b, 61, "dkSeaGreen"), + DarkSlateBlue (0xff483d8b, 62, "dkSlateBlue"), + DarkSlateGray (0xff2f4f4f, 63, "dkSlateGray"), + DarkTurquoise (0xff00ced1, 64, "dkTurquoise"), + DarkViolet (0xff9400d3, 65, "dkViolet"), + DeepPink (0xffff1493, 66, "deepPink"), + DeepSkyBlue (0xff00bfff, 67, "deepSkyBlue"), + DimGray (0xff696969, 68, "dimGray"), + DodgerBlue (0xff1e90ff, 69, "dodgerBlue"), + Firebrick (0xffb22222, 70, "firebrick"), + FloralWhite (0xfffffaf0, 71, "floralWhite"), + ForestGreen (0xff228b22, 72, "forestGreen"), + Fuchsia (0xffff00ff, 73, "fuchsia"), + Gainsboro (0xffdcdcdc, 74, "gainsboro"), + GhostWhite (0xfff8f8ff, 75, "ghostWhite"), + Gold (0xffffd700, 76, "gold"), + Goldenrod (0xffdaa520, 77, "goldenrod"), + Gray (0xff808080, 78, "gray"), + Green (0xff008000, 79, "green"), + GreenYellow (0xffadff2f, 80, "greenYellow"), + Honeydew (0xfff0fff0, 81, "honeydew"), + HotPink (0xffff69b4, 82, "hotPink"), + IndianRed (0xffcd5c5c, 83, "indianRed"), + Indigo (0xff4b0082, 84, "indigo"), + Ivory (0xfffffff0, 85, "ivory"), + Khaki (0xfff0e68c, 86, "khaki"), + Lavender (0xffe6e6fa, 87, "lavender"), + LavenderBlush (0xfffff0f5, 88, "lavenderBlush"), + LawnGreen (0xff7cfc00, 89, "lawnGreen"), + LemonChiffon (0xfffffacd, 90, "lemonChiffon"), + LightBlue (0xffadd8e6, 91, "ltBlue"), + LightCoral (0xfff08080, 92, "ltCoral"), + LightCyan (0xffe0ffff, 93, "ltCyan"), + LightGoldenrodYellow (0xfffafa78, 94, "ltGoldenrodYellow"), + LightGray (0xffd3d3d3, 95, "ltGray"), + LightGreen (0xff90ee90, 96, "ltGreen"), + LightPink (0xffffb6c1, 97, "ltPink"), + LightSalmon (0xffffa07a, 98, "ltSalmon"), + LightSeaGreen (0xff20b2aa, 99, "ltSeaGreen"), + LightSkyBlue (0xff87cefa, 100, "ltSkyBlue"), + LightSlateGray (0xff778899, 101, "ltSlateGray"), + LightSteelBlue (0xffb0c4de, 102, "ltSteelBlue"), + LightYellow (0xffffffe0, 103, "ltYellow"), + Lime (0xff00ff00, 104, "lime"), + LimeGreen (0xff32cd32, 105, "limeGreen"), + Linen (0xfffaf0e6, 106, "linen"), + Magenta (0xffff00ff, 107, "magenta"), + Maroon (0xff800000, 108, "maroon"), + MediumAquamarine (0xff66cdaa, 109, "medAquamarine"), + MediumBlue (0xff0000cd, 110, "medBlue"), + MediumOrchid (0xffba55d3, 111, "medOrchid"), + MediumPurple (0xff9370db, 112, "medPurple"), + MediumSeaGreen (0xff3cb371, 113, "medSeaGreen"), + MediumSlateBlue (0xff7b68ee, 114, "medSlateBlue"), + MediumSpringGreen (0xff00fa9a, 115, "medSpringGreen"), + MediumTurquoise (0xff48d1cc, 116, "medTurquoise"), + MediumVioletRed (0xffc71585, 117, "medVioletRed"), + MidnightBlue (0xff191970, 118, "midnightBlue"), + MintCream (0xfff5fffa, 119, "mintCream"), + MistyRose (0xffffe4e1, 120, "mistyRose"), + Moccasin (0xffffe4b5, 121, "moccasin"), + NavajoWhite (0xffffdead, 122, "navajoWhite"), + Navy (0xff000080, 123, "navy"), + OldLace (0xfffdf5e6, 124, "oldLace"), + Olive (0xff808000, 125, "olive"), + OliveDrab (0xff6b8e23, 126, "oliveDrab"), + Orange (0xffffa500, 127, "orange"), + OrangeRed (0xffff4500, 128, "orangeRed"), + Orchid (0xffda70d6, 129, "orchid"), + PaleGoldenrod (0xffeee8aa, 130, "paleGoldenrod"), + PaleGreen (0xff98fb98, 131, "paleGreen"), + PaleTurquoise (0xffafeeee, 132, "paleTurquoise"), + PaleVioletRed (0xffdb7093, 133, "paleVioletRed"), + PapayaWhip (0xffffefd5, 134, "papayaWhip"), + PeachPuff (0xffffdab9, 135, "peachPuff"), + Peru (0xffcd853f, 136, "peru"), + Pink (0xffffc0cb, 137, "pink"), + Plum (0xffdda0dd, 138, "plum"), + PowderBlue (0xffb0e0e6, 139, "powderBlue"), + Purple (0xff800080, 140, "purple"), + Red (0xffff0000, 141, "red"), + RosyBrown (0xffbc8f8f, 142, "rosyBrown"), + RoyalBlue (0xff4169e1, 143, "royalBlue"), + SaddleBrown (0xff8b4513, 144, "saddleBrown"), + Salmon (0xfffa8072, 145, "salmon"), + SandyBrown (0xfff4a460, 146, "sandyBrown"), + SeaGreen (0xff2e8b57, 147, "seaGreen"), + SeaShell (0xfffff5ee, 148, "seaShell"), + Sienna (0xffa0522d, 149, "sienna"), + Silver (0xffc0c0c0, 150, "silver"), + SkyBlue (0xff87ceeb, 151, "skyBlue"), + SlateBlue (0xff6a5acd, 152, "slateBlue"), + SlateGray (0xff708090, 153, "slateGray"), + Snow (0xfffffafa, 154, "snow"), + SpringGreen (0xff00ff7f, 155, "springGreen"), + SteelBlue (0xff4682b4, 156, "steelBlue"), + Tan (0xffd2b48c, 157, "tan"), + Teal (0xff008080, 158, "teal"), + Thistle (0xffd8bfd8, 159, "thistle"), + Tomato (0xffff6347, 160, "tomato"), + Turquoise (0xff40e0d0, 161, "turquoise"), + Violet (0xffee82ee, 162, "violet"), + Wheat (0xfff5deb3, 163, "wheat"), + White (0xffffffff, 164, "white"), + WhiteSmoke (0xfff5f5f5, 165, "whiteSmoke"), + Yellow (0xffffff00, 166, "yellow"), + YellowGreen (0xff9acd32, 167, "yellowGreen"), + /** The system-defined face color of a 3-D element. */ + ButtonFace (0xfff0f0f0, 168, null), + /** The system-defined color that is the highlight color of a 3-D element. This color is applied to parts of a 3-D element that face the light source. */ + ButtonHighlight (0xffffffff, 169, null), + /** The system-defined color that is the shadow color of a 3-D element. This color is applied to parts of a 3-D element that face away from the light source. */ + ButtonShadow (0xffa0a0a0, 170, null), + /** The system-defined color of the lightest color in the color gradient of an active window's title bar. */ + GradientActiveCaption (0xffb9d1ea, 171, "gradientActiveCaption"), + /** The system-defined color of the lightest color in the color gradient of an inactive window's title bar. */ + GradientInactiveCaption (0xffd7e4f2, 172, "gradientInactiveCaption"), + /** The system-defined color of the background of a menu bar. */ + MenuBar (0xfff0f0f0, 173, "menuBar"), + /** The system-defined color used to highlight menu items when the menu appears as a flat menu. */ + MenuHighlight (0xff3399ff, 174, "menuHighlight") + ; + + public final Color color; + public final int nativeId; + public final String ooxmlId; + + PresetColor(Integer rgb, int nativeId, String ooxmlId) { + this.color = (rgb == null) ? null : new Color(rgb, true); + this.nativeId = nativeId; + this.ooxmlId = ooxmlId; + } + + private static final Map lookupOoxmlId; + + static { + lookupOoxmlId = new HashMap(); + for(PresetColor pc : PresetColor.values()) { + if (pc.ooxmlId != null) { + lookupOoxmlId.put(pc.ooxmlId, pc); + } + } + } + + public static PresetColor valueOfOoxmlId(String ooxmlId) { + return lookupOoxmlId.get(ooxmlId); + } + + public static PresetColor valueOfNativeId(int nativeId) { + PresetColor vals[] = values(); + return (0 < nativeId && nativeId <= vals.length) ? vals[nativeId-1] : null; + } +} diff --git a/src/java/org/apache/poi/sl/usermodel/Shadow.java b/src/java/org/apache/poi/sl/usermodel/Shadow.java index 9afc4e64e9..2c99f32b64 100644 --- a/src/java/org/apache/poi/sl/usermodel/Shadow.java +++ b/src/java/org/apache/poi/sl/usermodel/Shadow.java @@ -1,53 +1,53 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; - - - -public interface Shadow< -S extends Shape, -P extends TextParagraph -> { - SimpleShape getShadowParent(); - - /** - * @return the offset of this shadow in points - */ - double getDistance(); - - /** - * - * @return the direction to offset the shadow in angles - */ - double getAngle(); - - /** - * - * @return the blur radius of the shadow - * TODO: figure out how to make sense of this property when rendering shadows - */ - double getBlur(); - - /** - * @return the color of this shadow. - * Depending whether the parent shape is filled or stroked, this color is used to fill or stroke this shadow - */ - SolidPaint getFillStyle(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; + + + +public interface Shadow< +S extends Shape, +P extends TextParagraph +> { + SimpleShape getShadowParent(); + + /** + * @return the offset of this shadow in points + */ + double getDistance(); + + /** + * + * @return the direction to offset the shadow in angles + */ + double getAngle(); + + /** + * + * @return the blur radius of the shadow + * TODO: figure out how to make sense of this property when rendering shadows + */ + double getBlur(); + + /** + * @return the color of this shadow. + * Depending whether the parent shape is filled or stroked, this color is used to fill or stroke this shadow + */ + SolidPaint getFillStyle(); +} diff --git a/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java b/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java index b61d55daf0..92575d1d6b 100644 --- a/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java +++ b/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java @@ -1,265 +1,265 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.sl.usermodel; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.PushbackInputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.OldFileFormatException; -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; -import org.apache.poi.poifs.crypt.Decryptor; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.poifs.filesystem.OfficeXmlFileException; -import org.apache.poi.util.IOUtils; - -public class SlideShowFactory { - /** - * Creates a SlideShow from the given NPOIFSFileSystem. - * - * @param fs The {@link NPOIFSFileSystem} to read the document from - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - */ - public static SlideShow create(NPOIFSFileSystem fs) throws IOException { - return create(fs, null); - } - - /** - * Creates a SlideShow from the given NPOIFSFileSystem, which may - * be password protected - * - * @param fs The {@link NPOIFSFileSystem} to read the document from - * @param password The password that should be used or null if no password is necessary. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - */ - public static SlideShow create(final NPOIFSFileSystem fs, String password) throws IOException { - DirectoryNode root = fs.getRoot(); - - // Encrypted OOXML files go inside OLE2 containers, is this one? - if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) { - InputStream stream = null; - try { - stream = DocumentFactoryHelper.getDecryptedStream(fs, password); - - return createXSLFSlideShow(stream); - } finally { - IOUtils.closeQuietly(stream); - } - } - - // If we get here, it isn't an encrypted PPTX file - // So, treat it as a regular HSLF PPT one - if (password != null) { - Biff8EncryptionKey.setCurrentUserPassword(password); - } - try { - return createHSLFSlideShow(fs); - } finally { - Biff8EncryptionKey.setCurrentUserPassword(null); - } - } - - /** - * Creates the appropriate HSLFSlideShow / XMLSlideShow from - * the given InputStream. - * - *

Your input stream MUST either support mark/reset, or - * be wrapped as a {@link PushbackInputStream}! Note that - * using an {@link InputStream} has a higher memory footprint - * than using a {@link File}.

- * - *

Note that in order to properly release resources the - * SlideShow should be closed after use. Note also that loading - * from an InputStream requires more memory than loading - * from a File, so prefer {@link #create(File)} where possible. - * - * @param inp The {@link InputStream} to read data from. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws EncryptedDocumentException If the SlideShow given is password protected - */ - public static SlideShow create(InputStream inp) throws IOException, EncryptedDocumentException { - return create(inp, null); - } - - /** - * Creates the appropriate HSLFSlideShow / XMLSlideShow from - * the given InputStream, which may be password protected. - *

Your input stream MUST either support mark/reset, or - * be wrapped as a {@link PushbackInputStream}! Note that - * using an {@link InputStream} has a higher memory footprint - * than using a {@link File}.

- * - *

Note that in order to properly release resources the - * SlideShow should be closed after use. Note also that loading - * from an InputStream requires more memory than loading - * from a File, so prefer {@link #create(File)} where possible.

- * - * @param inp The {@link InputStream} to read data from. - * @param password The password that should be used or null if no password is necessary. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws EncryptedDocumentException If the wrong password is given for a protected file - */ - public static SlideShow create(InputStream inp, String password) throws IOException, EncryptedDocumentException { - // If clearly doesn't do mark/reset, wrap up - if (! inp.markSupported()) { - inp = new PushbackInputStream(inp, 8); - } - - // Ensure that there is at least some data there - byte[] header8 = IOUtils.peekFirst8Bytes(inp); - - // Try to create - if (NPOIFSFileSystem.hasPOIFSHeader(header8)) { - NPOIFSFileSystem fs = new NPOIFSFileSystem(inp); - return create(fs, password); - } - if (DocumentFactoryHelper.hasOOXMLHeader(inp)) { - return createXSLFSlideShow(inp); - } - throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); - } - - /** - * Creates the appropriate HSLFSlideShow / XMLSlideShow from - * the given File, which must exist and be readable. - *

Note that in order to properly release resources the - * SlideShow should be closed after use. - * - * @param file The file to read data from. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws EncryptedDocumentException If the SlideShow given is password protected - */ - public static SlideShow create(File file) throws IOException, EncryptedDocumentException { - return create(file, null); - } - - /** - * Creates the appropriate HSLFSlideShow / XMLSlideShow from - * the given File, which must exist and be readable, and - * may be password protected - *

Note that in order to properly release resources the - * SlideShow should be closed after use. - * - * @param file The file to read data from. - * @param password The password that should be used or null if no password is necessary. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws EncryptedDocumentException If the wrong password is given for a protected file - */ - public static SlideShow create(File file, String password) throws IOException, EncryptedDocumentException { - return create(file, password, false); - } - - /** - * Creates the appropriate HSLFSlideShow / XMLSlideShow from - * the given File, which must exist and be readable, and - * may be password protected - *

Note that in order to properly release resources the - * SlideShow should be closed after use. - * - * @param file The file to read data from. - * @param password The password that should be used or null if no password is necessary. - * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back - * changes when the document is closed. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws EncryptedDocumentException If the wrong password is given for a protected file - */ - public static SlideShow create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException { - if (!file.exists()) { - throw new FileNotFoundException(file.toString()); - } - - NPOIFSFileSystem fs = null; - try { - fs = new NPOIFSFileSystem(file, readOnly); - return create(fs, password); - } catch(OfficeXmlFileException e) { - IOUtils.closeQuietly(fs); - return createXSLFSlideShow(file, readOnly); - } catch(RuntimeException e) { - IOUtils.closeQuietly(fs); - throw e; - } - } - - protected static SlideShow createHSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException { - return createSlideShow("org.apache.poi.hslf.usermodel.HSLFSlideShowFactory", args); - } - - protected static SlideShow createXSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException { - return createSlideShow("org.apache.poi.xslf.usermodel.XSLFSlideShowFactory", args); - } - - protected static SlideShow createSlideShow(String factoryClass, Object args[]) throws IOException, EncryptedDocumentException { - try { - Class clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass); - Class argsClz[] = new Class[args.length]; - int i=0; - for (Object o : args) { - Class c = o.getClass(); - if (Boolean.class.isAssignableFrom(c)) { - c = boolean.class; - } else if (InputStream.class.isAssignableFrom(c)) { - c = InputStream.class; - } - argsClz[i++] = c; - } - Method m = clazz.getMethod("createSlideShow", argsClz); - return (SlideShow)m.invoke(null, args); - } catch (InvocationTargetException e) { - Throwable t = e.getCause(); - if (t instanceof IOException) { - throw (IOException)t; - } else if (t instanceof EncryptedDocumentException) { - throw (EncryptedDocumentException)t; - } else if (t instanceof OldFileFormatException) { - throw (OldFileFormatException)t; - } else { - throw new IOException(t); - } - } catch (Exception e) { - throw new IOException(e); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.sl.usermodel; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.OldFileFormatException; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OfficeXmlFileException; +import org.apache.poi.util.IOUtils; + +public class SlideShowFactory { + /** + * Creates a SlideShow from the given NPOIFSFileSystem. + * + * @param fs The {@link NPOIFSFileSystem} to read the document from + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + */ + public static SlideShow create(NPOIFSFileSystem fs) throws IOException { + return create(fs, null); + } + + /** + * Creates a SlideShow from the given NPOIFSFileSystem, which may + * be password protected + * + * @param fs The {@link NPOIFSFileSystem} to read the document from + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + */ + public static SlideShow create(final NPOIFSFileSystem fs, String password) throws IOException { + DirectoryNode root = fs.getRoot(); + + // Encrypted OOXML files go inside OLE2 containers, is this one? + if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) { + InputStream stream = null; + try { + stream = DocumentFactoryHelper.getDecryptedStream(fs, password); + + return createXSLFSlideShow(stream); + } finally { + IOUtils.closeQuietly(stream); + } + } + + // If we get here, it isn't an encrypted PPTX file + // So, treat it as a regular HSLF PPT one + if (password != null) { + Biff8EncryptionKey.setCurrentUserPassword(password); + } + try { + return createHSLFSlideShow(fs); + } finally { + Biff8EncryptionKey.setCurrentUserPassword(null); + } + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given InputStream. + * + *

Your input stream MUST either support mark/reset, or + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.

+ * + *

Note that in order to properly release resources the + * SlideShow should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible. + * + * @param inp The {@link InputStream} to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the SlideShow given is password protected + */ + public static SlideShow create(InputStream inp) throws IOException, EncryptedDocumentException { + return create(inp, null); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given InputStream, which may be password protected. + *

Your input stream MUST either support mark/reset, or + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.

+ * + *

Note that in order to properly release resources the + * SlideShow should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible.

+ * + * @param inp The {@link InputStream} to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the wrong password is given for a protected file + */ + public static SlideShow create(InputStream inp, String password) throws IOException, EncryptedDocumentException { + // If clearly doesn't do mark/reset, wrap up + if (! inp.markSupported()) { + inp = new PushbackInputStream(inp, 8); + } + + // Ensure that there is at least some data there + byte[] header8 = IOUtils.peekFirst8Bytes(inp); + + // Try to create + if (NPOIFSFileSystem.hasPOIFSHeader(header8)) { + NPOIFSFileSystem fs = new NPOIFSFileSystem(inp); + return create(fs, password); + } + if (DocumentFactoryHelper.hasOOXMLHeader(inp)) { + return createXSLFSlideShow(inp); + } + throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable. + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the SlideShow given is password protected + */ + public static SlideShow create(File file) throws IOException, EncryptedDocumentException { + return create(file, null); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable, and + * may be password protected + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the wrong password is given for a protected file + */ + public static SlideShow create(File file, String password) throws IOException, EncryptedDocumentException { + return create(file, password, false); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable, and + * may be password protected + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * @param password The password that should be used or null if no password is necessary. + * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back + * changes when the document is closed. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the wrong password is given for a protected file + */ + public static SlideShow create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException { + if (!file.exists()) { + throw new FileNotFoundException(file.toString()); + } + + NPOIFSFileSystem fs = null; + try { + fs = new NPOIFSFileSystem(file, readOnly); + return create(fs, password); + } catch(OfficeXmlFileException e) { + IOUtils.closeQuietly(fs); + return createXSLFSlideShow(file, readOnly); + } catch(RuntimeException e) { + IOUtils.closeQuietly(fs); + throw e; + } + } + + protected static SlideShow createHSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException { + return createSlideShow("org.apache.poi.hslf.usermodel.HSLFSlideShowFactory", args); + } + + protected static SlideShow createXSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException { + return createSlideShow("org.apache.poi.xslf.usermodel.XSLFSlideShowFactory", args); + } + + protected static SlideShow createSlideShow(String factoryClass, Object args[]) throws IOException, EncryptedDocumentException { + try { + Class clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass); + Class argsClz[] = new Class[args.length]; + int i=0; + for (Object o : args) { + Class c = o.getClass(); + if (Boolean.class.isAssignableFrom(c)) { + c = boolean.class; + } else if (InputStream.class.isAssignableFrom(c)) { + c = InputStream.class; + } + argsClz[i++] = c; + } + Method m = clazz.getMethod("createSlideShow", argsClz); + return (SlideShow)m.invoke(null, args); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof IOException) { + throw (IOException)t; + } else if (t instanceof EncryptedDocumentException) { + throw (EncryptedDocumentException)t; + } else if (t instanceof OldFileFormatException) { + throw (OldFileFormatException)t; + } else { + throw new IOException(t); + } + } catch (Exception e) { + throw new IOException(e); + } + } +} diff --git a/src/java/org/apache/poi/sl/usermodel/TableCell.java b/src/java/org/apache/poi/sl/usermodel/TableCell.java index 9516196de9..1543148d77 100644 --- a/src/java/org/apache/poi/sl/usermodel/TableCell.java +++ b/src/java/org/apache/poi/sl/usermodel/TableCell.java @@ -1,114 +1,114 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import java.awt.Color; - -import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; -import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; - -public interface TableCell< - S extends Shape, - P extends TextParagraph -> extends TextShape { - enum BorderEdge { bottom, left, top, right } - - /** - * Return line style of given edge or {@code null} if border is not defined - * - * @param edge the border edge - * @return line style of given edge or {@code null} if border is not defined - */ - StrokeStyle getBorderStyle(BorderEdge edge); - - /** - * Sets the {@link StrokeStyle} of the given border edge. - * A {@code null} property of the style is ignored. - * - * @param edge border edge - * @param style the new stroke style - */ - void setBorderStyle(BorderEdge edge, StrokeStyle style); - - /** - * Convenience method for setting the border width. - * - * @param edge border edge - * @param width the new border width - */ - void setBorderWidth(BorderEdge edge, double width); - - /** - * Convenience method for setting the border color. - * - * @param edge border edge - * @param color the new border color - */ - void setBorderColor(BorderEdge edge, Color color); - - /** - * Convenience method for setting the border line compound. - * - * @param edge border edge - * @param compound the new border line compound - */ - void setBorderCompound(BorderEdge edge, LineCompound compound); - - /** - * Convenience method for setting the border line dash. - * - * @param edge border edge - * @param dash the new border line dash - */ - void setBorderDash(BorderEdge edge, LineDash dash); - - /** - * Remove all line attributes of the given border edge - * - * @param edge the border edge to be cleared - */ - void removeBorder(BorderEdge edge); - - /** - * Get the number of columns to be spanned/merged - * - * @return the grid span - * - * @since POI 3.15-beta2 - */ - int getGridSpan(); - - /** - * Get the number of rows to be spanned/merged - * - * @return the row span - * - * @since POI 3.15-beta2 - */ - int getRowSpan(); - - /** - * Return if this cell is part of a merged cell. The top/left cell of a merged region is not regarded as merged - - * its grid and/or row span is greater than one. - * - * @return true if this a merged cell - * - * @since POI 3.15-beta2 - */ - boolean isMerged(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.awt.Color; + +import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; +import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; + +public interface TableCell< + S extends Shape, + P extends TextParagraph +> extends TextShape { + enum BorderEdge { bottom, left, top, right } + + /** + * Return line style of given edge or {@code null} if border is not defined + * + * @param edge the border edge + * @return line style of given edge or {@code null} if border is not defined + */ + StrokeStyle getBorderStyle(BorderEdge edge); + + /** + * Sets the {@link StrokeStyle} of the given border edge. + * A {@code null} property of the style is ignored. + * + * @param edge border edge + * @param style the new stroke style + */ + void setBorderStyle(BorderEdge edge, StrokeStyle style); + + /** + * Convenience method for setting the border width. + * + * @param edge border edge + * @param width the new border width + */ + void setBorderWidth(BorderEdge edge, double width); + + /** + * Convenience method for setting the border color. + * + * @param edge border edge + * @param color the new border color + */ + void setBorderColor(BorderEdge edge, Color color); + + /** + * Convenience method for setting the border line compound. + * + * @param edge border edge + * @param compound the new border line compound + */ + void setBorderCompound(BorderEdge edge, LineCompound compound); + + /** + * Convenience method for setting the border line dash. + * + * @param edge border edge + * @param dash the new border line dash + */ + void setBorderDash(BorderEdge edge, LineDash dash); + + /** + * Remove all line attributes of the given border edge + * + * @param edge the border edge to be cleared + */ + void removeBorder(BorderEdge edge); + + /** + * Get the number of columns to be spanned/merged + * + * @return the grid span + * + * @since POI 3.15-beta2 + */ + int getGridSpan(); + + /** + * Get the number of rows to be spanned/merged + * + * @return the row span + * + * @since POI 3.15-beta2 + */ + int getRowSpan(); + + /** + * Return if this cell is part of a merged cell. The top/left cell of a merged region is not regarded as merged - + * its grid and/or row span is greater than one. + * + * @return true if this a merged cell + * + * @since POI 3.15-beta2 + */ + boolean isMerged(); +} diff --git a/src/java/org/apache/poi/sl/usermodel/TableShape.java b/src/java/org/apache/poi/sl/usermodel/TableShape.java index 13c5d0dc52..7dbb13f00c 100644 --- a/src/java/org/apache/poi/sl/usermodel/TableShape.java +++ b/src/java/org/apache/poi/sl/usermodel/TableShape.java @@ -1,80 +1,80 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -public interface TableShape< - S extends Shape, - P extends TextParagraph -> extends Shape, PlaceableShape { - /** - * Return the maximum number of columns. - * If the table contains merged cells, the number of columns might be less than the maximum. - * - * @return the maximum number of column - */ - int getNumberOfColumns(); - - /** - * Return the number of rows - * - * @return the row count - */ - int getNumberOfRows(); - - /** - * Gets a cell - * - * @param row the row index (0-based) - * @param col the column index (0-based) - * @return the cell or null if the cell doesn't exists, e.g. when accessing - * a merged cell or if the index is out of bounds - */ - TableCell getCell(int row, int col); - - /** - * Gets the width (in points) of the n-th column - * - * @param idx the column index (0-based) - * @return the width (in points) - */ - double getColumnWidth(int idx); - - /** - * Sets the width (in points) of the n-th column - * - * @param idx the column index (0-based) - * @param width the width (in points) - */ - void setColumnWidth(int idx, double width); - - /** - * Gets the row height - * - * @param row the row index (0-based) - * @return the height (in points) - */ - double getRowHeight(int row); - - /** - * Sets the row height. - * - * @param row the row index (0-based) - * @param height the height to set (in points) - */ - void setRowHeight(int row, double height); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +public interface TableShape< + S extends Shape, + P extends TextParagraph +> extends Shape, PlaceableShape { + /** + * Return the maximum number of columns. + * If the table contains merged cells, the number of columns might be less than the maximum. + * + * @return the maximum number of column + */ + int getNumberOfColumns(); + + /** + * Return the number of rows + * + * @return the row count + */ + int getNumberOfRows(); + + /** + * Gets a cell + * + * @param row the row index (0-based) + * @param col the column index (0-based) + * @return the cell or null if the cell doesn't exists, e.g. when accessing + * a merged cell or if the index is out of bounds + */ + TableCell getCell(int row, int col); + + /** + * Gets the width (in points) of the n-th column + * + * @param idx the column index (0-based) + * @return the width (in points) + */ + double getColumnWidth(int idx); + + /** + * Sets the width (in points) of the n-th column + * + * @param idx the column index (0-based) + * @param width the width (in points) + */ + void setColumnWidth(int idx, double width); + + /** + * Gets the row height + * + * @param row the row index (0-based) + * @return the height (in points) + */ + double getRowHeight(int row); + + /** + * Sets the row height. + * + * @param row the row index (0-based) + * @param height the height to set (in points) + */ + void setRowHeight(int row, double height); +} diff --git a/src/java/org/apache/poi/sl/usermodel/TextParagraph.java b/src/java/org/apache/poi/sl/usermodel/TextParagraph.java index 881a71da9b..1c0913614c 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextParagraph.java +++ b/src/java/org/apache/poi/sl/usermodel/TextParagraph.java @@ -1,377 +1,377 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import java.awt.Color; -import java.util.List; - - - -public interface TextParagraph< - S extends Shape, - P extends TextParagraph, - T extends TextRun -> extends Iterable { - - /** - * Specifies a list of text alignment types - */ - public enum TextAlign { - /** - * For horizontal text, left aligned. - * For vertical text, top aligned. - */ - LEFT, - - /** - * For horizontal text, centered. - * For vertical text, middle aligned. - */ - CENTER, - - /** - * For horizontal text, right aligned. - * For vertical text, bottom aligned. - */ - RIGHT, - - /** - * Align text so that it is justified across the whole line. It - * is smart in the sense that it will not justify sentences - * which are short - * - * For horizontal text, flush left and right. - * For vertical text, flush top and bottom. - */ - JUSTIFY, - - /** - * Kashida justify low. - */ - JUSTIFY_LOW, - - /** - * Distribute space between characters. - */ - DIST, - - /** - * Thai distribution justification. - */ - THAI_DIST - } - - /** - * - */ - public enum FontAlign { - AUTO, - - /** - * Characters hang from top of line height. - * Also known as "Hanging" - */ - TOP, - - /** - * Characters centered within line height. - */ - CENTER, - - /** - * Place characters on font baseline. - * Also known as "Roman" - */ - BASELINE, - - /** - * Characters are anchored to the very bottom of a single line. - * This is different than BASELINE because of letters such as "g", "q", and "y". - * Also known as "UpholdFixed" - */ - BOTTOM - } - - public interface BulletStyle { - String getBulletCharacter(); - String getBulletFont(); - - /** - * The bullet point font size - * If bulletFontSize >= 0, then space is a percentage of normal line height. - * If bulletFontSize < 0, the absolute value in points - * - * @return the bullet point font size - */ - Double getBulletFontSize(); - - /** - * Convenience function to set a solid color - */ - void setBulletFontColor(Color color); - - void setBulletFontColor(PaintStyle color); - - /** - * - * @return the color of bullet characters within a given paragraph. - * A {@code null} value means to use the text font color. - */ - PaintStyle getBulletFontColor(); - - AutoNumberingScheme getAutoNumberingScheme(); - /** - * Index (1-based) of the first auto number value, or null if auto numbering scheme - * wasn't assigned. - */ - Integer getAutoNumberingStartAt(); - } - - /** - * The amount of vertical white space before the paragraph - * This may be specified in two different ways, percentage spacing and font point spacing: - *

- * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value in points - *

- * - * @return the vertical white space before the paragraph, or null if unset - */ - Double getSpaceBefore(); - - /** - * Set the amount of vertical white space that will be present before the paragraph. - * This space is specified in either percentage or points: - *

- * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - *

- * Examples: - *

-     *      // The paragraph will be formatted to have a spacing before the paragraph text.
-     *      // The spacing will be 200% of the size of the largest text on each line
-     *      paragraph.setSpaceBefore(200);
-     *
-     *      // The spacing will be a size of 48 points
-     *      paragraph.setSpaceBefore(-48.0);
-     * 
- * - * @param spaceBefore the vertical white space before the paragraph, null to unset - */ - void setSpaceBefore(Double spaceBefore); - - /** - * The amount of vertical white space after the paragraph - * This may be specified in two different ways, percentage spacing and font point spacing: - *

- * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - *

- * - * @return the vertical white space after the paragraph or null, if unset - */ - Double getSpaceAfter(); - - /** - * Set the amount of vertical white space that will be present after the paragraph. - * This space is specified in either percentage or points: - *

- * If spaceAfter >= 0, then space is a percentage of normal line height. - * If spaceAfter < 0, the absolute value of linespacing is the spacing in points - *

- * Examples: - *

-     *      // The paragraph will be formatted to have a spacing after the paragraph text.
-     *      // The spacing will be 200% of the size of the largest text on each line
-     *      paragraph.setSpaceAfter(200);
-     *
-     *      // The spacing will be a size of 48 points
-     *      paragraph.setSpaceAfter(-48.0);
-     * 
- * - * @param spaceAfter the vertical white space after the paragraph, null to unset - */ - public void setSpaceAfter(Double spaceAfter); - - /** - * @return the left margin (in points) of the paragraph or null, if unset - */ - Double getLeftMargin(); - - /** - * Specifies the left margin of the paragraph. This is specified in addition to the text body - * inset and applies only to this text paragraph. That is the text body Inset and the LeftMargin - * attributes are additive with respect to the text position. - * - * @param leftMargin the left margin (in points) or null to unset - */ - void setLeftMargin(Double leftMargin); - - - /** - * Specifies the right margin of the paragraph. This is specified in addition to the text body - * inset and applies only to this text paragraph. That is the text body Inset and the RightMargin - * attributes are additive with respect to the text position. - * - * The right margin is not support and therefore ignored by the HSLF implementation. - * - * @return the right margin (in points) of the paragraph or null, if unset - */ - Double getRightMargin(); - - /** - * @param rightMargin the right margin (in points) of the paragraph - */ - void setRightMargin(Double rightMargin); - - /** - * @return the indent (in points) applied to the first line of text in the paragraph. - * or null, if unset - */ - Double getIndent(); - - /** - * Specifies the indent size that will be applied to the first line of text in the paragraph. - * - * @param indent the indent (in points) applied to the first line of text in the paragraph - */ - void setIndent(Double indent); - - - /** - * @return the text level of this paragraph (0-based). Default is 0. - */ - int getIndentLevel(); - - /** - * Specifies the particular level text properties that this paragraph will follow. - * The value for this attribute formats the text according to the corresponding level - * paragraph properties defined in the SlideMaster. - * - * @param level the level (0 ... 4) - */ - void setIndentLevel(int level); - - /** - * Returns the vertical line spacing that is to be used within a paragraph. - * This may be specified in two different ways, percentage spacing and font point spacing: - *

- * If linespacing >= 0, then linespacing is a percentage of normal line height. - * If linespacing < 0, the absolute value of linespacing is the spacing in points - *

- * - * @return the vertical line spacing or null, if unset - */ - Double getLineSpacing(); - - /** - * This element specifies the vertical line spacing that is to be used within a paragraph. - * This may be specified in two different ways, percentage spacing and font point spacing: - *

- * If linespacing >= 0, then linespacing is a percentage of normal line height - * If linespacing < 0, the absolute value of linespacing is the spacing in points - *

- * Examples: - *

-     *      // spacing will be 120% of the size of the largest text on each line
-     *      paragraph.setLineSpacing(120);
-     *
-     *      // spacing will be 200% of the size of the largest text on each line
-     *      paragraph.setLineSpacing(200);
-     *
-     *      // spacing will be 48 points
-     *      paragraph.setLineSpacing(-48.0);
-     * 
- * - * @param lineSpacing the vertical line spacing - */ - void setLineSpacing(Double lineSpacing); - - String getDefaultFontFamily(); - - /** - * @return the default font size, in case its not set in the textrun or null, if unset - */ - Double getDefaultFontSize(); - - /** - * Returns the alignment that is applied to the paragraph. - * - * If this attribute is omitted, then null is returned. - * User code can imply the value {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign#LEFT} then. - * - * @return alignment that is applied to the paragraph - */ - TextAlign getTextAlign(); - - /** - * Specifies the alignment that is to be applied to the paragraph. - * Possible values for this include left, right, centered, justified and distributed, - * see {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign}. - * - * @param align text align - */ - void setTextAlign(TextAlign align); - - /** - * Returns the font alignment that is applied to the paragraph. - * - * If this attribute is omitted, then null is return, - * user code can imply the a value of {@link FontAlign#AUTO} - * - * @return alignment that is applied to the paragraph - */ - FontAlign getFontAlign(); - - /** - * @return the bullet style of the paragraph, if {@code null} then no bullets are used - */ - BulletStyle getBulletStyle(); - - /** - * Sets the bullet styles. If no styles are given, the bullets are omitted. - * Possible attributes are integer/double (bullet size), Color (bullet color), - * character (bullet character), string (bullet font), AutoNumberingScheme - * - * @param styles - */ - void setBulletStyle(Object... styles); - - /** - * @return the default size for a tab character within this paragraph in points, null if unset - */ - Double getDefaultTabSize(); - - - TextShape getParentShape(); - - /** - * Fetch the text runs that are contained within this block of text - */ - List getTextRuns(); - - /** - * Convenience method to determine if this text paragraph is part of - * the slide header or footer - * - * @return true if this paragraph is part of a header or footer placeholder - * - * @since POI 3.15-beta2 - */ - boolean isHeaderOrFooter(); +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.awt.Color; +import java.util.List; + + + +public interface TextParagraph< + S extends Shape, + P extends TextParagraph, + T extends TextRun +> extends Iterable { + + /** + * Specifies a list of text alignment types + */ + public enum TextAlign { + /** + * For horizontal text, left aligned. + * For vertical text, top aligned. + */ + LEFT, + + /** + * For horizontal text, centered. + * For vertical text, middle aligned. + */ + CENTER, + + /** + * For horizontal text, right aligned. + * For vertical text, bottom aligned. + */ + RIGHT, + + /** + * Align text so that it is justified across the whole line. It + * is smart in the sense that it will not justify sentences + * which are short + * + * For horizontal text, flush left and right. + * For vertical text, flush top and bottom. + */ + JUSTIFY, + + /** + * Kashida justify low. + */ + JUSTIFY_LOW, + + /** + * Distribute space between characters. + */ + DIST, + + /** + * Thai distribution justification. + */ + THAI_DIST + } + + /** + * + */ + public enum FontAlign { + AUTO, + + /** + * Characters hang from top of line height. + * Also known as "Hanging" + */ + TOP, + + /** + * Characters centered within line height. + */ + CENTER, + + /** + * Place characters on font baseline. + * Also known as "Roman" + */ + BASELINE, + + /** + * Characters are anchored to the very bottom of a single line. + * This is different than BASELINE because of letters such as "g", "q", and "y". + * Also known as "UpholdFixed" + */ + BOTTOM + } + + public interface BulletStyle { + String getBulletCharacter(); + String getBulletFont(); + + /** + * The bullet point font size + * If bulletFontSize >= 0, then space is a percentage of normal line height. + * If bulletFontSize < 0, the absolute value in points + * + * @return the bullet point font size + */ + Double getBulletFontSize(); + + /** + * Convenience function to set a solid color + */ + void setBulletFontColor(Color color); + + void setBulletFontColor(PaintStyle color); + + /** + * + * @return the color of bullet characters within a given paragraph. + * A {@code null} value means to use the text font color. + */ + PaintStyle getBulletFontColor(); + + AutoNumberingScheme getAutoNumberingScheme(); + /** + * Index (1-based) of the first auto number value, or null if auto numbering scheme + * wasn't assigned. + */ + Integer getAutoNumberingStartAt(); + } + + /** + * The amount of vertical white space before the paragraph + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If spaceBefore >= 0, then space is a percentage of normal line height. + * If spaceBefore < 0, the absolute value in points + *

+ * + * @return the vertical white space before the paragraph, or null if unset + */ + Double getSpaceBefore(); + + /** + * Set the amount of vertical white space that will be present before the paragraph. + * This space is specified in either percentage or points: + *

+ * If spaceBefore >= 0, then space is a percentage of normal line height. + * If spaceBefore < 0, the absolute value of linespacing is the spacing in points + *

+ * Examples: + *

+     *      // The paragraph will be formatted to have a spacing before the paragraph text.
+     *      // The spacing will be 200% of the size of the largest text on each line
+     *      paragraph.setSpaceBefore(200);
+     *
+     *      // The spacing will be a size of 48 points
+     *      paragraph.setSpaceBefore(-48.0);
+     * 
+ * + * @param spaceBefore the vertical white space before the paragraph, null to unset + */ + void setSpaceBefore(Double spaceBefore); + + /** + * The amount of vertical white space after the paragraph + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If spaceBefore >= 0, then space is a percentage of normal line height. + * If spaceBefore < 0, the absolute value of linespacing is the spacing in points + *

+ * + * @return the vertical white space after the paragraph or null, if unset + */ + Double getSpaceAfter(); + + /** + * Set the amount of vertical white space that will be present after the paragraph. + * This space is specified in either percentage or points: + *

+ * If spaceAfter >= 0, then space is a percentage of normal line height. + * If spaceAfter < 0, the absolute value of linespacing is the spacing in points + *

+ * Examples: + *

+     *      // The paragraph will be formatted to have a spacing after the paragraph text.
+     *      // The spacing will be 200% of the size of the largest text on each line
+     *      paragraph.setSpaceAfter(200);
+     *
+     *      // The spacing will be a size of 48 points
+     *      paragraph.setSpaceAfter(-48.0);
+     * 
+ * + * @param spaceAfter the vertical white space after the paragraph, null to unset + */ + public void setSpaceAfter(Double spaceAfter); + + /** + * @return the left margin (in points) of the paragraph or null, if unset + */ + Double getLeftMargin(); + + /** + * Specifies the left margin of the paragraph. This is specified in addition to the text body + * inset and applies only to this text paragraph. That is the text body Inset and the LeftMargin + * attributes are additive with respect to the text position. + * + * @param leftMargin the left margin (in points) or null to unset + */ + void setLeftMargin(Double leftMargin); + + + /** + * Specifies the right margin of the paragraph. This is specified in addition to the text body + * inset and applies only to this text paragraph. That is the text body Inset and the RightMargin + * attributes are additive with respect to the text position. + * + * The right margin is not support and therefore ignored by the HSLF implementation. + * + * @return the right margin (in points) of the paragraph or null, if unset + */ + Double getRightMargin(); + + /** + * @param rightMargin the right margin (in points) of the paragraph + */ + void setRightMargin(Double rightMargin); + + /** + * @return the indent (in points) applied to the first line of text in the paragraph. + * or null, if unset + */ + Double getIndent(); + + /** + * Specifies the indent size that will be applied to the first line of text in the paragraph. + * + * @param indent the indent (in points) applied to the first line of text in the paragraph + */ + void setIndent(Double indent); + + + /** + * @return the text level of this paragraph (0-based). Default is 0. + */ + int getIndentLevel(); + + /** + * Specifies the particular level text properties that this paragraph will follow. + * The value for this attribute formats the text according to the corresponding level + * paragraph properties defined in the SlideMaster. + * + * @param level the level (0 ... 4) + */ + void setIndentLevel(int level); + + /** + * Returns the vertical line spacing that is to be used within a paragraph. + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If linespacing >= 0, then linespacing is a percentage of normal line height. + * If linespacing < 0, the absolute value of linespacing is the spacing in points + *

+ * + * @return the vertical line spacing or null, if unset + */ + Double getLineSpacing(); + + /** + * This element specifies the vertical line spacing that is to be used within a paragraph. + * This may be specified in two different ways, percentage spacing and font point spacing: + *

+ * If linespacing >= 0, then linespacing is a percentage of normal line height + * If linespacing < 0, the absolute value of linespacing is the spacing in points + *

+ * Examples: + *

+     *      // spacing will be 120% of the size of the largest text on each line
+     *      paragraph.setLineSpacing(120);
+     *
+     *      // spacing will be 200% of the size of the largest text on each line
+     *      paragraph.setLineSpacing(200);
+     *
+     *      // spacing will be 48 points
+     *      paragraph.setLineSpacing(-48.0);
+     * 
+ * + * @param lineSpacing the vertical line spacing + */ + void setLineSpacing(Double lineSpacing); + + String getDefaultFontFamily(); + + /** + * @return the default font size, in case its not set in the textrun or null, if unset + */ + Double getDefaultFontSize(); + + /** + * Returns the alignment that is applied to the paragraph. + * + * If this attribute is omitted, then null is returned. + * User code can imply the value {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign#LEFT} then. + * + * @return alignment that is applied to the paragraph + */ + TextAlign getTextAlign(); + + /** + * Specifies the alignment that is to be applied to the paragraph. + * Possible values for this include left, right, centered, justified and distributed, + * see {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign}. + * + * @param align text align + */ + void setTextAlign(TextAlign align); + + /** + * Returns the font alignment that is applied to the paragraph. + * + * If this attribute is omitted, then null is return, + * user code can imply the a value of {@link FontAlign#AUTO} + * + * @return alignment that is applied to the paragraph + */ + FontAlign getFontAlign(); + + /** + * @return the bullet style of the paragraph, if {@code null} then no bullets are used + */ + BulletStyle getBulletStyle(); + + /** + * Sets the bullet styles. If no styles are given, the bullets are omitted. + * Possible attributes are integer/double (bullet size), Color (bullet color), + * character (bullet character), string (bullet font), AutoNumberingScheme + * + * @param styles + */ + void setBulletStyle(Object... styles); + + /** + * @return the default size for a tab character within this paragraph in points, null if unset + */ + Double getDefaultTabSize(); + + + TextShape getParentShape(); + + /** + * Fetch the text runs that are contained within this block of text + */ + List getTextRuns(); + + /** + * Convenience method to determine if this text paragraph is part of + * the slide header or footer + * + * @return true if this paragraph is part of a header or footer placeholder + * + * @since POI 3.15-beta2 + */ + boolean isHeaderOrFooter(); } \ No newline at end of file diff --git a/src/java/org/apache/poi/sl/usermodel/TextShape.java b/src/java/org/apache/poi/sl/usermodel/TextShape.java index 45bd63e0d9..a26db81cc4 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextShape.java +++ b/src/java/org/apache/poi/sl/usermodel/TextShape.java @@ -1,258 +1,258 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.sl.usermodel; - -import java.util.List; - -public interface TextShape< - S extends Shape, - P extends TextParagraph -> extends SimpleShape, Iterable

{ - /** - * Vertical Text Types - */ - enum TextDirection { - /** - * Horizontal text. This should be default. - */ - HORIZONTAL, - /** - * Vertical orientation. - * (each line is 90 degrees rotated clockwise, so it goes - * from top to bottom; each next line is to the left from - * the previous one). - */ - VERTICAL, - /** - * Vertical orientation. - * (each line is 270 degrees rotated clockwise, so it goes - * from bottom to top; each next line is to the right from - * the previous one). - * For HSLF: always interpreted by Powerpoint as HORIZONTAL. - */ - VERTICAL_270, - /** - * Determines if all of the text is vertical - * ("one letter on top of another"). - * For HSLF: not supported - */ - STACKED - } - - /** - * Specifies alist of auto-fit types. - *

- * Autofit specofies that a shape should be auto-fit to fully contain the text described within it. - * Auto-fitting is when text within a shape is scaled in order to contain all the text inside - *

- */ - enum TextAutofit { - /** - * Specifies that text within the text body should not be auto-fit to the bounding box. - * Auto-fitting is when text within a text box is scaled in order to remain inside - * the text box. - */ - NONE, - /** - * Specifies that text within the text body should be normally auto-fit to the bounding box. - * Autofitting is when text within a text box is scaled in order to remain inside the text box. - * - *

- * Example: Consider the situation where a user is building a diagram and needs - * to have the text for each shape that they are using stay within the bounds of the shape. - * An easy way this might be done is by using NORMAL autofit - *

- */ - NORMAL, - /** - * Specifies that a shape should be auto-fit to fully contain the text described within it. - * Auto-fitting is when text within a shape is scaled in order to contain all the text inside. - * - *

- * Example: Consider the situation where a user is building a diagram and needs to have - * the text for each shape that they are using stay within the bounds of the shape. - * An easy way this might be done is by using SHAPE autofit - *

- */ - SHAPE - } - - /** - * This enum represents a compromise for the handling of - * HSLF run types (see org.apache.poi.hslf.record.TextHeaderAtom) and - * XSLF placeholders (see org.apache.poi.xslf.usermodel.Placeholder). - * When a shape is considered a placeholder by the generating application - * it can have special properties to alert the user that they may enter content into the shape. - * - * This enum and the handling around it may change significantly in future releases - */ - enum TextPlaceholder { - /** Title placeholder shape text */ - TITLE, - /** Body placeholder shape text */ - BODY, - /** Center title placeholder shape text */ - CENTER_TITLE, - /** Center body placeholder shape text */ - CENTER_BODY, - /** Half-sized body placeholder shape text */ - HALF_BODY, - /** Quarter-sized body placeholder shape text */ - QUARTER_BODY, - /** Notes placeholder shape text */ - NOTES, - /** Any other text */ - OTHER - } - - /** - * Returns the text contained in this text frame, which has been made safe - * for printing and other use. - * - * @return the text string for this textbox. - * - * @since POI 3.14-Beta2 - */ - String getText(); - - /** - * Sets (overwrites) the current text. - * Uses the properties of the first paragraph / textrun. - * Text paragraphs are split by \\r or \\n. - * New lines within text run are split by \\u000b - * - * @param text the text string used by this object. - * - * @return the last text run of the - potential split - text - */ - TextRun setText(String text); - - /** - * Adds the supplied text onto the end of the TextParagraphs, - * creating a new RichTextRun for it to sit in. - * - * @param text the text string to be appended. - * @param newParagraph if true, a new paragraph will be added, - * which will contain the added text - * - * @since POI 3.14-Beta1 - */ - TextRun appendText(String text, boolean newParagraph); - - /** - * @return the TextParagraphs for this text box - */ - List> getTextParagraphs(); - - /** - * @return text shape margin - */ - Insets2D getInsets(); - - /** - * Sets the shape margins - * - * @param insets the new shape margins - */ - void setInsets(Insets2D insets); - - /** - * Compute the cumulative height occupied by the text - */ - double getTextHeight(); - - /** - * Returns the type of vertical alignment for the text. - * - * @return the type of vertical alignment - */ - VerticalAlignment getVerticalAlignment(); - - /** - * Sets the type of vertical alignment for the text. - * - * @param vAlign - the type of alignment. - * A {@code null} values unsets this property. - */ - void setVerticalAlignment(VerticalAlignment vAlign); - - /** - * Returns if the text is centered. - * If true and if the individual paragraph settings allow it, - * the whole text block will be displayed centered, i.e. its left and right - * margin will be maximized while still keeping the alignment of the paragraphs - * - * @return true, if the text anchor is horizontal centered - */ - boolean isHorizontalCentered(); - - /** - * Sets if the paragraphs are horizontal centered - * - * @param isCentered true, if the paragraphs are horizontal centered - * A {@code null} values unsets this property. - */ - void setHorizontalCentered(Boolean isCentered); - - /** - * @return whether to wrap words within the bounding rectangle - */ - boolean getWordWrap(); - - /** - * @param wrap whether to wrap words within the bounding rectangle - */ - void setWordWrap(boolean wrap); - - /** - * @return vertical orientation of the text - */ - TextDirection getTextDirection(); - - /** - * sets the vertical orientation - * @param orientation vertical orientation of the text - */ - void setTextDirection(TextDirection orientation); - - /** - * The text rotation can be independent specified from the shape rotation. - * For XSLF this can be an arbitrary degree, for HSLF the degree is given in steps of 90 degrees - * - * @return text rotation in degrees, returns null if no rotation is given - */ - Double getTextRotation(); - - /** - * Sets the text rotation. - * For XSLF this can ben an arbitrary degree, for HSLF the rotation is rounded to next 90 degree step - * - * @param rotation the text rotation, or null to unset the rotation - */ - void setTextRotation(Double rotation); - - /** - * Sets the text placeholder - */ - void setTextPlaceholder(TextPlaceholder placeholder); - - /** - * @return the text placeholder - */ - TextPlaceholder getTextPlaceholder(); +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.sl.usermodel; + +import java.util.List; + +public interface TextShape< + S extends Shape, + P extends TextParagraph +> extends SimpleShape, Iterable

{ + /** + * Vertical Text Types + */ + enum TextDirection { + /** + * Horizontal text. This should be default. + */ + HORIZONTAL, + /** + * Vertical orientation. + * (each line is 90 degrees rotated clockwise, so it goes + * from top to bottom; each next line is to the left from + * the previous one). + */ + VERTICAL, + /** + * Vertical orientation. + * (each line is 270 degrees rotated clockwise, so it goes + * from bottom to top; each next line is to the right from + * the previous one). + * For HSLF: always interpreted by Powerpoint as HORIZONTAL. + */ + VERTICAL_270, + /** + * Determines if all of the text is vertical + * ("one letter on top of another"). + * For HSLF: not supported + */ + STACKED + } + + /** + * Specifies alist of auto-fit types. + *

+ * Autofit specofies that a shape should be auto-fit to fully contain the text described within it. + * Auto-fitting is when text within a shape is scaled in order to contain all the text inside + *

+ */ + enum TextAutofit { + /** + * Specifies that text within the text body should not be auto-fit to the bounding box. + * Auto-fitting is when text within a text box is scaled in order to remain inside + * the text box. + */ + NONE, + /** + * Specifies that text within the text body should be normally auto-fit to the bounding box. + * Autofitting is when text within a text box is scaled in order to remain inside the text box. + * + *

+ * Example: Consider the situation where a user is building a diagram and needs + * to have the text for each shape that they are using stay within the bounds of the shape. + * An easy way this might be done is by using NORMAL autofit + *

+ */ + NORMAL, + /** + * Specifies that a shape should be auto-fit to fully contain the text described within it. + * Auto-fitting is when text within a shape is scaled in order to contain all the text inside. + * + *

+ * Example: Consider the situation where a user is building a diagram and needs to have + * the text for each shape that they are using stay within the bounds of the shape. + * An easy way this might be done is by using SHAPE autofit + *

+ */ + SHAPE + } + + /** + * This enum represents a compromise for the handling of + * HSLF run types (see org.apache.poi.hslf.record.TextHeaderAtom) and + * XSLF placeholders (see org.apache.poi.xslf.usermodel.Placeholder). + * When a shape is considered a placeholder by the generating application + * it can have special properties to alert the user that they may enter content into the shape. + * + * This enum and the handling around it may change significantly in future releases + */ + enum TextPlaceholder { + /** Title placeholder shape text */ + TITLE, + /** Body placeholder shape text */ + BODY, + /** Center title placeholder shape text */ + CENTER_TITLE, + /** Center body placeholder shape text */ + CENTER_BODY, + /** Half-sized body placeholder shape text */ + HALF_BODY, + /** Quarter-sized body placeholder shape text */ + QUARTER_BODY, + /** Notes placeholder shape text */ + NOTES, + /** Any other text */ + OTHER + } + + /** + * Returns the text contained in this text frame, which has been made safe + * for printing and other use. + * + * @return the text string for this textbox. + * + * @since POI 3.14-Beta2 + */ + String getText(); + + /** + * Sets (overwrites) the current text. + * Uses the properties of the first paragraph / textrun. + * Text paragraphs are split by \\r or \\n. + * New lines within text run are split by \\u000b + * + * @param text the text string used by this object. + * + * @return the last text run of the - potential split - text + */ + TextRun setText(String text); + + /** + * Adds the supplied text onto the end of the TextParagraphs, + * creating a new RichTextRun for it to sit in. + * + * @param text the text string to be appended. + * @param newParagraph if true, a new paragraph will be added, + * which will contain the added text + * + * @since POI 3.14-Beta1 + */ + TextRun appendText(String text, boolean newParagraph); + + /** + * @return the TextParagraphs for this text box + */ + List> getTextParagraphs(); + + /** + * @return text shape margin + */ + Insets2D getInsets(); + + /** + * Sets the shape margins + * + * @param insets the new shape margins + */ + void setInsets(Insets2D insets); + + /** + * Compute the cumulative height occupied by the text + */ + double getTextHeight(); + + /** + * Returns the type of vertical alignment for the text. + * + * @return the type of vertical alignment + */ + VerticalAlignment getVerticalAlignment(); + + /** + * Sets the type of vertical alignment for the text. + * + * @param vAlign - the type of alignment. + * A {@code null} values unsets this property. + */ + void setVerticalAlignment(VerticalAlignment vAlign); + + /** + * Returns if the text is centered. + * If true and if the individual paragraph settings allow it, + * the whole text block will be displayed centered, i.e. its left and right + * margin will be maximized while still keeping the alignment of the paragraphs + * + * @return true, if the text anchor is horizontal centered + */ + boolean isHorizontalCentered(); + + /** + * Sets if the paragraphs are horizontal centered + * + * @param isCentered true, if the paragraphs are horizontal centered + * A {@code null} values unsets this property. + */ + void setHorizontalCentered(Boolean isCentered); + + /** + * @return whether to wrap words within the bounding rectangle + */ + boolean getWordWrap(); + + /** + * @param wrap whether to wrap words within the bounding rectangle + */ + void setWordWrap(boolean wrap); + + /** + * @return vertical orientation of the text + */ + TextDirection getTextDirection(); + + /** + * sets the vertical orientation + * @param orientation vertical orientation of the text + */ + void setTextDirection(TextDirection orientation); + + /** + * The text rotation can be independent specified from the shape rotation. + * For XSLF this can be an arbitrary degree, for HSLF the degree is given in steps of 90 degrees + * + * @return text rotation in degrees, returns null if no rotation is given + */ + Double getTextRotation(); + + /** + * Sets the text rotation. + * For XSLF this can ben an arbitrary degree, for HSLF the rotation is rounded to next 90 degree step + * + * @param rotation the text rotation, or null to unset the rotation + */ + void setTextRotation(Double rotation); + + /** + * Sets the text placeholder + */ + void setTextPlaceholder(TextPlaceholder placeholder); + + /** + * @return the text placeholder + */ + TextPlaceholder getTextPlaceholder(); } \ No newline at end of file diff --git a/src/java/org/apache/poi/sl/usermodel/VerticalAlignment.java b/src/java/org/apache/poi/sl/usermodel/VerticalAlignment.java index a38da00bf1..f302d8288f 100644 --- a/src/java/org/apache/poi/sl/usermodel/VerticalAlignment.java +++ b/src/java/org/apache/poi/sl/usermodel/VerticalAlignment.java @@ -1,74 +1,74 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.sl.usermodel; - -/** - * Specifies a list of available anchoring types for text - * - * - * - * @author Yegor Kozlov - */ -public enum VerticalAlignment { - /** - * Anchor the text at the top of the bounding rectangle - */ - TOP, - - /** - * Anchor the text at the middle of the bounding rectangle - */ - MIDDLE, - - /** - * Anchor the text at the bottom of the bounding rectangle. - */ - BOTTOM, - - /** - * Anchor the text so that it is justified vertically. - *

- * When text is horizontal, this spaces out the actual lines of - * text and is almost always identical in behavior to - * {@link #DISTRIBUTED} (special case: if only 1 line, then anchored at top). - *

- *

- * When text is vertical, then it justifies the letters - * vertically. This is different than {@link #DISTRIBUTED}, - * because in some cases such as very little text in a line, - * it will not justify. - *

- */ - JUSTIFIED, - - /** - * Anchor the text so that it is distributed vertically. - *

- * When text is horizontal, this spaces out the actual lines - * of text and is almost always identical in behavior to - * {@link #JUSTIFIED} (special case: if only 1 line, then anchored in middle). - *

- *

- * When text is vertical, then it distributes the letters vertically. - * This is different than {@link #JUSTIFIED}, because it always forces distribution - * of the words, even if there are only one or two words in a line. - */ - DISTRIBUTED -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.sl.usermodel; + +/** + * Specifies a list of available anchoring types for text + * + * + * + * @author Yegor Kozlov + */ +public enum VerticalAlignment { + /** + * Anchor the text at the top of the bounding rectangle + */ + TOP, + + /** + * Anchor the text at the middle of the bounding rectangle + */ + MIDDLE, + + /** + * Anchor the text at the bottom of the bounding rectangle. + */ + BOTTOM, + + /** + * Anchor the text so that it is justified vertically. + *

+ * When text is horizontal, this spaces out the actual lines of + * text and is almost always identical in behavior to + * {@link #DISTRIBUTED} (special case: if only 1 line, then anchored at top). + *

+ *

+ * When text is vertical, then it justifies the letters + * vertically. This is different than {@link #DISTRIBUTED}, + * because in some cases such as very little text in a line, + * it will not justify. + *

+ */ + JUSTIFIED, + + /** + * Anchor the text so that it is distributed vertically. + *

+ * When text is horizontal, this spaces out the actual lines + * of text and is almost always identical in behavior to + * {@link #JUSTIFIED} (special case: if only 1 line, then anchored in middle). + *

+ *

+ * When text is vertical, then it distributes the letters vertically. + * This is different than {@link #JUSTIFIED}, because it always forces distribution + * of the words, even if there are only one or two words in a line. + */ + DISTRIBUTED +} diff --git a/src/java/org/apache/poi/ss/format/CellNumberPartHandler.java b/src/java/org/apache/poi/ss/format/CellNumberPartHandler.java index f563db2490..8f2c024abb 100644 --- a/src/java/org/apache/poi/ss/format/CellNumberPartHandler.java +++ b/src/java/org/apache/poi/ss/format/CellNumberPartHandler.java @@ -1,164 +1,164 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.format; - -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.regex.Matcher; - -import org.apache.poi.ss.format.CellFormatPart.PartHandler; -import org.apache.poi.ss.format.CellNumberFormatter.Special; -import org.apache.poi.util.Internal; - -/** - * Internal helper class for CellNumberFormatter - */ -@Internal -public class CellNumberPartHandler implements PartHandler { - private char insertSignForExponent; - private double scale = 1; - private Special decimalPoint; - private Special slash; - private Special exponent; - private Special numerator; - private final List specials = new LinkedList(); - private boolean improperFraction; - - public String handlePart(Matcher m, String part, CellFormatType type, StringBuffer descBuf) { - int pos = descBuf.length(); - char firstCh = part.charAt(0); - switch (firstCh) { - case 'e': - case 'E': - // See comment in writeScientific -- exponent handling is complex. - // (1) When parsing the format, remove the sign from after the 'e' and - // put it before the first digit of the exponent. - if (exponent == null && specials.size() > 0) { - exponent = new Special('.', pos); - specials.add(exponent); - insertSignForExponent = part.charAt(1); - return part.substring(0, 1); - } - break; - - case '0': - case '?': - case '#': - if (insertSignForExponent != '\0') { - specials.add(new Special(insertSignForExponent, pos)); - descBuf.append(insertSignForExponent); - insertSignForExponent = '\0'; - pos++; - } - for (int i = 0; i < part.length(); i++) { - char ch = part.charAt(i); - specials.add(new Special(ch, pos + i)); - } - break; - - case '.': - if (decimalPoint == null && specials.size() > 0) { - decimalPoint = new Special('.', pos); - specials.add(decimalPoint); - } - break; - - case '/': - //!! This assumes there is a numerator and a denominator, but these are actually optional - if (slash == null && specials.size() > 0) { - numerator = previousNumber(); - // If the first number in the whole format is the numerator, the - // entire number should be printed as an improper fraction - improperFraction |= (numerator == firstDigit(specials)); - slash = new Special('.', pos); - specials.add(slash); - } - break; - - case '%': - // don't need to remember because we don't need to do anything with these - scale *= 100; - break; - - default: - return null; - } - return part; - } - - public double getScale() { - return scale; - } - - public Special getDecimalPoint() { - return decimalPoint; - } - - public Special getSlash() { - return slash; - } - - public Special getExponent() { - return exponent; - } - - public Special getNumerator() { - return numerator; - } - - public List getSpecials() { - return specials; - } - - public boolean isImproperFraction() { - return improperFraction; - } - - private Special previousNumber() { - ListIterator it = specials.listIterator(specials.size()); - while (it.hasPrevious()) { - Special s = it.previous(); - if (isDigitFmt(s)) { - Special last = s; - while (it.hasPrevious()) { - s = it.previous(); - // it has to be continuous digits - if (last.pos - s.pos > 1 || !isDigitFmt(s)) { - break; - } - last = s; - } - return last; - } - } - return null; - } - - private static boolean isDigitFmt(Special s) { - return s.ch == '0' || s.ch == '?' || s.ch == '#'; - } - - private static Special firstDigit(List specials) { - for (Special s : specials) { - if (isDigitFmt(s)) { - return s; - } - } - return null; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.format; + +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.regex.Matcher; + +import org.apache.poi.ss.format.CellFormatPart.PartHandler; +import org.apache.poi.ss.format.CellNumberFormatter.Special; +import org.apache.poi.util.Internal; + +/** + * Internal helper class for CellNumberFormatter + */ +@Internal +public class CellNumberPartHandler implements PartHandler { + private char insertSignForExponent; + private double scale = 1; + private Special decimalPoint; + private Special slash; + private Special exponent; + private Special numerator; + private final List specials = new LinkedList(); + private boolean improperFraction; + + public String handlePart(Matcher m, String part, CellFormatType type, StringBuffer descBuf) { + int pos = descBuf.length(); + char firstCh = part.charAt(0); + switch (firstCh) { + case 'e': + case 'E': + // See comment in writeScientific -- exponent handling is complex. + // (1) When parsing the format, remove the sign from after the 'e' and + // put it before the first digit of the exponent. + if (exponent == null && specials.size() > 0) { + exponent = new Special('.', pos); + specials.add(exponent); + insertSignForExponent = part.charAt(1); + return part.substring(0, 1); + } + break; + + case '0': + case '?': + case '#': + if (insertSignForExponent != '\0') { + specials.add(new Special(insertSignForExponent, pos)); + descBuf.append(insertSignForExponent); + insertSignForExponent = '\0'; + pos++; + } + for (int i = 0; i < part.length(); i++) { + char ch = part.charAt(i); + specials.add(new Special(ch, pos + i)); + } + break; + + case '.': + if (decimalPoint == null && specials.size() > 0) { + decimalPoint = new Special('.', pos); + specials.add(decimalPoint); + } + break; + + case '/': + //!! This assumes there is a numerator and a denominator, but these are actually optional + if (slash == null && specials.size() > 0) { + numerator = previousNumber(); + // If the first number in the whole format is the numerator, the + // entire number should be printed as an improper fraction + improperFraction |= (numerator == firstDigit(specials)); + slash = new Special('.', pos); + specials.add(slash); + } + break; + + case '%': + // don't need to remember because we don't need to do anything with these + scale *= 100; + break; + + default: + return null; + } + return part; + } + + public double getScale() { + return scale; + } + + public Special getDecimalPoint() { + return decimalPoint; + } + + public Special getSlash() { + return slash; + } + + public Special getExponent() { + return exponent; + } + + public Special getNumerator() { + return numerator; + } + + public List getSpecials() { + return specials; + } + + public boolean isImproperFraction() { + return improperFraction; + } + + private Special previousNumber() { + ListIterator it = specials.listIterator(specials.size()); + while (it.hasPrevious()) { + Special s = it.previous(); + if (isDigitFmt(s)) { + Special last = s; + while (it.hasPrevious()) { + s = it.previous(); + // it has to be continuous digits + if (last.pos - s.pos > 1 || !isDigitFmt(s)) { + break; + } + last = s; + } + return last; + } + } + return null; + } + + private static boolean isDigitFmt(Special s) { + return s.ch == '0' || s.ch == '?' || s.ch == '#'; + } + + private static Special firstDigit(List specials) { + for (Special s : specials) { + if (isDigitFmt(s)) { + return s; + } + } + return null; + } +} diff --git a/src/java/org/apache/poi/ss/format/CellNumberStringMod.java b/src/java/org/apache/poi/ss/format/CellNumberStringMod.java index 050a1512c8..30c10f1258 100644 --- a/src/java/org/apache/poi/ss/format/CellNumberStringMod.java +++ b/src/java/org/apache/poi/ss/format/CellNumberStringMod.java @@ -1,105 +1,105 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.format; - -import org.apache.poi.ss.format.CellNumberFormatter.Special; -import org.apache.poi.util.Internal; - -/** - * Internal helper class for CellNumberFormatter - * - * This class represents a single modification to a result string. The way - * this works is complicated, but so is numeric formatting. In general, for - * most formats, we use a DecimalFormat object that will put the string out - * in a known format, usually with all possible leading and trailing zeros. - * We then walk through the result and the original format, and note any - * modifications that need to be made. Finally, we go through and apply - * them all, dealing with overlapping modifications. - */ -@Internal -public class CellNumberStringMod implements Comparable { - public static final int BEFORE = 1; - public static final int AFTER = 2; - public static final int REPLACE = 3; - - private final Special special; - private final int op; - private CharSequence toAdd; - private Special end; - private boolean startInclusive; - private boolean endInclusive; - - public CellNumberStringMod(Special special, CharSequence toAdd, int op) { - this.special = special; - this.toAdd = toAdd; - this.op = op; - } - - public CellNumberStringMod(Special start, boolean startInclusive, Special end, boolean endInclusive, char toAdd) { - this(start, startInclusive, end, endInclusive); - this.toAdd = toAdd + ""; - } - - public CellNumberStringMod(Special start, boolean startInclusive, Special end, boolean endInclusive) { - special = start; - this.startInclusive = startInclusive; - this.end = end; - this.endInclusive = endInclusive; - op = REPLACE; - toAdd = ""; - } - - @Override - public int compareTo(CellNumberStringMod that) { - int diff = special.pos - that.special.pos; - return (diff != 0) ? diff : (op - that.op); - } - - @Override - public boolean equals(Object that) { - return (that instanceof CellNumberStringMod) && compareTo((CellNumberStringMod) that) == 0; - } - - @Override - public int hashCode() { - return special.hashCode() + op; - } - - public Special getSpecial() { - return special; - } - - public int getOp() { - return op; - } - - public CharSequence getToAdd() { - return toAdd; - } - - public Special getEnd() { - return end; - } - - public boolean isStartInclusive() { - return startInclusive; - } - - public boolean isEndInclusive() { - return endInclusive; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.format; + +import org.apache.poi.ss.format.CellNumberFormatter.Special; +import org.apache.poi.util.Internal; + +/** + * Internal helper class for CellNumberFormatter + * + * This class represents a single modification to a result string. The way + * this works is complicated, but so is numeric formatting. In general, for + * most formats, we use a DecimalFormat object that will put the string out + * in a known format, usually with all possible leading and trailing zeros. + * We then walk through the result and the original format, and note any + * modifications that need to be made. Finally, we go through and apply + * them all, dealing with overlapping modifications. + */ +@Internal +public class CellNumberStringMod implements Comparable { + public static final int BEFORE = 1; + public static final int AFTER = 2; + public static final int REPLACE = 3; + + private final Special special; + private final int op; + private CharSequence toAdd; + private Special end; + private boolean startInclusive; + private boolean endInclusive; + + public CellNumberStringMod(Special special, CharSequence toAdd, int op) { + this.special = special; + this.toAdd = toAdd; + this.op = op; + } + + public CellNumberStringMod(Special start, boolean startInclusive, Special end, boolean endInclusive, char toAdd) { + this(start, startInclusive, end, endInclusive); + this.toAdd = toAdd + ""; + } + + public CellNumberStringMod(Special start, boolean startInclusive, Special end, boolean endInclusive) { + special = start; + this.startInclusive = startInclusive; + this.end = end; + this.endInclusive = endInclusive; + op = REPLACE; + toAdd = ""; + } + + @Override + public int compareTo(CellNumberStringMod that) { + int diff = special.pos - that.special.pos; + return (diff != 0) ? diff : (op - that.op); + } + + @Override + public boolean equals(Object that) { + return (that instanceof CellNumberStringMod) && compareTo((CellNumberStringMod) that) == 0; + } + + @Override + public int hashCode() { + return special.hashCode() + op; + } + + public Special getSpecial() { + return special; + } + + public int getOp() { + return op; + } + + public CharSequence getToAdd() { + return toAdd; + } + + public Special getEnd() { + return end; + } + + public boolean isStartInclusive() { + return startInclusive; + } + + public boolean isEndInclusive() { + return endInclusive; + } +} diff --git a/src/java/org/apache/poi/ss/formula/EvaluationCell.java b/src/java/org/apache/poi/ss/formula/EvaluationCell.java index a7e855c443..ecf53ed793 100644 --- a/src/java/org/apache/poi/ss/formula/EvaluationCell.java +++ b/src/java/org/apache/poi/ss/formula/EvaluationCell.java @@ -53,9 +53,9 @@ public interface EvaluationCell { CellType getCellTypeEnum(); double getNumericCellValue(); - String getStringCellValue(); - boolean getBooleanCellValue(); - int getErrorCellValue(); + String getStringCellValue(); + boolean getBooleanCellValue(); + int getErrorCellValue(); /** * Will return {@link CellType} in a future version of POI. @@ -69,6 +69,6 @@ public interface EvaluationCell { * @since POI 3.15 beta 3 * @deprecated POI 3.15 beta 3. * Will be deleted when we make the CellType enum transition. See bug 59791. - */ - CellType getCachedFormulaResultTypeEnum(); -} + */ + CellType getCachedFormulaResultTypeEnum(); +} diff --git a/src/java/org/apache/poi/ss/formula/SharedFormula.java b/src/java/org/apache/poi/ss/formula/SharedFormula.java index 0cf492e9cd..ed7e58b3bd 100644 --- a/src/java/org/apache/poi/ss/formula/SharedFormula.java +++ b/src/java/org/apache/poi/ss/formula/SharedFormula.java @@ -1,98 +1,98 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula; - -import org.apache.poi.ss.formula.ptg.*; -import org.apache.poi.ss.SpreadsheetVersion; - -/** - * Encapsulates logic to convert shared formulaa into non shared equivalent - */ -public class SharedFormula { - - private final int _columnWrappingMask; - private final int _rowWrappingMask; - - public SharedFormula(SpreadsheetVersion ssVersion){ - _columnWrappingMask = ssVersion.getLastColumnIndex(); //"IV" for .xls and "XFD" for .xlsx - _rowWrappingMask = ssVersion.getLastRowIndex(); - } - - /** - * Creates a non shared formula from the shared formula counterpart, i.e. - * Converts the shared formula into the equivalent {@link org.apache.poi.ss.formula.ptg.Ptg} array that it would have, - * were it not shared. - * - * @param ptgs parsed tokens of the shared formula - * @param formulaRow - * @param formulaColumn - */ - public Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) { - - Ptg[] newPtgStack = new Ptg[ptgs.length]; - - for (int k = 0; k < ptgs.length; k++) { - Ptg ptg = ptgs[k]; - byte originalOperandClass = -1; - if (!ptg.isBaseToken()) { - originalOperandClass = ptg.getPtgClass(); - } - if (ptg instanceof RefPtgBase) { - RefPtgBase refNPtg = (RefPtgBase)ptg; - ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()), - fixupRelativeColumn(formulaColumn,refNPtg.getColumn(),refNPtg.isColRelative()), - refNPtg.isRowRelative(), - refNPtg.isColRelative()); - ptg.setClass(originalOperandClass); - } else if (ptg instanceof AreaPtgBase) { - AreaPtgBase areaNPtg = (AreaPtgBase)ptg; - ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()), - fixupRelativeRow(formulaRow,areaNPtg.getLastRow(),areaNPtg.isLastRowRelative()), - fixupRelativeColumn(formulaColumn,areaNPtg.getFirstColumn(),areaNPtg.isFirstColRelative()), - fixupRelativeColumn(formulaColumn,areaNPtg.getLastColumn(),areaNPtg.isLastColRelative()), - areaNPtg.isFirstRowRelative(), - areaNPtg.isLastRowRelative(), - areaNPtg.isFirstColRelative(), - areaNPtg.isLastColRelative()); - ptg.setClass(originalOperandClass); - } else if (ptg instanceof OperandPtg) { - // Any subclass of OperandPtg is mutable, so it's safest to not share these instances. - ptg = ((OperandPtg) ptg).copy(); - } else { - // all other Ptgs are immutable and can be shared - } - newPtgStack[k] = ptg; - } - return newPtgStack; - } - - private int fixupRelativeColumn(int currentcolumn, int column, boolean relative) { - if(relative) { - // mask out upper bits to produce 'wrapping' at the maximum column ("IV" for .xls and "XFD" for .xlsx) - return (column + currentcolumn) & _columnWrappingMask; - } - return column; - } - - private int fixupRelativeRow(int currentrow, int row, boolean relative) { - if(relative) { - return (row+currentrow) & _rowWrappingMask; - } - return row; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula; + +import org.apache.poi.ss.formula.ptg.*; +import org.apache.poi.ss.SpreadsheetVersion; + +/** + * Encapsulates logic to convert shared formulaa into non shared equivalent + */ +public class SharedFormula { + + private final int _columnWrappingMask; + private final int _rowWrappingMask; + + public SharedFormula(SpreadsheetVersion ssVersion){ + _columnWrappingMask = ssVersion.getLastColumnIndex(); //"IV" for .xls and "XFD" for .xlsx + _rowWrappingMask = ssVersion.getLastRowIndex(); + } + + /** + * Creates a non shared formula from the shared formula counterpart, i.e. + * Converts the shared formula into the equivalent {@link org.apache.poi.ss.formula.ptg.Ptg} array that it would have, + * were it not shared. + * + * @param ptgs parsed tokens of the shared formula + * @param formulaRow + * @param formulaColumn + */ + public Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) { + + Ptg[] newPtgStack = new Ptg[ptgs.length]; + + for (int k = 0; k < ptgs.length; k++) { + Ptg ptg = ptgs[k]; + byte originalOperandClass = -1; + if (!ptg.isBaseToken()) { + originalOperandClass = ptg.getPtgClass(); + } + if (ptg instanceof RefPtgBase) { + RefPtgBase refNPtg = (RefPtgBase)ptg; + ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()), + fixupRelativeColumn(formulaColumn,refNPtg.getColumn(),refNPtg.isColRelative()), + refNPtg.isRowRelative(), + refNPtg.isColRelative()); + ptg.setClass(originalOperandClass); + } else if (ptg instanceof AreaPtgBase) { + AreaPtgBase areaNPtg = (AreaPtgBase)ptg; + ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()), + fixupRelativeRow(formulaRow,areaNPtg.getLastRow(),areaNPtg.isLastRowRelative()), + fixupRelativeColumn(formulaColumn,areaNPtg.getFirstColumn(),areaNPtg.isFirstColRelative()), + fixupRelativeColumn(formulaColumn,areaNPtg.getLastColumn(),areaNPtg.isLastColRelative()), + areaNPtg.isFirstRowRelative(), + areaNPtg.isLastRowRelative(), + areaNPtg.isFirstColRelative(), + areaNPtg.isLastColRelative()); + ptg.setClass(originalOperandClass); + } else if (ptg instanceof OperandPtg) { + // Any subclass of OperandPtg is mutable, so it's safest to not share these instances. + ptg = ((OperandPtg) ptg).copy(); + } else { + // all other Ptgs are immutable and can be shared + } + newPtgStack[k] = ptg; + } + return newPtgStack; + } + + private int fixupRelativeColumn(int currentcolumn, int column, boolean relative) { + if(relative) { + // mask out upper bits to produce 'wrapping' at the maximum column ("IV" for .xls and "XFD" for .xlsx) + return (column + currentcolumn) & _columnWrappingMask; + } + return column; + } + + private int fixupRelativeRow(int currentrow, int row, boolean relative) { + if(relative) { + return (row+currentrow) & _rowWrappingMask; + } + return row; + } + +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Address.java b/src/java/org/apache/poi/ss/formula/functions/Address.java index e0680dff66..29aeae6930 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Address.java +++ b/src/java/org/apache/poi/ss/formula/functions/Address.java @@ -1,103 +1,103 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.SheetNameFormatter; -import org.apache.poi.ss.formula.eval.*; -import org.apache.poi.ss.util.CellReference; - -/** - * Creates a text reference as text, given specified row and column numbers. - * - * @author Aniket Banerjee (banerjee@google.com) - */ -public class Address implements Function { - public static final int REF_ABSOLUTE = 1; - public static final int REF_ROW_ABSOLUTE_COLUMN_RELATIVE = 2; - public static final int REF_ROW_RELATIVE_RELATIVE_ABSOLUTE = 3; - public static final int REF_RELATIVE = 4; - - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, - int srcColumnIndex) { - if(args.length < 2 || args.length > 5) { - return ErrorEval.VALUE_INVALID; - } - try { - boolean pAbsRow, pAbsCol; - - int row = (int)NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex); - int col = (int)NumericFunction.singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex); - - int refType; - if (args.length > 2 && args[2] != MissingArgEval.instance) { - refType = (int)NumericFunction.singleOperandEvaluate(args[2], srcRowIndex, srcColumnIndex); - } else { - refType = REF_ABSOLUTE; // this is also the default if parameter is not given - } - switch (refType){ - case REF_ABSOLUTE: - pAbsRow = true; - pAbsCol = true; - break; - case REF_ROW_ABSOLUTE_COLUMN_RELATIVE: - pAbsRow = true; - pAbsCol = false; - break; - case REF_ROW_RELATIVE_RELATIVE_ABSOLUTE: - pAbsRow = false; - pAbsCol = true; - break; - case REF_RELATIVE: - pAbsRow = false; - pAbsCol = false; - break; - default: - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - -// boolean a1; -// if(args.length > 3){ -// ValueEval ve = OperandResolver.getSingleValue(args[3], srcRowIndex, srcColumnIndex); -// // TODO R1C1 style is not yet supported -// a1 = ve == MissingArgEval.instance ? true : OperandResolver.coerceValueToBoolean(ve, false); -// } else { -// a1 = true; -// } - - String sheetName; - if(args.length == 5){ - ValueEval ve = OperandResolver.getSingleValue(args[4], srcRowIndex, srcColumnIndex); - sheetName = ve == MissingArgEval.instance ? null : OperandResolver.coerceValueToString(ve); - } else { - sheetName = null; - } - - CellReference ref = new CellReference(row - 1, col - 1, pAbsRow, pAbsCol); - StringBuffer sb = new StringBuffer(32); - if(sheetName != null) { - SheetNameFormatter.appendFormat(sb, sheetName); - sb.append('!'); - } - sb.append(ref.formatAsString()); - - return new StringEval(sb.toString()); - - } catch (EvaluationException e){ - return e.getErrorEval(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.SheetNameFormatter; +import org.apache.poi.ss.formula.eval.*; +import org.apache.poi.ss.util.CellReference; + +/** + * Creates a text reference as text, given specified row and column numbers. + * + * @author Aniket Banerjee (banerjee@google.com) + */ +public class Address implements Function { + public static final int REF_ABSOLUTE = 1; + public static final int REF_ROW_ABSOLUTE_COLUMN_RELATIVE = 2; + public static final int REF_ROW_RELATIVE_RELATIVE_ABSOLUTE = 3; + public static final int REF_RELATIVE = 4; + + public ValueEval evaluate(ValueEval[] args, int srcRowIndex, + int srcColumnIndex) { + if(args.length < 2 || args.length > 5) { + return ErrorEval.VALUE_INVALID; + } + try { + boolean pAbsRow, pAbsCol; + + int row = (int)NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex); + int col = (int)NumericFunction.singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex); + + int refType; + if (args.length > 2 && args[2] != MissingArgEval.instance) { + refType = (int)NumericFunction.singleOperandEvaluate(args[2], srcRowIndex, srcColumnIndex); + } else { + refType = REF_ABSOLUTE; // this is also the default if parameter is not given + } + switch (refType){ + case REF_ABSOLUTE: + pAbsRow = true; + pAbsCol = true; + break; + case REF_ROW_ABSOLUTE_COLUMN_RELATIVE: + pAbsRow = true; + pAbsCol = false; + break; + case REF_ROW_RELATIVE_RELATIVE_ABSOLUTE: + pAbsRow = false; + pAbsCol = true; + break; + case REF_RELATIVE: + pAbsRow = false; + pAbsCol = false; + break; + default: + throw new EvaluationException(ErrorEval.VALUE_INVALID); + } + +// boolean a1; +// if(args.length > 3){ +// ValueEval ve = OperandResolver.getSingleValue(args[3], srcRowIndex, srcColumnIndex); +// // TODO R1C1 style is not yet supported +// a1 = ve == MissingArgEval.instance ? true : OperandResolver.coerceValueToBoolean(ve, false); +// } else { +// a1 = true; +// } + + String sheetName; + if(args.length == 5){ + ValueEval ve = OperandResolver.getSingleValue(args[4], srcRowIndex, srcColumnIndex); + sheetName = ve == MissingArgEval.instance ? null : OperandResolver.coerceValueToString(ve); + } else { + sheetName = null; + } + + CellReference ref = new CellReference(row - 1, col - 1, pAbsRow, pAbsCol); + StringBuffer sb = new StringBuffer(32); + if(sheetName != null) { + SheetNameFormatter.appendFormat(sb, sheetName); + sb.append('!'); + } + sb.append(ref.formatAsString()); + + return new StringEval(sb.toString()); + + } catch (EvaluationException e){ + return e.getErrorEval(); + } + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java b/src/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java index 6130311d60..460b87a30e 100644 --- a/src/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java +++ b/src/java/org/apache/poi/ss/formula/functions/BaseNumberUtils.java @@ -1,78 +1,78 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -/** - *

Some utils for converting from and to any base

- * - * @author cedric dot walter @ gmail dot com - */ -public class BaseNumberUtils { - - - public static double convertToDecimal(String value, int base, int maxNumberOfPlaces) throws IllegalArgumentException { - if (value == null || value.length() == 0) { - return 0.0; - } - - long stringLength = value.length(); - if (stringLength > maxNumberOfPlaces) { - throw new IllegalArgumentException(); - } - - double decimalValue = 0.0; - - long signedDigit = 0; - boolean hasSignedDigit = true; - char[] characters = value.toCharArray(); - for (char character : characters) { - long digit; - - if ('0' <= character && character <= '9') { - digit = character - '0'; - } else if ('A' <= character && character <= 'Z') { - digit = 10 + (character - 'A'); - } else if ('a' <= character && character <= 'z') { - digit = 10 + (character - 'a'); - } else { - digit = base; - } - - if (digit < base) { - if (hasSignedDigit) { - hasSignedDigit = false; - signedDigit = digit; - } - decimalValue = decimalValue * base + digit; - } else { - throw new IllegalArgumentException("character not allowed"); - } - } - - boolean isNegative = (!hasSignedDigit && stringLength == maxNumberOfPlaces && (signedDigit >= base / 2)); - if (isNegative) { - decimalValue = getTwoComplement(base, maxNumberOfPlaces, decimalValue); - decimalValue = decimalValue * -1.0; - } - - return decimalValue; - } - - private static double getTwoComplement(double base, double maxNumberOfPlaces, double decimalValue) { - return (Math.pow(base, maxNumberOfPlaces) - decimalValue); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +/** + *

Some utils for converting from and to any base

+ * + * @author cedric dot walter @ gmail dot com + */ +public class BaseNumberUtils { + + + public static double convertToDecimal(String value, int base, int maxNumberOfPlaces) throws IllegalArgumentException { + if (value == null || value.length() == 0) { + return 0.0; + } + + long stringLength = value.length(); + if (stringLength > maxNumberOfPlaces) { + throw new IllegalArgumentException(); + } + + double decimalValue = 0.0; + + long signedDigit = 0; + boolean hasSignedDigit = true; + char[] characters = value.toCharArray(); + for (char character : characters) { + long digit; + + if ('0' <= character && character <= '9') { + digit = character - '0'; + } else if ('A' <= character && character <= 'Z') { + digit = 10 + (character - 'A'); + } else if ('a' <= character && character <= 'z') { + digit = 10 + (character - 'a'); + } else { + digit = base; + } + + if (digit < base) { + if (hasSignedDigit) { + hasSignedDigit = false; + signedDigit = digit; + } + decimalValue = decimalValue * base + digit; + } else { + throw new IllegalArgumentException("character not allowed"); + } + } + + boolean isNegative = (!hasSignedDigit && stringLength == maxNumberOfPlaces && (signedDigit >= base / 2)); + if (isNegative) { + decimalValue = getTwoComplement(base, maxNumberOfPlaces, decimalValue); + decimalValue = decimalValue * -1.0; + } + + return decimalValue; + } + + private static double getTwoComplement(double base, double maxNumberOfPlaces, double decimalValue) { + return (Math.pow(base, maxNumberOfPlaces) - decimalValue); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java b/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java index cb206051c0..92cc2d2c4b 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java +++ b/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java @@ -1,124 +1,124 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.RefEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Implementation for Excel Bin2Dec() function.

- *

- * Syntax:
Bin2Dec (number)
- *

- * Converts a binary number to decimal. - *

- * Number is the binary number you want to convert. Number cannot contain more than 10 characters (10 bits). - * The most significant bit of number is the sign bit. The remaining 9 bits are magnitude bits. - * Negative numbers are represented using two's-complement notation. - *

- * Remark - * If number is not a valid binary number, or if number contains more than 10 characters (10 bits), - * BIN2DEC returns the #NUM! error value. - * - * @author cedric dot walter @ gmail dot com - */ -public class Bin2Dec extends Fixed1ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Bin2Dec(); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { - final String number; - if (numberVE instanceof RefEval) { - RefEval re = (RefEval) numberVE; - number = OperandResolver.coerceValueToString(re.getInnerValueEval(re.getFirstSheetIndex())); - } else { - number = OperandResolver.coerceValueToString(numberVE); - } - if (number.length() > 10) { - return ErrorEval.NUM_ERROR; - } - - String unsigned; - - //If the leftmost bit is 0 -- number is positive. - boolean isPositive; - if (number.length() < 10) { - unsigned = number; - isPositive = true; - } else { - unsigned = number.substring(1); - isPositive = number.startsWith("0"); - } - - String value; - try { - if (isPositive) { - //bit9*2^8 + bit8*2^7 + bit7*2^6 + bit6*2^5 + bit5*2^4+ bit3*2^2+ bit2*2^1+ bit1*2^0 - int sum = getDecimalValue(unsigned); - value = String.valueOf(sum); - } else { - //The leftmost bit is 1 -- this is negative number - //Inverse bits [1-9] - String inverted = toggleBits(unsigned); - // Calculate decimal number - int sum = getDecimalValue(inverted); - - //Add 1 to obtained number - sum++; - - value = "-" + sum; - } - } catch (NumberFormatException e) { - return ErrorEval.NUM_ERROR; - } - - return new NumberEval(Long.parseLong(value)); - } - - private int getDecimalValue(String unsigned) { - int sum = 0; - int numBits = unsigned.length(); - int power = numBits - 1; - - for (int i = 0; i < numBits; i++) { - int bit = Integer.parseInt(unsigned.substring(i, i + 1)); - int term = (int) (bit * Math.pow(2, power)); - sum += term; - power--; - } - return sum; - } - - private static String toggleBits(String s) { - long i = Long.parseLong(s, 2); - long i2 = i ^ ((1L << s.length()) - 1); - String s2 = Long.toBinaryString(i2); - while (s2.length() < s.length()) s2 = '0' + s2; - return s2; - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.RefEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Implementation for Excel Bin2Dec() function.

+ *

+ * Syntax:
Bin2Dec (number)
+ *

+ * Converts a binary number to decimal. + *

+ * Number is the binary number you want to convert. Number cannot contain more than 10 characters (10 bits). + * The most significant bit of number is the sign bit. The remaining 9 bits are magnitude bits. + * Negative numbers are represented using two's-complement notation. + *

+ * Remark + * If number is not a valid binary number, or if number contains more than 10 characters (10 bits), + * BIN2DEC returns the #NUM! error value. + * + * @author cedric dot walter @ gmail dot com + */ +public class Bin2Dec extends Fixed1ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Bin2Dec(); + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { + final String number; + if (numberVE instanceof RefEval) { + RefEval re = (RefEval) numberVE; + number = OperandResolver.coerceValueToString(re.getInnerValueEval(re.getFirstSheetIndex())); + } else { + number = OperandResolver.coerceValueToString(numberVE); + } + if (number.length() > 10) { + return ErrorEval.NUM_ERROR; + } + + String unsigned; + + //If the leftmost bit is 0 -- number is positive. + boolean isPositive; + if (number.length() < 10) { + unsigned = number; + isPositive = true; + } else { + unsigned = number.substring(1); + isPositive = number.startsWith("0"); + } + + String value; + try { + if (isPositive) { + //bit9*2^8 + bit8*2^7 + bit7*2^6 + bit6*2^5 + bit5*2^4+ bit3*2^2+ bit2*2^1+ bit1*2^0 + int sum = getDecimalValue(unsigned); + value = String.valueOf(sum); + } else { + //The leftmost bit is 1 -- this is negative number + //Inverse bits [1-9] + String inverted = toggleBits(unsigned); + // Calculate decimal number + int sum = getDecimalValue(inverted); + + //Add 1 to obtained number + sum++; + + value = "-" + sum; + } + } catch (NumberFormatException e) { + return ErrorEval.NUM_ERROR; + } + + return new NumberEval(Long.parseLong(value)); + } + + private int getDecimalValue(String unsigned) { + int sum = 0; + int numBits = unsigned.length(); + int power = numBits - 1; + + for (int i = 0; i < numBits; i++) { + int bit = Integer.parseInt(unsigned.substring(i, i + 1)); + int term = (int) (bit * Math.pow(2, power)); + sum += term; + power--; + } + return sum; + } + + private static String toggleBits(String s) { + long i = Long.parseLong(s, 2); + long i2 = i ^ ((1L << s.length()) - 1); + String s2 = Long.toBinaryString(i2); + while (s2.length() < s.length()) s2 = '0' + s2; + return s2; + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 1) { + return ErrorEval.VALUE_INVALID; + } + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Code.java b/src/java/org/apache/poi/ss/formula/functions/Code.java index ee1622f584..881bcac4ae 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Code.java +++ b/src/java/org/apache/poi/ss/formula/functions/Code.java @@ -1,54 +1,54 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.eval.*; - -/** - * Implementation for Excel CODE () function.

- *

- * Syntax:
CODE (text )
- *

- * Returns a numeric code for the first character in a text string. The returned code corresponds to the character set used by your computer. - *

- * text The text for which you want the code of the first character. - * - * @author cedric dot walter @ gmail dot com - */ -public class Code extends Fixed1ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval textArg) { - - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(textArg, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String text = OperandResolver.coerceValueToString(veText1); - - if (text.length() == 0) { - return ErrorEval.VALUE_INVALID; - } - - int code = text.charAt(0); - - return new StringEval(String.valueOf(code)); - } -} - +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.*; + +/** + * Implementation for Excel CODE () function.

+ *

+ * Syntax:
CODE (text )
+ *

+ * Returns a numeric code for the first character in a text string. The returned code corresponds to the character set used by your computer. + *

+ * text The text for which you want the code of the first character. + * + * @author cedric dot walter @ gmail dot com + */ +public class Code extends Fixed1ArgFunction { + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval textArg) { + + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(textArg, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String text = OperandResolver.coerceValueToString(veText1); + + if (text.length() == 0) { + return ErrorEval.VALUE_INVALID; + } + + int code = text.charAt(0); + + return new StringEval(String.valueOf(code)); + } +} + diff --git a/src/java/org/apache/poi/ss/formula/functions/Complex.java b/src/java/org/apache/poi/ss/formula/functions/Complex.java index 628a2670ff..8273f6a052 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Complex.java +++ b/src/java/org/apache/poi/ss/formula/functions/Complex.java @@ -1,150 +1,150 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Locale; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Implementation for Excel COMPLEX () function.

- *

- * Syntax:
COMPLEX (real_num,i_num,suffix )
- *

- * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj. - *

- *

- * All complex number functions accept "i" and "j" for suffix, but neither "I" nor "J". - * Using uppercase results in the #VALUE! error value. All functions that accept two - * or more complex numbers require that all suffixes match. - *

- * real_num The real coefficient of the complex number. - * If this argument is nonnumeric, this function returns the #VALUE! error value. - *

- *

- * i_num The imaginary coefficient of the complex number. - * If this argument is nonnumeric, this function returns the #VALUE! error value. - *

- *

- * suffix The suffix for the imaginary component of the complex number. - *

    - *
  • If omitted, suffix is assumed to be "i".
  • - *
  • If suffix is neither "i" nor "j", COMPLEX returns the #VALUE! error value.
  • - *
- * - * @author cedric dot walter @ gmail dot com - */ -public class Complex extends Var2or3ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Complex(); - - public static final String DEFAULT_SUFFIX = "i"; - public static final String SUPPORTED_SUFFIX = "j"; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num) { - return this.evaluate(srcRowIndex, srcColumnIndex, real_num, i_num, new StringEval(DEFAULT_SUFFIX)); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num, ValueEval suffix) { - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(real_num, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - double realNum = 0; - try { - realNum = OperandResolver.coerceValueToDouble(veText1); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - - ValueEval veINum; - try { - veINum = OperandResolver.getSingleValue(i_num, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - double realINum = 0; - try { - realINum = OperandResolver.coerceValueToDouble(veINum); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - - String suffixValue = OperandResolver.coerceValueToString(suffix); - if (suffixValue.length() == 0) { - suffixValue = DEFAULT_SUFFIX; - } - if (suffixValue.equals(DEFAULT_SUFFIX.toUpperCase(Locale.ROOT)) || - suffixValue.equals(SUPPORTED_SUFFIX.toUpperCase(Locale.ROOT))) { - return ErrorEval.VALUE_INVALID; - } - if (!(suffixValue.equals(DEFAULT_SUFFIX) || suffixValue.equals(SUPPORTED_SUFFIX))) { - return ErrorEval.VALUE_INVALID; - } - - StringBuffer strb = new StringBuffer(""); - if (realNum != 0) { - if (isDoubleAnInt(realNum)) { - strb.append((int)realNum); - } else { - strb.append(realNum); - } - } - if (realINum != 0) { - if (strb.length() != 0) { - if (realINum > 0) { - strb.append("+"); - } - } - - if (realINum != 1 && realINum != -1) { - if (isDoubleAnInt(realINum)) { - strb.append((int)realINum); - } else { - strb.append(realINum); - } - } - - strb.append(suffixValue); - } - - return new StringEval(strb.toString()); - } - - private boolean isDoubleAnInt(double number) { - return (number == Math.floor(number)) && !Double.isInfinite(number); - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length == 2) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); - } - if (args.length == 3) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1], args[2]); - } - - return ErrorEval.VALUE_INVALID; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Locale; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Implementation for Excel COMPLEX () function.

+ *

+ * Syntax:
COMPLEX (real_num,i_num,suffix )
+ *

+ * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj. + *

+ *

+ * All complex number functions accept "i" and "j" for suffix, but neither "I" nor "J". + * Using uppercase results in the #VALUE! error value. All functions that accept two + * or more complex numbers require that all suffixes match. + *

+ * real_num The real coefficient of the complex number. + * If this argument is nonnumeric, this function returns the #VALUE! error value. + *

+ *

+ * i_num The imaginary coefficient of the complex number. + * If this argument is nonnumeric, this function returns the #VALUE! error value. + *

+ *

+ * suffix The suffix for the imaginary component of the complex number. + *

    + *
  • If omitted, suffix is assumed to be "i".
  • + *
  • If suffix is neither "i" nor "j", COMPLEX returns the #VALUE! error value.
  • + *
+ * + * @author cedric dot walter @ gmail dot com + */ +public class Complex extends Var2or3ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Complex(); + + public static final String DEFAULT_SUFFIX = "i"; + public static final String SUPPORTED_SUFFIX = "j"; + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num) { + return this.evaluate(srcRowIndex, srcColumnIndex, real_num, i_num, new StringEval(DEFAULT_SUFFIX)); + } + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num, ValueEval suffix) { + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(real_num, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + double realNum = 0; + try { + realNum = OperandResolver.coerceValueToDouble(veText1); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + + ValueEval veINum; + try { + veINum = OperandResolver.getSingleValue(i_num, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + double realINum = 0; + try { + realINum = OperandResolver.coerceValueToDouble(veINum); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + + String suffixValue = OperandResolver.coerceValueToString(suffix); + if (suffixValue.length() == 0) { + suffixValue = DEFAULT_SUFFIX; + } + if (suffixValue.equals(DEFAULT_SUFFIX.toUpperCase(Locale.ROOT)) || + suffixValue.equals(SUPPORTED_SUFFIX.toUpperCase(Locale.ROOT))) { + return ErrorEval.VALUE_INVALID; + } + if (!(suffixValue.equals(DEFAULT_SUFFIX) || suffixValue.equals(SUPPORTED_SUFFIX))) { + return ErrorEval.VALUE_INVALID; + } + + StringBuffer strb = new StringBuffer(""); + if (realNum != 0) { + if (isDoubleAnInt(realNum)) { + strb.append((int)realNum); + } else { + strb.append(realNum); + } + } + if (realINum != 0) { + if (strb.length() != 0) { + if (realINum > 0) { + strb.append("+"); + } + } + + if (realINum != 1 && realINum != -1) { + if (isDoubleAnInt(realINum)) { + strb.append((int)realINum); + } else { + strb.append(realINum); + } + } + + strb.append(suffixValue); + } + + return new StringEval(strb.toString()); + } + + private boolean isDoubleAnInt(double number) { + return (number == Math.floor(number)) && !Double.isInfinite(number); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length == 2) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); + } + if (args.length == 3) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1], args[2]); + } + + return ErrorEval.VALUE_INVALID; + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Dec2Bin.java b/src/java/org/apache/poi/ss/formula/functions/Dec2Bin.java index 21d8bcfaf0..74f115c199 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Dec2Bin.java +++ b/src/java/org/apache/poi/ss/formula/functions/Dec2Bin.java @@ -1,131 +1,131 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Implementation for Excel Bin2Dec() function.

- *

- * Syntax:
Bin2Dec (number,[places] )
- *

- * Converts a decimal number to binary. - *

- * The DEC2BIN function syntax has the following arguments: - *

    - *
  • Number Required. The decimal integer you want to convert. If number is negative, valid place values are ignored and DEC2BIN returns a 10-character (10-bit) binary number in which the most significant bit is the sign bit. The remaining 9 bits are magnitude bits. Negative numbers are represented using two's-complement notation.
  • - *
  • Places Optional. The number of characters to use. If places is omitted, DEC2BIN uses the minimum number of characters necessary. Places is useful for padding the return value with leading 0s (zeros).
  • - *
- *

- * Remarks - *

    - *
  • If number < -512 or if number > 511, DEC2BIN returns the #NUM! error value.
  • - *
  • If number is nonnumeric, DEC2BIN returns the #VALUE! error value.
  • - *
  • If DEC2BIN requires more than places characters, it returns the #NUM! error value.
  • - *
  • If places is not an integer, it is truncated.
  • - *
  • If places is nonnumeric, DEC2BIN returns the #VALUE! error value.
  • - *
  • If places is zero or negative, DEC2BIN returns the #NUM! error value.
  • - *
- * - * @author cedric dot walter @ gmail dot com - */ -public class Dec2Bin extends Var1or2ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Dec2Bin(); - - private final static long MIN_VALUE = -512; - private final static long MAX_VALUE = 511; - private final static int DEFAULT_PLACES_VALUE = 10; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE, ValueEval placesVE) { - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(numberVE, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String strText1 = OperandResolver.coerceValueToString(veText1); - Double number = OperandResolver.parseDouble(strText1); - - //If this number argument is non numeric, this function returns the #VALUE! error value. - if (number == null) { - return ErrorEval.VALUE_INVALID; - } - - //If number < -512 or if number > 512, this function returns the #NUM! error value. - if (number.longValue() < MIN_VALUE || number.longValue() > MAX_VALUE) { - return ErrorEval.NUM_ERROR; - } - - int placesNumber; - if (number < 0 || placesVE == null) { - placesNumber = DEFAULT_PLACES_VALUE; - } else { - ValueEval placesValueEval; - try { - placesValueEval = OperandResolver.getSingleValue(placesVE, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String placesStr = OperandResolver.coerceValueToString(placesValueEval); - Double placesNumberDouble = OperandResolver.parseDouble(placesStr); - - //non numeric value - if (placesNumberDouble == null) { - return ErrorEval.VALUE_INVALID; - } - - //If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point. - placesNumber = placesNumberDouble.intValue(); - - if (placesNumber < 0 || placesNumber == 0) { - return ErrorEval.NUM_ERROR; - } - } - String binary = Integer.toBinaryString(number.intValue()); - - if (binary.length() > DEFAULT_PLACES_VALUE) { - binary = binary.substring(binary.length() - DEFAULT_PLACES_VALUE, binary.length()); - } - //If DEC2BIN requires more than places characters, it returns the #NUM! error value. - if (binary.length() > placesNumber) { - return ErrorEval.NUM_ERROR; - } - - return new StringEval(binary); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { - return this.evaluate(srcRowIndex, srcColumnIndex, numberVE, null); - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length == 1) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } - if (args.length == 2) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); - } - - return ErrorEval.VALUE_INVALID; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Implementation for Excel Bin2Dec() function.

+ *

+ * Syntax:
Bin2Dec (number,[places] )
+ *

+ * Converts a decimal number to binary. + *

+ * The DEC2BIN function syntax has the following arguments: + *

    + *
  • Number Required. The decimal integer you want to convert. If number is negative, valid place values are ignored and DEC2BIN returns a 10-character (10-bit) binary number in which the most significant bit is the sign bit. The remaining 9 bits are magnitude bits. Negative numbers are represented using two's-complement notation.
  • + *
  • Places Optional. The number of characters to use. If places is omitted, DEC2BIN uses the minimum number of characters necessary. Places is useful for padding the return value with leading 0s (zeros).
  • + *
+ *

+ * Remarks + *

    + *
  • If number < -512 or if number > 511, DEC2BIN returns the #NUM! error value.
  • + *
  • If number is nonnumeric, DEC2BIN returns the #VALUE! error value.
  • + *
  • If DEC2BIN requires more than places characters, it returns the #NUM! error value.
  • + *
  • If places is not an integer, it is truncated.
  • + *
  • If places is nonnumeric, DEC2BIN returns the #VALUE! error value.
  • + *
  • If places is zero or negative, DEC2BIN returns the #NUM! error value.
  • + *
+ * + * @author cedric dot walter @ gmail dot com + */ +public class Dec2Bin extends Var1or2ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Dec2Bin(); + + private final static long MIN_VALUE = -512; + private final static long MAX_VALUE = 511; + private final static int DEFAULT_PLACES_VALUE = 10; + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE, ValueEval placesVE) { + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(numberVE, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String strText1 = OperandResolver.coerceValueToString(veText1); + Double number = OperandResolver.parseDouble(strText1); + + //If this number argument is non numeric, this function returns the #VALUE! error value. + if (number == null) { + return ErrorEval.VALUE_INVALID; + } + + //If number < -512 or if number > 512, this function returns the #NUM! error value. + if (number.longValue() < MIN_VALUE || number.longValue() > MAX_VALUE) { + return ErrorEval.NUM_ERROR; + } + + int placesNumber; + if (number < 0 || placesVE == null) { + placesNumber = DEFAULT_PLACES_VALUE; + } else { + ValueEval placesValueEval; + try { + placesValueEval = OperandResolver.getSingleValue(placesVE, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String placesStr = OperandResolver.coerceValueToString(placesValueEval); + Double placesNumberDouble = OperandResolver.parseDouble(placesStr); + + //non numeric value + if (placesNumberDouble == null) { + return ErrorEval.VALUE_INVALID; + } + + //If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point. + placesNumber = placesNumberDouble.intValue(); + + if (placesNumber < 0 || placesNumber == 0) { + return ErrorEval.NUM_ERROR; + } + } + String binary = Integer.toBinaryString(number.intValue()); + + if (binary.length() > DEFAULT_PLACES_VALUE) { + binary = binary.substring(binary.length() - DEFAULT_PLACES_VALUE, binary.length()); + } + //If DEC2BIN requires more than places characters, it returns the #NUM! error value. + if (binary.length() > placesNumber) { + return ErrorEval.NUM_ERROR; + } + + return new StringEval(binary); + } + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { + return this.evaluate(srcRowIndex, srcColumnIndex, numberVE, null); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length == 1) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } + if (args.length == 2) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); + } + + return ErrorEval.VALUE_INVALID; + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java b/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java index 6318f98460..eed4b1677b 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java +++ b/src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java @@ -1,138 +1,138 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Locale; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.*; - -/** - * Implementation for Excel DELTA() function.

- *

- * Syntax:
DEC2HEX (number,places )
- *

- * Converts a decimal number to hexadecimal. - * - * The decimal integer you want to convert. If number is negative, places is ignored - * and this function returns a 10-character (40-bit) hexadecimal number in which the - * most significant bit is the sign bit. The remaining 39 bits are magnitude bits. - * Negative numbers are represented using two's-complement notation. - * - *

    - *
  • If number < -549,755,813,888 or if number > 549,755,813,887, this function returns the #NUM! error value.
  • - *
  • If number is nonnumeric, this function returns the #VALUE! error value.
  • - *
- * - *

places

- * - * The number of characters to use. The places argument is useful for padding the - * return value with leading 0s (zeros). - * - *
    - *
  • If this argument is omitted, this function uses the minimum number of characters necessary.
  • - *
  • If this function requires more than places characters, it returns the #NUM! error value.
  • - *
  • If this argument is non numeric, this function returns the #VALUE! error value.
  • - *
  • If this argument is negative, this function returns the #NUM! error value.
  • - *
  • If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point.
  • - *
- */ -public final class Dec2Hex extends Var1or2ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Dec2Hex(); - - private final static long MIN_VALUE = Long.parseLong("-549755813888"); - private final static long MAX_VALUE = Long.parseLong("549755813887"); - private final static int DEFAULT_PLACES_VALUE = 10; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval number, ValueEval places) { - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(number, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String strText1 = OperandResolver.coerceValueToString(veText1); - Double number1 = OperandResolver.parseDouble(strText1); - - //If this number argument is non numeric, this function returns the #VALUE! error value. - if (number1 == null) { - return ErrorEval.VALUE_INVALID; - } - - //If number < -549,755,813,888 or if number > 549,755,813,887, this function returns the #NUM! error value. - if (number1.longValue() < MIN_VALUE || number1.longValue() > MAX_VALUE) { - return ErrorEval.NUM_ERROR; - } - - int placesNumber = 0; - if (number1 < 0) { - placesNumber = DEFAULT_PLACES_VALUE; - } - else if (places != null) { - ValueEval placesValueEval; - try { - placesValueEval = OperandResolver.getSingleValue(places, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String placesStr = OperandResolver.coerceValueToString(placesValueEval); - Double placesNumberDouble = OperandResolver.parseDouble(placesStr); - - //non numeric value - if (placesNumberDouble == null) { - return ErrorEval.VALUE_INVALID; - } - - //If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point. - placesNumber = placesNumberDouble.intValue(); - - if (placesNumber < 0) { - return ErrorEval.NUM_ERROR; - } - } - - String hex; - if (placesNumber != 0) { - hex = String.format(Locale.ROOT, "%0"+placesNumber+"X", number1.intValue()); - } - else { - hex = Long.toHexString(number1.longValue()); - } - - if (number1 < 0) { - hex = "FF"+ hex.substring(2); - } - - return new StringEval(hex.toUpperCase(Locale.ROOT)); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - return this.evaluate(srcRowIndex, srcColumnIndex, arg0, null); - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length == 1) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } - if (args.length == 2) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); - } - return ErrorEval.VALUE_INVALID; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Locale; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.*; + +/** + * Implementation for Excel DELTA() function.

+ *

+ * Syntax:
DEC2HEX (number,places )
+ *

+ * Converts a decimal number to hexadecimal. + * + * The decimal integer you want to convert. If number is negative, places is ignored + * and this function returns a 10-character (40-bit) hexadecimal number in which the + * most significant bit is the sign bit. The remaining 39 bits are magnitude bits. + * Negative numbers are represented using two's-complement notation. + * + *

    + *
  • If number < -549,755,813,888 or if number > 549,755,813,887, this function returns the #NUM! error value.
  • + *
  • If number is nonnumeric, this function returns the #VALUE! error value.
  • + *
+ * + *

places

+ * + * The number of characters to use. The places argument is useful for padding the + * return value with leading 0s (zeros). + * + *
    + *
  • If this argument is omitted, this function uses the minimum number of characters necessary.
  • + *
  • If this function requires more than places characters, it returns the #NUM! error value.
  • + *
  • If this argument is non numeric, this function returns the #VALUE! error value.
  • + *
  • If this argument is negative, this function returns the #NUM! error value.
  • + *
  • If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point.
  • + *
+ */ +public final class Dec2Hex extends Var1or2ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Dec2Hex(); + + private final static long MIN_VALUE = Long.parseLong("-549755813888"); + private final static long MAX_VALUE = Long.parseLong("549755813887"); + private final static int DEFAULT_PLACES_VALUE = 10; + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval number, ValueEval places) { + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(number, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String strText1 = OperandResolver.coerceValueToString(veText1); + Double number1 = OperandResolver.parseDouble(strText1); + + //If this number argument is non numeric, this function returns the #VALUE! error value. + if (number1 == null) { + return ErrorEval.VALUE_INVALID; + } + + //If number < -549,755,813,888 or if number > 549,755,813,887, this function returns the #NUM! error value. + if (number1.longValue() < MIN_VALUE || number1.longValue() > MAX_VALUE) { + return ErrorEval.NUM_ERROR; + } + + int placesNumber = 0; + if (number1 < 0) { + placesNumber = DEFAULT_PLACES_VALUE; + } + else if (places != null) { + ValueEval placesValueEval; + try { + placesValueEval = OperandResolver.getSingleValue(places, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String placesStr = OperandResolver.coerceValueToString(placesValueEval); + Double placesNumberDouble = OperandResolver.parseDouble(placesStr); + + //non numeric value + if (placesNumberDouble == null) { + return ErrorEval.VALUE_INVALID; + } + + //If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point. + placesNumber = placesNumberDouble.intValue(); + + if (placesNumber < 0) { + return ErrorEval.NUM_ERROR; + } + } + + String hex; + if (placesNumber != 0) { + hex = String.format(Locale.ROOT, "%0"+placesNumber+"X", number1.intValue()); + } + else { + hex = Long.toHexString(number1.longValue()); + } + + if (number1 < 0) { + hex = "FF"+ hex.substring(2); + } + + return new StringEval(hex.toUpperCase(Locale.ROOT)); + } + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { + return this.evaluate(srcRowIndex, srcColumnIndex, arg0, null); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length == 1) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } + if (args.length == 2) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); + } + return ErrorEval.VALUE_INVALID; + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Delta.java b/src/java/org/apache/poi/ss/formula/functions/Delta.java index 2f1bd88dfc..0d70e67690 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Delta.java +++ b/src/java/org/apache/poi/ss/formula/functions/Delta.java @@ -1,85 +1,85 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.*; - -import java.math.BigDecimal; - -/** - * Implementation for Excel DELTA() function.

- *

- * Syntax:
DELTA (number1,number2 )
- *

- * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise. - * Use this function to filter a set of values. For example, by summing several DELTA functions - * you calculate the count of equal pairs. This function is also known as the Kronecker Delta function. - * - *

    - *
  • If number1 is nonnumeric, DELTA returns the #VALUE! error value.
  • - *
  • If number2 is nonnumeric, DELTA returns the #VALUE! error value.
  • - *
- * - * @author cedric dot walter @ gmail dot com - */ -public final class Delta extends Fixed2ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Delta(); - - private final static NumberEval ONE = new NumberEval(1); - private final static NumberEval ZERO = new NumberEval(0); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg1, ValueEval arg2) { - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String strText1 = OperandResolver.coerceValueToString(veText1); - Double number1 = OperandResolver.parseDouble(strText1); - if (number1 == null) { - return ErrorEval.VALUE_INVALID; - } - - ValueEval veText2; - try { - veText2 = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - String strText2 = OperandResolver.coerceValueToString(veText2); - Double number2 = OperandResolver.parseDouble(strText2); - if (number2 == null) { - return ErrorEval.VALUE_INVALID; - } - - int result = new BigDecimal(number1.doubleValue()).compareTo(new BigDecimal(number2.doubleValue())); - return result == 0 ? ONE : ZERO; - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length == 2) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); - } - - return ErrorEval.VALUE_INVALID; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.*; + +import java.math.BigDecimal; + +/** + * Implementation for Excel DELTA() function.

+ *

+ * Syntax:
DELTA (number1,number2 )
+ *

+ * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise. + * Use this function to filter a set of values. For example, by summing several DELTA functions + * you calculate the count of equal pairs. This function is also known as the Kronecker Delta function. + * + *

    + *
  • If number1 is nonnumeric, DELTA returns the #VALUE! error value.
  • + *
  • If number2 is nonnumeric, DELTA returns the #VALUE! error value.
  • + *
+ * + * @author cedric dot walter @ gmail dot com + */ +public final class Delta extends Fixed2ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Delta(); + + private final static NumberEval ONE = new NumberEval(1); + private final static NumberEval ZERO = new NumberEval(0); + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg1, ValueEval arg2) { + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String strText1 = OperandResolver.coerceValueToString(veText1); + Double number1 = OperandResolver.parseDouble(strText1); + if (number1 == null) { + return ErrorEval.VALUE_INVALID; + } + + ValueEval veText2; + try { + veText2 = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + + String strText2 = OperandResolver.coerceValueToString(veText2); + Double number2 = OperandResolver.parseDouble(strText2); + if (number2 == null) { + return ErrorEval.VALUE_INVALID; + } + + int result = new BigDecimal(number1.doubleValue()).compareTo(new BigDecimal(number2.doubleValue())); + return result == 0 ? ONE : ZERO; + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length == 2) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); + } + + return ErrorEval.VALUE_INVALID; + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/ss/formula/functions/EOMonth.java b/src/java/org/apache/poi/ss/formula/functions/EOMonth.java index 63836e591c..6809db15d6 100644 --- a/src/java/org/apache/poi/ss/formula/functions/EOMonth.java +++ b/src/java/org/apache/poi/ss/formula/functions/EOMonth.java @@ -1,82 +1,82 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Calendar; -import java.util.Date; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.util.LocaleUtil; - -/** - * Implementation for the Excel EOMONTH() function.

- *

- * EOMONTH() returns the date of the last day of a month..

- *

- * Syntax:
- * EOMONTH(start_date,months)

- *

- * start_date is the starting date of the calculation - * months is the number of months to be added to start_date, - * to give a new date. For this new date, EOMONTH returns the date of - * the last day of the month. months may be positive (in the future), - * zero or negative (in the past). - */ -public class EOMonth implements FreeRefFunction { - public static final FreeRefFunction instance = new EOMonth(); - - @Override - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 2) { - return ErrorEval.VALUE_INVALID; - } - - try { - double startDateAsNumber = NumericFunction.singleOperandEvaluate(args[0], ec.getRowIndex(), ec.getColumnIndex()); - int months = (int) NumericFunction.singleOperandEvaluate(args[1], ec.getRowIndex(), ec.getColumnIndex()); - - // Excel treats date 0 as 1900-01-00; EOMONTH results in 1900-01-31 - if (startDateAsNumber >= 0.0 && startDateAsNumber < 1.0) { - startDateAsNumber = 1.0; - } - - Date startDate = DateUtil.getJavaDate(startDateAsNumber, false); - - Calendar cal = LocaleUtil.getLocaleCalendar(); - cal.setTime(startDate); - cal.clear(Calendar.HOUR); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.clear(Calendar.MINUTE); - cal.clear(Calendar.SECOND); - cal.clear(Calendar.MILLISECOND); - - cal.add(Calendar.MONTH, months + 1); - cal.set(Calendar.DAY_OF_MONTH, 1); - cal.add(Calendar.DAY_OF_MONTH, -1); - - return new NumberEval(DateUtil.getExcelDate(cal.getTime())); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Calendar; +import java.util.Date; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.util.LocaleUtil; + +/** + * Implementation for the Excel EOMONTH() function.

+ *

+ * EOMONTH() returns the date of the last day of a month..

+ *

+ * Syntax:
+ * EOMONTH(start_date,months)

+ *

+ * start_date is the starting date of the calculation + * months is the number of months to be added to start_date, + * to give a new date. For this new date, EOMONTH returns the date of + * the last day of the month. months may be positive (in the future), + * zero or negative (in the past). + */ +public class EOMonth implements FreeRefFunction { + public static final FreeRefFunction instance = new EOMonth(); + + @Override + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 2) { + return ErrorEval.VALUE_INVALID; + } + + try { + double startDateAsNumber = NumericFunction.singleOperandEvaluate(args[0], ec.getRowIndex(), ec.getColumnIndex()); + int months = (int) NumericFunction.singleOperandEvaluate(args[1], ec.getRowIndex(), ec.getColumnIndex()); + + // Excel treats date 0 as 1900-01-00; EOMONTH results in 1900-01-31 + if (startDateAsNumber >= 0.0 && startDateAsNumber < 1.0) { + startDateAsNumber = 1.0; + } + + Date startDate = DateUtil.getJavaDate(startDateAsNumber, false); + + Calendar cal = LocaleUtil.getLocaleCalendar(); + cal.setTime(startDate); + cal.clear(Calendar.HOUR); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.clear(Calendar.MINUTE); + cal.clear(Calendar.SECOND); + cal.clear(Calendar.MILLISECOND); + + cal.add(Calendar.MONTH, months + 1); + cal.set(Calendar.DAY_OF_MONTH, 1); + cal.add(Calendar.DAY_OF_MONTH, -1); + + return new NumberEval(DateUtil.getExcelDate(cal.getTime())); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/FactDouble.java b/src/java/org/apache/poi/ss/formula/functions/FactDouble.java index 28c2171869..42657b7ded 100644 --- a/src/java/org/apache/poi/ss/formula/functions/FactDouble.java +++ b/src/java/org/apache/poi/ss/formula/functions/FactDouble.java @@ -1,86 +1,86 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.*; - -import java.math.BigInteger; -import java.util.HashMap; - -/** - * Implementation for Excel FACTDOUBLE() function.

- *

- * Syntax:
FACTDOUBLE (number)
- *

- * Returns the double factorial of a number. - *

- * Number is the value for which to return the double factorial. If number is not an integer, it is truncated. - *

- * Remarks - *

    - *
  • If number is nonnumeric, FACTDOUBLE returns the #VALUE! error value.
  • - *
  • If number is negative, FACTDOUBLE returns the #NUM! error value.
  • - *
- * Use a cache for more speed of previously calculated factorial - * - * @author cedric dot walter @ gmail dot com - */ -public class FactDouble extends Fixed1ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new FactDouble(); - - //Caching of previously calculated factorial for speed - static HashMap cache = new HashMap(); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { - int number; - try { - number = OperandResolver.coerceValueToInt(numberVE); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - - if (number < 0) { - return ErrorEval.NUM_ERROR; - } - - return new NumberEval(factorial(number).longValue()); - } - - public static BigInteger factorial(int n) { - if (n == 0 || n < 0) { - return BigInteger.ONE; - } - - if (cache.containsKey(n)) { - return cache.get(n); - } - - BigInteger result = BigInteger.valueOf(n).multiply(factorial(n - 2)); - cache.put(n, result); - return result; - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.*; + +import java.math.BigInteger; +import java.util.HashMap; + +/** + * Implementation for Excel FACTDOUBLE() function.

+ *

+ * Syntax:
FACTDOUBLE (number)
+ *

+ * Returns the double factorial of a number. + *

+ * Number is the value for which to return the double factorial. If number is not an integer, it is truncated. + *

+ * Remarks + *

    + *
  • If number is nonnumeric, FACTDOUBLE returns the #VALUE! error value.
  • + *
  • If number is negative, FACTDOUBLE returns the #NUM! error value.
  • + *
+ * Use a cache for more speed of previously calculated factorial + * + * @author cedric dot walter @ gmail dot com + */ +public class FactDouble extends Fixed1ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new FactDouble(); + + //Caching of previously calculated factorial for speed + static HashMap cache = new HashMap(); + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { + int number; + try { + number = OperandResolver.coerceValueToInt(numberVE); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + + if (number < 0) { + return ErrorEval.NUM_ERROR; + } + + return new NumberEval(factorial(number).longValue()); + } + + public static BigInteger factorial(int n) { + if (n == 0 || n < 0) { + return BigInteger.ONE; + } + + if (cache.containsKey(n)) { + return cache.get(n); + } + + BigInteger result = BigInteger.valueOf(n).multiply(factorial(n - 2)); + cache.put(n, result); + return result; + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 1) { + return ErrorEval.VALUE_INVALID; + } + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Hex2Dec.java b/src/java/org/apache/poi/ss/formula/functions/Hex2Dec.java index 907b62916f..46b92f2e21 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Hex2Dec.java +++ b/src/java/org/apache/poi/ss/formula/functions/Hex2Dec.java @@ -1,66 +1,66 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.*; - -/** - * Implementation for Excel HEX2DEC() function.

- *

- * Syntax:
HEX2DEC (number)
- *

- * Converts a hexadecimal number to decimal. - *

- * Number is the hexadecimal number you want to convert. Number cannot contain more than 10 characters (40 bits). - * The most significant bit of number is the sign bit. - * The remaining 39 bits are magnitude bits. Negative numbers are represented using two's-complement notation. - * Remark - * If number is not a valid hexadecimal number, HEX2DEC returns the #NUM! error value. - * - * @author cedric dot walter @ gmail dot com - */ -public class Hex2Dec extends Fixed1ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Hex2Dec(); - - static final int HEXADECIMAL_BASE = 16; - static final int MAX_NUMBER_OF_PLACES = 10; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { - final String hex; - if (numberVE instanceof RefEval) { - RefEval re = (RefEval) numberVE; - hex = OperandResolver.coerceValueToString(re.getInnerValueEval(re.getFirstSheetIndex())); - } else { - hex = OperandResolver.coerceValueToString(numberVE); - } - try { - return new NumberEval(BaseNumberUtils.convertToDecimal(hex, HEXADECIMAL_BASE, MAX_NUMBER_OF_PLACES)); - } catch (IllegalArgumentException e) { - return ErrorEval.NUM_ERROR; - } - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.*; + +/** + * Implementation for Excel HEX2DEC() function.

+ *

+ * Syntax:
HEX2DEC (number)
+ *

+ * Converts a hexadecimal number to decimal. + *

+ * Number is the hexadecimal number you want to convert. Number cannot contain more than 10 characters (40 bits). + * The most significant bit of number is the sign bit. + * The remaining 39 bits are magnitude bits. Negative numbers are represented using two's-complement notation. + * Remark + * If number is not a valid hexadecimal number, HEX2DEC returns the #NUM! error value. + * + * @author cedric dot walter @ gmail dot com + */ +public class Hex2Dec extends Fixed1ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Hex2Dec(); + + static final int HEXADECIMAL_BASE = 16; + static final int MAX_NUMBER_OF_PLACES = 10; + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { + final String hex; + if (numberVE instanceof RefEval) { + RefEval re = (RefEval) numberVE; + hex = OperandResolver.coerceValueToString(re.getInnerValueEval(re.getFirstSheetIndex())); + } else { + hex = OperandResolver.coerceValueToString(numberVE); + } + try { + return new NumberEval(BaseNumberUtils.convertToDecimal(hex, HEXADECIMAL_BASE, MAX_NUMBER_OF_PLACES)); + } catch (IllegalArgumentException e) { + return ErrorEval.NUM_ERROR; + } + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 1) { + return ErrorEval.VALUE_INVALID; + } + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/ImReal.java b/src/java/org/apache/poi/ss/formula/functions/ImReal.java index f7c17adef1..4687ccc9df 100644 --- a/src/java/org/apache/poi/ss/formula/functions/ImReal.java +++ b/src/java/org/apache/poi/ss/formula/functions/ImReal.java @@ -1,98 +1,98 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.regex.Matcher; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Implementation for Excel ImReal() function.

- *

- * Syntax:
ImReal (Inumber)
- *

- * Returns the real coefficient of a complex number in x + yi or x + yj text format. - *

- * Inumber A complex number for which you want the real coefficient. - *

- * Remarks - *

    - *
  • If inumber is not in the form x + yi or x + yj, this function returns the #NUM! error value.
  • - *
  • Use COMPLEX to convert real and imaginary coefficients into a complex number.
  • - *
- * - * @author cedric dot walter @ gmail dot com - */ -public class ImReal extends Fixed1ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new ImReal(); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval inumberVE) { - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(inumberVE, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String iNumber = OperandResolver.coerceValueToString(veText1); - - Matcher m = Imaginary.COMPLEX_NUMBER_PATTERN.matcher(iNumber); - boolean result = m.matches(); - - String real = ""; - if (result == true) { - String realGroup = m.group(2); - boolean hasRealPart = realGroup.length() != 0; - - if (realGroup.length() == 0) { - return new StringEval(String.valueOf(0)); - } - - if (hasRealPart) { - String sign = ""; - String realSign = m.group(Imaginary.GROUP1_REAL_SIGN); - if (realSign.length() != 0 && !(realSign.equals("+"))) { - sign = realSign; - } - - String groupRealNumber = m.group(Imaginary.GROUP2_IMAGINARY_INTEGER_OR_DOUBLE); - if (groupRealNumber.length() != 0) { - real = sign + groupRealNumber; - } else { - real = sign + "1"; - } - } - } else { - return ErrorEval.NUM_ERROR; - } - - return new StringEval(real); - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.regex.Matcher; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Implementation for Excel ImReal() function.

+ *

+ * Syntax:
ImReal (Inumber)
+ *

+ * Returns the real coefficient of a complex number in x + yi or x + yj text format. + *

+ * Inumber A complex number for which you want the real coefficient. + *

+ * Remarks + *

    + *
  • If inumber is not in the form x + yi or x + yj, this function returns the #NUM! error value.
  • + *
  • Use COMPLEX to convert real and imaginary coefficients into a complex number.
  • + *
+ * + * @author cedric dot walter @ gmail dot com + */ +public class ImReal extends Fixed1ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new ImReal(); + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval inumberVE) { + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(inumberVE, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String iNumber = OperandResolver.coerceValueToString(veText1); + + Matcher m = Imaginary.COMPLEX_NUMBER_PATTERN.matcher(iNumber); + boolean result = m.matches(); + + String real = ""; + if (result == true) { + String realGroup = m.group(2); + boolean hasRealPart = realGroup.length() != 0; + + if (realGroup.length() == 0) { + return new StringEval(String.valueOf(0)); + } + + if (hasRealPart) { + String sign = ""; + String realSign = m.group(Imaginary.GROUP1_REAL_SIGN); + if (realSign.length() != 0 && !(realSign.equals("+"))) { + sign = realSign; + } + + String groupRealNumber = m.group(Imaginary.GROUP2_IMAGINARY_INTEGER_OR_DOUBLE); + if (groupRealNumber.length() != 0) { + real = sign + groupRealNumber; + } else { + real = sign + "1"; + } + } + } else { + return ErrorEval.NUM_ERROR; + } + + return new StringEval(real); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 1) { + return ErrorEval.VALUE_INVALID; + } + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Imaginary.java b/src/java/org/apache/poi/ss/formula/functions/Imaginary.java index 2b1309310d..6fa9ae7d9c 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Imaginary.java +++ b/src/java/org/apache/poi/ss/formula/functions/Imaginary.java @@ -1,109 +1,109 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.*; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Implementation for Excel IMAGINARY() function.

- *

- * Syntax:
IMAGINARY (Inumber)
- *

- * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format. - *

- * Inumber is a complex number for which you want the imaginary coefficient. - *

- * Remarks - *

    - *
  • Use COMPLEX to convert real and imaginary coefficients into a complex number.
  • - *
- * - * @author cedric dot walter @ gmail dot com - */ -public class Imaginary extends Fixed1ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Imaginary(); - - public static final String GROUP1_REAL_SIGN_REGEX = "([+-]?)"; - public static final String GROUP2_REAL_INTEGER_OR_DOUBLE_REGEX = "([0-9]+\\.[0-9]+|[0-9]*)"; - public static final String GROUP3_IMAGINARY_SIGN_REGEX = "([+-]?)"; - public static final String GROUP4_IMAGINARY_INTEGER_OR_DOUBLE_REGEX = "([0-9]+\\.[0-9]+|[0-9]*)"; - public static final String GROUP5_IMAGINARY_GROUP_REGEX = "([ij]?)"; - - public static final Pattern COMPLEX_NUMBER_PATTERN - = Pattern.compile(GROUP1_REAL_SIGN_REGEX + GROUP2_REAL_INTEGER_OR_DOUBLE_REGEX + - GROUP3_IMAGINARY_SIGN_REGEX + GROUP4_IMAGINARY_INTEGER_OR_DOUBLE_REGEX + GROUP5_IMAGINARY_GROUP_REGEX); - - public static final int GROUP1_REAL_SIGN = 1; - public static final int GROUP2_IMAGINARY_INTEGER_OR_DOUBLE = 2; - public static final int GROUP3_IMAGINARY_SIGN = 3; - public static final int GROUP4_IMAGINARY_INTEGER_OR_DOUBLE = 4; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval inumberVE) { - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(inumberVE, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String iNumber = OperandResolver.coerceValueToString(veText1); - - Matcher m = COMPLEX_NUMBER_PATTERN.matcher(iNumber); - boolean result = m.matches(); - - String imaginary = ""; - if (result == true) { - String imaginaryGroup = m.group(5); - boolean hasImaginaryPart = imaginaryGroup.equals("i") || imaginaryGroup.equals("j"); - - if (imaginaryGroup.length() == 0) { - return new StringEval(String.valueOf(0)); - } - - if (hasImaginaryPart) { - String sign = ""; - String imaginarySign = m.group(GROUP3_IMAGINARY_SIGN); - if (imaginarySign.length() != 0 && !(imaginarySign.equals("+"))) { - sign = imaginarySign; - } - - String groupImaginaryNumber = m.group(GROUP4_IMAGINARY_INTEGER_OR_DOUBLE); - if (groupImaginaryNumber.length() != 0) { - imaginary = sign + groupImaginaryNumber; - } else { - imaginary = sign + "1"; - } - } - } else { - return ErrorEval.NUM_ERROR; - } - - return new StringEval(imaginary); - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implementation for Excel IMAGINARY() function.

+ *

+ * Syntax:
IMAGINARY (Inumber)
+ *

+ * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format. + *

+ * Inumber is a complex number for which you want the imaginary coefficient. + *

+ * Remarks + *

    + *
  • Use COMPLEX to convert real and imaginary coefficients into a complex number.
  • + *
+ * + * @author cedric dot walter @ gmail dot com + */ +public class Imaginary extends Fixed1ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Imaginary(); + + public static final String GROUP1_REAL_SIGN_REGEX = "([+-]?)"; + public static final String GROUP2_REAL_INTEGER_OR_DOUBLE_REGEX = "([0-9]+\\.[0-9]+|[0-9]*)"; + public static final String GROUP3_IMAGINARY_SIGN_REGEX = "([+-]?)"; + public static final String GROUP4_IMAGINARY_INTEGER_OR_DOUBLE_REGEX = "([0-9]+\\.[0-9]+|[0-9]*)"; + public static final String GROUP5_IMAGINARY_GROUP_REGEX = "([ij]?)"; + + public static final Pattern COMPLEX_NUMBER_PATTERN + = Pattern.compile(GROUP1_REAL_SIGN_REGEX + GROUP2_REAL_INTEGER_OR_DOUBLE_REGEX + + GROUP3_IMAGINARY_SIGN_REGEX + GROUP4_IMAGINARY_INTEGER_OR_DOUBLE_REGEX + GROUP5_IMAGINARY_GROUP_REGEX); + + public static final int GROUP1_REAL_SIGN = 1; + public static final int GROUP2_IMAGINARY_INTEGER_OR_DOUBLE = 2; + public static final int GROUP3_IMAGINARY_SIGN = 3; + public static final int GROUP4_IMAGINARY_INTEGER_OR_DOUBLE = 4; + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval inumberVE) { + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(inumberVE, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String iNumber = OperandResolver.coerceValueToString(veText1); + + Matcher m = COMPLEX_NUMBER_PATTERN.matcher(iNumber); + boolean result = m.matches(); + + String imaginary = ""; + if (result == true) { + String imaginaryGroup = m.group(5); + boolean hasImaginaryPart = imaginaryGroup.equals("i") || imaginaryGroup.equals("j"); + + if (imaginaryGroup.length() == 0) { + return new StringEval(String.valueOf(0)); + } + + if (hasImaginaryPart) { + String sign = ""; + String imaginarySign = m.group(GROUP3_IMAGINARY_SIGN); + if (imaginarySign.length() != 0 && !(imaginarySign.equals("+"))) { + sign = imaginarySign; + } + + String groupImaginaryNumber = m.group(GROUP4_IMAGINARY_INTEGER_OR_DOUBLE); + if (groupImaginaryNumber.length() != 0) { + imaginary = sign + groupImaginaryNumber; + } else { + imaginary = sign + "1"; + } + } + } else { + return ErrorEval.NUM_ERROR; + } + + return new StringEval(imaginary); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 1) { + return ErrorEval.VALUE_INVALID; + } + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Mirr.java b/src/java/org/apache/poi/ss/formula/functions/Mirr.java index 934f508811..52d00b36f8 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Mirr.java +++ b/src/java/org/apache/poi/ss/formula/functions/Mirr.java @@ -1,109 +1,109 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; - -/** - * Calculates Modified internal rate of return. Syntax is MIRR(cash_flow_values, finance_rate, reinvest_rate) - * - *

Returns the modified internal rate of return for a series of periodic cash flows. MIRR considers both the cost - * of the investment and the interest received on reinvestment of cash.

- * - * Values is an array or a reference to cells that contain numbers. These numbers represent a series of payments (negative values) and income (positive values) occurring at regular periods. - *
    - *
  • Values must contain at least one positive value and one negative value to calculate the modified internal rate of return. Otherwise, MIRR returns the #DIV/0! error value.
  • - *
  • If an array or reference argument contains text, logical values, or empty cells, those values are ignored; however, cells with the value zero are included.
  • - *
- * - * Finance_rate is the interest rate you pay on the money used in the cash flows. - * Reinvest_rate is the interest rate you receive on the cash flows as you reinvest them. - * - * @author Carlos Delgado (carlos dot del dot est at gmail dot com) - * @author Cedric Walter (cedric dot walter at gmail dot com) - * - * @see Wikipedia on MIRR - * @see Excel MIRR - * @see Irr - */ -public class Mirr extends MultiOperandNumericFunction { - - public Mirr() { - super(false, false); - } - - @Override - protected int getMaxNumOperands() { - return 3; - } - - @Override - protected double evaluate(double[] values) throws EvaluationException { - - double financeRate = values[values.length-1]; - double reinvestRate = values[values.length-2]; - - double[] mirrValues = new double[values.length - 2]; - System.arraycopy(values, 0, mirrValues, 0, mirrValues.length); - - boolean mirrValuesAreAllNegatives = true; - for (double mirrValue : mirrValues) { - mirrValuesAreAllNegatives &= mirrValue < 0; - } - if (mirrValuesAreAllNegatives) { - return -1.0d; - } - - boolean mirrValuesAreAllPositives = true; - for (double mirrValue : mirrValues) { - mirrValuesAreAllPositives &= mirrValue > 0; - } - if (mirrValuesAreAllPositives) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - - return mirr(mirrValues, financeRate, reinvestRate); - } - - private static double mirr(double[] in, double financeRate, double reinvestRate) { - double value = 0; - int numOfYears = in.length - 1; - double pv = 0; - double fv = 0; - - int indexN = 0; - for (double anIn : in) { - if (anIn < 0) { - pv += anIn / Math.pow(1 + financeRate + reinvestRate, indexN++); - } - } - - for (double anIn : in) { - if (anIn > 0) { - fv += anIn * Math.pow(1 + financeRate, numOfYears - indexN++); - } - } - - if (fv != 0 && pv != 0) { - value = Math.pow(-fv / pv, 1d / numOfYears) - 1; - } - return value; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; + +/** + * Calculates Modified internal rate of return. Syntax is MIRR(cash_flow_values, finance_rate, reinvest_rate) + * + *

Returns the modified internal rate of return for a series of periodic cash flows. MIRR considers both the cost + * of the investment and the interest received on reinvestment of cash.

+ * + * Values is an array or a reference to cells that contain numbers. These numbers represent a series of payments (negative values) and income (positive values) occurring at regular periods. + *
    + *
  • Values must contain at least one positive value and one negative value to calculate the modified internal rate of return. Otherwise, MIRR returns the #DIV/0! error value.
  • + *
  • If an array or reference argument contains text, logical values, or empty cells, those values are ignored; however, cells with the value zero are included.
  • + *
+ * + * Finance_rate is the interest rate you pay on the money used in the cash flows. + * Reinvest_rate is the interest rate you receive on the cash flows as you reinvest them. + * + * @author Carlos Delgado (carlos dot del dot est at gmail dot com) + * @author Cedric Walter (cedric dot walter at gmail dot com) + * + * @see Wikipedia on MIRR + * @see Excel MIRR + * @see Irr + */ +public class Mirr extends MultiOperandNumericFunction { + + public Mirr() { + super(false, false); + } + + @Override + protected int getMaxNumOperands() { + return 3; + } + + @Override + protected double evaluate(double[] values) throws EvaluationException { + + double financeRate = values[values.length-1]; + double reinvestRate = values[values.length-2]; + + double[] mirrValues = new double[values.length - 2]; + System.arraycopy(values, 0, mirrValues, 0, mirrValues.length); + + boolean mirrValuesAreAllNegatives = true; + for (double mirrValue : mirrValues) { + mirrValuesAreAllNegatives &= mirrValue < 0; + } + if (mirrValuesAreAllNegatives) { + return -1.0d; + } + + boolean mirrValuesAreAllPositives = true; + for (double mirrValue : mirrValues) { + mirrValuesAreAllPositives &= mirrValue > 0; + } + if (mirrValuesAreAllPositives) { + throw new EvaluationException(ErrorEval.DIV_ZERO); + } + + return mirr(mirrValues, financeRate, reinvestRate); + } + + private static double mirr(double[] in, double financeRate, double reinvestRate) { + double value = 0; + int numOfYears = in.length - 1; + double pv = 0; + double fv = 0; + + int indexN = 0; + for (double anIn : in) { + if (anIn < 0) { + pv += anIn / Math.pow(1 + financeRate + reinvestRate, indexN++); + } + } + + for (double anIn : in) { + if (anIn > 0) { + fv += anIn * Math.pow(1 + financeRate, numOfYears - indexN++); + } + } + + if (fv != 0 && pv != 0) { + value = Math.pow(-fv / pv, 1d / numOfYears) - 1; + } + return value; + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Oct2Dec.java b/src/java/org/apache/poi/ss/formula/functions/Oct2Dec.java index db9447df57..d24c63e5a8 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Oct2Dec.java +++ b/src/java/org/apache/poi/ss/formula/functions/Oct2Dec.java @@ -1,64 +1,64 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - *

Implementation for Excel Oct2Dec() function.

- *

- * Converts an octal number to decimal. - *

- *

- * Syntax:
Oct2Dec (number ) - *

- *

- * Number is the octal number you want to convert. Number may not contain more than 10 octal characters (30 bits). - * The most significant bit of number is the sign bit. The remaining 29 bits are magnitude bits. - * Negative numbers are represented using two's-complement notation.. - *

- * If number is not a valid octal number, OCT2DEC returns the #NUM! error value. - * - * @author cedric dot walter @ gmail dot com - */ -public class Oct2Dec extends Fixed1ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Oct2Dec(); - - static final int MAX_NUMBER_OF_PLACES = 10; - static final int OCTAL_BASE = 8; - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { - String octal = OperandResolver.coerceValueToString(numberVE); - try { - return new NumberEval(BaseNumberUtils.convertToDecimal(octal, OCTAL_BASE, MAX_NUMBER_OF_PLACES)); - } catch (IllegalArgumentException e) { - return ErrorEval.NUM_ERROR; - } - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + *

Implementation for Excel Oct2Dec() function.

+ *

+ * Converts an octal number to decimal. + *

+ *

+ * Syntax:
Oct2Dec (number ) + *

+ *

+ * Number is the octal number you want to convert. Number may not contain more than 10 octal characters (30 bits). + * The most significant bit of number is the sign bit. The remaining 29 bits are magnitude bits. + * Negative numbers are represented using two's-complement notation.. + *

+ * If number is not a valid octal number, OCT2DEC returns the #NUM! error value. + * + * @author cedric dot walter @ gmail dot com + */ +public class Oct2Dec extends Fixed1ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Oct2Dec(); + + static final int MAX_NUMBER_OF_PLACES = 10; + static final int OCTAL_BASE = 8; + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) { + String octal = OperandResolver.coerceValueToString(numberVE); + try { + return new NumberEval(BaseNumberUtils.convertToDecimal(octal, OCTAL_BASE, MAX_NUMBER_OF_PLACES)); + } catch (IllegalArgumentException e) { + return ErrorEval.NUM_ERROR; + } + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 1) { + return ErrorEval.VALUE_INVALID; + } + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Quotient.java b/src/java/org/apache/poi/ss/formula/functions/Quotient.java index 40d1debd32..4adac79807 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Quotient.java +++ b/src/java/org/apache/poi/ss/formula/functions/Quotient.java @@ -1,73 +1,73 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ValueEval; - -import org.apache.poi.ss.formula.eval.*; - -/** - *

Implementation for Excel QUOTIENT () function.

- *

- * Syntax:
QUOTIENT(Numerator,Denominator)
- *

- *

- * Numerator is the dividend. - * Denominator is the divisor. - * - * Returns the integer portion of a division. Use this function when you want to discard the remainder of a division. - *

- * - * If either enumerator/denominator is non numeric, QUOTIENT returns the #VALUE! error value. - * If denominator is equals to zero, QUOTIENT returns the #DIV/0! error value. - */ -public class Quotient extends Fixed2ArgFunction implements FreeRefFunction { - - public static final FreeRefFunction instance = new Quotient(); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval venumerator, ValueEval vedenominator) { - - double enumerator = 0; - try { - enumerator = OperandResolver.coerceValueToDouble(venumerator); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - - double denominator = 0; - try { - denominator = OperandResolver.coerceValueToDouble(vedenominator); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - - if (denominator == 0) { - return ErrorEval.DIV_ZERO; - } - - return new NumberEval((int)(enumerator / denominator)); - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length != 2) { - return ErrorEval.VALUE_INVALID; - } - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ValueEval; + +import org.apache.poi.ss.formula.eval.*; + +/** + *

Implementation for Excel QUOTIENT () function.

+ *

+ * Syntax:
QUOTIENT(Numerator,Denominator)
+ *

+ *

+ * Numerator is the dividend. + * Denominator is the divisor. + * + * Returns the integer portion of a division. Use this function when you want to discard the remainder of a division. + *

+ * + * If either enumerator/denominator is non numeric, QUOTIENT returns the #VALUE! error value. + * If denominator is equals to zero, QUOTIENT returns the #DIV/0! error value. + */ +public class Quotient extends Fixed2ArgFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new Quotient(); + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval venumerator, ValueEval vedenominator) { + + double enumerator = 0; + try { + enumerator = OperandResolver.coerceValueToDouble(venumerator); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + + double denominator = 0; + try { + denominator = OperandResolver.coerceValueToDouble(vedenominator); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + + if (denominator == 0) { + return ErrorEval.DIV_ZERO; + } + + return new NumberEval((int)(enumerator / denominator)); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 2) { + return ErrorEval.VALUE_INVALID; + } + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Rate.java b/src/java/org/apache/poi/ss/formula/functions/Rate.java index 2a28b95f37..a9e8d5d78b 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Rate.java +++ b/src/java/org/apache/poi/ss/formula/functions/Rate.java @@ -1,123 +1,123 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.ValueEval; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * Implements the Excel Rate function - */ -public class Rate implements Function { - private static final POILogger LOG = POILogFactory.getLogger(Rate.class); - - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length < 3) { //First 3 parameters are mandatory - return ErrorEval.VALUE_INVALID; - } - - double periods, payment, present_val, future_val = 0, type = 0, estimate = 0.1, rate; - - try { - ValueEval v1 = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex); - ValueEval v2 = OperandResolver.getSingleValue(args[1], srcRowIndex, srcColumnIndex); - ValueEval v3 = OperandResolver.getSingleValue(args[2], srcRowIndex, srcColumnIndex); - ValueEval v4 = null; - if (args.length >= 4) - v4 = OperandResolver.getSingleValue(args[3], srcRowIndex, srcColumnIndex); - ValueEval v5 = null; - if (args.length >= 5) - v5 = OperandResolver.getSingleValue(args[4], srcRowIndex, srcColumnIndex); - ValueEval v6 = null; - if (args.length >= 6) - v6 = OperandResolver.getSingleValue(args[5], srcRowIndex, srcColumnIndex); - - periods = OperandResolver.coerceValueToDouble(v1); - payment = OperandResolver.coerceValueToDouble(v2); - present_val = OperandResolver.coerceValueToDouble(v3); - if (args.length >= 4) - future_val = OperandResolver.coerceValueToDouble(v4); - if (args.length >= 5) - type = OperandResolver.coerceValueToDouble(v5); - if (args.length >= 6) - estimate = OperandResolver.coerceValueToDouble(v6); - rate = calculateRate(periods, payment, present_val, future_val, type, estimate) ; - - checkValue(rate); - } catch (EvaluationException e) { - LOG.log(POILogger.ERROR, "Can't evaluate rate function", e); - return e.getErrorEval(); - } - - return new NumberEval( rate ) ; - } - - private double calculateRate(double nper, double pmt, double pv, double fv, double type, double guess) { - //FROM MS http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx - int FINANCIAL_MAX_ITERATIONS = 20;//Bet accuracy with 128 - double FINANCIAL_PRECISION = 0.0000001;//1.0e-8 - - double y, y0, y1, x0, x1 = 0, f = 0, i = 0; - double rate = guess; - if (Math.abs(rate) < FINANCIAL_PRECISION) { - y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv; - } else { - f = Math.exp(nper * Math.log(1 + rate)); - y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv; - } - y0 = pv + pmt * nper + fv; - y1 = pv * f + pmt * (1 / rate + type) * (f - 1) + fv; - - // find root by Newton secant method - i = x0 = 0.0; - x1 = rate; - while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) { - rate = (y1 * x0 - y0 * x1) / (y1 - y0); - x0 = x1; - x1 = rate; - - if (Math.abs(rate) < FINANCIAL_PRECISION) { - y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv; - } else { - f = Math.exp(nper * Math.log(1 + rate)); - y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv; - } - - y0 = y1; - y1 = y; - ++i; - } - return rate; - } - - /** - * Excel does not support infinities and NaNs, rather, it gives a #NUM! error in these cases - * - * @throws EvaluationException (#NUM!) if result is NaN or Infinity - */ - static final void checkValue(double result) throws EvaluationException { - if (Double.isNaN(result) || Double.isInfinite(result)) { - throw new EvaluationException(ErrorEval.NUM_ERROR); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * Implements the Excel Rate function + */ +public class Rate implements Function { + private static final POILogger LOG = POILogFactory.getLogger(Rate.class); + + public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length < 3) { //First 3 parameters are mandatory + return ErrorEval.VALUE_INVALID; + } + + double periods, payment, present_val, future_val = 0, type = 0, estimate = 0.1, rate; + + try { + ValueEval v1 = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex); + ValueEval v2 = OperandResolver.getSingleValue(args[1], srcRowIndex, srcColumnIndex); + ValueEval v3 = OperandResolver.getSingleValue(args[2], srcRowIndex, srcColumnIndex); + ValueEval v4 = null; + if (args.length >= 4) + v4 = OperandResolver.getSingleValue(args[3], srcRowIndex, srcColumnIndex); + ValueEval v5 = null; + if (args.length >= 5) + v5 = OperandResolver.getSingleValue(args[4], srcRowIndex, srcColumnIndex); + ValueEval v6 = null; + if (args.length >= 6) + v6 = OperandResolver.getSingleValue(args[5], srcRowIndex, srcColumnIndex); + + periods = OperandResolver.coerceValueToDouble(v1); + payment = OperandResolver.coerceValueToDouble(v2); + present_val = OperandResolver.coerceValueToDouble(v3); + if (args.length >= 4) + future_val = OperandResolver.coerceValueToDouble(v4); + if (args.length >= 5) + type = OperandResolver.coerceValueToDouble(v5); + if (args.length >= 6) + estimate = OperandResolver.coerceValueToDouble(v6); + rate = calculateRate(periods, payment, present_val, future_val, type, estimate) ; + + checkValue(rate); + } catch (EvaluationException e) { + LOG.log(POILogger.ERROR, "Can't evaluate rate function", e); + return e.getErrorEval(); + } + + return new NumberEval( rate ) ; + } + + private double calculateRate(double nper, double pmt, double pv, double fv, double type, double guess) { + //FROM MS http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx + int FINANCIAL_MAX_ITERATIONS = 20;//Bet accuracy with 128 + double FINANCIAL_PRECISION = 0.0000001;//1.0e-8 + + double y, y0, y1, x0, x1 = 0, f = 0, i = 0; + double rate = guess; + if (Math.abs(rate) < FINANCIAL_PRECISION) { + y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv; + } else { + f = Math.exp(nper * Math.log(1 + rate)); + y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv; + } + y0 = pv + pmt * nper + fv; + y1 = pv * f + pmt * (1 / rate + type) * (f - 1) + fv; + + // find root by Newton secant method + i = x0 = 0.0; + x1 = rate; + while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) { + rate = (y1 * x0 - y0 * x1) / (y1 - y0); + x0 = x1; + x1 = rate; + + if (Math.abs(rate) < FINANCIAL_PRECISION) { + y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv; + } else { + f = Math.exp(nper * Math.log(1 + rate)); + y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv; + } + + y0 = y1; + y1 = y; + ++i; + } + return rate; + } + + /** + * Excel does not support infinities and NaNs, rather, it gives a #NUM! error in these cases + * + * @throws EvaluationException (#NUM!) if result is NaN or Infinity + */ + static final void checkValue(double result) throws EvaluationException { + if (Double.isNaN(result) || Double.isInfinite(result)) { + throw new EvaluationException(ErrorEval.NUM_ERROR); + } + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Rept.java b/src/java/org/apache/poi/ss/formula/functions/Rept.java index 0c8a5f876e..83e43a95fd 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Rept.java +++ b/src/java/org/apache/poi/ss/formula/functions/Rept.java @@ -1,74 +1,74 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Implementation for Excel REPT () function.

- *

- * Syntax:
REPT (text,number_times )
- *

- * Repeats text a given number of times. Use REPT to fill a cell with a number of instances of a text string. - * - * text : text The text that you want to repeat. - * number_times: A positive number specifying the number of times to repeat text. - * - * If number_times is 0 (zero), REPT returns "" (empty text). - * If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point. - * - * The result of the REPT function cannot be longer than 32,767 characters, or REPT returns #VALUE!. - * - * @author cedric dot walter @ gmail dot com - */ -public class Rept extends Fixed2ArgFunction { - - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval text, ValueEval number_times) { - - ValueEval veText1; - try { - veText1 = OperandResolver.getSingleValue(text, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - String strText1 = OperandResolver.coerceValueToString(veText1); - double numberOfTime = 0; - try { - numberOfTime = OperandResolver.coerceValueToDouble(number_times); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - - int numberOfTimeInt = (int)numberOfTime; - StringBuffer strb = new StringBuffer(strText1.length() * numberOfTimeInt); - for(int i = 0; i < numberOfTimeInt; i++) { - strb.append(strText1); - } - - if (strb.toString().length() > 32767) { - return ErrorEval.VALUE_INVALID; - } - - return new StringEval(strb.toString()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Implementation for Excel REPT () function.

+ *

+ * Syntax:
REPT (text,number_times )
+ *

+ * Repeats text a given number of times. Use REPT to fill a cell with a number of instances of a text string. + * + * text : text The text that you want to repeat. + * number_times: A positive number specifying the number of times to repeat text. + * + * If number_times is 0 (zero), REPT returns "" (empty text). + * If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point. + * + * The result of the REPT function cannot be longer than 32,767 characters, or REPT returns #VALUE!. + * + * @author cedric dot walter @ gmail dot com + */ +public class Rept extends Fixed2ArgFunction { + + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval text, ValueEval number_times) { + + ValueEval veText1; + try { + veText1 = OperandResolver.getSingleValue(text, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + String strText1 = OperandResolver.coerceValueToString(veText1); + double numberOfTime = 0; + try { + numberOfTime = OperandResolver.coerceValueToDouble(number_times); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + + int numberOfTimeInt = (int)numberOfTime; + StringBuffer strb = new StringBuffer(strText1.length() * numberOfTimeInt); + for(int i = 0; i < numberOfTimeInt; i++) { + strb.append(strText1); + } + + if (strb.toString().length() > 32767) { + return ErrorEval.VALUE_INVALID; + } + + return new StringEval(strb.toString()); + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/Roman.java b/src/java/org/apache/poi/ss/formula/functions/Roman.java index 45b400e2f7..ff06443f9e 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Roman.java +++ b/src/java/org/apache/poi/ss/formula/functions/Roman.java @@ -1,150 +1,150 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Implementation for Excel WeekNum() function.

- *

- * Syntax:
WeekNum (Serial_num,Return_type)
- *

- * Returns a number that indicates where the week falls numerically within a year. - *

- *

- * Serial_num is a date within the week. Dates should be entered by using the DATE function, - * or as results of other formulas or functions. For example, use DATE(2008,5,23) - * for the 23rd day of May, 2008. Problems can occur if dates are entered as text. - * Return_type is a number that determines on which day the week begins. The default is 1. - * 1 Week begins on Sunday. Weekdays are numbered 1 through 7. - * 2 Week begins on Monday. Weekdays are numbered 1 through 7. - * - * @author cedric dot walter @ gmail dot com - */ -public class Roman extends Fixed2ArgFunction { - - //M (1000), CM (900), D (500), CD (400), C (100), XC (90), L (50), XL (40), X (10), IX (9), V (5), IV (4) and I (1). - public static final int[] VALUES = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; - public static final String[] ROMAN = new String[] - {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; - - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE, ValueEval formVE) { - int number = 0; - try { - ValueEval ve = OperandResolver.getSingleValue(numberVE, srcRowIndex, srcColumnIndex); - number = OperandResolver.coerceValueToInt(ve); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - if (number < 0) { - return ErrorEval.VALUE_INVALID; - } - if (number > 3999) { - return ErrorEval.VALUE_INVALID; - } - if (number == 0) { - return new StringEval(""); - } - - int form = 0; - try { - ValueEval ve = OperandResolver.getSingleValue(formVE, srcRowIndex, srcColumnIndex); - form = OperandResolver.coerceValueToInt(ve); - } catch (EvaluationException e) { - return ErrorEval.NUM_ERROR; - } - - if (form > 4 || form < 0) { - return ErrorEval.VALUE_INVALID; - } - - String result = this.integerToRoman(number); - - if (form == 0) { - return new StringEval(result); - } - - return new StringEval(makeConcise(result, form)); - } - - /** - * Classic conversion. - * - * @param number - */ - private String integerToRoman(int number) { - StringBuilder result = new StringBuilder(); - for (int i = 0; i < 13; i++) { - while (number >= VALUES[i]) { - number -= VALUES[i]; - result.append(ROMAN[i]); - } - } - return result.toString(); - } - - /** - * Use conversion rule to factor some parts and make them more concise - * - * @param result - * @param form - */ - public String makeConcise(String result, int form) { - if (form > 0) { - result = result.replaceAll("XLV", "VL"); //45 - result = result.replaceAll("XCV", "VC"); //95 - result = result.replaceAll("CDL", "LD"); //450 - result = result.replaceAll("CML", "LM"); //950 - result = result.replaceAll("CMVC", "LMVL"); //995 - } - if (form == 1) { - result = result.replaceAll("CDXC", "LDXL"); //490 - result = result.replaceAll("CDVC", "LDVL"); //495 - result = result.replaceAll("CMXC", "LMXL"); //990 - result = result.replaceAll("XCIX", "VCIV"); //99 - result = result.replaceAll("XLIX", "VLIV"); //49 - } - if (form > 1) { - result = result.replaceAll("XLIX", "IL"); //49 - result = result.replaceAll("XCIX", "IC"); //99 - result = result.replaceAll("CDXC", "XD"); //490 - result = result.replaceAll("CDVC", "XDV"); //495 - result = result.replaceAll("CDIC", "XDIX"); //499 - result = result.replaceAll("LMVL", "XMV"); //995 - result = result.replaceAll("CMIC", "XMIX"); //999 - result = result.replaceAll("CMXC", "XM"); // 990 - } - if (form > 2) { - result = result.replaceAll("XDV", "VD"); //495 - result = result.replaceAll("XDIX", "VDIV"); //499 - result = result.replaceAll("XMV", "VM"); // 995 - result = result.replaceAll("XMIX", "VMIV"); //999 - } - if (form == 4) { - result = result.replaceAll("VDIV", "ID"); //499 - result = result.replaceAll("VMIV", "IM"); //999 - } - - return result; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Implementation for Excel WeekNum() function.

+ *

+ * Syntax:
WeekNum (Serial_num,Return_type)
+ *

+ * Returns a number that indicates where the week falls numerically within a year. + *

+ *

+ * Serial_num is a date within the week. Dates should be entered by using the DATE function, + * or as results of other formulas or functions. For example, use DATE(2008,5,23) + * for the 23rd day of May, 2008. Problems can occur if dates are entered as text. + * Return_type is a number that determines on which day the week begins. The default is 1. + * 1 Week begins on Sunday. Weekdays are numbered 1 through 7. + * 2 Week begins on Monday. Weekdays are numbered 1 through 7. + * + * @author cedric dot walter @ gmail dot com + */ +public class Roman extends Fixed2ArgFunction { + + //M (1000), CM (900), D (500), CD (400), C (100), XC (90), L (50), XL (40), X (10), IX (9), V (5), IV (4) and I (1). + public static final int[] VALUES = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + public static final String[] ROMAN = new String[] + {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE, ValueEval formVE) { + int number = 0; + try { + ValueEval ve = OperandResolver.getSingleValue(numberVE, srcRowIndex, srcColumnIndex); + number = OperandResolver.coerceValueToInt(ve); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + if (number < 0) { + return ErrorEval.VALUE_INVALID; + } + if (number > 3999) { + return ErrorEval.VALUE_INVALID; + } + if (number == 0) { + return new StringEval(""); + } + + int form = 0; + try { + ValueEval ve = OperandResolver.getSingleValue(formVE, srcRowIndex, srcColumnIndex); + form = OperandResolver.coerceValueToInt(ve); + } catch (EvaluationException e) { + return ErrorEval.NUM_ERROR; + } + + if (form > 4 || form < 0) { + return ErrorEval.VALUE_INVALID; + } + + String result = this.integerToRoman(number); + + if (form == 0) { + return new StringEval(result); + } + + return new StringEval(makeConcise(result, form)); + } + + /** + * Classic conversion. + * + * @param number + */ + private String integerToRoman(int number) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < 13; i++) { + while (number >= VALUES[i]) { + number -= VALUES[i]; + result.append(ROMAN[i]); + } + } + return result.toString(); + } + + /** + * Use conversion rule to factor some parts and make them more concise + * + * @param result + * @param form + */ + public String makeConcise(String result, int form) { + if (form > 0) { + result = result.replaceAll("XLV", "VL"); //45 + result = result.replaceAll("XCV", "VC"); //95 + result = result.replaceAll("CDL", "LD"); //450 + result = result.replaceAll("CML", "LM"); //950 + result = result.replaceAll("CMVC", "LMVL"); //995 + } + if (form == 1) { + result = result.replaceAll("CDXC", "LDXL"); //490 + result = result.replaceAll("CDVC", "LDVL"); //495 + result = result.replaceAll("CMXC", "LMXL"); //990 + result = result.replaceAll("XCIX", "VCIV"); //99 + result = result.replaceAll("XLIX", "VLIV"); //49 + } + if (form > 1) { + result = result.replaceAll("XLIX", "IL"); //49 + result = result.replaceAll("XCIX", "IC"); //99 + result = result.replaceAll("CDXC", "XD"); //490 + result = result.replaceAll("CDVC", "XDV"); //495 + result = result.replaceAll("CDIC", "XDIX"); //499 + result = result.replaceAll("LMVL", "XMV"); //995 + result = result.replaceAll("CMIC", "XMIX"); //999 + result = result.replaceAll("CMXC", "XM"); // 990 + } + if (form > 2) { + result = result.replaceAll("XDV", "VD"); //495 + result = result.replaceAll("XDIX", "VDIV"); //499 + result = result.replaceAll("XMV", "VM"); // 995 + result = result.replaceAll("XMIX", "VMIV"); //999 + } + if (form == 4) { + result = result.replaceAll("VDIV", "ID"); //499 + result = result.replaceAll("VMIV", "IM"); //999 + } + + return result; + } +} diff --git a/src/java/org/apache/poi/ss/formula/functions/WeekNum.java b/src/java/org/apache/poi/ss/formula/functions/WeekNum.java index 888ad11a03..09542312a5 100644 --- a/src/java/org/apache/poi/ss/formula/functions/WeekNum.java +++ b/src/java/org/apache/poi/ss/formula/functions/WeekNum.java @@ -1,89 +1,89 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Calendar; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.OperandResolver; -import org.apache.poi.ss.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.util.LocaleUtil; - -/** - * Implementation for Excel WeekNum() function.

- *

- * Syntax:
WeekNum (Serial_num,Return_type)
- *

- * Returns a number that indicates where the week falls numerically within a year. - *

- *

- * Serial_num is a date within the week. Dates should be entered by using the DATE function, - * or as results of other formulas or functions. For example, use DATE(2008,5,23) - * for the 23rd day of May, 2008. Problems can occur if dates are entered as text. - * Return_type is a number that determines on which day the week begins. The default is 1. - * 1 Week begins on Sunday. Weekdays are numbered 1 through 7. - * 2 Week begins on Monday. Weekdays are numbered 1 through 7. - */ -public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction { - public static final FreeRefFunction instance = new WeekNum(); - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval serialNumVE, ValueEval returnTypeVE) { - double serialNum = 0.0; - try { - serialNum = NumericFunction.singleOperandEvaluate(serialNumVE, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return ErrorEval.VALUE_INVALID; - } - Calendar serialNumCalendar = LocaleUtil.getLocaleCalendar(); - serialNumCalendar.setTime(DateUtil.getJavaDate(serialNum, false)); - - int returnType = 0; - try { - ValueEval ve = OperandResolver.getSingleValue(returnTypeVE, srcRowIndex, srcColumnIndex); - returnType = OperandResolver.coerceValueToInt(ve); - } catch (EvaluationException e) { - return ErrorEval.NUM_ERROR; - } - - if (returnType != 1 && returnType != 2) { - return ErrorEval.NUM_ERROR; - } - - return new NumberEval(this.getWeekNo(serialNumCalendar, returnType)); - } - - public int getWeekNo(Calendar cal, int weekStartOn) { - if (weekStartOn == 1) { - cal.setFirstDayOfWeek(Calendar.SUNDAY); - } else { - cal.setFirstDayOfWeek(Calendar.MONDAY); - } - return cal.get(Calendar.WEEK_OF_YEAR); - } - - public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { - if (args.length == 2) { - return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); - } - return ErrorEval.VALUE_INVALID; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Calendar; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.OperandResolver; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.util.LocaleUtil; + +/** + * Implementation for Excel WeekNum() function.

+ *

+ * Syntax:
WeekNum (Serial_num,Return_type)
+ *

+ * Returns a number that indicates where the week falls numerically within a year. + *

+ *

+ * Serial_num is a date within the week. Dates should be entered by using the DATE function, + * or as results of other formulas or functions. For example, use DATE(2008,5,23) + * for the 23rd day of May, 2008. Problems can occur if dates are entered as text. + * Return_type is a number that determines on which day the week begins. The default is 1. + * 1 Week begins on Sunday. Weekdays are numbered 1 through 7. + * 2 Week begins on Monday. Weekdays are numbered 1 through 7. + */ +public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction { + public static final FreeRefFunction instance = new WeekNum(); + + public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval serialNumVE, ValueEval returnTypeVE) { + double serialNum = 0.0; + try { + serialNum = NumericFunction.singleOperandEvaluate(serialNumVE, srcRowIndex, srcColumnIndex); + } catch (EvaluationException e) { + return ErrorEval.VALUE_INVALID; + } + Calendar serialNumCalendar = LocaleUtil.getLocaleCalendar(); + serialNumCalendar.setTime(DateUtil.getJavaDate(serialNum, false)); + + int returnType = 0; + try { + ValueEval ve = OperandResolver.getSingleValue(returnTypeVE, srcRowIndex, srcColumnIndex); + returnType = OperandResolver.coerceValueToInt(ve); + } catch (EvaluationException e) { + return ErrorEval.NUM_ERROR; + } + + if (returnType != 1 && returnType != 2) { + return ErrorEval.NUM_ERROR; + } + + return new NumberEval(this.getWeekNo(serialNumCalendar, returnType)); + } + + public int getWeekNo(Calendar cal, int weekStartOn) { + if (weekStartOn == 1) { + cal.setFirstDayOfWeek(Calendar.SUNDAY); + } else { + cal.setFirstDayOfWeek(Calendar.MONDAY); + } + return cal.get(Calendar.WEEK_OF_YEAR); + } + + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length == 2) { + return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0], args[1]); + } + return ErrorEval.VALUE_INVALID; + } +} diff --git a/src/java/org/apache/poi/ss/usermodel/AutoFilter.java b/src/java/org/apache/poi/ss/usermodel/AutoFilter.java index 82c7a439d0..2b8c2446c5 100644 --- a/src/java/org/apache/poi/ss/usermodel/AutoFilter.java +++ b/src/java/org/apache/poi/ss/usermodel/AutoFilter.java @@ -1,79 +1,79 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.usermodel; - -/** - * Represents autofiltering for the specified worksheet. - * - *

- * Filtering data is a quick and easy way to find and work with a subset of data in a range of cells or table. - * For example, you can filter to see only the values that you specify, filter to see the top or bottom values, - * or filter to quickly see duplicate values. - *

- * - * TODO YK: For now (Aug 2010) POI only supports setting a basic autofilter on a range of cells. - * In future, when we support more auto-filter functions like custom criteria, sort, etc. we will add - * corresponding methods to this interface. - */ -public interface AutoFilter { - /** - * Apply a custom filter - * - *

- * A custom AutoFilter specifies an operator and a value. - * There can be at most two customFilters specified, and in that case the parent element - * specifies whether the two conditions are joined by 'and' or 'or'. For any cells whose - * values do not meet the specified criteria, the corresponding rows shall be hidden from - * view when the filter is applied. - *

- * - *

- * Example: - *

-     *  AutoFilter filter = sheet.setAutoFilter(CellRangeAddress.valueOf("A1:F200"));
-     *  filter.applyFilter(0, FilterOperator.GreaterThanOrEqual", "0.2");
-     *  filter.applyFilter(1, FilterOperator.LessThanOrEqual"", "0.5");
-     * 
- *

- * - * @param columnIndex 0-based column index - * @param operator the operator to apply - * @param criteria top or bottom value used in the filter criteria. - * - * TODO YK: think how to combine AutoFilter with with DataValidationConstraint, they are really close relatives - * void applyFilter(int columnIndex, FilterOperator operator, String criteria); - */ - - - /** - * Apply a filter against a list of values - * - *

- * Example: - *

-     *  AutoFilter filter = sheet.setAutoFilter(CellRangeAddress.valueOf("A1:F200"));
-     *  filter.applyFilter(0, "apache", "poi", "java", "api");
-     * 
- *

- * - * @param columnIndex 0-based column index - * @param values the filter values - * - * void applyFilter(int columnIndex, String ... values); - */ - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.usermodel; + +/** + * Represents autofiltering for the specified worksheet. + * + *

+ * Filtering data is a quick and easy way to find and work with a subset of data in a range of cells or table. + * For example, you can filter to see only the values that you specify, filter to see the top or bottom values, + * or filter to quickly see duplicate values. + *

+ * + * TODO YK: For now (Aug 2010) POI only supports setting a basic autofilter on a range of cells. + * In future, when we support more auto-filter functions like custom criteria, sort, etc. we will add + * corresponding methods to this interface. + */ +public interface AutoFilter { + /** + * Apply a custom filter + * + *

+ * A custom AutoFilter specifies an operator and a value. + * There can be at most two customFilters specified, and in that case the parent element + * specifies whether the two conditions are joined by 'and' or 'or'. For any cells whose + * values do not meet the specified criteria, the corresponding rows shall be hidden from + * view when the filter is applied. + *

+ * + *

+ * Example: + *

+     *  AutoFilter filter = sheet.setAutoFilter(CellRangeAddress.valueOf("A1:F200"));
+     *  filter.applyFilter(0, FilterOperator.GreaterThanOrEqual", "0.2");
+     *  filter.applyFilter(1, FilterOperator.LessThanOrEqual"", "0.5");
+     * 
+ *

+ * + * @param columnIndex 0-based column index + * @param operator the operator to apply + * @param criteria top or bottom value used in the filter criteria. + * + * TODO YK: think how to combine AutoFilter with with DataValidationConstraint, they are really close relatives + * void applyFilter(int columnIndex, FilterOperator operator, String criteria); + */ + + + /** + * Apply a filter against a list of values + * + *

+ * Example: + *

+     *  AutoFilter filter = sheet.setAutoFilter(CellRangeAddress.valueOf("A1:F200"));
+     *  filter.applyFilter(0, "apache", "poi", "java", "api");
+     * 
+ *

+ * + * @param columnIndex 0-based column index + * @param values the filter values + * + * void applyFilter(int columnIndex, String ... values); + */ + +} diff --git a/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java b/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java index 949cc3d00e..da8aabdfa6 100644 --- a/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java @@ -1,258 +1,258 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -import org.apache.poi.util.Removal; - -/** - * High level representation for Border Formatting component - * of Conditional Formatting settings - */ -public interface BorderFormatting { - /** No border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#NONE} - */ - @Removal(version="3.17") - short BORDER_NONE = 0x0; - - /** Thin border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#THIN} - */ - @Removal(version="3.17") - short BORDER_THIN = 0x1; - - /** Medium border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM} - */ - @Removal(version="3.17") - short BORDER_MEDIUM = 0x2; - - /** dash border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASHED} - */ - @Removal(version="3.17") - short BORDER_DASHED = 0x3; - - /** dot border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#DOTTED} - */ - @Removal(version="3.17") - short BORDER_DOTTED = 0x4; - - /** Thick border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#THICK} - */ - @Removal(version="3.17") - short BORDER_THICK = 0x5; - - /** double-line border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#DOUBLE} - */ - @Removal(version="3.17") - short BORDER_DOUBLE = 0x6; - - /** hair-line border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#HAIR} - */ - @Removal(version="3.17") - short BORDER_HAIR = 0x7; - - /** Medium dashed border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASHED} - */ - @Removal(version="3.17") - short BORDER_MEDIUM_DASHED = 0x8; - - /** dash-dot border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT} - */ - @Removal(version="3.17") - short BORDER_DASH_DOT = 0x9; - - /** medium dash-dot border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT} - */ - @Removal(version="3.17") - short BORDER_MEDIUM_DASH_DOT = 0xA; - - /** dash-dot-dot border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT_DOT} - */ - @Removal(version="3.17") - short BORDER_DASH_DOT_DOT = 0xB; - - /** medium dash-dot-dot border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT_DOT} - */ - @Removal(version="3.17") - short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; - - /** slanted dash-dot border - * @deprecated 3.15 beta 2. Use {@link BorderStyle#SLANTED_DASH_DOT} - */ - @Removal(version="3.17") - short BORDER_SLANTED_DASH_DOT = 0xD; - - /** - * @deprecated POI 3.15. Use {@link #getBorderBottomEnum()}. - * This method will return an BorderStyle enum in the future. - */ - short getBorderBottom(); - /** @since POI 3.15 */ - BorderStyle getBorderBottomEnum(); - - /** - * @deprecated POI 3.15. Use {@link #getBorderDiagonalEnum()}. - * This method will return an BorderStyle enum in the future. - */ - short getBorderDiagonal(); - /** @since POI 3.15 */ - BorderStyle getBorderDiagonalEnum(); - - /** - * @deprecated POI 3.15. Use {@link #getBorderLeftEnum()}. - * This method will return an BorderStyle enum in the future. - */ - short getBorderLeft(); - /** @since POI 3.15 */ - BorderStyle getBorderLeftEnum(); - - /** - * @deprecated POI 3.15. Use {@link #getBorderRightEnum()}. - * This method will return an BorderStyle enum in the future. - */ - short getBorderRight(); - /** @since POI 3.15 */ - BorderStyle getBorderRightEnum(); - - /** - * @deprecated POI 3.15. Use {@link #getBorderTopEnum()}. - * This method will return an BorderStyle enum in the future. - */ - short getBorderTop(); - /** @since POI 3.15 */ - BorderStyle getBorderTopEnum(); - - - short getBottomBorderColor(); - Color getBottomBorderColorColor(); - - short getDiagonalBorderColor(); - Color getDiagonalBorderColorColor(); - - short getLeftBorderColor(); - Color getLeftBorderColorColor(); - - short getRightBorderColor(); - Color getRightBorderColorColor(); - - short getTopBorderColor(); - Color getTopBorderColorColor(); - - /** - * Set bottom border. - * - * @param border MUST be a BORDER_* constant - * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderBottom(BorderStyle)} - */ - void setBorderBottom(short border); - - /** - * Set bottom border. - * - * @param border - */ - void setBorderBottom(BorderStyle border); - - /** - * Set diagonal border. - * - * @param border MUST be a BORDER_* constant - * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderDiagonal(BorderStyle)} - */ - void setBorderDiagonal(short border); - - /** - * Set diagonal border. - * - * @param border - */ - void setBorderDiagonal(BorderStyle border); - - /** - * Set left border. - * - * @param border MUST be a BORDER_* constant - * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderLeft(BorderStyle)} - */ - void setBorderLeft(short border); - - /** - * Set left border. - * - * @param border - */ - void setBorderLeft(BorderStyle border); - - /** - * Set right border. - * - * @param border MUST be a BORDER_* constant - * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderRight(BorderStyle)} - */ - void setBorderRight(short border); - - /** - * Set right border. - * - * @param border - */ - void setBorderRight(BorderStyle border); - - /** - * Set top border. - * - * @param border MUST be a BORDER_* constant - * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderTop(BorderStyle)} - */ - void setBorderTop(short border); - - /** - * Set top border. - * - * @param border - */ - void setBorderTop(BorderStyle border); - - void setBottomBorderColor(short color); - void setBottomBorderColor(Color color); - - void setDiagonalBorderColor(short color); - void setDiagonalBorderColor(Color color); - - void setLeftBorderColor(short color); - void setLeftBorderColor(Color color); - - void setRightBorderColor(short color); - void setRightBorderColor(Color color); - - void setTopBorderColor(short color); - void setTopBorderColor(Color color); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import org.apache.poi.util.Removal; + +/** + * High level representation for Border Formatting component + * of Conditional Formatting settings + */ +public interface BorderFormatting { + /** No border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#NONE} + */ + @Removal(version="3.17") + short BORDER_NONE = 0x0; + + /** Thin border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#THIN} + */ + @Removal(version="3.17") + short BORDER_THIN = 0x1; + + /** Medium border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM} + */ + @Removal(version="3.17") + short BORDER_MEDIUM = 0x2; + + /** dash border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASHED} + */ + @Removal(version="3.17") + short BORDER_DASHED = 0x3; + + /** dot border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#DOTTED} + */ + @Removal(version="3.17") + short BORDER_DOTTED = 0x4; + + /** Thick border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#THICK} + */ + @Removal(version="3.17") + short BORDER_THICK = 0x5; + + /** double-line border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#DOUBLE} + */ + @Removal(version="3.17") + short BORDER_DOUBLE = 0x6; + + /** hair-line border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#HAIR} + */ + @Removal(version="3.17") + short BORDER_HAIR = 0x7; + + /** Medium dashed border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASHED} + */ + @Removal(version="3.17") + short BORDER_MEDIUM_DASHED = 0x8; + + /** dash-dot border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT} + */ + @Removal(version="3.17") + short BORDER_DASH_DOT = 0x9; + + /** medium dash-dot border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT} + */ + @Removal(version="3.17") + short BORDER_MEDIUM_DASH_DOT = 0xA; + + /** dash-dot-dot border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT_DOT} + */ + @Removal(version="3.17") + short BORDER_DASH_DOT_DOT = 0xB; + + /** medium dash-dot-dot border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT_DOT} + */ + @Removal(version="3.17") + short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; + + /** slanted dash-dot border + * @deprecated 3.15 beta 2. Use {@link BorderStyle#SLANTED_DASH_DOT} + */ + @Removal(version="3.17") + short BORDER_SLANTED_DASH_DOT = 0xD; + + /** + * @deprecated POI 3.15. Use {@link #getBorderBottomEnum()}. + * This method will return an BorderStyle enum in the future. + */ + short getBorderBottom(); + /** @since POI 3.15 */ + BorderStyle getBorderBottomEnum(); + + /** + * @deprecated POI 3.15. Use {@link #getBorderDiagonalEnum()}. + * This method will return an BorderStyle enum in the future. + */ + short getBorderDiagonal(); + /** @since POI 3.15 */ + BorderStyle getBorderDiagonalEnum(); + + /** + * @deprecated POI 3.15. Use {@link #getBorderLeftEnum()}. + * This method will return an BorderStyle enum in the future. + */ + short getBorderLeft(); + /** @since POI 3.15 */ + BorderStyle getBorderLeftEnum(); + + /** + * @deprecated POI 3.15. Use {@link #getBorderRightEnum()}. + * This method will return an BorderStyle enum in the future. + */ + short getBorderRight(); + /** @since POI 3.15 */ + BorderStyle getBorderRightEnum(); + + /** + * @deprecated POI 3.15. Use {@link #getBorderTopEnum()}. + * This method will return an BorderStyle enum in the future. + */ + short getBorderTop(); + /** @since POI 3.15 */ + BorderStyle getBorderTopEnum(); + + + short getBottomBorderColor(); + Color getBottomBorderColorColor(); + + short getDiagonalBorderColor(); + Color getDiagonalBorderColorColor(); + + short getLeftBorderColor(); + Color getLeftBorderColorColor(); + + short getRightBorderColor(); + Color getRightBorderColorColor(); + + short getTopBorderColor(); + Color getTopBorderColorColor(); + + /** + * Set bottom border. + * + * @param border MUST be a BORDER_* constant + * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderBottom(BorderStyle)} + */ + void setBorderBottom(short border); + + /** + * Set bottom border. + * + * @param border + */ + void setBorderBottom(BorderStyle border); + + /** + * Set diagonal border. + * + * @param border MUST be a BORDER_* constant + * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderDiagonal(BorderStyle)} + */ + void setBorderDiagonal(short border); + + /** + * Set diagonal border. + * + * @param border + */ + void setBorderDiagonal(BorderStyle border); + + /** + * Set left border. + * + * @param border MUST be a BORDER_* constant + * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderLeft(BorderStyle)} + */ + void setBorderLeft(short border); + + /** + * Set left border. + * + * @param border + */ + void setBorderLeft(BorderStyle border); + + /** + * Set right border. + * + * @param border MUST be a BORDER_* constant + * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderRight(BorderStyle)} + */ + void setBorderRight(short border); + + /** + * Set right border. + * + * @param border + */ + void setBorderRight(BorderStyle border); + + /** + * Set top border. + * + * @param border MUST be a BORDER_* constant + * @deprecated 3.15 beta 2. Use {@link BorderFormatting#setBorderTop(BorderStyle)} + */ + void setBorderTop(short border); + + /** + * Set top border. + * + * @param border + */ + void setBorderTop(BorderStyle border); + + void setBottomBorderColor(short color); + void setBottomBorderColor(Color color); + + void setDiagonalBorderColor(short color); + void setDiagonalBorderColor(Color color); + + void setLeftBorderColor(short color); + void setLeftBorderColor(Color color); + + void setRightBorderColor(short color); + void setRightBorderColor(Color color); + + void setTopBorderColor(short color); + void setTopBorderColor(Color color); +} diff --git a/src/java/org/apache/poi/ss/usermodel/ColorScaleFormatting.java b/src/java/org/apache/poi/ss/usermodel/ColorScaleFormatting.java index 4d6f58b580..8bdbb07355 100644 --- a/src/java/org/apache/poi/ss/usermodel/ColorScaleFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/ColorScaleFormatting.java @@ -1,66 +1,66 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -import org.apache.poi.hssf.record.cf.Threshold; - -/** - * High level representation for the Color Scale / Colour Scale / - * Color Gradient Formatting component of Conditional Formatting settings - */ -public interface ColorScaleFormatting { - /** - * How many control points should be used to map - * the colours? Normally 2 or 3 - */ - int getNumControlPoints(); - /** - * Sets the number of control points to use to map - * the colours. Should normally be 2 or 3. - *

After updating, you need to ensure that the - * {@link Threshold} count and Color count match - */ - void setNumControlPoints(int num); - - /** - * Gets the list of colours that are interpolated - * between. - */ - Color[] getColors(); - /** - * Sets the list of colours that are interpolated - * between. The number must match {@link #getNumControlPoints()} - */ - void setColors(Color[] colors); - - /** - * Gets the list of thresholds - */ - ConditionalFormattingThreshold[] getThresholds(); - /** - * Sets the of thresholds. The number must match - * {@link #getNumControlPoints()} - */ - void setThresholds(ConditionalFormattingThreshold[] thresholds); - /** - * Creates a new, empty Threshold - */ - ConditionalFormattingThreshold createThreshold(); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import org.apache.poi.hssf.record.cf.Threshold; + +/** + * High level representation for the Color Scale / Colour Scale / + * Color Gradient Formatting component of Conditional Formatting settings + */ +public interface ColorScaleFormatting { + /** + * How many control points should be used to map + * the colours? Normally 2 or 3 + */ + int getNumControlPoints(); + /** + * Sets the number of control points to use to map + * the colours. Should normally be 2 or 3. + *

After updating, you need to ensure that the + * {@link Threshold} count and Color count match + */ + void setNumControlPoints(int num); + + /** + * Gets the list of colours that are interpolated + * between. + */ + Color[] getColors(); + /** + * Sets the list of colours that are interpolated + * between. The number must match {@link #getNumControlPoints()} + */ + void setColors(Color[] colors); + + /** + * Gets the list of thresholds + */ + ConditionalFormattingThreshold[] getThresholds(); + /** + * Sets the of thresholds. The number must match + * {@link #getNumControlPoints()} + */ + void setThresholds(ConditionalFormattingThreshold[] thresholds); + /** + * Creates a new, empty Threshold + */ + ConditionalFormattingThreshold createThreshold(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java b/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java index 7eee789037..80f70d315a 100644 --- a/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java +++ b/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java @@ -1,70 +1,70 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -/** - * The conditional format operators used for "Highlight Cells That Contain..." rules. - *

- * For example, "highlight cells that begin with "M2" and contain "Mountain Gear". - *

- */ -public final class ComparisonOperator { - public static final byte NO_COMPARISON = 0; - - /** - * 'Between' operator - */ - public static final byte BETWEEN = 1; - - /** - * 'Not between' operator - */ - public static final byte NOT_BETWEEN = 2; - - /** - * 'Equal to' operator - */ - public static final byte EQUAL = 3; - - /** - * 'Not equal to' operator - */ - public static final byte NOT_EQUAL = 4; - - /** - * 'Greater than' operator - */ - public static final byte GT = 5; - - /** - * 'Less than' operator - */ - public static final byte LT = 6; - - /** - * 'Greater than or equal to' operator - */ - public static final byte GE = 7; - - /** - * 'Less than or equal to' operator - */ - public static final byte LE = 8; -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * The conditional format operators used for "Highlight Cells That Contain..." rules. + *

+ * For example, "highlight cells that begin with "M2" and contain "Mountain Gear". + *

+ */ +public final class ComparisonOperator { + public static final byte NO_COMPARISON = 0; + + /** + * 'Between' operator + */ + public static final byte BETWEEN = 1; + + /** + * 'Not between' operator + */ + public static final byte NOT_BETWEEN = 2; + + /** + * 'Equal to' operator + */ + public static final byte EQUAL = 3; + + /** + * 'Not equal to' operator + */ + public static final byte NOT_EQUAL = 4; + + /** + * 'Greater than' operator + */ + public static final byte GT = 5; + + /** + * 'Less than' operator + */ + public static final byte LT = 6; + + /** + * 'Greater than or equal to' operator + */ + public static final byte GE = 7; + + /** + * 'Less than or equal to' operator + */ + public static final byte LE = 8; +} diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionType.java b/src/java/org/apache/poi/ss/usermodel/ConditionType.java index 8bd61410e0..ab3653af33 100644 --- a/src/java/org/apache/poi/ss/usermodel/ConditionType.java +++ b/src/java/org/apache/poi/ss/usermodel/ConditionType.java @@ -1,92 +1,92 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -import java.util.HashMap; -import java.util.Map; - -/** - * Represents a type of a conditional formatting rule - */ -public class ConditionType { - private static Map lookup = new HashMap(); - - /** - * This conditional formatting rule compares a cell value - * to a formula calculated result, using an operator - */ - public static final ConditionType CELL_VALUE_IS = - new ConditionType(1, "cellIs"); - - /** - * This conditional formatting rule contains a formula to evaluate. - * When the formula result is true, the cell is highlighted. - */ - public static final ConditionType FORMULA = - new ConditionType(2, "expression"); - - /** - * This conditional formatting rule contains a color scale, - * with the cell background set according to a gradient. - */ - public static final ConditionType COLOR_SCALE = - new ConditionType(3, "colorScale"); - - /** - * This conditional formatting rule sets a data bar, with the - * cell populated with bars based on their values - */ - public static final ConditionType DATA_BAR = - new ConditionType(4, "dataBar"); - - /** - * This conditional formatting rule that files the values - */ - public static final ConditionType FILTER = - new ConditionType(5, null); - - /** - * This conditional formatting rule sets a data bar, with the - * cell populated with bars based on their values - */ - public static final ConditionType ICON_SET = - new ConditionType(6, "iconSet"); - - - public final byte id; - public final String type; - - public String toString() { - return id + " - " + type; - } - - - public static ConditionType forId(byte id) { - return forId((int)id); - } - public static ConditionType forId(int id) { - return lookup.get(id); - } - - private ConditionType(int id, String type) { - this.id = (byte)id; this.type = type; - lookup.put(id, this); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import java.util.HashMap; +import java.util.Map; + +/** + * Represents a type of a conditional formatting rule + */ +public class ConditionType { + private static Map lookup = new HashMap(); + + /** + * This conditional formatting rule compares a cell value + * to a formula calculated result, using an operator + */ + public static final ConditionType CELL_VALUE_IS = + new ConditionType(1, "cellIs"); + + /** + * This conditional formatting rule contains a formula to evaluate. + * When the formula result is true, the cell is highlighted. + */ + public static final ConditionType FORMULA = + new ConditionType(2, "expression"); + + /** + * This conditional formatting rule contains a color scale, + * with the cell background set according to a gradient. + */ + public static final ConditionType COLOR_SCALE = + new ConditionType(3, "colorScale"); + + /** + * This conditional formatting rule sets a data bar, with the + * cell populated with bars based on their values + */ + public static final ConditionType DATA_BAR = + new ConditionType(4, "dataBar"); + + /** + * This conditional formatting rule that files the values + */ + public static final ConditionType FILTER = + new ConditionType(5, null); + + /** + * This conditional formatting rule sets a data bar, with the + * cell populated with bars based on their values + */ + public static final ConditionType ICON_SET = + new ConditionType(6, "iconSet"); + + + public final byte id; + public final String type; + + public String toString() { + return id + " - " + type; + } + + + public static ConditionType forId(byte id) { + return forId((int)id); + } + public static ConditionType forId(int id) { + return lookup.get(id); + } + + private ConditionType(int id, String type) { + this.id = (byte)id; this.type = type; + lookup.put(id, this); + } +} diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java b/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java index 09d63a407d..d7789e14ea 100644 --- a/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java @@ -1,117 +1,117 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -import org.apache.poi.ss.util.CellRangeAddress; - -/** - * The ConditionalFormatting class encapsulates all settings of Conditional Formatting. - * - * The class can be used - * - *
    - *
  • - * to make a copy ConditionalFormatting settings. - *
  • - * - * - * For example: - *
    - * ConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
    - * newSheet.addConditionalFormatting(cf);
    - * 
    - * - *
  • - * or to modify existing Conditional Formatting settings (formatting regions and/or rules). - *
  • - *
- * - * Use {@link org.apache.poi.ss.usermodel.Sheet#getSheetConditionalFormatting()} - * to get access to an instance of this class. - *

- * To create a new Conditional Formatting set use the following approach: - * - *

- *
- * // Define a Conditional Formatting rule, which triggers formatting
- * // when cell's value is greater or equal than 100.0 and
- * // applies patternFormatting defined below.
- * ConditionalFormattingRule rule = sheet.createConditionalFormattingRule(
- *     ComparisonOperator.GE,
- *     "100.0", // 1st formula
- *     null     // 2nd formula is not used for comparison operator GE
- * );
- *
- * // Create pattern with red background
- * PatternFormatting patternFmt = rule.cretePatternFormatting();
- * patternFormatting.setFillBackgroundColor(IndexedColor.RED.getIndex());
- *
- * // Define a region containing first column
- * Region [] regions =
- * {
- *     new Region(1,(short)1,-1,(short)1)
- * };
- *
- * // Apply Conditional Formatting rule defined above to the regions
- * sheet.addConditionalFormatting(regions, rule);
- * 
- */ -public interface ConditionalFormatting { - - /** - * @return array of CellRangeAddresss. Never null - */ - CellRangeAddress[] getFormattingRanges(); - - /** - * Sets the cell ranges the rule conditional formatting must be applied to. - * @param ranges non-null array of CellRangeAddresss - */ - void setFormattingRanges(CellRangeAddress[] ranges); - - /** - * Replaces an existing Conditional Formatting rule at position idx. - * Excel pre-2007 allows to create up to 3 Conditional Formatting rules, - * 2007 and later allow unlimited numbers. - * This method can be useful to modify existing Conditional Formatting rules. - * - * @param idx position of the rule. Should be between 0 and 2 for Excel before 2007, otherwise 0+. - * @param cfRule - Conditional Formatting rule - */ - void setRule(int idx, ConditionalFormattingRule cfRule); - - /** - * Add a Conditional Formatting rule. - * Excel pre-2007 allows to create up to 3 Conditional Formatting rules. - * - * @param cfRule - Conditional Formatting rule - */ - void addRule(ConditionalFormattingRule cfRule); - - /** - * @return the Conditional Formatting rule at position idx. - */ - ConditionalFormattingRule getRule(int idx); - - /** - * @return number of Conditional Formatting rules. - */ - int getNumberOfRules(); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import org.apache.poi.ss.util.CellRangeAddress; + +/** + * The ConditionalFormatting class encapsulates all settings of Conditional Formatting. + * + * The class can be used + * + *
    + *
  • + * to make a copy ConditionalFormatting settings. + *
  • + * + * + * For example: + *
    + * ConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
    + * newSheet.addConditionalFormatting(cf);
    + * 
    + * + *
  • + * or to modify existing Conditional Formatting settings (formatting regions and/or rules). + *
  • + *
+ * + * Use {@link org.apache.poi.ss.usermodel.Sheet#getSheetConditionalFormatting()} + * to get access to an instance of this class. + *

+ * To create a new Conditional Formatting set use the following approach: + * + *

+ *
+ * // Define a Conditional Formatting rule, which triggers formatting
+ * // when cell's value is greater or equal than 100.0 and
+ * // applies patternFormatting defined below.
+ * ConditionalFormattingRule rule = sheet.createConditionalFormattingRule(
+ *     ComparisonOperator.GE,
+ *     "100.0", // 1st formula
+ *     null     // 2nd formula is not used for comparison operator GE
+ * );
+ *
+ * // Create pattern with red background
+ * PatternFormatting patternFmt = rule.cretePatternFormatting();
+ * patternFormatting.setFillBackgroundColor(IndexedColor.RED.getIndex());
+ *
+ * // Define a region containing first column
+ * Region [] regions =
+ * {
+ *     new Region(1,(short)1,-1,(short)1)
+ * };
+ *
+ * // Apply Conditional Formatting rule defined above to the regions
+ * sheet.addConditionalFormatting(regions, rule);
+ * 
+ */ +public interface ConditionalFormatting { + + /** + * @return array of CellRangeAddresss. Never null + */ + CellRangeAddress[] getFormattingRanges(); + + /** + * Sets the cell ranges the rule conditional formatting must be applied to. + * @param ranges non-null array of CellRangeAddresss + */ + void setFormattingRanges(CellRangeAddress[] ranges); + + /** + * Replaces an existing Conditional Formatting rule at position idx. + * Excel pre-2007 allows to create up to 3 Conditional Formatting rules, + * 2007 and later allow unlimited numbers. + * This method can be useful to modify existing Conditional Formatting rules. + * + * @param idx position of the rule. Should be between 0 and 2 for Excel before 2007, otherwise 0+. + * @param cfRule - Conditional Formatting rule + */ + void setRule(int idx, ConditionalFormattingRule cfRule); + + /** + * Add a Conditional Formatting rule. + * Excel pre-2007 allows to create up to 3 Conditional Formatting rules. + * + * @param cfRule - Conditional Formatting rule + */ + void addRule(ConditionalFormattingRule cfRule); + + /** + * @return the Conditional Formatting rule at position idx. + */ + ConditionalFormattingRule getRule(int idx); + + /** + * @return number of Conditional Formatting rules. + */ + int getNumberOfRules(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java index 28f5d2258b..635aaa21f4 100644 --- a/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java +++ b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java @@ -1,122 +1,122 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -/** - * Represents a description of a conditional formatting rule - */ -public interface ConditionalFormattingRule { - /** - * Create a new border formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - border formatting object, never returns null. - */ - BorderFormatting createBorderFormatting(); - - /** - * @return - border formatting object if defined, null otherwise - */ - BorderFormatting getBorderFormatting(); - - /** - * Create a new font formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - font formatting object, never returns null. - */ - FontFormatting createFontFormatting(); - - /** - * @return - font formatting object if defined, null otherwise - */ - FontFormatting getFontFormatting(); - - /** - * Create a new pattern formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - pattern formatting object, never returns null. - */ - PatternFormatting createPatternFormatting(); - - /** - * @return - pattern formatting object if defined, null otherwise - */ - PatternFormatting getPatternFormatting(); - - /** - * @return - databar / data-bar formatting object if defined, null otherwise - */ - DataBarFormatting getDataBarFormatting(); - - /** - * @return - icon / multi-state formatting object if defined, null otherwise - */ - IconMultiStateFormatting getMultiStateFormatting(); - - /** - * @return color scale / color grate formatting object if defined, null otherwise - */ - ColorScaleFormatting getColorScaleFormatting(); - - /** - * Type of conditional formatting rule. - * - * @return the type of condition - */ - ConditionType getConditionType(); - - /** - * The comparison function used when the type of conditional formatting is set to - * {@link ConditionType#CELL_VALUE_IS} - *

- * MUST be a constant from {@link ComparisonOperator} - *

- * - * @return the conditional format operator - */ - byte getComparisonOperation(); - - /** - * The formula used to evaluate the first operand for the conditional formatting rule. - *

- * If the condition type is {@link ConditionType#CELL_VALUE_IS}, - * this field is the first operand of the comparison. - * If type is {@link ConditionType#FORMULA}, this formula is used - * to determine if the conditional formatting is applied. - *

- *

- * If comparison type is {@link ConditionType#FORMULA} the formula MUST be a Boolean function - *

- * - * @return the first formula - */ - String getFormula1(); - - /** - * The formula used to evaluate the second operand of the comparison when - * comparison type is {@link ConditionType#CELL_VALUE_IS} and operator - * is either {@link ComparisonOperator#BETWEEN} or {@link ComparisonOperator#NOT_BETWEEN} - * - * @return the second formula - */ - String getFormula2(); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * Represents a description of a conditional formatting rule + */ +public interface ConditionalFormattingRule { + /** + * Create a new border formatting structure if it does not exist, + * otherwise just return existing object. + * + * @return - border formatting object, never returns null. + */ + BorderFormatting createBorderFormatting(); + + /** + * @return - border formatting object if defined, null otherwise + */ + BorderFormatting getBorderFormatting(); + + /** + * Create a new font formatting structure if it does not exist, + * otherwise just return existing object. + * + * @return - font formatting object, never returns null. + */ + FontFormatting createFontFormatting(); + + /** + * @return - font formatting object if defined, null otherwise + */ + FontFormatting getFontFormatting(); + + /** + * Create a new pattern formatting structure if it does not exist, + * otherwise just return existing object. + * + * @return - pattern formatting object, never returns null. + */ + PatternFormatting createPatternFormatting(); + + /** + * @return - pattern formatting object if defined, null otherwise + */ + PatternFormatting getPatternFormatting(); + + /** + * @return - databar / data-bar formatting object if defined, null otherwise + */ + DataBarFormatting getDataBarFormatting(); + + /** + * @return - icon / multi-state formatting object if defined, null otherwise + */ + IconMultiStateFormatting getMultiStateFormatting(); + + /** + * @return color scale / color grate formatting object if defined, null otherwise + */ + ColorScaleFormatting getColorScaleFormatting(); + + /** + * Type of conditional formatting rule. + * + * @return the type of condition + */ + ConditionType getConditionType(); + + /** + * The comparison function used when the type of conditional formatting is set to + * {@link ConditionType#CELL_VALUE_IS} + *

+ * MUST be a constant from {@link ComparisonOperator} + *

+ * + * @return the conditional format operator + */ + byte getComparisonOperation(); + + /** + * The formula used to evaluate the first operand for the conditional formatting rule. + *

+ * If the condition type is {@link ConditionType#CELL_VALUE_IS}, + * this field is the first operand of the comparison. + * If type is {@link ConditionType#FORMULA}, this formula is used + * to determine if the conditional formatting is applied. + *

+ *

+ * If comparison type is {@link ConditionType#FORMULA} the formula MUST be a Boolean function + *

+ * + * @return the first formula + */ + String getFormula1(); + + /** + * The formula used to evaluate the second operand of the comparison when + * comparison type is {@link ConditionType#CELL_VALUE_IS} and operator + * is either {@link ComparisonOperator#BETWEEN} or {@link ComparisonOperator#NOT_BETWEEN} + * + * @return the second formula + */ + String getFormula2(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingThreshold.java b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingThreshold.java index a5e52b1b3a..c70e3d1d24 100644 --- a/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingThreshold.java +++ b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingThreshold.java @@ -1,110 +1,110 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - - -/** - * The Threshold / CFVO / Conditional Formatting Value Object. - *

This defines how to calculate the ranges for a conditional - * formatting rule, eg which values get a Green Traffic Light - * icon and which Yellow or Red.

- */ -public interface ConditionalFormattingThreshold { - public enum RangeType { - /** Number / Parameter */ - NUMBER(1, "num"), - /** The minimum value from the range */ - MIN(2, "min"), - /** The maximum value from the range */ - MAX(3, "max"), - /** Percent of the way from the mi to the max value in the range */ - PERCENT(4, "percent"), - /** The minimum value of the cell that is in X percentile of the range */ - PERCENTILE(5, "percentile"), - UNALLOCATED(6, null), - /** Formula result */ - FORMULA(7, "formula"); - - /** Numeric ID of the type */ - public final int id; - /** Name (system) of the type */ - public final String name; - - public String toString() { - return id + " - " + name; - } - - public static RangeType byId(int id) { - return values()[id-1]; // 1-based IDs - } - public static RangeType byName(String name) { - for (RangeType t : values()) { - if (t.name.equals(name)) return t; - } - return null; - } - - private RangeType(int id, String name) { - this.id = id; this.name = name; - } - } - - /** - * Get the Range Type used - */ - RangeType getRangeType(); - - /** - * Changes the Range Type used - * - *

If you change the range type, you need to - * ensure that the Formula and Value parameters - * are compatible with it before saving

- */ - void setRangeType(RangeType type); - - /** - * Formula to use to calculate the threshold, - * or null if no formula - */ - String getFormula(); - - /** - * Sets the formula used to calculate the threshold, - * or unsets it if null is given. - */ - void setFormula(String formula); - - /** - * Gets the value used for the threshold, or - * null if there isn't one. - */ - Double getValue(); - - /** - * Sets the value used for the threshold. - *

If the type is {@link RangeType#PERCENT} or - * {@link RangeType#PERCENTILE} it must be between 0 and 100. - *

If the type is {@link RangeType#MIN} or {@link RangeType#MAX} - * or {@link RangeType#FORMULA} it shouldn't be set. - *

Use null to unset - */ - void setValue(Double value); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + + +/** + * The Threshold / CFVO / Conditional Formatting Value Object. + *

This defines how to calculate the ranges for a conditional + * formatting rule, eg which values get a Green Traffic Light + * icon and which Yellow or Red.

+ */ +public interface ConditionalFormattingThreshold { + public enum RangeType { + /** Number / Parameter */ + NUMBER(1, "num"), + /** The minimum value from the range */ + MIN(2, "min"), + /** The maximum value from the range */ + MAX(3, "max"), + /** Percent of the way from the mi to the max value in the range */ + PERCENT(4, "percent"), + /** The minimum value of the cell that is in X percentile of the range */ + PERCENTILE(5, "percentile"), + UNALLOCATED(6, null), + /** Formula result */ + FORMULA(7, "formula"); + + /** Numeric ID of the type */ + public final int id; + /** Name (system) of the type */ + public final String name; + + public String toString() { + return id + " - " + name; + } + + public static RangeType byId(int id) { + return values()[id-1]; // 1-based IDs + } + public static RangeType byName(String name) { + for (RangeType t : values()) { + if (t.name.equals(name)) return t; + } + return null; + } + + private RangeType(int id, String name) { + this.id = id; this.name = name; + } + } + + /** + * Get the Range Type used + */ + RangeType getRangeType(); + + /** + * Changes the Range Type used + * + *

If you change the range type, you need to + * ensure that the Formula and Value parameters + * are compatible with it before saving

+ */ + void setRangeType(RangeType type); + + /** + * Formula to use to calculate the threshold, + * or null if no formula + */ + String getFormula(); + + /** + * Sets the formula used to calculate the threshold, + * or unsets it if null is given. + */ + void setFormula(String formula); + + /** + * Gets the value used for the threshold, or + * null if there isn't one. + */ + Double getValue(); + + /** + * Sets the value used for the threshold. + *

If the type is {@link RangeType#PERCENT} or + * {@link RangeType#PERCENTILE} it must be between 0 and 100. + *

If the type is {@link RangeType#MIN} or {@link RangeType#MAX} + * or {@link RangeType#FORMULA} it shouldn't be set. + *

Use null to unset + */ + void setValue(Double value); +} diff --git a/src/java/org/apache/poi/ss/usermodel/DataBarFormatting.java b/src/java/org/apache/poi/ss/usermodel/DataBarFormatting.java index df9a0fef71..bcdd34a6d2 100644 --- a/src/java/org/apache/poi/ss/usermodel/DataBarFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/DataBarFormatting.java @@ -1,72 +1,72 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -/** - * High level representation for the DataBar Formatting - * component of Conditional Formatting settings - */ -public interface DataBarFormatting { - /** - * Is the bar drawn from Left-to-Right, or from - * Right-to-Left - */ - boolean isLeftToRight(); - /** - * Control if the bar is drawn from Left-to-Right, - * or from Right-to-Left - */ - void setLeftToRight(boolean ltr); - - /** - * Should Icon + Value be displayed, or only the Icon? - */ - boolean isIconOnly(); - /** - * Control if only the Icon is shown, or Icon + Value - */ - void setIconOnly(boolean only); - - /** - * How much of the cell width, in %, should be given to - * the min value? - */ - int getWidthMin(); - void setWidthMin(int width); - - /** - * How much of the cell width, in %, should be given to - * the max value? - */ - int getWidthMax(); - void setWidthMax(int width); - - Color getColor(); - void setColor(Color color); - - /** - * The threshold that defines "everything from here down is minimum" - */ - ConditionalFormattingThreshold getMinThreshold(); - /** - * The threshold that defines "everything from here up is maximum" - */ - ConditionalFormattingThreshold getMaxThreshold(); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * High level representation for the DataBar Formatting + * component of Conditional Formatting settings + */ +public interface DataBarFormatting { + /** + * Is the bar drawn from Left-to-Right, or from + * Right-to-Left + */ + boolean isLeftToRight(); + /** + * Control if the bar is drawn from Left-to-Right, + * or from Right-to-Left + */ + void setLeftToRight(boolean ltr); + + /** + * Should Icon + Value be displayed, or only the Icon? + */ + boolean isIconOnly(); + /** + * Control if only the Icon is shown, or Icon + Value + */ + void setIconOnly(boolean only); + + /** + * How much of the cell width, in %, should be given to + * the min value? + */ + int getWidthMin(); + void setWidthMin(int width); + + /** + * How much of the cell width, in %, should be given to + * the max value? + */ + int getWidthMax(); + void setWidthMax(int width); + + Color getColor(); + void setColor(Color color); + + /** + * The threshold that defines "everything from here down is minimum" + */ + ConditionalFormattingThreshold getMinThreshold(); + /** + * The threshold that defines "everything from here up is maximum" + */ + ConditionalFormattingThreshold getMaxThreshold(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/FontFormatting.java b/src/java/org/apache/poi/ss/usermodel/FontFormatting.java index a6f21bde4d..fe65f7eaea 100644 --- a/src/java/org/apache/poi/ss/usermodel/FontFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/FontFormatting.java @@ -1,151 +1,151 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -/** - * High level representation for Font Formatting component - * of Conditional Formatting settings - */ -public interface FontFormatting { - /** Escapement type - None */ - public final static short SS_NONE = 0; - /** Escapement type - Superscript */ - public final static short SS_SUPER = 1; - /** Escapement type - Subscript */ - public final static short SS_SUB = 2; - - /** Underline type - None */ - public final static byte U_NONE = 0; - /** Underline type - Single */ - public final static byte U_SINGLE = 1; - /** Underline type - Double */ - public final static byte U_DOUBLE = 2; - /** Underline type - Single Accounting */ - public final static byte U_SINGLE_ACCOUNTING = 0x21; - /** Underline type - Double Accounting */ - public final static byte U_DOUBLE_ACCOUNTING = 0x22; - - /** - * get the type of super or subscript for the font - * - * @return super or subscript option - * @see #SS_NONE - * @see #SS_SUPER - * @see #SS_SUB - */ - short getEscapementType(); - - /** - * set the escapement type for the font - * - * @param escapementType super or subscript option - * @see #SS_NONE - * @see #SS_SUPER - * @see #SS_SUB - */ - void setEscapementType(short escapementType); - - /** - * @return font colour index, or 0 if not indexed (XSSF only) - */ - short getFontColorIndex(); - - /** - * Sets the indexed colour to use - * @param color font colour index - */ - void setFontColorIndex(short color); - - /** - * @return The colour of the font, or null if no colour applied - */ - Color getFontColor(); - - /** - * Sets the colour to use - * @param color font colour to use - */ - void setFontColor(Color color); - - /** - * gets the height of the font in 1/20th point units - * - * @return fontheight (in points/20); or -1 if not modified - */ - int getFontHeight(); - - /** - * Sets the height of the font in 1/20th point units - * - * @param height the height in twips (in points/20) - */ - void setFontHeight(int height); - - /** - * get the type of underlining for the font - * - * @return font underlining type - * - * @see #U_NONE - * @see #U_SINGLE - * @see #U_DOUBLE - * @see #U_SINGLE_ACCOUNTING - * @see #U_DOUBLE_ACCOUNTING - */ - short getUnderlineType(); - - /** - * set the type of underlining type for the font - * - * @param underlineType super or subscript option - * - * @see #U_NONE - * @see #U_SINGLE - * @see #U_DOUBLE - * @see #U_SINGLE_ACCOUNTING - * @see #U_DOUBLE_ACCOUNTING - */ - void setUnderlineType(short underlineType); - - /** - * get whether the font weight is set to bold or not - * - * @return bold - whether the font is bold or not - */ - boolean isBold(); - - /** - * @return true if font style was set to italic - */ - boolean isItalic(); - - /** - * set font style options. - * - * @param italic - if true, set posture style to italic, otherwise to normal - * @param bold if true, set font weight to bold, otherwise to normal - */ - void setFontStyle(boolean italic, boolean bold); - - /** - * set font style options to default values (non-italic, non-bold) - */ - void resetFontStyle(); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * High level representation for Font Formatting component + * of Conditional Formatting settings + */ +public interface FontFormatting { + /** Escapement type - None */ + public final static short SS_NONE = 0; + /** Escapement type - Superscript */ + public final static short SS_SUPER = 1; + /** Escapement type - Subscript */ + public final static short SS_SUB = 2; + + /** Underline type - None */ + public final static byte U_NONE = 0; + /** Underline type - Single */ + public final static byte U_SINGLE = 1; + /** Underline type - Double */ + public final static byte U_DOUBLE = 2; + /** Underline type - Single Accounting */ + public final static byte U_SINGLE_ACCOUNTING = 0x21; + /** Underline type - Double Accounting */ + public final static byte U_DOUBLE_ACCOUNTING = 0x22; + + /** + * get the type of super or subscript for the font + * + * @return super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + short getEscapementType(); + + /** + * set the escapement type for the font + * + * @param escapementType super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + void setEscapementType(short escapementType); + + /** + * @return font colour index, or 0 if not indexed (XSSF only) + */ + short getFontColorIndex(); + + /** + * Sets the indexed colour to use + * @param color font colour index + */ + void setFontColorIndex(short color); + + /** + * @return The colour of the font, or null if no colour applied + */ + Color getFontColor(); + + /** + * Sets the colour to use + * @param color font colour to use + */ + void setFontColor(Color color); + + /** + * gets the height of the font in 1/20th point units + * + * @return fontheight (in points/20); or -1 if not modified + */ + int getFontHeight(); + + /** + * Sets the height of the font in 1/20th point units + * + * @param height the height in twips (in points/20) + */ + void setFontHeight(int height); + + /** + * get the type of underlining for the font + * + * @return font underlining type + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + short getUnderlineType(); + + /** + * set the type of underlining type for the font + * + * @param underlineType super or subscript option + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + void setUnderlineType(short underlineType); + + /** + * get whether the font weight is set to bold or not + * + * @return bold - whether the font is bold or not + */ + boolean isBold(); + + /** + * @return true if font style was set to italic + */ + boolean isItalic(); + + /** + * set font style options. + * + * @param italic - if true, set posture style to italic, otherwise to normal + * @param bold if true, set font weight to bold, otherwise to normal + */ + void setFontStyle(boolean italic, boolean bold); + + /** + * set font style options to default values (non-italic, non-bold) + */ + void resetFontStyle(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/FractionFormat.java b/src/java/org/apache/poi/ss/usermodel/FractionFormat.java index bd5c8c8fec..e4e7d61f37 100644 --- a/src/java/org/apache/poi/ss/usermodel/FractionFormat.java +++ b/src/java/org/apache/poi/ss/usermodel/FractionFormat.java @@ -1,184 +1,184 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.poi.ss.usermodel; -import java.text.FieldPosition; -import java.text.Format; -import java.text.ParsePosition; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.poi.ss.format.SimpleFraction; -import org.apache.poi.ss.formula.eval.NotImplementedException; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - *

Format class that handles Excel style fractions, such as "# #/#" and "#/###"

- * - *

As of this writing, this is still not 100% accurate, but it does a reasonable job - * of trying to mimic Excel's fraction calculations. It does not currently - * maintain Excel's spacing.

- * - *

This class relies on a method lifted nearly verbatim from org.apache.math.fraction. - * If further uses for Commons Math are found, we will consider adding it as a dependency. - * For now, we have in-lined the one method to keep things simple.

- */ - -@SuppressWarnings("serial") -public class FractionFormat extends Format { - private static final POILogger LOGGER = POILogFactory.getLogger(FractionFormat.class); - private static final Pattern DENOM_FORMAT_PATTERN = Pattern.compile("(?:(#+)|(\\d+))"); - - //this was chosen to match the earlier limitation of max denom power - //it can be expanded to get closer to Excel's calculations - //with custom formats # #/######### - //but as of this writing, the numerators and denominators - //with formats of that nature on very small values were quite - //far from Excel's calculations - private static final int MAX_DENOM_POW = 4; - - //there are two options: - //a) an exact denominator is specified in the formatString - //b) the maximum denominator can be calculated from the formatString - private final int exactDenom; - private final int maxDenom; - - private final String wholePartFormatString; - /** - * Single parameter ctor - * @param denomFormatString The format string for the denominator - */ - public FractionFormat(String wholePartFormatString, String denomFormatString) { - this.wholePartFormatString = wholePartFormatString; - //init exactDenom and maxDenom - Matcher m = DENOM_FORMAT_PATTERN.matcher(denomFormatString); - int tmpExact = -1; - int tmpMax = -1; - if (m.find()){ - if (m.group(2) != null){ - try{ - tmpExact = Integer.parseInt(m.group(2)); - //if the denom is 0, fall back to the default: tmpExact=100 - - if (tmpExact == 0){ - tmpExact = -1; - } - } catch (NumberFormatException e){ - //should never happen - } - } else if (m.group(1) != null) { - int len = m.group(1).length(); - len = len > MAX_DENOM_POW ? MAX_DENOM_POW : len; - tmpMax = (int)Math.pow(10, len); - } else { - tmpExact = 100; - } - } - if (tmpExact <= 0 && tmpMax <= 0){ - //use 100 as the default denom if something went horribly wrong - tmpExact = 100; - } - exactDenom = tmpExact; - maxDenom = tmpMax; - } - - public String format(Number num) { - - final double doubleValue = num.doubleValue(); - - final boolean isNeg = (doubleValue < 0.0f) ? true : false; - final double absDoubleValue = Math.abs(doubleValue); - - final double wholePart = Math.floor(absDoubleValue); - final double decPart = absDoubleValue - wholePart; - if (wholePart + decPart == 0) { - return "0"; - } - - // if the absolute value is smaller than 1 over the exact or maxDenom - // you can stop here and return "0" - // reciprocal is result of an int devision ... and so it's nearly always 0 - // double reciprocal = 1/Math.max(exactDenom, maxDenom); - // if (absDoubleValue < reciprocal) { - // return "0"; - // } - - //this is necessary to prevent overflow in the maxDenom calculation - if (Double.compare(decPart, 0) == 0){ - - StringBuilder sb = new StringBuilder(); - if (isNeg){ - sb.append("-"); - } - sb.append((int)wholePart); - return sb.toString(); - } - - SimpleFraction fract = null; - try{ - //this should be the case because of the constructor - if (exactDenom > 0){ - fract = SimpleFraction.buildFractionExactDenominator(decPart, exactDenom); - } else { - fract = SimpleFraction.buildFractionMaxDenominator(decPart, maxDenom); - } - } catch (RuntimeException e){ - LOGGER.log(POILogger.WARN, "Can't format fraction", e); - return Double.toString(doubleValue); - } - - StringBuilder sb = new StringBuilder(); - - //now format the results - if (isNeg){ - sb.append("-"); - } - - //if whole part has to go into the numerator - if ("".equals(wholePartFormatString)){ - int trueNum = (fract.getDenominator()*(int)wholePart)+fract.getNumerator(); - sb.append(trueNum).append("/").append(fract.getDenominator()); - return sb.toString(); - } - - - //short circuit if fraction is 0 or 1 - if (fract.getNumerator() == 0){ - sb.append(Integer.toString((int)wholePart)); - return sb.toString(); - } else if (fract.getNumerator() == fract.getDenominator()){ - sb.append(Integer.toString((int)wholePart+1)); - return sb.toString(); - } - //as mentioned above, this ignores the exact space formatting in Excel - if (wholePart > 0){ - sb.append(Integer.toString((int)wholePart)).append(" "); - } - sb.append(fract.getNumerator()).append("/").append(fract.getDenominator()); - return sb.toString(); - } - - public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { - return toAppendTo.append(format((Number)obj)); - } - - public Object parseObject(String source, ParsePosition pos) { - throw new NotImplementedException("Reverse parsing not supported"); - } - -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.poi.ss.usermodel; +import java.text.FieldPosition; +import java.text.Format; +import java.text.ParsePosition; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.poi.ss.format.SimpleFraction; +import org.apache.poi.ss.formula.eval.NotImplementedException; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + *

Format class that handles Excel style fractions, such as "# #/#" and "#/###"

+ * + *

As of this writing, this is still not 100% accurate, but it does a reasonable job + * of trying to mimic Excel's fraction calculations. It does not currently + * maintain Excel's spacing.

+ * + *

This class relies on a method lifted nearly verbatim from org.apache.math.fraction. + * If further uses for Commons Math are found, we will consider adding it as a dependency. + * For now, we have in-lined the one method to keep things simple.

+ */ + +@SuppressWarnings("serial") +public class FractionFormat extends Format { + private static final POILogger LOGGER = POILogFactory.getLogger(FractionFormat.class); + private static final Pattern DENOM_FORMAT_PATTERN = Pattern.compile("(?:(#+)|(\\d+))"); + + //this was chosen to match the earlier limitation of max denom power + //it can be expanded to get closer to Excel's calculations + //with custom formats # #/######### + //but as of this writing, the numerators and denominators + //with formats of that nature on very small values were quite + //far from Excel's calculations + private static final int MAX_DENOM_POW = 4; + + //there are two options: + //a) an exact denominator is specified in the formatString + //b) the maximum denominator can be calculated from the formatString + private final int exactDenom; + private final int maxDenom; + + private final String wholePartFormatString; + /** + * Single parameter ctor + * @param denomFormatString The format string for the denominator + */ + public FractionFormat(String wholePartFormatString, String denomFormatString) { + this.wholePartFormatString = wholePartFormatString; + //init exactDenom and maxDenom + Matcher m = DENOM_FORMAT_PATTERN.matcher(denomFormatString); + int tmpExact = -1; + int tmpMax = -1; + if (m.find()){ + if (m.group(2) != null){ + try{ + tmpExact = Integer.parseInt(m.group(2)); + //if the denom is 0, fall back to the default: tmpExact=100 + + if (tmpExact == 0){ + tmpExact = -1; + } + } catch (NumberFormatException e){ + //should never happen + } + } else if (m.group(1) != null) { + int len = m.group(1).length(); + len = len > MAX_DENOM_POW ? MAX_DENOM_POW : len; + tmpMax = (int)Math.pow(10, len); + } else { + tmpExact = 100; + } + } + if (tmpExact <= 0 && tmpMax <= 0){ + //use 100 as the default denom if something went horribly wrong + tmpExact = 100; + } + exactDenom = tmpExact; + maxDenom = tmpMax; + } + + public String format(Number num) { + + final double doubleValue = num.doubleValue(); + + final boolean isNeg = (doubleValue < 0.0f) ? true : false; + final double absDoubleValue = Math.abs(doubleValue); + + final double wholePart = Math.floor(absDoubleValue); + final double decPart = absDoubleValue - wholePart; + if (wholePart + decPart == 0) { + return "0"; + } + + // if the absolute value is smaller than 1 over the exact or maxDenom + // you can stop here and return "0" + // reciprocal is result of an int devision ... and so it's nearly always 0 + // double reciprocal = 1/Math.max(exactDenom, maxDenom); + // if (absDoubleValue < reciprocal) { + // return "0"; + // } + + //this is necessary to prevent overflow in the maxDenom calculation + if (Double.compare(decPart, 0) == 0){ + + StringBuilder sb = new StringBuilder(); + if (isNeg){ + sb.append("-"); + } + sb.append((int)wholePart); + return sb.toString(); + } + + SimpleFraction fract = null; + try{ + //this should be the case because of the constructor + if (exactDenom > 0){ + fract = SimpleFraction.buildFractionExactDenominator(decPart, exactDenom); + } else { + fract = SimpleFraction.buildFractionMaxDenominator(decPart, maxDenom); + } + } catch (RuntimeException e){ + LOGGER.log(POILogger.WARN, "Can't format fraction", e); + return Double.toString(doubleValue); + } + + StringBuilder sb = new StringBuilder(); + + //now format the results + if (isNeg){ + sb.append("-"); + } + + //if whole part has to go into the numerator + if ("".equals(wholePartFormatString)){ + int trueNum = (fract.getDenominator()*(int)wholePart)+fract.getNumerator(); + sb.append(trueNum).append("/").append(fract.getDenominator()); + return sb.toString(); + } + + + //short circuit if fraction is 0 or 1 + if (fract.getNumerator() == 0){ + sb.append(Integer.toString((int)wholePart)); + return sb.toString(); + } else if (fract.getNumerator() == fract.getDenominator()){ + sb.append(Integer.toString((int)wholePart+1)); + return sb.toString(); + } + //as mentioned above, this ignores the exact space formatting in Excel + if (wholePart > 0){ + sb.append(Integer.toString((int)wholePart)).append(" "); + } + sb.append(fract.getNumerator()).append("/").append(fract.getDenominator()); + return sb.toString(); + } + + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { + return toAppendTo.append(format((Number)obj)); + } + + public Object parseObject(String source, ParsePosition pos) { + throw new NotImplementedException("Reverse parsing not supported"); + } + +} diff --git a/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java index e7577c3f67..24eebdf201 100644 --- a/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java @@ -1,127 +1,127 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -/** - * High level representation for the Icon / Multi-State Formatting - * component of Conditional Formatting settings - */ -public interface IconMultiStateFormatting { - public enum IconSet { - /** Green Up / Yellow Side / Red Down arrows */ - GYR_3_ARROW(0, 3, "3Arrows"), - /** Grey Up / Side / Down arrows */ - GREY_3_ARROWS(1, 3, "3ArrowsGray"), - /** Green / Yellow / Red flags */ - GYR_3_FLAGS(2, 3, "3Flags"), - /** Green / Yellow / Red traffic lights (no background). Default */ - GYR_3_TRAFFIC_LIGHTS(3, 3, "3TrafficLights1"), - /** Green / Yellow / Red traffic lights on a black square background. - * Note, MS-XLS docs v20141018 say this is id=5 but seems to be id=4 */ - GYR_3_TRAFFIC_LIGHTS_BOX(4, 3, "3TrafficLights2"), - /** Green Circle / Yellow Triangle / Red Diamond. - * Note, MS-XLS docs v20141018 say this is id=4 but seems to be id=5 */ - GYR_3_SHAPES(5, 3, "3Signs"), - /** Green Tick / Yellow ! / Red Cross on a circle background */ - GYR_3_SYMBOLS_CIRCLE(6, 3, "3Symbols"), - /** Green Tick / Yellow ! / Red Cross (no background) */ - GYR_3_SYMBOLS(7, 3, "3Symbols2"), - /** Green Up / Yellow NE / Yellow SE / Red Down arrows */ - GYR_4_ARROWS(8, 4, "4Arrows"), - /** Grey Up / NE / SE / Down arrows */ - GREY_4_ARROWS(9, 4, "4ArrowsGray"), - /** Red / Light Red / Grey / Black traffic lights */ - RB_4_TRAFFIC_LIGHTS(0xA, 4, "4RedToBlack"), - RATINGS_4(0xB, 4, "4Rating"), - /** Green / Yellow / Red / Black traffic lights */ - GYRB_4_TRAFFIC_LIGHTS(0xC, 4, "4TrafficLights"), - GYYYR_5_ARROWS(0xD, 5, "5Arrows"), - GREY_5_ARROWS(0xE, 5, "5ArrowsGray"), - RATINGS_5(0xF, 5, "5Rating"), - QUARTERS_5(0x10, 5, "5Quarters"); - - protected static final IconSet DEFAULT_ICONSET = IconSet.GYR_3_TRAFFIC_LIGHTS; - - /** Numeric ID of the icon set */ - public final int id; - /** How many icons in the set */ - public final int num; - /** Name (system) of the set */ - public final String name; - - public String toString() { - return id + " - " + name; - } - - public static IconSet byId(int id) { - return values()[id]; - } - public static IconSet byName(String name) { - for (IconSet set : values()) { - if (set.name.equals(name)) return set; - } - return null; - } - - private IconSet(int id, int num, String name) { - this.id = id; this.num = num; this.name = name; - } - } - - /** - * Get the Icon Set used - */ - IconSet getIconSet(); - - /** - * Changes the Icon Set used - * - *

If the new Icon Set has a different number of - * icons to the old one, you must update the - * thresholds before saving!

- */ - void setIconSet(IconSet set); - - /** - * Should Icon + Value be displayed, or only the Icon? - */ - boolean isIconOnly(); - /** - * Control if only the Icon is shown, or Icon + Value - */ - void setIconOnly(boolean only); - - boolean isReversed(); - void setReversed(boolean reversed); - - /** - * Gets the list of thresholds - */ - ConditionalFormattingThreshold[] getThresholds(); - /** - * Sets the of thresholds. The number must match - * {@link IconSet#num} for the current {@link #getIconSet()} - */ - void setThresholds(ConditionalFormattingThreshold[] thresholds); - /** - * Creates a new, empty Threshold - */ - ConditionalFormattingThreshold createThreshold(); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * High level representation for the Icon / Multi-State Formatting + * component of Conditional Formatting settings + */ +public interface IconMultiStateFormatting { + public enum IconSet { + /** Green Up / Yellow Side / Red Down arrows */ + GYR_3_ARROW(0, 3, "3Arrows"), + /** Grey Up / Side / Down arrows */ + GREY_3_ARROWS(1, 3, "3ArrowsGray"), + /** Green / Yellow / Red flags */ + GYR_3_FLAGS(2, 3, "3Flags"), + /** Green / Yellow / Red traffic lights (no background). Default */ + GYR_3_TRAFFIC_LIGHTS(3, 3, "3TrafficLights1"), + /** Green / Yellow / Red traffic lights on a black square background. + * Note, MS-XLS docs v20141018 say this is id=5 but seems to be id=4 */ + GYR_3_TRAFFIC_LIGHTS_BOX(4, 3, "3TrafficLights2"), + /** Green Circle / Yellow Triangle / Red Diamond. + * Note, MS-XLS docs v20141018 say this is id=4 but seems to be id=5 */ + GYR_3_SHAPES(5, 3, "3Signs"), + /** Green Tick / Yellow ! / Red Cross on a circle background */ + GYR_3_SYMBOLS_CIRCLE(6, 3, "3Symbols"), + /** Green Tick / Yellow ! / Red Cross (no background) */ + GYR_3_SYMBOLS(7, 3, "3Symbols2"), + /** Green Up / Yellow NE / Yellow SE / Red Down arrows */ + GYR_4_ARROWS(8, 4, "4Arrows"), + /** Grey Up / NE / SE / Down arrows */ + GREY_4_ARROWS(9, 4, "4ArrowsGray"), + /** Red / Light Red / Grey / Black traffic lights */ + RB_4_TRAFFIC_LIGHTS(0xA, 4, "4RedToBlack"), + RATINGS_4(0xB, 4, "4Rating"), + /** Green / Yellow / Red / Black traffic lights */ + GYRB_4_TRAFFIC_LIGHTS(0xC, 4, "4TrafficLights"), + GYYYR_5_ARROWS(0xD, 5, "5Arrows"), + GREY_5_ARROWS(0xE, 5, "5ArrowsGray"), + RATINGS_5(0xF, 5, "5Rating"), + QUARTERS_5(0x10, 5, "5Quarters"); + + protected static final IconSet DEFAULT_ICONSET = IconSet.GYR_3_TRAFFIC_LIGHTS; + + /** Numeric ID of the icon set */ + public final int id; + /** How many icons in the set */ + public final int num; + /** Name (system) of the set */ + public final String name; + + public String toString() { + return id + " - " + name; + } + + public static IconSet byId(int id) { + return values()[id]; + } + public static IconSet byName(String name) { + for (IconSet set : values()) { + if (set.name.equals(name)) return set; + } + return null; + } + + private IconSet(int id, int num, String name) { + this.id = id; this.num = num; this.name = name; + } + } + + /** + * Get the Icon Set used + */ + IconSet getIconSet(); + + /** + * Changes the Icon Set used + * + *

If the new Icon Set has a different number of + * icons to the old one, you must update the + * thresholds before saving!

+ */ + void setIconSet(IconSet set); + + /** + * Should Icon + Value be displayed, or only the Icon? + */ + boolean isIconOnly(); + /** + * Control if only the Icon is shown, or Icon + Value + */ + void setIconOnly(boolean only); + + boolean isReversed(); + void setReversed(boolean reversed); + + /** + * Gets the list of thresholds + */ + ConditionalFormattingThreshold[] getThresholds(); + /** + * Sets the of thresholds. The number must match + * {@link IconSet#num} for the current {@link #getIconSet()} + */ + void setThresholds(ConditionalFormattingThreshold[] thresholds); + /** + * Creates a new, empty Threshold + */ + ConditionalFormattingThreshold createThreshold(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java b/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java index 0311ffb75e..8a328e571e 100644 --- a/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java @@ -1,78 +1,78 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -/** - * @author Yegor Kozlov - */ -public interface PatternFormatting { - /** No background */ - public final static short NO_FILL = 0 ; - /** Solidly filled */ - public final static short SOLID_FOREGROUND = 1 ; - /** Small fine dots */ - public final static short FINE_DOTS = 2 ; - /** Wide dots */ - public final static short ALT_BARS = 3 ; - /** Sparse dots */ - public final static short SPARSE_DOTS = 4 ; - /** Thick horizontal bands */ - public final static short THICK_HORZ_BANDS = 5 ; - /** Thick vertical bands */ - public final static short THICK_VERT_BANDS = 6 ; - /** Thick backward facing diagonals */ - public final static short THICK_BACKWARD_DIAG = 7 ; - /** Thick forward facing diagonals */ - public final static short THICK_FORWARD_DIAG = 8 ; - /** Large spots */ - public final static short BIG_SPOTS = 9 ; - /** Brick-like layout */ - public final static short BRICKS = 10 ; - /** Thin horizontal bands */ - public final static short THIN_HORZ_BANDS = 11 ; - /** Thin vertical bands */ - public final static short THIN_VERT_BANDS = 12 ; - /** Thin backward diagonal */ - public final static short THIN_BACKWARD_DIAG = 13 ; - /** Thin forward diagonal */ - public final static short THIN_FORWARD_DIAG = 14 ; - /** Squares */ - public final static short SQUARES = 15 ; - /** Diamonds */ - public final static short DIAMONDS = 16 ; - /** Less Dots */ - public final static short LESS_DOTS = 17 ; - /** Least Dots */ - public final static short LEAST_DOTS = 18 ; - - short getFillBackgroundColor(); - short getFillForegroundColor(); - Color getFillBackgroundColorColor(); - Color getFillForegroundColorColor(); - - short getFillPattern(); - - void setFillBackgroundColor(short bg); - void setFillForegroundColor(short fg); - void setFillBackgroundColor(Color bg); - void setFillForegroundColor(Color fg); - - void setFillPattern(short fp); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * @author Yegor Kozlov + */ +public interface PatternFormatting { + /** No background */ + public final static short NO_FILL = 0 ; + /** Solidly filled */ + public final static short SOLID_FOREGROUND = 1 ; + /** Small fine dots */ + public final static short FINE_DOTS = 2 ; + /** Wide dots */ + public final static short ALT_BARS = 3 ; + /** Sparse dots */ + public final static short SPARSE_DOTS = 4 ; + /** Thick horizontal bands */ + public final static short THICK_HORZ_BANDS = 5 ; + /** Thick vertical bands */ + public final static short THICK_VERT_BANDS = 6 ; + /** Thick backward facing diagonals */ + public final static short THICK_BACKWARD_DIAG = 7 ; + /** Thick forward facing diagonals */ + public final static short THICK_FORWARD_DIAG = 8 ; + /** Large spots */ + public final static short BIG_SPOTS = 9 ; + /** Brick-like layout */ + public final static short BRICKS = 10 ; + /** Thin horizontal bands */ + public final static short THIN_HORZ_BANDS = 11 ; + /** Thin vertical bands */ + public final static short THIN_VERT_BANDS = 12 ; + /** Thin backward diagonal */ + public final static short THIN_BACKWARD_DIAG = 13 ; + /** Thin forward diagonal */ + public final static short THIN_FORWARD_DIAG = 14 ; + /** Squares */ + public final static short SQUARES = 15 ; + /** Diamonds */ + public final static short DIAMONDS = 16 ; + /** Less Dots */ + public final static short LESS_DOTS = 17 ; + /** Least Dots */ + public final static short LEAST_DOTS = 18 ; + + short getFillBackgroundColor(); + short getFillForegroundColor(); + Color getFillBackgroundColorColor(); + Color getFillForegroundColorColor(); + + short getFillPattern(); + + void setFillBackgroundColor(short bg); + void setFillForegroundColor(short fg); + void setFillBackgroundColor(Color bg); + void setFillForegroundColor(Color fg); + + void setFillPattern(short fp); +} diff --git a/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java b/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java index 853eec6ff0..98e2aa7846 100644 --- a/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java @@ -1,195 +1,195 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; -import org.apache.poi.ss.util.CellRangeAddress; - -/** - * The 'Conditional Formatting' facet of Sheet - * - * @since 3.8 - */ -public interface SheetConditionalFormatting { - /** - * Add a new Conditional Formatting to the sheet. - * - * @param regions - list of rectangular regions to apply conditional formatting rules - * @param rule - the rule to apply - * - * @return index of the newly created Conditional Formatting object - */ - int addConditionalFormatting(CellRangeAddress[] regions, - ConditionalFormattingRule rule); - - /** - * Add a new Conditional Formatting consisting of two rules. - * - * @param regions - list of rectangular regions to apply conditional formatting rules - * @param rule1 - the first rule - * @param rule2 - the second rule - * - * @return index of the newly created Conditional Formatting object - */ - int addConditionalFormatting(CellRangeAddress[] regions, - ConditionalFormattingRule rule1, - ConditionalFormattingRule rule2); - - /** - * Add a new Conditional Formatting set to the sheet. - * - * @param regions - list of rectangular regions to apply conditional formatting rules - * @param cfRules - set of up to conditional formatting rules (max 3 for Excel pre-2007) - * - * @return index of the newly created Conditional Formatting object - */ - int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules); - - /** - * Adds a copy of a ConditionalFormatting object to the sheet - *

- * This method could be used to copy ConditionalFormatting object - * from one sheet to another. For example: - *

- *
-     * ConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
-     * newSheet.addConditionalFormatting(cf);
-     * 
- * - * @param cf the Conditional Formatting to clone - * @return index of the new Conditional Formatting object - */ - int addConditionalFormatting(ConditionalFormatting cf); - - /** - * A factory method allowing to create a conditional formatting rule - * with a cell comparison operator - *

- * The created conditional formatting rule compares a cell value - * to a formula calculated result, using the specified operator. - * The type of the created condition is {@link ConditionType#CELL_VALUE_IS} - *

- * - * @param comparisonOperation - MUST be a constant value from - * {@link ComparisonOperator}:

- *

    - *
  • BETWEEN
  • - *
  • NOT_BETWEEN
  • - *
  • EQUAL
  • - *
  • NOT_EQUAL
  • - *
  • GT
  • - *
  • LT
  • - *
  • GE
  • - *
  • LE
  • - *
- *

- * @param formula1 - formula for the valued, compared with the cell - * @param formula2 - second formula (only used with - * {@link ComparisonOperator#BETWEEN}) and {@link ComparisonOperator#NOT_BETWEEN} operations) - */ - ConditionalFormattingRule createConditionalFormattingRule( - byte comparisonOperation, - String formula1, - String formula2); - - /** - * Create a conditional formatting rule that compares a cell value - * to a formula calculated result, using an operator * - *

- * The type of the created condition is {@link ConditionType#CELL_VALUE_IS} - *

- * - * @param comparisonOperation MUST be a constant value from - * {@link ComparisonOperator} except BETWEEN and NOT_BETWEEN - * - * @param formula the formula to determine if the conditional formatting is applied - */ - ConditionalFormattingRule createConditionalFormattingRule( - byte comparisonOperation, - String formula); - - /** - * Create a conditional formatting rule based on a Boolean formula. - * When the formula result is true, the cell is highlighted. - * - *

- * The type of the created format condition is {@link ConditionType#FORMULA} - *

- * @param formula the formula to evaluate. MUST be a Boolean function. - */ - ConditionalFormattingRule createConditionalFormattingRule(String formula); - - /** - * Create a Databar conditional formatting rule. - *

The thresholds and colour for it will be created, but will be - * empty and require configuring with - * {@link ConditionalFormattingRule#getDataBarFormatting()} - * then - * {@link DataBarFormatting#getMinThreshold()} - * and - * {@link DataBarFormatting#getMaxThreshold()} - */ - ConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color); - - /** - * Create an Icon Set / Multi-State conditional formatting rule. - *

The thresholds for it will be created, but will be empty - * and require configuring with - * {@link ConditionalFormattingRule#getMultiStateFormatting()} - * then - * {@link IconMultiStateFormatting#getThresholds()} - */ - ConditionalFormattingRule createConditionalFormattingRule(IconSet iconSet); - - /** - * Create a Color Scale / Color Gradient conditional formatting rule. - *

The thresholds and colours for it will be created, but will be - * empty and require configuring with - * {@link ConditionalFormattingRule#getColorScaleFormatting()} - * then - * {@link ColorScaleFormatting#getThresholds()} - * and - * {@link ColorScaleFormatting#getColors()} - */ - ConditionalFormattingRule createConditionalFormattingColorScaleRule(); - - /** - * Gets Conditional Formatting object at a particular index - * - * @param index 0-based index of the Conditional Formatting object to fetch - * @return Conditional Formatting object or null if not found - * @throws IllegalArgumentException if the index is outside of the allowable range (0 ... numberOfFormats-1) - */ - ConditionalFormatting getConditionalFormattingAt(int index); - - /** - * - * @return the number of conditional formats in this sheet - */ - int getNumConditionalFormattings(); - - /** - * Removes a Conditional Formatting object by index - * - * @param index 0-based index of the Conditional Formatting object to remove - * @throws IllegalArgumentException if the index is outside of the allowable range (0 ... numberOfFormats-1) - */ - void removeConditionalFormatting(int index); -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; +import org.apache.poi.ss.util.CellRangeAddress; + +/** + * The 'Conditional Formatting' facet of Sheet + * + * @since 3.8 + */ +public interface SheetConditionalFormatting { + /** + * Add a new Conditional Formatting to the sheet. + * + * @param regions - list of rectangular regions to apply conditional formatting rules + * @param rule - the rule to apply + * + * @return index of the newly created Conditional Formatting object + */ + int addConditionalFormatting(CellRangeAddress[] regions, + ConditionalFormattingRule rule); + + /** + * Add a new Conditional Formatting consisting of two rules. + * + * @param regions - list of rectangular regions to apply conditional formatting rules + * @param rule1 - the first rule + * @param rule2 - the second rule + * + * @return index of the newly created Conditional Formatting object + */ + int addConditionalFormatting(CellRangeAddress[] regions, + ConditionalFormattingRule rule1, + ConditionalFormattingRule rule2); + + /** + * Add a new Conditional Formatting set to the sheet. + * + * @param regions - list of rectangular regions to apply conditional formatting rules + * @param cfRules - set of up to conditional formatting rules (max 3 for Excel pre-2007) + * + * @return index of the newly created Conditional Formatting object + */ + int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules); + + /** + * Adds a copy of a ConditionalFormatting object to the sheet + *

+ * This method could be used to copy ConditionalFormatting object + * from one sheet to another. For example: + *

+ *
+     * ConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
+     * newSheet.addConditionalFormatting(cf);
+     * 
+ * + * @param cf the Conditional Formatting to clone + * @return index of the new Conditional Formatting object + */ + int addConditionalFormatting(ConditionalFormatting cf); + + /** + * A factory method allowing to create a conditional formatting rule + * with a cell comparison operator + *

+ * The created conditional formatting rule compares a cell value + * to a formula calculated result, using the specified operator. + * The type of the created condition is {@link ConditionType#CELL_VALUE_IS} + *

+ * + * @param comparisonOperation - MUST be a constant value from + * {@link ComparisonOperator}:

+ *

    + *
  • BETWEEN
  • + *
  • NOT_BETWEEN
  • + *
  • EQUAL
  • + *
  • NOT_EQUAL
  • + *
  • GT
  • + *
  • LT
  • + *
  • GE
  • + *
  • LE
  • + *
+ *

+ * @param formula1 - formula for the valued, compared with the cell + * @param formula2 - second formula (only used with + * {@link ComparisonOperator#BETWEEN}) and {@link ComparisonOperator#NOT_BETWEEN} operations) + */ + ConditionalFormattingRule createConditionalFormattingRule( + byte comparisonOperation, + String formula1, + String formula2); + + /** + * Create a conditional formatting rule that compares a cell value + * to a formula calculated result, using an operator * + *

+ * The type of the created condition is {@link ConditionType#CELL_VALUE_IS} + *

+ * + * @param comparisonOperation MUST be a constant value from + * {@link ComparisonOperator} except BETWEEN and NOT_BETWEEN + * + * @param formula the formula to determine if the conditional formatting is applied + */ + ConditionalFormattingRule createConditionalFormattingRule( + byte comparisonOperation, + String formula); + + /** + * Create a conditional formatting rule based on a Boolean formula. + * When the formula result is true, the cell is highlighted. + * + *

+ * The type of the created format condition is {@link ConditionType#FORMULA} + *

+ * @param formula the formula to evaluate. MUST be a Boolean function. + */ + ConditionalFormattingRule createConditionalFormattingRule(String formula); + + /** + * Create a Databar conditional formatting rule. + *

The thresholds and colour for it will be created, but will be + * empty and require configuring with + * {@link ConditionalFormattingRule#getDataBarFormatting()} + * then + * {@link DataBarFormatting#getMinThreshold()} + * and + * {@link DataBarFormatting#getMaxThreshold()} + */ + ConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color); + + /** + * Create an Icon Set / Multi-State conditional formatting rule. + *

The thresholds for it will be created, but will be empty + * and require configuring with + * {@link ConditionalFormattingRule#getMultiStateFormatting()} + * then + * {@link IconMultiStateFormatting#getThresholds()} + */ + ConditionalFormattingRule createConditionalFormattingRule(IconSet iconSet); + + /** + * Create a Color Scale / Color Gradient conditional formatting rule. + *

The thresholds and colours for it will be created, but will be + * empty and require configuring with + * {@link ConditionalFormattingRule#getColorScaleFormatting()} + * then + * {@link ColorScaleFormatting#getThresholds()} + * and + * {@link ColorScaleFormatting#getColors()} + */ + ConditionalFormattingRule createConditionalFormattingColorScaleRule(); + + /** + * Gets Conditional Formatting object at a particular index + * + * @param index 0-based index of the Conditional Formatting object to fetch + * @return Conditional Formatting object or null if not found + * @throws IllegalArgumentException if the index is outside of the allowable range (0 ... numberOfFormats-1) + */ + ConditionalFormatting getConditionalFormattingAt(int index); + + /** + * + * @return the number of conditional formats in this sheet + */ + int getNumConditionalFormattings(); + + /** + * Removes a Conditional Formatting object by index + * + * @param index 0-based index of the Conditional Formatting object to remove + * @throws IllegalArgumentException if the index is outside of the allowable range (0 ... numberOfFormats-1) + */ + void removeConditionalFormatting(int index); +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/AxisTickMark.java b/src/java/org/apache/poi/ss/usermodel/charts/AxisTickMark.java index 5c7d16a4e6..d25a00ad8c 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/AxisTickMark.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/AxisTickMark.java @@ -1,30 +1,30 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -/** - * Enumeration of possible axis tick marks. - * - * @author Martin Andersson - */ -public enum AxisTickMark { - NONE, - CROSS, - IN, - OUT -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +/** + * Enumeration of possible axis tick marks. + * + * @author Martin Andersson + */ +public enum AxisTickMark { + NONE, + CROSS, + IN, + OUT +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ChartSeries.java b/src/java/org/apache/poi/ss/usermodel/charts/ChartSeries.java index 05a39d45e5..2ad666a8b8 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ChartSeries.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ChartSeries.java @@ -1,55 +1,55 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -import org.apache.poi.ss.util.CellReference; - -/** - * Basic settings for all chart series. - */ -public interface ChartSeries { - - /** - * Sets the title of the series as a string literal. - * - * @param title - */ - void setTitle(String title); - - /** - * Sets the title of the series as a cell reference. - * - * @param titleReference - */ - void setTitle(CellReference titleReference); - - /** - * @return title as string literal. - */ - String getTitleString(); - - /** - * @return title as cell reference. - */ - CellReference getTitleCellReference(); - - /** - * @return title type. - */ - TitleType getTitleType(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +import org.apache.poi.ss.util.CellReference; + +/** + * Basic settings for all chart series. + */ +public interface ChartSeries { + + /** + * Sets the title of the series as a string literal. + * + * @param title + */ + void setTitle(String title); + + /** + * Sets the title of the series as a cell reference. + * + * @param titleReference + */ + void setTitle(CellReference titleReference); + + /** + * @return title as string literal. + */ + String getTitleString(); + + /** + * @return title as cell reference. + */ + CellReference getTitleCellReference(); + + /** + * @return title type. + */ + TitleType getTitleType(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/LayoutMode.java b/src/java/org/apache/poi/ss/usermodel/charts/LayoutMode.java index 87769701b0..794c774887 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/LayoutMode.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/LayoutMode.java @@ -1,35 +1,35 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -/** - * Specifies the possible ways to store a chart element's position. - * @author Roman Kashitsyn - */ -public enum LayoutMode { - /** - * Specifies that the Width or Height shall be interpreted as the - * Right or Bottom of the chart element. - */ - EDGE, - /** - * Specifies that the Width or Height shall be interpreted as the - * Width or Height of the chart element. - */ - FACTOR -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +/** + * Specifies the possible ways to store a chart element's position. + * @author Roman Kashitsyn + */ +public enum LayoutMode { + /** + * Specifies that the Width or Height shall be interpreted as the + * Right or Bottom of the chart element. + */ + EDGE, + /** + * Specifies that the Width or Height shall be interpreted as the + * Width or Height of the chart element. + */ + FACTOR +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/LayoutTarget.java b/src/java/org/apache/poi/ss/usermodel/charts/LayoutTarget.java index f95c5370fb..2a8b110cb1 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/LayoutTarget.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/LayoutTarget.java @@ -1,39 +1,39 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -/** - * Specifies whether to layout the plot area by its inside (not including axis - * and axis labels) or outside (including axis and axis labels). - * - * @author Roman Kashitsyn - */ -public enum LayoutTarget { - /** - * Specifies that the plot area size shall determine the - * size of the plot area, not including the tick marks and - * axis labels. - */ - INNER, - /** - * Specifies that the plot area size shall determine the - * size of the plot area, the tick marks, and the axis - * labels. - */ - OUTER -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +/** + * Specifies whether to layout the plot area by its inside (not including axis + * and axis labels) or outside (including axis and axis labels). + * + * @author Roman Kashitsyn + */ +public enum LayoutTarget { + /** + * Specifies that the plot area size shall determine the + * size of the plot area, not including the tick marks and + * axis labels. + */ + INNER, + /** + * Specifies that the plot area size shall determine the + * size of the plot area, the tick marks, and the axis + * labels. + */ + OUTER +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/LineChartData.java b/src/java/org/apache/poi/ss/usermodel/charts/LineChartData.java index f3bf10f566..4fa9f8e6fa 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/LineChartData.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/LineChartData.java @@ -1,41 +1,41 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -import java.util.List; - -import org.apache.poi.util.Beta; - -/** - * Data for a Line Chart - */ -@Beta -public interface LineChartData extends ChartData { - - /** - * @param categories data source for categories. - * @param values data source for values. - * @return a new line chart serie. - */ - LineChartSeries addSeries(ChartDataSource categories, ChartDataSource values); - - /** - * @return list of all series. - */ - List getSeries(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +import java.util.List; + +import org.apache.poi.util.Beta; + +/** + * Data for a Line Chart + */ +@Beta +public interface LineChartData extends ChartData { + + /** + * @param categories data source for categories. + * @param values data source for values. + * @return a new line chart serie. + */ + LineChartSeries addSeries(ChartDataSource categories, ChartDataSource values); + + /** + * @return list of all series. + */ + List getSeries(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/LineChartSeries.java b/src/java/org/apache/poi/ss/usermodel/charts/LineChartSeries.java index d1c03a951a..842c442a5c 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/LineChartSeries.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/LineChartSeries.java @@ -1,38 +1,38 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -import org.apache.poi.util.Beta; - -/** - * Represents a line chart series. - */ -@Beta -public interface LineChartSeries extends ChartSeries { - - /** - * @return data source used for category axis data. - */ - ChartDataSource getCategoryAxisData(); - - /** - * @return data source used for value axis. - */ - ChartDataSource getValues(); - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +import org.apache.poi.util.Beta; + +/** + * Represents a line chart series. + */ +@Beta +public interface LineChartSeries extends ChartSeries { + + /** + * @return data source used for category axis data. + */ + ChartDataSource getCategoryAxisData(); + + /** + * @return data source used for value axis. + */ + ChartDataSource getValues(); + +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java b/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java index 2d8bfbd96f..cd78c1c95a 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ManualLayout.java @@ -1,153 +1,153 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -import org.apache.poi.util.Beta; - -/** - * High level representation of chart element manual layout. - * - * @author Roman Kashitsyn - */ -@Beta -public interface ManualLayout { - - /** - * Sets the layout target. - * @param target new layout target. - */ - public void setTarget(LayoutTarget target); - - /** - * Returns current layout target. - * @return current layout target - */ - public LayoutTarget getTarget(); - - /** - * Sets the x-coordinate layout mode. - * @param mode new x-coordinate layout mode. - */ - public void setXMode(LayoutMode mode); - - /** - * Returns current x-coordinnate layout mode. - * @return current x-coordinate layout mode. - */ - public LayoutMode getXMode(); - - /** - * Sets the y-coordinate layout mode. - * @param mode new y-coordinate layout mode. - */ - public void setYMode(LayoutMode mode); - - /** - * Returns current y-coordinate layout mode. - * @return current y-coordinate layout mode. - */ - public LayoutMode getYMode(); - - /** - * Returns the x location of the chart element. - * @return the x location (left) of the chart element or 0.0 if - * not set. - */ - public double getX(); - - /** - * Specifies the x location (left) of the chart element as a - * fraction of the width of the chart. If Left Mode is Factor, - * then the position is relative to the default position for the - * chart element. - */ - public void setX(double x); - - - /** - * Returns current y location of the chart element. - * @return the y location (top) of the chart element or 0.0 if not - * set. - */ - public double getY(); - - /** - * Specifies the y location (top) of the chart element as a - * fraction of the height of the chart. If Top Mode is Factor, - * then the position is relative to the default position for the - * chart element. - */ - public void setY(double y); - - - /** - * Specifies how to interpret the Width element for this manual - * layout. - * @param mode new width layout mode of this manual layout. - */ - public void setWidthMode(LayoutMode mode); - - - /** - * Returns current width mode of this manual layout. - * @return width mode of this manual layout. - */ - public LayoutMode getWidthMode(); - - /** - * Specifies how to interpret the Height element for this manual - * layout. - * @param mode new height mode of this manual layout. - */ - public void setHeightMode(LayoutMode mode); - - /** - * Returns current height mode of this - * @return height mode of this manual layout. - */ - public LayoutMode getHeightMode(); - - /** - * Specifies the width (if Width Mode is Factor) or right (if - * Width Mode is Edge) of the chart element as a fraction of the - * width of the chart. - * @param ratio a fraction of the width of the chart. - */ - public void setWidthRatio(double ratio); - - /** - * Returns current fraction of the width of the chart. - * @return fraction of the width of the chart or 0.0 if not set. - */ - public double getWidthRatio(); - - /** - * Specifies the height (if Height Mode is Factor) or bottom (if - * Height Mode is edge) of the chart element as a fraction of the - * height of the chart. - * @param ratio a fraction of the height of the chart. - */ - public void setHeightRatio(double ratio); - - /** - * Returns current fraction of the height of the chart. - * @return fraction of the height of the chart or 0.0 if not set. - */ - public double getHeightRatio(); - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +import org.apache.poi.util.Beta; + +/** + * High level representation of chart element manual layout. + * + * @author Roman Kashitsyn + */ +@Beta +public interface ManualLayout { + + /** + * Sets the layout target. + * @param target new layout target. + */ + public void setTarget(LayoutTarget target); + + /** + * Returns current layout target. + * @return current layout target + */ + public LayoutTarget getTarget(); + + /** + * Sets the x-coordinate layout mode. + * @param mode new x-coordinate layout mode. + */ + public void setXMode(LayoutMode mode); + + /** + * Returns current x-coordinnate layout mode. + * @return current x-coordinate layout mode. + */ + public LayoutMode getXMode(); + + /** + * Sets the y-coordinate layout mode. + * @param mode new y-coordinate layout mode. + */ + public void setYMode(LayoutMode mode); + + /** + * Returns current y-coordinate layout mode. + * @return current y-coordinate layout mode. + */ + public LayoutMode getYMode(); + + /** + * Returns the x location of the chart element. + * @return the x location (left) of the chart element or 0.0 if + * not set. + */ + public double getX(); + + /** + * Specifies the x location (left) of the chart element as a + * fraction of the width of the chart. If Left Mode is Factor, + * then the position is relative to the default position for the + * chart element. + */ + public void setX(double x); + + + /** + * Returns current y location of the chart element. + * @return the y location (top) of the chart element or 0.0 if not + * set. + */ + public double getY(); + + /** + * Specifies the y location (top) of the chart element as a + * fraction of the height of the chart. If Top Mode is Factor, + * then the position is relative to the default position for the + * chart element. + */ + public void setY(double y); + + + /** + * Specifies how to interpret the Width element for this manual + * layout. + * @param mode new width layout mode of this manual layout. + */ + public void setWidthMode(LayoutMode mode); + + + /** + * Returns current width mode of this manual layout. + * @return width mode of this manual layout. + */ + public LayoutMode getWidthMode(); + + /** + * Specifies how to interpret the Height element for this manual + * layout. + * @param mode new height mode of this manual layout. + */ + public void setHeightMode(LayoutMode mode); + + /** + * Returns current height mode of this + * @return height mode of this manual layout. + */ + public LayoutMode getHeightMode(); + + /** + * Specifies the width (if Width Mode is Factor) or right (if + * Width Mode is Edge) of the chart element as a fraction of the + * width of the chart. + * @param ratio a fraction of the width of the chart. + */ + public void setWidthRatio(double ratio); + + /** + * Returns current fraction of the width of the chart. + * @return fraction of the width of the chart or 0.0 if not set. + */ + public double getWidthRatio(); + + /** + * Specifies the height (if Height Mode is Factor) or bottom (if + * Height Mode is edge) of the chart element as a fraction of the + * height of the chart. + * @param ratio a fraction of the height of the chart. + */ + public void setHeightRatio(double ratio); + + /** + * Returns current fraction of the height of the chart. + * @return fraction of the height of the chart or 0.0 if not set. + */ + public double getHeightRatio(); + +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java b/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java index 0d749fb4b9..3fc5ba1fb6 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/ManuallyPositionable.java @@ -1,36 +1,36 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -import org.apache.poi.util.Beta; - -/** - * Abstraction of chart element that can be positioned with manual - * layout. - * - * @author Roman Kashitsyn - */ -@Beta -public interface ManuallyPositionable { - - /** - * Returns manual layout for the chart element. - * @return manual layout for the chart element. - */ - public ManualLayout getManualLayout(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +import org.apache.poi.util.Beta; + +/** + * Abstraction of chart element that can be positioned with manual + * layout. + * + * @author Roman Kashitsyn + */ +@Beta +public interface ManuallyPositionable { + + /** + * Returns manual layout for the chart element. + * @return manual layout for the chart element. + */ + public ManualLayout getManualLayout(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/charts/TitleType.java b/src/java/org/apache/poi/ss/usermodel/charts/TitleType.java index 6d93d61d36..07b5beb8a3 100644 --- a/src/java/org/apache/poi/ss/usermodel/charts/TitleType.java +++ b/src/java/org/apache/poi/ss/usermodel/charts/TitleType.java @@ -1,28 +1,28 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.usermodel.charts; - -/** - * Title types for charts. - * - * @author Martin Andersson - */ -public enum TitleType { - STRING, - CELL_REFERENCE -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.usermodel.charts; + +/** + * Title types for charts. + * + * @author Martin Andersson + */ +public enum TitleType { + STRING, + CELL_REFERENCE +} diff --git a/src/java/org/apache/poi/ss/util/DateFormatConverter.java b/src/java/org/apache/poi/ss/util/DateFormatConverter.java index 6339a6ea7a..4d24a62ec8 100644 --- a/src/java/org/apache/poi/ss/util/DateFormatConverter.java +++ b/src/java/org/apache/poi/ss/util/DateFormatConverter.java @@ -1,433 +1,433 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.util; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * Convert java DateFormat patterns into Excel custom number formats. - * For example, to format a date in excel using the "dd MMMM, yyyy" pattern and Japanese - * locale, use the following code: - * - *


- *      // returns "[$-0411]dd MMMM, yyyy;@" where the [$-0411] prefix tells Excel to use the Japanese locale
- *      String excelFormatPattern = DateFormatConverter.convert(Locale.JAPANESE, "dd MMMM, yyyy");
- *
- *      CellStyle cellStyle = workbook.createCellStyle();
- *
- *      DataFormat poiFormat = workbook.createDataFormat();
- *      cellStyle.setDataFormat(poiFormat.getFormat(excelFormatPattern));
- *      cell.setCellValue(new Date());
- *      cell.setCellStyle(cellStyle);  // formats date as '2012\u5e743\u670817\u65e5'
- *  
- * - * TODO Generalise this for all Excel format strings - */ -public class DateFormatConverter { - private static POILogger logger = POILogFactory.getLogger(DateFormatConverter.class); - - public static class DateFormatTokenizer { - String format; - int pos; - - public DateFormatTokenizer(String format) { - this.format = format; - } - - public String getNextToken() { - if( pos >= format.length() ) { - return null; - } - int subStart = pos; - char curChar = format.charAt(pos); - ++pos; - if( curChar == '\'' ) { - while( ( pos < format.length() ) && ( ( curChar = format.charAt(pos) ) != '\'' ) ) { - ++pos; - } - if( pos < format.length() ) { - ++pos; - } - } else { - char activeChar = curChar; - while( ( pos < format.length() ) && ( ( curChar = format.charAt(pos) ) == activeChar ) ) { - ++pos; - } - } - return format.substring(subStart,pos); - } - - public static String[] tokenize( String format ) { - List result = new ArrayList(); - - DateFormatTokenizer tokenizer = new DateFormatTokenizer(format); - String token; - while( ( token = tokenizer.getNextToken() ) != null ) { - result.add(token); - } - - return result.toArray(new String[0]); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - - DateFormatTokenizer tokenizer = new DateFormatTokenizer(format); - String token; - while( ( token = tokenizer.getNextToken() ) != null ) { - if( result.length() > 0 ) { - result.append( ", " ); - } - result.append("[").append(token).append("]"); - } - - return result.toString(); - } - } - - private static Map tokenConversions = prepareTokenConversions(); - private static Map localePrefixes = prepareLocalePrefixes(); - - private static Map prepareTokenConversions() { - Map result = new HashMap(); - - result.put( "EEEE", "dddd" ); - result.put( "EEE", "ddd" ); - result.put( "EE", "ddd" ); - result.put( "E", "d" ); - result.put( "Z", "" ); - result.put( "z", "" ); - result.put( "a", "am/pm" ); - result.put( "A", "AM/PM" ); - result.put( "K", "H" ); - result.put( "KK", "HH" ); - result.put( "k", "h" ); - result.put( "kk", "hh" ); - result.put( "S", "0" ); - result.put( "SS", "00" ); - result.put( "SSS", "000" ); - - return result; - } - - private static Map prepareLocalePrefixes() { - Map result = new HashMap(); - - result.put( "af", "[$-0436]" ); - result.put( "am", "[$-45E]" ); - result.put( "ar_ae", "[$-3801]" ); - result.put( "ar_bh", "[$-3C01]" ); - result.put( "ar_dz", "[$-1401]" ); - result.put( "ar_eg", "[$-C01]" ); - result.put( "ar_iq", "[$-0801]" ); - result.put( "ar_jo", "[$-2C01]" ); - result.put( "ar_kw", "[$-3401]" ); - result.put( "ar_lb", "[$-3001]" ); - result.put( "ar_ly", "[$-1001]" ); - result.put( "ar_ma", "[$-1801]" ); - result.put( "ar_om", "[$-2001]" ); - result.put( "ar_qa", "[$-4001]" ); - result.put( "ar_sa", "[$-0401]" ); - result.put( "ar_sy", "[$-2801]" ); - result.put( "ar_tn", "[$-1C01]" ); - result.put( "ar_ye", "[$-2401]" ); - result.put( "as", "[$-44D]" ); - result.put( "az_az", "[$-82C]" ); - result.put( "az_az", "[$-42C]" ); - result.put( "be", "[$-0423]" ); - result.put( "bg", "[$-0402]" ); - result.put( "bn", "[$-0845]" ); - result.put( "bn", "[$-0445]" ); - result.put( "bo", "[$-0451]" ); - result.put( "bs", "[$-141A]" ); - result.put( "ca", "[$-0403]" ); - result.put( "cs", "[$-0405]" ); - result.put( "cy", "[$-0452]" ); - result.put( "da", "[$-0406]" ); - result.put( "de_at", "[$-C07]" ); - result.put( "de_ch", "[$-0807]" ); - result.put( "de_de", "[$-0407]" ); - result.put( "de_li", "[$-1407]" ); - result.put( "de_lu", "[$-1007]" ); - result.put( "dv", "[$-0465]" ); - result.put( "el", "[$-0408]" ); - result.put( "en_au", "[$-C09]" ); - result.put( "en_bz", "[$-2809]" ); - result.put( "en_ca", "[$-1009]" ); - result.put( "en_cb", "[$-2409]" ); - result.put( "en_gb", "[$-0809]" ); - result.put( "en_ie", "[$-1809]" ); - result.put( "en_in", "[$-4009]" ); - result.put( "en_jm", "[$-2009]" ); - result.put( "en_nz", "[$-1409]" ); - result.put( "en_ph", "[$-3409]" ); - result.put( "en_tt", "[$-2C09]" ); - result.put( "en_us", "[$-0409]" ); - result.put( "en_za", "[$-1C09]" ); - result.put( "es_ar", "[$-2C0A]" ); - result.put( "es_bo", "[$-400A]" ); - result.put( "es_cl", "[$-340A]" ); - result.put( "es_co", "[$-240A]" ); - result.put( "es_cr", "[$-140A]" ); - result.put( "es_do", "[$-1C0A]" ); - result.put( "es_ec", "[$-300A]" ); - result.put( "es_es", "[$-40A]" ); - result.put( "es_gt", "[$-100A]" ); - result.put( "es_hn", "[$-480A]" ); - result.put( "es_mx", "[$-80A]" ); - result.put( "es_ni", "[$-4C0A]" ); - result.put( "es_pa", "[$-180A]" ); - result.put( "es_pe", "[$-280A]" ); - result.put( "es_pr", "[$-500A]" ); - result.put( "es_py", "[$-3C0A]" ); - result.put( "es_sv", "[$-440A]" ); - result.put( "es_uy", "[$-380A]" ); - result.put( "es_ve", "[$-200A]" ); - result.put( "et", "[$-0425]" ); - result.put( "eu", "[$-42D]" ); - result.put( "fa", "[$-0429]" ); - result.put( "fi", "[$-40B]" ); - result.put( "fo", "[$-0438]" ); - result.put( "fr_be", "[$-80C]" ); - result.put( "fr_ca", "[$-C0C]" ); - result.put( "fr_ch", "[$-100C]" ); - result.put( "fr_fr", "[$-40C]" ); - result.put( "fr_lu", "[$-140C]" ); - result.put( "gd", "[$-43C]" ); - result.put( "gd_ie", "[$-83C]" ); - result.put( "gn", "[$-0474]" ); - result.put( "gu", "[$-0447]" ); - result.put( "he", "[$-40D]" ); - result.put( "hi", "[$-0439]" ); - result.put( "hr", "[$-41A]" ); - result.put( "hu", "[$-40E]" ); - result.put( "hy", "[$-42B]" ); - result.put( "id", "[$-0421]" ); - result.put( "is", "[$-40F]" ); - result.put( "it_ch", "[$-0810]" ); - result.put( "it_it", "[$-0410]" ); - result.put( "ja", "[$-0411]" ); - result.put( "kk", "[$-43F]" ); - result.put( "km", "[$-0453]" ); - result.put( "kn", "[$-44B]" ); - result.put( "ko", "[$-0412]" ); - result.put( "ks", "[$-0460]" ); - result.put( "la", "[$-0476]" ); - result.put( "lo", "[$-0454]" ); - result.put( "lt", "[$-0427]" ); - result.put( "lv", "[$-0426]" ); - result.put( "mi", "[$-0481]" ); - result.put( "mk", "[$-42F]" ); - result.put( "ml", "[$-44C]" ); - result.put( "mn", "[$-0850]" ); - result.put( "mn", "[$-0450]" ); - result.put( "mr", "[$-44E]" ); - result.put( "ms_bn", "[$-83E]" ); - result.put( "ms_my", "[$-43E]" ); - result.put( "mt", "[$-43A]" ); - result.put( "my", "[$-0455]" ); - result.put( "ne", "[$-0461]" ); - result.put( "nl_be", "[$-0813]" ); - result.put( "nl_nl", "[$-0413]" ); - result.put( "no_no", "[$-0814]" ); - result.put( "or", "[$-0448]" ); - result.put( "pa", "[$-0446]" ); - result.put( "pl", "[$-0415]" ); - result.put( "pt_br", "[$-0416]" ); - result.put( "pt_pt", "[$-0816]" ); - result.put( "rm", "[$-0417]" ); - result.put( "ro", "[$-0418]" ); - result.put( "ro_mo", "[$-0818]" ); - result.put( "ru", "[$-0419]" ); - result.put( "ru_mo", "[$-0819]" ); - result.put( "sa", "[$-44F]" ); - result.put( "sb", "[$-42E]" ); - result.put( "sd", "[$-0459]" ); - result.put( "si", "[$-45B]" ); - result.put( "sk", "[$-41B]" ); - result.put( "sl", "[$-0424]" ); - result.put( "so", "[$-0477]" ); - result.put( "sq", "[$-41C]" ); - result.put( "sr_sp", "[$-C1A]" ); - result.put( "sr_sp", "[$-81A]" ); - result.put( "sv_fi", "[$-81D]" ); - result.put( "sv_se", "[$-41D]" ); - result.put( "sw", "[$-0441]" ); - result.put( "ta", "[$-0449]" ); - result.put( "te", "[$-44A]" ); - result.put( "tg", "[$-0428]" ); - result.put( "th", "[$-41E]" ); - result.put( "tk", "[$-0442]" ); - result.put( "tn", "[$-0432]" ); - result.put( "tr", "[$-41F]" ); - result.put( "ts", "[$-0431]" ); - result.put( "tt", "[$-0444]" ); - result.put( "uk", "[$-0422]" ); - result.put( "ur", "[$-0420]" ); - result.put( "UTF_8", "[$-0000]" ); - result.put( "uz_uz", "[$-0843]" ); - result.put( "uz_uz", "[$-0443]" ); - result.put( "vi", "[$-42A]" ); - result.put( "xh", "[$-0434]" ); - result.put( "yi", "[$-43D]" ); - result.put( "zh_cn", "[$-0804]" ); - result.put( "zh_hk", "[$-C04]" ); - result.put( "zh_mo", "[$-1404]" ); - result.put( "zh_sg", "[$-1004]" ); - result.put( "zh_tw", "[$-0404]" ); - result.put( "zu", "[$-0435]" ); - - result.put( "ar", "[$-0401]" ); - result.put( "bn", "[$-0845]" ); - result.put( "de", "[$-0407]" ); - result.put( "en", "[$-0409]" ); - result.put( "es", "[$-40A]" ); - result.put( "fr", "[$-40C]" ); - result.put( "it", "[$-0410]" ); - result.put( "ms", "[$-43E]" ); - result.put( "nl", "[$-0413]" ); - result.put( "nn", "[$-0814]" ); - result.put( "no", "[$-0414]" ); - result.put( "pt", "[$-0816]" ); - result.put( "sr", "[$-C1A]" ); - result.put( "sv", "[$-41D]" ); - result.put( "uz", "[$-0843]" ); - result.put( "zh", "[$-0804]" ); - - result.put( "ga", "[$-43C]" ); - result.put( "ga_ie", "[$-83C]" ); - result.put( "in", "[$-0421]" ); - result.put( "iw", "[$-40D]" ); - - // JDK 8 adds an empty locale-string, see also https://issues.apache.org/jira/browse/LANG-941 - result.put( "", "[$-0409]" ); - - return result; - } - - public static String getPrefixForLocale( Locale locale ) { - String localeString = locale.toString().toLowerCase(locale); - String result = localePrefixes.get( localeString ); - if( result == null ) { - result = localePrefixes.get( localeString.substring( 0, 2 ) ); - if( result == null ) { - Locale parentLocale = new Locale(localeString.substring( 0, 2 )); - logger.log( POILogger.ERROR, "Unable to find prefix for " + locale + "(" + locale.getDisplayName(Locale.ROOT) + ") or " - + localeString.substring( 0, 2 ) + "(" + parentLocale.getDisplayName(Locale.ROOT) + ")" ); - return ""; - } - } - return result; - } - - public static String convert( Locale locale, DateFormat df ) { - String ptrn = ((SimpleDateFormat)df).toPattern(); - return convert(locale, ptrn); - } - - public static String convert( Locale locale, String format ) { - StringBuilder result = new StringBuilder(); - - result.append(getPrefixForLocale(locale)); - DateFormatTokenizer tokenizer = new DateFormatTokenizer(format); - String token; - while( ( token = tokenizer.getNextToken() ) != null ) { - if( token.startsWith("'") ) { - result.append( token.replaceAll("'", "\"") ); - } else if( ! Character.isLetter( token.charAt( 0 ) ) ) { - result.append( token ); - } else { - // It's a code, translate it if necessary - String mappedToken = tokenConversions.get(token); - result.append( mappedToken == null ? token : mappedToken ); - } - } - result.append(";@"); - return result.toString().trim(); - } - - public static String getJavaDatePattern(int style, Locale locale) { - DateFormat df = DateFormat.getDateInstance(style, locale); - if( df instanceof SimpleDateFormat ) { - return ((SimpleDateFormat)df).toPattern(); - } else { - switch( style ) { - case DateFormat.SHORT: - return "d/MM/yy"; - case DateFormat.MEDIUM: - return "MMM d, yyyy"; - case DateFormat.LONG: - return "MMMM d, yyyy"; - case DateFormat.FULL: - return "dddd, MMMM d, yyyy"; - default: - return "MMM d, yyyy"; - } - } - } - - public static String getJavaTimePattern(int style, Locale locale) { - DateFormat df = DateFormat.getTimeInstance(style, locale); - if( df instanceof SimpleDateFormat ) { - return ((SimpleDateFormat)df).toPattern(); - } else { - switch( style ) { - case DateFormat.SHORT: - return "h:mm a"; - case DateFormat.MEDIUM: - return "h:mm:ss a"; - case DateFormat.LONG: - return "h:mm:ss a"; - case DateFormat.FULL: - return "h:mm:ss a"; - default: - return "h:mm:ss a"; - } - } - } - - public static String getJavaDateTimePattern(int style, Locale locale) { - DateFormat df = DateFormat.getDateTimeInstance(style, style, locale); - if( df instanceof SimpleDateFormat ) { - return ((SimpleDateFormat)df).toPattern(); - } else { - switch( style ) { - case DateFormat.SHORT: - return "M/d/yy h:mm a"; - case DateFormat.MEDIUM: - return "MMM d, yyyy h:mm:ss a"; - case DateFormat.LONG: - return "MMMM d, yyyy h:mm:ss a"; - case DateFormat.FULL: - return "dddd, MMMM d, yyyy h:mm:ss a"; - default: - return "MMM d, yyyy h:mm:ss a"; - } - } - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.util; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * Convert java DateFormat patterns into Excel custom number formats. + * For example, to format a date in excel using the "dd MMMM, yyyy" pattern and Japanese + * locale, use the following code: + * + *

+ *      // returns "[$-0411]dd MMMM, yyyy;@" where the [$-0411] prefix tells Excel to use the Japanese locale
+ *      String excelFormatPattern = DateFormatConverter.convert(Locale.JAPANESE, "dd MMMM, yyyy");
+ *
+ *      CellStyle cellStyle = workbook.createCellStyle();
+ *
+ *      DataFormat poiFormat = workbook.createDataFormat();
+ *      cellStyle.setDataFormat(poiFormat.getFormat(excelFormatPattern));
+ *      cell.setCellValue(new Date());
+ *      cell.setCellStyle(cellStyle);  // formats date as '2012\u5e743\u670817\u65e5'
+ *  
+ * + * TODO Generalise this for all Excel format strings + */ +public class DateFormatConverter { + private static POILogger logger = POILogFactory.getLogger(DateFormatConverter.class); + + public static class DateFormatTokenizer { + String format; + int pos; + + public DateFormatTokenizer(String format) { + this.format = format; + } + + public String getNextToken() { + if( pos >= format.length() ) { + return null; + } + int subStart = pos; + char curChar = format.charAt(pos); + ++pos; + if( curChar == '\'' ) { + while( ( pos < format.length() ) && ( ( curChar = format.charAt(pos) ) != '\'' ) ) { + ++pos; + } + if( pos < format.length() ) { + ++pos; + } + } else { + char activeChar = curChar; + while( ( pos < format.length() ) && ( ( curChar = format.charAt(pos) ) == activeChar ) ) { + ++pos; + } + } + return format.substring(subStart,pos); + } + + public static String[] tokenize( String format ) { + List result = new ArrayList(); + + DateFormatTokenizer tokenizer = new DateFormatTokenizer(format); + String token; + while( ( token = tokenizer.getNextToken() ) != null ) { + result.add(token); + } + + return result.toArray(new String[0]); + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + + DateFormatTokenizer tokenizer = new DateFormatTokenizer(format); + String token; + while( ( token = tokenizer.getNextToken() ) != null ) { + if( result.length() > 0 ) { + result.append( ", " ); + } + result.append("[").append(token).append("]"); + } + + return result.toString(); + } + } + + private static Map tokenConversions = prepareTokenConversions(); + private static Map localePrefixes = prepareLocalePrefixes(); + + private static Map prepareTokenConversions() { + Map result = new HashMap(); + + result.put( "EEEE", "dddd" ); + result.put( "EEE", "ddd" ); + result.put( "EE", "ddd" ); + result.put( "E", "d" ); + result.put( "Z", "" ); + result.put( "z", "" ); + result.put( "a", "am/pm" ); + result.put( "A", "AM/PM" ); + result.put( "K", "H" ); + result.put( "KK", "HH" ); + result.put( "k", "h" ); + result.put( "kk", "hh" ); + result.put( "S", "0" ); + result.put( "SS", "00" ); + result.put( "SSS", "000" ); + + return result; + } + + private static Map prepareLocalePrefixes() { + Map result = new HashMap(); + + result.put( "af", "[$-0436]" ); + result.put( "am", "[$-45E]" ); + result.put( "ar_ae", "[$-3801]" ); + result.put( "ar_bh", "[$-3C01]" ); + result.put( "ar_dz", "[$-1401]" ); + result.put( "ar_eg", "[$-C01]" ); + result.put( "ar_iq", "[$-0801]" ); + result.put( "ar_jo", "[$-2C01]" ); + result.put( "ar_kw", "[$-3401]" ); + result.put( "ar_lb", "[$-3001]" ); + result.put( "ar_ly", "[$-1001]" ); + result.put( "ar_ma", "[$-1801]" ); + result.put( "ar_om", "[$-2001]" ); + result.put( "ar_qa", "[$-4001]" ); + result.put( "ar_sa", "[$-0401]" ); + result.put( "ar_sy", "[$-2801]" ); + result.put( "ar_tn", "[$-1C01]" ); + result.put( "ar_ye", "[$-2401]" ); + result.put( "as", "[$-44D]" ); + result.put( "az_az", "[$-82C]" ); + result.put( "az_az", "[$-42C]" ); + result.put( "be", "[$-0423]" ); + result.put( "bg", "[$-0402]" ); + result.put( "bn", "[$-0845]" ); + result.put( "bn", "[$-0445]" ); + result.put( "bo", "[$-0451]" ); + result.put( "bs", "[$-141A]" ); + result.put( "ca", "[$-0403]" ); + result.put( "cs", "[$-0405]" ); + result.put( "cy", "[$-0452]" ); + result.put( "da", "[$-0406]" ); + result.put( "de_at", "[$-C07]" ); + result.put( "de_ch", "[$-0807]" ); + result.put( "de_de", "[$-0407]" ); + result.put( "de_li", "[$-1407]" ); + result.put( "de_lu", "[$-1007]" ); + result.put( "dv", "[$-0465]" ); + result.put( "el", "[$-0408]" ); + result.put( "en_au", "[$-C09]" ); + result.put( "en_bz", "[$-2809]" ); + result.put( "en_ca", "[$-1009]" ); + result.put( "en_cb", "[$-2409]" ); + result.put( "en_gb", "[$-0809]" ); + result.put( "en_ie", "[$-1809]" ); + result.put( "en_in", "[$-4009]" ); + result.put( "en_jm", "[$-2009]" ); + result.put( "en_nz", "[$-1409]" ); + result.put( "en_ph", "[$-3409]" ); + result.put( "en_tt", "[$-2C09]" ); + result.put( "en_us", "[$-0409]" ); + result.put( "en_za", "[$-1C09]" ); + result.put( "es_ar", "[$-2C0A]" ); + result.put( "es_bo", "[$-400A]" ); + result.put( "es_cl", "[$-340A]" ); + result.put( "es_co", "[$-240A]" ); + result.put( "es_cr", "[$-140A]" ); + result.put( "es_do", "[$-1C0A]" ); + result.put( "es_ec", "[$-300A]" ); + result.put( "es_es", "[$-40A]" ); + result.put( "es_gt", "[$-100A]" ); + result.put( "es_hn", "[$-480A]" ); + result.put( "es_mx", "[$-80A]" ); + result.put( "es_ni", "[$-4C0A]" ); + result.put( "es_pa", "[$-180A]" ); + result.put( "es_pe", "[$-280A]" ); + result.put( "es_pr", "[$-500A]" ); + result.put( "es_py", "[$-3C0A]" ); + result.put( "es_sv", "[$-440A]" ); + result.put( "es_uy", "[$-380A]" ); + result.put( "es_ve", "[$-200A]" ); + result.put( "et", "[$-0425]" ); + result.put( "eu", "[$-42D]" ); + result.put( "fa", "[$-0429]" ); + result.put( "fi", "[$-40B]" ); + result.put( "fo", "[$-0438]" ); + result.put( "fr_be", "[$-80C]" ); + result.put( "fr_ca", "[$-C0C]" ); + result.put( "fr_ch", "[$-100C]" ); + result.put( "fr_fr", "[$-40C]" ); + result.put( "fr_lu", "[$-140C]" ); + result.put( "gd", "[$-43C]" ); + result.put( "gd_ie", "[$-83C]" ); + result.put( "gn", "[$-0474]" ); + result.put( "gu", "[$-0447]" ); + result.put( "he", "[$-40D]" ); + result.put( "hi", "[$-0439]" ); + result.put( "hr", "[$-41A]" ); + result.put( "hu", "[$-40E]" ); + result.put( "hy", "[$-42B]" ); + result.put( "id", "[$-0421]" ); + result.put( "is", "[$-40F]" ); + result.put( "it_ch", "[$-0810]" ); + result.put( "it_it", "[$-0410]" ); + result.put( "ja", "[$-0411]" ); + result.put( "kk", "[$-43F]" ); + result.put( "km", "[$-0453]" ); + result.put( "kn", "[$-44B]" ); + result.put( "ko", "[$-0412]" ); + result.put( "ks", "[$-0460]" ); + result.put( "la", "[$-0476]" ); + result.put( "lo", "[$-0454]" ); + result.put( "lt", "[$-0427]" ); + result.put( "lv", "[$-0426]" ); + result.put( "mi", "[$-0481]" ); + result.put( "mk", "[$-42F]" ); + result.put( "ml", "[$-44C]" ); + result.put( "mn", "[$-0850]" ); + result.put( "mn", "[$-0450]" ); + result.put( "mr", "[$-44E]" ); + result.put( "ms_bn", "[$-83E]" ); + result.put( "ms_my", "[$-43E]" ); + result.put( "mt", "[$-43A]" ); + result.put( "my", "[$-0455]" ); + result.put( "ne", "[$-0461]" ); + result.put( "nl_be", "[$-0813]" ); + result.put( "nl_nl", "[$-0413]" ); + result.put( "no_no", "[$-0814]" ); + result.put( "or", "[$-0448]" ); + result.put( "pa", "[$-0446]" ); + result.put( "pl", "[$-0415]" ); + result.put( "pt_br", "[$-0416]" ); + result.put( "pt_pt", "[$-0816]" ); + result.put( "rm", "[$-0417]" ); + result.put( "ro", "[$-0418]" ); + result.put( "ro_mo", "[$-0818]" ); + result.put( "ru", "[$-0419]" ); + result.put( "ru_mo", "[$-0819]" ); + result.put( "sa", "[$-44F]" ); + result.put( "sb", "[$-42E]" ); + result.put( "sd", "[$-0459]" ); + result.put( "si", "[$-45B]" ); + result.put( "sk", "[$-41B]" ); + result.put( "sl", "[$-0424]" ); + result.put( "so", "[$-0477]" ); + result.put( "sq", "[$-41C]" ); + result.put( "sr_sp", "[$-C1A]" ); + result.put( "sr_sp", "[$-81A]" ); + result.put( "sv_fi", "[$-81D]" ); + result.put( "sv_se", "[$-41D]" ); + result.put( "sw", "[$-0441]" ); + result.put( "ta", "[$-0449]" ); + result.put( "te", "[$-44A]" ); + result.put( "tg", "[$-0428]" ); + result.put( "th", "[$-41E]" ); + result.put( "tk", "[$-0442]" ); + result.put( "tn", "[$-0432]" ); + result.put( "tr", "[$-41F]" ); + result.put( "ts", "[$-0431]" ); + result.put( "tt", "[$-0444]" ); + result.put( "uk", "[$-0422]" ); + result.put( "ur", "[$-0420]" ); + result.put( "UTF_8", "[$-0000]" ); + result.put( "uz_uz", "[$-0843]" ); + result.put( "uz_uz", "[$-0443]" ); + result.put( "vi", "[$-42A]" ); + result.put( "xh", "[$-0434]" ); + result.put( "yi", "[$-43D]" ); + result.put( "zh_cn", "[$-0804]" ); + result.put( "zh_hk", "[$-C04]" ); + result.put( "zh_mo", "[$-1404]" ); + result.put( "zh_sg", "[$-1004]" ); + result.put( "zh_tw", "[$-0404]" ); + result.put( "zu", "[$-0435]" ); + + result.put( "ar", "[$-0401]" ); + result.put( "bn", "[$-0845]" ); + result.put( "de", "[$-0407]" ); + result.put( "en", "[$-0409]" ); + result.put( "es", "[$-40A]" ); + result.put( "fr", "[$-40C]" ); + result.put( "it", "[$-0410]" ); + result.put( "ms", "[$-43E]" ); + result.put( "nl", "[$-0413]" ); + result.put( "nn", "[$-0814]" ); + result.put( "no", "[$-0414]" ); + result.put( "pt", "[$-0816]" ); + result.put( "sr", "[$-C1A]" ); + result.put( "sv", "[$-41D]" ); + result.put( "uz", "[$-0843]" ); + result.put( "zh", "[$-0804]" ); + + result.put( "ga", "[$-43C]" ); + result.put( "ga_ie", "[$-83C]" ); + result.put( "in", "[$-0421]" ); + result.put( "iw", "[$-40D]" ); + + // JDK 8 adds an empty locale-string, see also https://issues.apache.org/jira/browse/LANG-941 + result.put( "", "[$-0409]" ); + + return result; + } + + public static String getPrefixForLocale( Locale locale ) { + String localeString = locale.toString().toLowerCase(locale); + String result = localePrefixes.get( localeString ); + if( result == null ) { + result = localePrefixes.get( localeString.substring( 0, 2 ) ); + if( result == null ) { + Locale parentLocale = new Locale(localeString.substring( 0, 2 )); + logger.log( POILogger.ERROR, "Unable to find prefix for " + locale + "(" + locale.getDisplayName(Locale.ROOT) + ") or " + + localeString.substring( 0, 2 ) + "(" + parentLocale.getDisplayName(Locale.ROOT) + ")" ); + return ""; + } + } + return result; + } + + public static String convert( Locale locale, DateFormat df ) { + String ptrn = ((SimpleDateFormat)df).toPattern(); + return convert(locale, ptrn); + } + + public static String convert( Locale locale, String format ) { + StringBuilder result = new StringBuilder(); + + result.append(getPrefixForLocale(locale)); + DateFormatTokenizer tokenizer = new DateFormatTokenizer(format); + String token; + while( ( token = tokenizer.getNextToken() ) != null ) { + if( token.startsWith("'") ) { + result.append( token.replaceAll("'", "\"") ); + } else if( ! Character.isLetter( token.charAt( 0 ) ) ) { + result.append( token ); + } else { + // It's a code, translate it if necessary + String mappedToken = tokenConversions.get(token); + result.append( mappedToken == null ? token : mappedToken ); + } + } + result.append(";@"); + return result.toString().trim(); + } + + public static String getJavaDatePattern(int style, Locale locale) { + DateFormat df = DateFormat.getDateInstance(style, locale); + if( df instanceof SimpleDateFormat ) { + return ((SimpleDateFormat)df).toPattern(); + } else { + switch( style ) { + case DateFormat.SHORT: + return "d/MM/yy"; + case DateFormat.MEDIUM: + return "MMM d, yyyy"; + case DateFormat.LONG: + return "MMMM d, yyyy"; + case DateFormat.FULL: + return "dddd, MMMM d, yyyy"; + default: + return "MMM d, yyyy"; + } + } + } + + public static String getJavaTimePattern(int style, Locale locale) { + DateFormat df = DateFormat.getTimeInstance(style, locale); + if( df instanceof SimpleDateFormat ) { + return ((SimpleDateFormat)df).toPattern(); + } else { + switch( style ) { + case DateFormat.SHORT: + return "h:mm a"; + case DateFormat.MEDIUM: + return "h:mm:ss a"; + case DateFormat.LONG: + return "h:mm:ss a"; + case DateFormat.FULL: + return "h:mm:ss a"; + default: + return "h:mm:ss a"; + } + } + } + + public static String getJavaDateTimePattern(int style, Locale locale) { + DateFormat df = DateFormat.getDateTimeInstance(style, style, locale); + if( df instanceof SimpleDateFormat ) { + return ((SimpleDateFormat)df).toPattern(); + } else { + switch( style ) { + case DateFormat.SHORT: + return "M/d/yy h:mm a"; + case DateFormat.MEDIUM: + return "MMM d, yyyy h:mm:ss a"; + case DateFormat.LONG: + return "MMMM d, yyyy h:mm:ss a"; + case DateFormat.FULL: + return "dddd, MMMM d, yyyy h:mm:ss a"; + default: + return "MMM d, yyyy h:mm:ss a"; + } + } + } + +} diff --git a/src/java/org/apache/poi/ss/util/ExpandedDouble.java b/src/java/org/apache/poi/ss/util/ExpandedDouble.java index 41827df044..ad9489a737 100644 --- a/src/java/org/apache/poi/ss/util/ExpandedDouble.java +++ b/src/java/org/apache/poi/ss/util/ExpandedDouble.java @@ -1,98 +1,98 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.util; - -import java.math.BigInteger; -import static org.apache.poi.ss.util.IEEEDouble.*; - -/** - * Represents a 64 bit IEEE double quantity expressed with both decimal and binary exponents - * Does not handle negative numbers or zero - *

- * The value of a {@link ExpandedDouble} is given by
- * a × 2b - *
- * where:
- * - * a = significand
- * b = binaryExponent - bitLength(significand) + 1
- * - * @author Josh Micich - */ -final class ExpandedDouble { - private static final BigInteger BI_FRAC_MASK = BigInteger.valueOf(FRAC_MASK); - private static final BigInteger BI_IMPLIED_FRAC_MSB = BigInteger.valueOf(FRAC_ASSUMED_HIGH_BIT); - - private static BigInteger getFrac(long rawBits) { - return BigInteger.valueOf(rawBits).and(BI_FRAC_MASK).or(BI_IMPLIED_FRAC_MSB).shiftLeft(11); - } - - - public static ExpandedDouble fromRawBitsAndExponent(long rawBits, int exp) { - return new ExpandedDouble(getFrac(rawBits), exp); - } - - /** - * Always 64 bits long (MSB, bit-63 is '1') - */ - private final BigInteger _significand; - private final int _binaryExponent; - - public ExpandedDouble(long rawBits) { - int biasedExp = (int) (rawBits >> 52); - if (biasedExp == 0) { - // sub-normal numbers - BigInteger frac = BigInteger.valueOf(rawBits).and(BI_FRAC_MASK); - int expAdj = 64 - frac.bitLength(); - _significand = frac.shiftLeft(expAdj); - _binaryExponent = (biasedExp & 0x07FF) - 1023 - expAdj; - } else { - BigInteger frac = getFrac(rawBits); - _significand = frac; - _binaryExponent = (biasedExp & 0x07FF) - 1023; - } - } - - ExpandedDouble(BigInteger frac, int binaryExp) { - if (frac.bitLength() != 64) { - throw new IllegalArgumentException("bad bit length"); - } - _significand = frac; - _binaryExponent = binaryExp; - } - - - /** - * Convert to an equivalent {@link NormalisedDecimal} representation having 15 decimal digits of precision in the - * non-fractional bits of the significand. - */ - public NormalisedDecimal normaliseBaseTen() { - return NormalisedDecimal.create(_significand, _binaryExponent); - } - - /** - * @return the number of non-fractional bits after the MSB of the significand - */ - public int getBinaryExponent() { - return _binaryExponent; - } - - public BigInteger getSignificand() { - return _significand; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.util; + +import java.math.BigInteger; +import static org.apache.poi.ss.util.IEEEDouble.*; + +/** + * Represents a 64 bit IEEE double quantity expressed with both decimal and binary exponents + * Does not handle negative numbers or zero + *

+ * The value of a {@link ExpandedDouble} is given by
+ * a × 2b + *
+ * where:
+ * + * a = significand
+ * b = binaryExponent - bitLength(significand) + 1
+ * + * @author Josh Micich + */ +final class ExpandedDouble { + private static final BigInteger BI_FRAC_MASK = BigInteger.valueOf(FRAC_MASK); + private static final BigInteger BI_IMPLIED_FRAC_MSB = BigInteger.valueOf(FRAC_ASSUMED_HIGH_BIT); + + private static BigInteger getFrac(long rawBits) { + return BigInteger.valueOf(rawBits).and(BI_FRAC_MASK).or(BI_IMPLIED_FRAC_MSB).shiftLeft(11); + } + + + public static ExpandedDouble fromRawBitsAndExponent(long rawBits, int exp) { + return new ExpandedDouble(getFrac(rawBits), exp); + } + + /** + * Always 64 bits long (MSB, bit-63 is '1') + */ + private final BigInteger _significand; + private final int _binaryExponent; + + public ExpandedDouble(long rawBits) { + int biasedExp = (int) (rawBits >> 52); + if (biasedExp == 0) { + // sub-normal numbers + BigInteger frac = BigInteger.valueOf(rawBits).and(BI_FRAC_MASK); + int expAdj = 64 - frac.bitLength(); + _significand = frac.shiftLeft(expAdj); + _binaryExponent = (biasedExp & 0x07FF) - 1023 - expAdj; + } else { + BigInteger frac = getFrac(rawBits); + _significand = frac; + _binaryExponent = (biasedExp & 0x07FF) - 1023; + } + } + + ExpandedDouble(BigInteger frac, int binaryExp) { + if (frac.bitLength() != 64) { + throw new IllegalArgumentException("bad bit length"); + } + _significand = frac; + _binaryExponent = binaryExp; + } + + + /** + * Convert to an equivalent {@link NormalisedDecimal} representation having 15 decimal digits of precision in the + * non-fractional bits of the significand. + */ + public NormalisedDecimal normaliseBaseTen() { + return NormalisedDecimal.create(_significand, _binaryExponent); + } + + /** + * @return the number of non-fractional bits after the MSB of the significand + */ + public int getBinaryExponent() { + return _binaryExponent; + } + + public BigInteger getSignificand() { + return _significand; + } +} diff --git a/src/java/org/apache/poi/ss/util/ImageUtils.java b/src/java/org/apache/poi/ss/util/ImageUtils.java index 13c07c3533..be83ce838e 100644 --- a/src/java/org/apache/poi/ss/util/ImageUtils.java +++ b/src/java/org/apache/poi/ss/util/ImageUtils.java @@ -1,285 +1,285 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.util; - -import static org.apache.poi.util.Units.EMU_PER_PIXEL; - -import java.awt.Dimension; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; - -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.stream.ImageInputStream; - -import org.apache.poi.hssf.usermodel.HSSFClientAnchor; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Picture; -import org.apache.poi.ss.usermodel.PictureData; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.Units; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -/** - * @author Yegor Kozlov - */ -public class ImageUtils { - private static final POILogger logger = POILogFactory.getLogger(ImageUtils.class); - - public static final int PIXEL_DPI = 96; - - /** - * Return the dimension of this image - * - * @param is the stream containing the image data - * @param type type of the picture: {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_JPEG}, - * {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_PNG} or {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_DIB} - * - * @return image dimension in pixels - */ - public static Dimension getImageDimension(InputStream is, int type){ - Dimension size = new Dimension(); - - switch (type){ - //we can calculate the preferred size only for JPEG, PNG and BMP - //other formats like WMF, EMF and PICT are not supported in Java - case Workbook.PICTURE_TYPE_JPEG: - case Workbook.PICTURE_TYPE_PNG: - case Workbook.PICTURE_TYPE_DIB: - try { - //read the image using javax.imageio.* - ImageInputStream iis = ImageIO.createImageInputStream( is ); - try { - Iterator i = ImageIO.getImageReaders( iis ); - ImageReader r = i.next(); - try { - r.setInput( iis ); - BufferedImage img = r.read(0); - - int[] dpi = getResolution(r); - - //if DPI is zero then assume standard 96 DPI - //since cannot divide by zero - if (dpi[0] == 0) dpi[0] = PIXEL_DPI; - if (dpi[1] == 0) dpi[1] = PIXEL_DPI; - - size.width = img.getWidth()*PIXEL_DPI/dpi[0]; - size.height = img.getHeight()*PIXEL_DPI/dpi[1]; - } finally { - r.dispose(); - } - } finally { - iis.close(); - } - - } catch (IOException e) { - //silently return if ImageIO failed to read the image - logger.log(POILogger.WARN, e); - } - - break; - default: - logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized"); - } - return size; - } - - /** - * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. - * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize - * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. - * - * @return array of two elements: {horisontalPdi, verticalDpi}. - * {96, 96} is the default. - */ - public static int[] getResolution(ImageReader r) throws IOException { - int hdpi=96, vdpi=96; - double mm2inch = 25.4; - - NodeList lst; - Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); - lst = node.getElementsByTagName("HorizontalPixelSize"); - if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - lst = node.getElementsByTagName("VerticalPixelSize"); - if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - return new int[]{hdpi, vdpi}; - } - - /** - * Calculate and set the preferred size (anchor) for this picture. - * - * @param scaleX the amount by which image width is multiplied relative to the original width. - * @param scaleY the amount by which image height is multiplied relative to the original height. - * @return the new Dimensions of the scaled picture in EMUs - */ - public static Dimension setPreferredSize(Picture picture, double scaleX, double scaleY){ - ClientAnchor anchor = picture.getClientAnchor(); - boolean isHSSF = (anchor instanceof HSSFClientAnchor); - PictureData data = picture.getPictureData(); - Sheet sheet = picture.getSheet(); - - // in pixel - Dimension imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType()); - // in emus - Dimension anchorSize = ImageUtils.getDimensionFromAnchor(picture); - final double scaledWidth = (scaleX == Double.MAX_VALUE) - ? imgSize.getWidth() : anchorSize.getWidth()/EMU_PER_PIXEL * scaleX; - final double scaledHeight = (scaleY == Double.MAX_VALUE) - ? imgSize.getHeight() : anchorSize.getHeight()/EMU_PER_PIXEL * scaleY; - - double w = 0; - int col2 = anchor.getCol1(); - int dx2 = 0; - - //space in the leftmost cell - w = sheet.getColumnWidthInPixels(col2++); - if (isHSSF) { - w *= 1d - anchor.getDx1()/1024d; - } else { - w -= anchor.getDx1()/(double)EMU_PER_PIXEL; - } - - while(w < scaledWidth){ - w += sheet.getColumnWidthInPixels(col2++); - } - - if(w > scaledWidth) { - //calculate dx2, offset in the rightmost cell - double cw = sheet.getColumnWidthInPixels(--col2); - double delta = w - scaledWidth; - if (isHSSF) { - dx2 = (int)((cw-delta)/cw*1024); - } else { - dx2 = (int)((cw-delta)*EMU_PER_PIXEL); - } - if (dx2 < 0) dx2 = 0; - } - anchor.setCol2(col2); - anchor.setDx2(dx2); - - double h = 0; - int row2 = anchor.getRow1(); - int dy2 = 0; - - h = getRowHeightInPixels(sheet,row2++); - if (isHSSF) { - h *= 1 - anchor.getDy1()/256d; - } else { - h -= anchor.getDy1()/(double)EMU_PER_PIXEL; - } - - while(h < scaledHeight){ - h += getRowHeightInPixels(sheet,row2++); - } - - if(h > scaledHeight) { - double ch = getRowHeightInPixels(sheet,--row2); - double delta = h - scaledHeight; - if (isHSSF) { - dy2 = (int)((ch-delta)/ch*256); - } else { - dy2 = (int)((ch-delta)*EMU_PER_PIXEL); - } - if (dy2 < 0) dy2 = 0; - } - - anchor.setRow2(row2); - anchor.setDy2(dy2); - - Dimension dim = new Dimension( - (int)Math.round(scaledWidth*EMU_PER_PIXEL), - (int)Math.round(scaledHeight*EMU_PER_PIXEL) - ); - - return dim; - } - - /** - * Calculates the dimensions in EMUs for the anchor of the given picture - * - * @param picture the picture containing the anchor - * @return the dimensions in EMUs - */ - public static Dimension getDimensionFromAnchor(Picture picture) { - ClientAnchor anchor = picture.getClientAnchor(); - boolean isHSSF = (anchor instanceof HSSFClientAnchor); - Sheet sheet = picture.getSheet(); - - double w = 0; - int col2 = anchor.getCol1(); - - //space in the leftmost cell - w = sheet.getColumnWidthInPixels(col2++); - if (isHSSF) { - w *= 1 - anchor.getDx1()/1024d; - } else { - w -= anchor.getDx1()/(double)EMU_PER_PIXEL; - } - - while(col2 < anchor.getCol2()){ - w += sheet.getColumnWidthInPixels(col2++); - } - - if (isHSSF) { - w += sheet.getColumnWidthInPixels(col2) * anchor.getDx2()/1024d; - } else { - w += anchor.getDx2()/(double)EMU_PER_PIXEL; - } - - double h = 0; - int row2 = anchor.getRow1(); - - h = getRowHeightInPixels(sheet,row2++); - if (isHSSF) { - h *= 1 - anchor.getDy1()/256d; - } else { - h -= anchor.getDy1()/(double)EMU_PER_PIXEL; - } - - while(row2 < anchor.getRow2()){ - h += getRowHeightInPixels(sheet,row2++); - } - - if (isHSSF) { - h += getRowHeightInPixels(sheet,row2) * anchor.getDy2()/256; - } else { - h += anchor.getDy2()/(double)EMU_PER_PIXEL; - } - - w *= EMU_PER_PIXEL; - h *= EMU_PER_PIXEL; - - return new Dimension((int)Math.rint(w), (int)Math.rint(h)); - } - - - public static double getRowHeightInPixels(Sheet sheet, int rowNum) { - Row r = sheet.getRow(rowNum); - double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints(); - return Units.toEMU(points)/(double)EMU_PER_PIXEL; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.util; + +import static org.apache.poi.util.Units.EMU_PER_PIXEL; + +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +import org.apache.poi.hssf.usermodel.HSSFClientAnchor; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Picture; +import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.Units; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * @author Yegor Kozlov + */ +public class ImageUtils { + private static final POILogger logger = POILogFactory.getLogger(ImageUtils.class); + + public static final int PIXEL_DPI = 96; + + /** + * Return the dimension of this image + * + * @param is the stream containing the image data + * @param type type of the picture: {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_JPEG}, + * {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_PNG} or {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_DIB} + * + * @return image dimension in pixels + */ + public static Dimension getImageDimension(InputStream is, int type){ + Dimension size = new Dimension(); + + switch (type){ + //we can calculate the preferred size only for JPEG, PNG and BMP + //other formats like WMF, EMF and PICT are not supported in Java + case Workbook.PICTURE_TYPE_JPEG: + case Workbook.PICTURE_TYPE_PNG: + case Workbook.PICTURE_TYPE_DIB: + try { + //read the image using javax.imageio.* + ImageInputStream iis = ImageIO.createImageInputStream( is ); + try { + Iterator i = ImageIO.getImageReaders( iis ); + ImageReader r = i.next(); + try { + r.setInput( iis ); + BufferedImage img = r.read(0); + + int[] dpi = getResolution(r); + + //if DPI is zero then assume standard 96 DPI + //since cannot divide by zero + if (dpi[0] == 0) dpi[0] = PIXEL_DPI; + if (dpi[1] == 0) dpi[1] = PIXEL_DPI; + + size.width = img.getWidth()*PIXEL_DPI/dpi[0]; + size.height = img.getHeight()*PIXEL_DPI/dpi[1]; + } finally { + r.dispose(); + } + } finally { + iis.close(); + } + + } catch (IOException e) { + //silently return if ImageIO failed to read the image + logger.log(POILogger.WARN, e); + } + + break; + default: + logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized"); + } + return size; + } + + /** + * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. + * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize + * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. + * + * @return array of two elements: {horisontalPdi, verticalDpi}. + * {96, 96} is the default. + */ + public static int[] getResolution(ImageReader r) throws IOException { + int hdpi=96, vdpi=96; + double mm2inch = 25.4; + + NodeList lst; + Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); + lst = node.getElementsByTagName("HorizontalPixelSize"); + if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + lst = node.getElementsByTagName("VerticalPixelSize"); + if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + return new int[]{hdpi, vdpi}; + } + + /** + * Calculate and set the preferred size (anchor) for this picture. + * + * @param scaleX the amount by which image width is multiplied relative to the original width. + * @param scaleY the amount by which image height is multiplied relative to the original height. + * @return the new Dimensions of the scaled picture in EMUs + */ + public static Dimension setPreferredSize(Picture picture, double scaleX, double scaleY){ + ClientAnchor anchor = picture.getClientAnchor(); + boolean isHSSF = (anchor instanceof HSSFClientAnchor); + PictureData data = picture.getPictureData(); + Sheet sheet = picture.getSheet(); + + // in pixel + Dimension imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType()); + // in emus + Dimension anchorSize = ImageUtils.getDimensionFromAnchor(picture); + final double scaledWidth = (scaleX == Double.MAX_VALUE) + ? imgSize.getWidth() : anchorSize.getWidth()/EMU_PER_PIXEL * scaleX; + final double scaledHeight = (scaleY == Double.MAX_VALUE) + ? imgSize.getHeight() : anchorSize.getHeight()/EMU_PER_PIXEL * scaleY; + + double w = 0; + int col2 = anchor.getCol1(); + int dx2 = 0; + + //space in the leftmost cell + w = sheet.getColumnWidthInPixels(col2++); + if (isHSSF) { + w *= 1d - anchor.getDx1()/1024d; + } else { + w -= anchor.getDx1()/(double)EMU_PER_PIXEL; + } + + while(w < scaledWidth){ + w += sheet.getColumnWidthInPixels(col2++); + } + + if(w > scaledWidth) { + //calculate dx2, offset in the rightmost cell + double cw = sheet.getColumnWidthInPixels(--col2); + double delta = w - scaledWidth; + if (isHSSF) { + dx2 = (int)((cw-delta)/cw*1024); + } else { + dx2 = (int)((cw-delta)*EMU_PER_PIXEL); + } + if (dx2 < 0) dx2 = 0; + } + anchor.setCol2(col2); + anchor.setDx2(dx2); + + double h = 0; + int row2 = anchor.getRow1(); + int dy2 = 0; + + h = getRowHeightInPixels(sheet,row2++); + if (isHSSF) { + h *= 1 - anchor.getDy1()/256d; + } else { + h -= anchor.getDy1()/(double)EMU_PER_PIXEL; + } + + while(h < scaledHeight){ + h += getRowHeightInPixels(sheet,row2++); + } + + if(h > scaledHeight) { + double ch = getRowHeightInPixels(sheet,--row2); + double delta = h - scaledHeight; + if (isHSSF) { + dy2 = (int)((ch-delta)/ch*256); + } else { + dy2 = (int)((ch-delta)*EMU_PER_PIXEL); + } + if (dy2 < 0) dy2 = 0; + } + + anchor.setRow2(row2); + anchor.setDy2(dy2); + + Dimension dim = new Dimension( + (int)Math.round(scaledWidth*EMU_PER_PIXEL), + (int)Math.round(scaledHeight*EMU_PER_PIXEL) + ); + + return dim; + } + + /** + * Calculates the dimensions in EMUs for the anchor of the given picture + * + * @param picture the picture containing the anchor + * @return the dimensions in EMUs + */ + public static Dimension getDimensionFromAnchor(Picture picture) { + ClientAnchor anchor = picture.getClientAnchor(); + boolean isHSSF = (anchor instanceof HSSFClientAnchor); + Sheet sheet = picture.getSheet(); + + double w = 0; + int col2 = anchor.getCol1(); + + //space in the leftmost cell + w = sheet.getColumnWidthInPixels(col2++); + if (isHSSF) { + w *= 1 - anchor.getDx1()/1024d; + } else { + w -= anchor.getDx1()/(double)EMU_PER_PIXEL; + } + + while(col2 < anchor.getCol2()){ + w += sheet.getColumnWidthInPixels(col2++); + } + + if (isHSSF) { + w += sheet.getColumnWidthInPixels(col2) * anchor.getDx2()/1024d; + } else { + w += anchor.getDx2()/(double)EMU_PER_PIXEL; + } + + double h = 0; + int row2 = anchor.getRow1(); + + h = getRowHeightInPixels(sheet,row2++); + if (isHSSF) { + h *= 1 - anchor.getDy1()/256d; + } else { + h -= anchor.getDy1()/(double)EMU_PER_PIXEL; + } + + while(row2 < anchor.getRow2()){ + h += getRowHeightInPixels(sheet,row2++); + } + + if (isHSSF) { + h += getRowHeightInPixels(sheet,row2) * anchor.getDy2()/256; + } else { + h += anchor.getDy2()/(double)EMU_PER_PIXEL; + } + + w *= EMU_PER_PIXEL; + h *= EMU_PER_PIXEL; + + return new Dimension((int)Math.rint(w), (int)Math.rint(h)); + } + + + public static double getRowHeightInPixels(Sheet sheet, int rowNum) { + Row r = sheet.getRow(rowNum); + double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints(); + return Units.toEMU(points)/(double)EMU_PER_PIXEL; + } +} diff --git a/src/java/org/apache/poi/ss/util/NormalisedDecimal.java b/src/java/org/apache/poi/ss/util/NormalisedDecimal.java index 84f4d72851..00a50e1431 100644 --- a/src/java/org/apache/poi/ss/util/NormalisedDecimal.java +++ b/src/java/org/apache/poi/ss/util/NormalisedDecimal.java @@ -1,271 +1,271 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.util; - -import java.math.BigDecimal; -import java.math.BigInteger; - -/** - * Represents a transformation of a 64 bit IEEE double quantity having a decimal exponent and a - * fixed point (15 decimal digit) significand. Some quirks of Excel's calculation behaviour are - * simpler to reproduce with numeric quantities in this format. This class is currently used to - * help: - *

    - *
  1. Comparison operations
  2. - *
  3. Conversions to text
  4. - *
- * - *

- * This class does not handle negative numbers or zero. - *

- * The value of a {@link NormalisedDecimal} is given by
- * significand × 10decimalExponent - *
- * where:
- * - * significand = wholePart + fractionalPart / 224
- * - * @author Josh Micich - */ -final class NormalisedDecimal { - /** - * Number of powers of ten contained in the significand - */ - private static final int EXPONENT_OFFSET = 14; - - private static final BigDecimal BD_2_POW_24 = new BigDecimal(BigInteger.ONE.shiftLeft(24)); - - /** - * log10(2)×220 - */ - private static final int LOG_BASE_10_OF_2_TIMES_2_POW_20 = 315653; // 315652.8287 - - /** - * 219 - */ - private static final int C_2_POW_19 = 1 << 19; - - - /** - * the value of {@link #_fractionalPart} that represents 0.5 - */ - private static final int FRAC_HALF = 0x800000; - - /** - * 1015 - */ - private static final long MAX_REP_WHOLE_PART = 0x38D7EA4C68000L; - - - - public static NormalisedDecimal create(BigInteger frac, int binaryExponent) { - // estimate pow2&pow10 first, perform optional mulShift, then normalize - int pow10; - if (binaryExponent > 49 || binaryExponent < 46) { - - // working with ints (left shifted 20) instead of doubles - // x = 14.5 - binaryExponent * log10(2); - int x = (29 << 19) - binaryExponent * LOG_BASE_10_OF_2_TIMES_2_POW_20; - x += C_2_POW_19; // round - pow10 = -(x >> 20); - } else { - pow10 = 0; - } - MutableFPNumber cc = new MutableFPNumber(frac, binaryExponent); - if (pow10 != 0) { - cc.multiplyByPowerOfTen(-pow10); - } - - switch (cc.get64BitNormalisedExponent()) { - case 46: - if (cc.isAboveMinRep()) { - break; - } - case 44: - case 45: - cc.multiplyByPowerOfTen(1); - pow10--; - break; - case 47: - case 48: - break; - case 49: - if (cc.isBelowMaxRep()) { - break; - } - case 50: - cc.multiplyByPowerOfTen(-1); - pow10++; - break; - - default: - throw new IllegalStateException("Bad binary exp " + cc.get64BitNormalisedExponent() + "."); - } - cc.normalise64bit(); - - return cc.createNormalisedDecimal(pow10); - } - - /** - * Rounds at the digit with value 10decimalExponent - */ - public NormalisedDecimal roundUnits() { - long wholePart = _wholePart; - if (_fractionalPart >= FRAC_HALF) { - wholePart++; - } - - int de = _relativeDecimalExponent; - - if (wholePart < MAX_REP_WHOLE_PART) { - return new NormalisedDecimal(wholePart, 0, de); - } - return new NormalisedDecimal(wholePart/10, 0, de+1); - } - - /** - * The decimal exponent increased by one less than the digit count of {@link #_wholePart} - */ - private final int _relativeDecimalExponent; - /** - * The whole part of the significand (typically 15 digits). - * - * 47-50 bits long (MSB may be anywhere from bit 46 to 49) - * LSB is units bit. - */ - private final long _wholePart; - /** - * The fractional part of the significand. - * 24 bits (only top 14-17 bits significant): a value between 0x000000 and 0xFFFF80 - */ - private final int _fractionalPart; - - - NormalisedDecimal(long wholePart, int fracPart, int decimalExponent) { - _wholePart = wholePart; - _fractionalPart = fracPart; - _relativeDecimalExponent = decimalExponent; - } - - - /** - * Convert to an equivalent {@link ExpandedDouble} representation (binary frac and exponent). - * The resulting transformed object is easily converted to a 64 bit IEEE double: - *

    - *
  • bits 2-53 of the {@link #getSignificand()} become the 52 bit 'fraction'.
  • - *
  • {@link #getBinaryExponent()} is biased by 1023 to give the 'exponent'.
  • - *
- * The sign bit must be obtained from somewhere else. - * @return a new {@link NormalisedDecimal} normalised to base 2 representation. - */ - public ExpandedDouble normaliseBaseTwo() { - MutableFPNumber cc = new MutableFPNumber(composeFrac(), 39); - cc.multiplyByPowerOfTen(_relativeDecimalExponent); - cc.normalise64bit(); - return cc.createExpandedDouble(); - } - - /** - * @return the significand as a fixed point number (with 24 fraction bits and 47-50 whole bits) - */ - BigInteger composeFrac() { - long wp = _wholePart; - int fp = _fractionalPart; - return new BigInteger(new byte[] { - (byte) (wp >> 56), // N.B. assuming sign bit is zero - (byte) (wp >> 48), - (byte) (wp >> 40), - (byte) (wp >> 32), - (byte) (wp >> 24), - (byte) (wp >> 16), - (byte) (wp >> 8), - (byte) (wp >> 0), - (byte) (fp >> 16), - (byte) (fp >> 8), - (byte) (fp >> 0), - }); - } - - public String getSignificantDecimalDigits() { - return Long.toString(_wholePart); - } - /** - * Rounds the first whole digit position (considers only units digit, not frational part). - * Caller should check total digit count of result to see whether the rounding operation caused - * a carry out of the most significant digit - */ - public String getSignificantDecimalDigitsLastDigitRounded() { - long wp = _wholePart + 5; // rounds last digit - StringBuilder sb = new StringBuilder(24); - sb.append(wp); - sb.setCharAt(sb.length()-1, '0'); - return sb.toString(); - } - - /** - * @return the number of powers of 10 which have been extracted from the significand and binary exponent. - */ - public int getDecimalExponent() { - return _relativeDecimalExponent+EXPONENT_OFFSET; - } - - /** - * assumes both this and other are normalised - */ - public int compareNormalised(NormalisedDecimal other) { - int cmp = _relativeDecimalExponent - other._relativeDecimalExponent; - if (cmp != 0) { - return cmp; - } - if (_wholePart > other._wholePart) { - return 1; - } - if (_wholePart < other._wholePart) { - return -1; - } - return _fractionalPart - other._fractionalPart; - } - public BigDecimal getFractionalPart() { - return new BigDecimal(_fractionalPart).divide(BD_2_POW_24); - } - - private String getFractionalDigits() { - if (_fractionalPart == 0) { - return "0"; - } - return getFractionalPart().toString().substring(2); - } - - @Override - public String toString() { - - StringBuilder sb = new StringBuilder(); - sb.append(getClass().getName()); - sb.append(" ["); - String ws = String.valueOf(_wholePart); - sb.append(ws.charAt(0)); - sb.append('.'); - sb.append(ws.substring(1)); - sb.append(' '); - sb.append(getFractionalDigits()); - sb.append("E"); - sb.append(getDecimalExponent()); - sb.append("]"); - return sb.toString(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.util; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * Represents a transformation of a 64 bit IEEE double quantity having a decimal exponent and a + * fixed point (15 decimal digit) significand. Some quirks of Excel's calculation behaviour are + * simpler to reproduce with numeric quantities in this format. This class is currently used to + * help: + *
    + *
  1. Comparison operations
  2. + *
  3. Conversions to text
  4. + *
+ * + *

+ * This class does not handle negative numbers or zero. + *

+ * The value of a {@link NormalisedDecimal} is given by
+ * significand × 10decimalExponent + *
+ * where:
+ * + * significand = wholePart + fractionalPart / 224
+ * + * @author Josh Micich + */ +final class NormalisedDecimal { + /** + * Number of powers of ten contained in the significand + */ + private static final int EXPONENT_OFFSET = 14; + + private static final BigDecimal BD_2_POW_24 = new BigDecimal(BigInteger.ONE.shiftLeft(24)); + + /** + * log10(2)×220 + */ + private static final int LOG_BASE_10_OF_2_TIMES_2_POW_20 = 315653; // 315652.8287 + + /** + * 219 + */ + private static final int C_2_POW_19 = 1 << 19; + + + /** + * the value of {@link #_fractionalPart} that represents 0.5 + */ + private static final int FRAC_HALF = 0x800000; + + /** + * 1015 + */ + private static final long MAX_REP_WHOLE_PART = 0x38D7EA4C68000L; + + + + public static NormalisedDecimal create(BigInteger frac, int binaryExponent) { + // estimate pow2&pow10 first, perform optional mulShift, then normalize + int pow10; + if (binaryExponent > 49 || binaryExponent < 46) { + + // working with ints (left shifted 20) instead of doubles + // x = 14.5 - binaryExponent * log10(2); + int x = (29 << 19) - binaryExponent * LOG_BASE_10_OF_2_TIMES_2_POW_20; + x += C_2_POW_19; // round + pow10 = -(x >> 20); + } else { + pow10 = 0; + } + MutableFPNumber cc = new MutableFPNumber(frac, binaryExponent); + if (pow10 != 0) { + cc.multiplyByPowerOfTen(-pow10); + } + + switch (cc.get64BitNormalisedExponent()) { + case 46: + if (cc.isAboveMinRep()) { + break; + } + case 44: + case 45: + cc.multiplyByPowerOfTen(1); + pow10--; + break; + case 47: + case 48: + break; + case 49: + if (cc.isBelowMaxRep()) { + break; + } + case 50: + cc.multiplyByPowerOfTen(-1); + pow10++; + break; + + default: + throw new IllegalStateException("Bad binary exp " + cc.get64BitNormalisedExponent() + "."); + } + cc.normalise64bit(); + + return cc.createNormalisedDecimal(pow10); + } + + /** + * Rounds at the digit with value 10decimalExponent + */ + public NormalisedDecimal roundUnits() { + long wholePart = _wholePart; + if (_fractionalPart >= FRAC_HALF) { + wholePart++; + } + + int de = _relativeDecimalExponent; + + if (wholePart < MAX_REP_WHOLE_PART) { + return new NormalisedDecimal(wholePart, 0, de); + } + return new NormalisedDecimal(wholePart/10, 0, de+1); + } + + /** + * The decimal exponent increased by one less than the digit count of {@link #_wholePart} + */ + private final int _relativeDecimalExponent; + /** + * The whole part of the significand (typically 15 digits). + * + * 47-50 bits long (MSB may be anywhere from bit 46 to 49) + * LSB is units bit. + */ + private final long _wholePart; + /** + * The fractional part of the significand. + * 24 bits (only top 14-17 bits significant): a value between 0x000000 and 0xFFFF80 + */ + private final int _fractionalPart; + + + NormalisedDecimal(long wholePart, int fracPart, int decimalExponent) { + _wholePart = wholePart; + _fractionalPart = fracPart; + _relativeDecimalExponent = decimalExponent; + } + + + /** + * Convert to an equivalent {@link ExpandedDouble} representation (binary frac and exponent). + * The resulting transformed object is easily converted to a 64 bit IEEE double: + *

    + *
  • bits 2-53 of the {@link #getSignificand()} become the 52 bit 'fraction'.
  • + *
  • {@link #getBinaryExponent()} is biased by 1023 to give the 'exponent'.
  • + *
+ * The sign bit must be obtained from somewhere else. + * @return a new {@link NormalisedDecimal} normalised to base 2 representation. + */ + public ExpandedDouble normaliseBaseTwo() { + MutableFPNumber cc = new MutableFPNumber(composeFrac(), 39); + cc.multiplyByPowerOfTen(_relativeDecimalExponent); + cc.normalise64bit(); + return cc.createExpandedDouble(); + } + + /** + * @return the significand as a fixed point number (with 24 fraction bits and 47-50 whole bits) + */ + BigInteger composeFrac() { + long wp = _wholePart; + int fp = _fractionalPart; + return new BigInteger(new byte[] { + (byte) (wp >> 56), // N.B. assuming sign bit is zero + (byte) (wp >> 48), + (byte) (wp >> 40), + (byte) (wp >> 32), + (byte) (wp >> 24), + (byte) (wp >> 16), + (byte) (wp >> 8), + (byte) (wp >> 0), + (byte) (fp >> 16), + (byte) (fp >> 8), + (byte) (fp >> 0), + }); + } + + public String getSignificantDecimalDigits() { + return Long.toString(_wholePart); + } + /** + * Rounds the first whole digit position (considers only units digit, not frational part). + * Caller should check total digit count of result to see whether the rounding operation caused + * a carry out of the most significant digit + */ + public String getSignificantDecimalDigitsLastDigitRounded() { + long wp = _wholePart + 5; // rounds last digit + StringBuilder sb = new StringBuilder(24); + sb.append(wp); + sb.setCharAt(sb.length()-1, '0'); + return sb.toString(); + } + + /** + * @return the number of powers of 10 which have been extracted from the significand and binary exponent. + */ + public int getDecimalExponent() { + return _relativeDecimalExponent+EXPONENT_OFFSET; + } + + /** + * assumes both this and other are normalised + */ + public int compareNormalised(NormalisedDecimal other) { + int cmp = _relativeDecimalExponent - other._relativeDecimalExponent; + if (cmp != 0) { + return cmp; + } + if (_wholePart > other._wholePart) { + return 1; + } + if (_wholePart < other._wholePart) { + return -1; + } + return _fractionalPart - other._fractionalPart; + } + public BigDecimal getFractionalPart() { + return new BigDecimal(_fractionalPart).divide(BD_2_POW_24); + } + + private String getFractionalDigits() { + if (_fractionalPart == 0) { + return "0"; + } + return getFractionalPart().toString().substring(2); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getName()); + sb.append(" ["); + String ws = String.valueOf(_wholePart); + sb.append(ws.charAt(0)); + sb.append('.'); + sb.append(ws.substring(1)); + sb.append(' '); + sb.append(getFractionalDigits()); + sb.append("E"); + sb.append(getDecimalExponent()); + sb.append("]"); + return sb.toString(); + } +} diff --git a/src/java/org/apache/poi/util/Configurator.java b/src/java/org/apache/poi/util/Configurator.java index 4c9651f8e0..b1ee1a77da 100644 --- a/src/java/org/apache/poi/util/Configurator.java +++ b/src/java/org/apache/poi/util/Configurator.java @@ -1,36 +1,36 @@ -package org.apache.poi.util; - -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/** - * Helper for fetching int values from system properties - */ -public class Configurator { - private static POILogger logger = POILogFactory.getLogger(Configurator.class); - - public static int getIntValue(String systemProperty, int defaultValue) { - int result = defaultValue; - String property = System.getProperty(systemProperty); - try { - result = Integer.parseInt(property); - } catch (Exception e) { - logger.log(POILogger.ERROR, "System property -D"+systemProperty +" do not contains a valid integer " + property); - } - return result; - } -} +package org.apache.poi.util; + +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/** + * Helper for fetching int values from system properties + */ +public class Configurator { + private static POILogger logger = POILogFactory.getLogger(Configurator.class); + + public static int getIntValue(String systemProperty, int defaultValue) { + int result = defaultValue; + String property = System.getProperty(systemProperty); + try { + result = Integer.parseInt(property); + } catch (Exception e) { + logger.log(POILogger.ERROR, "System property -D"+systemProperty +" do not contains a valid integer " + property); + } + return result; + } +} diff --git a/src/java/org/apache/poi/util/JvmBugs.java b/src/java/org/apache/poi/util/JvmBugs.java index 66e8468e49..221d74e643 100644 --- a/src/java/org/apache/poi/util/JvmBugs.java +++ b/src/java/org/apache/poi/util/JvmBugs.java @@ -1,55 +1,55 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.util; - -import java.util.Locale; - -public class JvmBugs { - private static final POILogger LOG = POILogFactory.getLogger(JvmBugs.class); - - /** - * The LineBreakMeasurer is used for calculating text bounds. - * The last official JDK 6 version (1.6.0_45) and also JDK 7 (1.7.0_21) - * for Windows are affected. For JDK 7 - update to a more recent version. - * For JDK 6 - replace the fontmanager.dll with the previous release. - * - * For performance reasons, this method only checks for a windows jvm - * with version 1.6.0_45 and 1.7.0_21. - * - * Set system property "org.apache.poi.JvmBugs.LineBreakMeasurer.ignore" to "true" - * to bypass this check and use the normal fonts. - * - * @return true, if jvm is bugged, caller code should use Lucida Sans - * instead of Calibri and Lucida Bright instead of Cambria - * - * @see Workaround for XSLF - * @see Workaround for XSSF and HSSF - * @see POI Bug #54904 - * @see JDK Bug #6501991 - * @see LineBreakMeasurerTest - */ - public static boolean hasLineBreakMeasurerBug() { - String version = System.getProperty("java.version"); - String os = System.getProperty("os.name").toLowerCase(Locale.ROOT); - boolean ignore = Boolean.getBoolean("org.apache.poi.JvmBugs.LineBreakMeasurer.ignore"); - boolean hasBug = (!ignore && (os.contains("win") && ("1.6.0_45".equals(version) || "1.7.0_21".equals(version)))); - if (hasBug) { - LOG.log(POILogger.WARN, "JVM has LineBreakMeasurer bug - see POI bug #54904 - caller code might default to Lucida Sans"); - } - return hasBug; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.util; + +import java.util.Locale; + +public class JvmBugs { + private static final POILogger LOG = POILogFactory.getLogger(JvmBugs.class); + + /** + * The LineBreakMeasurer is used for calculating text bounds. + * The last official JDK 6 version (1.6.0_45) and also JDK 7 (1.7.0_21) + * for Windows are affected. For JDK 7 - update to a more recent version. + * For JDK 6 - replace the fontmanager.dll with the previous release. + * + * For performance reasons, this method only checks for a windows jvm + * with version 1.6.0_45 and 1.7.0_21. + * + * Set system property "org.apache.poi.JvmBugs.LineBreakMeasurer.ignore" to "true" + * to bypass this check and use the normal fonts. + * + * @return true, if jvm is bugged, caller code should use Lucida Sans + * instead of Calibri and Lucida Bright instead of Cambria + * + * @see Workaround for XSLF + * @see Workaround for XSSF and HSSF + * @see POI Bug #54904 + * @see JDK Bug #6501991 + * @see LineBreakMeasurerTest + */ + public static boolean hasLineBreakMeasurerBug() { + String version = System.getProperty("java.version"); + String os = System.getProperty("os.name").toLowerCase(Locale.ROOT); + boolean ignore = Boolean.getBoolean("org.apache.poi.JvmBugs.LineBreakMeasurer.ignore"); + boolean hasBug = (!ignore && (os.contains("win") && ("1.6.0_45".equals(version) || "1.7.0_21".equals(version)))); + if (hasBug) { + LOG.log(POILogger.WARN, "JVM has LineBreakMeasurer bug - see POI bug #54904 - caller code might default to Lucida Sans"); + } + return hasBug; + } +} diff --git a/src/java/org/apache/poi/util/LocaleUtil.java b/src/java/org/apache/poi/util/LocaleUtil.java index 81bdd4a079..7ad6ca1483 100644 --- a/src/java/org/apache/poi/util/LocaleUtil.java +++ b/src/java/org/apache/poi/util/LocaleUtil.java @@ -1,150 +1,150 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - - -package org.apache.poi.util; - -import java.nio.charset.Charset; -import java.util.Calendar; -import java.util.Locale; -import java.util.TimeZone; - -/** - * This utility class is used to set locale and time zone settings beside - * of the JDK internal {@link java.util.Locale#setDefault(Locale)} and - * {@link java.util.TimeZone#setDefault(TimeZone)} methods, because - * the locale/time zone specific handling of certain office documents - - * maybe for different time zones / locales ... - shouldn't affect - * other java components. - * - * The settings are saved in a {@link java.lang.ThreadLocal}, - * so they only apply to the current thread and can't be set globally. - */ -public final class LocaleUtil { - private LocaleUtil() { - // no instances of this class - } - - /** - * Excel doesn't store TimeZone information in the file, so if in doubt, - * use UTC to perform calculations - */ - public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC"); - - /** - * Default encoding for unknown byte encodings of native files - * (at least it's better than to rely on a platform dependent encoding - * for legacy stuff ...) - */ - public static final Charset CHARSET_1252 = Charset.forName("CP1252"); - - private static final ThreadLocal userTimeZone = new ThreadLocal(); - private static final ThreadLocal userLocale = new ThreadLocal(); - - /** - * As time zone information is not stored in any format, it can be - * set before any date calculations take place. - * This setting is specific to the current thread. - * - * @param timezone the timezone under which date calculations take place - */ - public static void setUserTimeZone(TimeZone timezone) { - userTimeZone.set(timezone); - } - - /** - * @return the time zone which is used for date calculations. If not set, returns {@link TimeZone#getDefault()}. +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.util; + +import java.nio.charset.Charset; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + * This utility class is used to set locale and time zone settings beside + * of the JDK internal {@link java.util.Locale#setDefault(Locale)} and + * {@link java.util.TimeZone#setDefault(TimeZone)} methods, because + * the locale/time zone specific handling of certain office documents - + * maybe for different time zones / locales ... - shouldn't affect + * other java components. + * + * The settings are saved in a {@link java.lang.ThreadLocal}, + * so they only apply to the current thread and can't be set globally. + */ +public final class LocaleUtil { + private LocaleUtil() { + // no instances of this class + } + + /** + * Excel doesn't store TimeZone information in the file, so if in doubt, + * use UTC to perform calculations + */ + public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC"); + + /** + * Default encoding for unknown byte encodings of native files + * (at least it's better than to rely on a platform dependent encoding + * for legacy stuff ...) + */ + public static final Charset CHARSET_1252 = Charset.forName("CP1252"); + + private static final ThreadLocal userTimeZone = new ThreadLocal(); + private static final ThreadLocal userLocale = new ThreadLocal(); + + /** + * As time zone information is not stored in any format, it can be + * set before any date calculations take place. + * This setting is specific to the current thread. + * + * @param timezone the timezone under which date calculations take place + */ + public static void setUserTimeZone(TimeZone timezone) { + userTimeZone.set(timezone); + } + + /** + * @return the time zone which is used for date calculations. If not set, returns {@link TimeZone#getDefault()}. */ - @SuppressForbidden("implementation around default locales in POI") - public static TimeZone getUserTimeZone() { + @SuppressForbidden("implementation around default locales in POI") + public static TimeZone getUserTimeZone() { TimeZone timeZone = userTimeZone.get(); - return (timeZone != null) ? timeZone : TimeZone.getDefault(); - } + return (timeZone != null) ? timeZone : TimeZone.getDefault(); + } /** * Clear the thread-local user time zone. - */ - public static void resetUserTimeZone() { - userTimeZone.remove(); - } - - /** - * Sets default user locale. - * This setting is specific to the current thread. - */ - public static void setUserLocale(Locale locale) { - userLocale.set(locale); - } - - /** - * @return the default user locale. If not set, returns {@link Locale#getDefault()}. + */ + public static void resetUserTimeZone() { + userTimeZone.remove(); + } + + /** + * Sets default user locale. + * This setting is specific to the current thread. */ - @SuppressForbidden("implementation around default locales in POI") - public static Locale getUserLocale() { + public static void setUserLocale(Locale locale) { + userLocale.set(locale); + } + + /** + * @return the default user locale. If not set, returns {@link Locale#getDefault()}. + */ + @SuppressForbidden("implementation around default locales in POI") + public static Locale getUserLocale() { Locale locale = userLocale.get(); - return (locale != null) ? locale : Locale.getDefault(); + return (locale != null) ? locale : Locale.getDefault(); + } + + public static void resetUserLocale() { + userLocale.remove(); + } + + /** + * @return a calendar for the user locale and time zone + */ + public static Calendar getLocaleCalendar() { + return getLocaleCalendar(getUserTimeZone()); + } + + /** + * Convenience method - month is 0-based as in java.util.Calendar + * + * @param year + * @param month + * @param day + * @return a calendar for the user locale and time zone, and the given date + */ + public static Calendar getLocaleCalendar(int year, int month, int day) { + return getLocaleCalendar(year, month, day, 0, 0, 0); + } + + /** + * Convenience method - month is 0-based as in java.util.Calendar + * + * @param year + * @param month + * @param day + * @param hour + * @param minute + * @param second + * @return a calendar for the user locale and time zone, and the given date + */ + public static Calendar getLocaleCalendar(int year, int month, int day, int hour, int minute, int second) { + Calendar cal = getLocaleCalendar(); + cal.set(year, month, day, hour, minute, second); + cal.clear(Calendar.MILLISECOND); + return cal; + } + + /** + * @return a calendar for the user locale and time zone + */ + public static Calendar getLocaleCalendar(TimeZone timeZone) { + return Calendar.getInstance(timeZone, getUserLocale()); } +} - public static void resetUserLocale() { - userLocale.remove(); - } - - /** - * @return a calendar for the user locale and time zone - */ - public static Calendar getLocaleCalendar() { - return getLocaleCalendar(getUserTimeZone()); - } - - /** - * Convenience method - month is 0-based as in java.util.Calendar - * - * @param year - * @param month - * @param day - * @return a calendar for the user locale and time zone, and the given date - */ - public static Calendar getLocaleCalendar(int year, int month, int day) { - return getLocaleCalendar(year, month, day, 0, 0, 0); - } - - /** - * Convenience method - month is 0-based as in java.util.Calendar - * - * @param year - * @param month - * @param day - * @param hour - * @param minute - * @param second - * @return a calendar for the user locale and time zone, and the given date - */ - public static Calendar getLocaleCalendar(int year, int month, int day, int hour, int minute, int second) { - Calendar cal = getLocaleCalendar(); - cal.set(year, month, day, hour, minute, second); - cal.clear(Calendar.MILLISECOND); - return cal; - } - - /** - * @return a calendar for the user locale and time zone - */ - public static Calendar getLocaleCalendar(TimeZone timeZone) { - return Calendar.getInstance(timeZone, getUserLocale()); - } -} - diff --git a/src/java/org/apache/poi/util/PngUtils.java b/src/java/org/apache/poi/util/PngUtils.java index 4fed98ef90..f9126c9392 100644 --- a/src/java/org/apache/poi/util/PngUtils.java +++ b/src/java/org/apache/poi/util/PngUtils.java @@ -1,53 +1,53 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.util; - - -public final class PngUtils { - - /** - * File header for PNG format. - */ - private static final byte[] PNG_FILE_HEADER = - new byte[] { (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; - - private PngUtils() { - // no instances of this class - } - - /** - * Checks if the offset matches the PNG header. - * - * @param data the data to check. - * @param offset the offset to check at. - * @return {@code true} if the offset matches. - */ - public static boolean matchesPngHeader(byte[] data, int offset) { - if (data == null || data.length - offset < PNG_FILE_HEADER.length) { - return false; - } - - for (int i = 0; i < PNG_FILE_HEADER.length; i++) { - if (PNG_FILE_HEADER[i] != data[i + offset]) { - return false; - } - } - - return true; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.util; + + +public final class PngUtils { + + /** + * File header for PNG format. + */ + private static final byte[] PNG_FILE_HEADER = + new byte[] { (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; + + private PngUtils() { + // no instances of this class + } + + /** + * Checks if the offset matches the PNG header. + * + * @param data the data to check. + * @param offset the offset to check at. + * @return {@code true} if the offset matches. + */ + public static boolean matchesPngHeader(byte[] data, int offset) { + if (data == null || data.length - offset < PNG_FILE_HEADER.length) { + return false; + } + + for (int i = 0; i < PNG_FILE_HEADER.length; i++) { + if (PNG_FILE_HEADER[i] != data[i + offset]) { + return false; + } + } + + return true; + } +} diff --git a/src/java/org/apache/poi/util/SuppressForbidden.java b/src/java/org/apache/poi/util/SuppressForbidden.java index c2b7657041..1160cc20bd 100644 --- a/src/java/org/apache/poi/util/SuppressForbidden.java +++ b/src/java/org/apache/poi/util/SuppressForbidden.java @@ -1,33 +1,33 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Marking class for elements to be ignored by the forbidden apis check - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface SuppressForbidden { - /** A reason for suppressing should always be given. */ - String value() default ""; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marking class for elements to be ignored by the forbidden apis check + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface SuppressForbidden { + /** A reason for suppressing should always be given. */ + String value() default ""; +} diff --git a/src/java/org/apache/poi/util/Units.java b/src/java/org/apache/poi/util/Units.java index 4ee12cb9c5..1d376e936d 100644 --- a/src/java/org/apache/poi/util/Units.java +++ b/src/java/org/apache/poi/util/Units.java @@ -1,130 +1,130 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.util; - -/** - * @author Yegor Kozlov - */ -public class Units { - /** - * In Escher absolute distances are specified in - * English Metric Units (EMUs), occasionally referred to as A units; - * there are 360000 EMUs per centimeter, 914400 EMUs per inch, 12700 EMUs per point. - */ - public static final int EMU_PER_PIXEL = 9525; - public static final int EMU_PER_POINT = 12700; - public static final int EMU_PER_CENTIMETER = 360000; - - /** - * Master DPI (576 pixels per inch). - * Used by the reference coordinate system in PowerPoint (HSLF) - */ - public static final int MASTER_DPI = 576; - - /** - * Pixels DPI (96 pixels per inch) - */ - public static final int PIXEL_DPI = 96; - - /** - * Points DPI (72 pixels per inch) - */ - public static final int POINT_DPI = 72; - - /** - * Converts points to EMUs - * @param points points - * @return EMUs - */ - public static int toEMU(double points){ - return (int)Math.rint(EMU_PER_POINT*points); - } - - /** - * Converts pixels to EMUs - * @param pixels pixels - * @return EMUs - */ - public static int pixelToEMU(int pixels) { - return pixels*EMU_PER_PIXEL; - } - - /** - * Converts EMUs to points - * @param emu emu - * @return points - */ - public static double toPoints(long emu){ - return (double)emu/EMU_PER_POINT; - } - - /** - * Converts a value of type FixedPoint to a floating point - * - * @param fixedPoint value in fixed point notation - * @return floating point (double) - * - * @see [MS-OSHARED] - 2.2.1.6 FixedPoint - */ - public static double fixedPointToDouble(int fixedPoint) { - int i = (fixedPoint >> 16); - int f = fixedPoint & 0xFFFF; - return (i + f/65536d); - } - - /** - * Converts a value of type floating point to a FixedPoint - * - * @param floatPoint value in floating point notation - * @return fixedPoint value in fixed points notation - * - * @see [MS-OSHARED] - 2.2.1.6 FixedPoint - */ - public static int doubleToFixedPoint(double floatPoint) { - double fractionalPart = floatPoint % 1d; - double integralPart = floatPoint - fractionalPart; - int i = (int)Math.floor(integralPart); - int f = (int)Math.rint(fractionalPart*65536d); - return (i << 16) | (f & 0xFFFF); - } - - public static double masterToPoints(int masterDPI) { - double points = masterDPI; - points *= POINT_DPI; - points /= MASTER_DPI; - return points; - } - - public static int pointsToMaster(double points) { - points *= MASTER_DPI; - points /= POINT_DPI; - return (int)Math.rint(points); - } - - public static int pointsToPixel(double points) { - points *= PIXEL_DPI; - points /= POINT_DPI; - return (int)Math.rint(points); - } - - public static double pixelToPoints(int pixel) { - double points = pixel; - points *= POINT_DPI; - points /= PIXEL_DPI; - return points; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.util; + +/** + * @author Yegor Kozlov + */ +public class Units { + /** + * In Escher absolute distances are specified in + * English Metric Units (EMUs), occasionally referred to as A units; + * there are 360000 EMUs per centimeter, 914400 EMUs per inch, 12700 EMUs per point. + */ + public static final int EMU_PER_PIXEL = 9525; + public static final int EMU_PER_POINT = 12700; + public static final int EMU_PER_CENTIMETER = 360000; + + /** + * Master DPI (576 pixels per inch). + * Used by the reference coordinate system in PowerPoint (HSLF) + */ + public static final int MASTER_DPI = 576; + + /** + * Pixels DPI (96 pixels per inch) + */ + public static final int PIXEL_DPI = 96; + + /** + * Points DPI (72 pixels per inch) + */ + public static final int POINT_DPI = 72; + + /** + * Converts points to EMUs + * @param points points + * @return EMUs + */ + public static int toEMU(double points){ + return (int)Math.rint(EMU_PER_POINT*points); + } + + /** + * Converts pixels to EMUs + * @param pixels pixels + * @return EMUs + */ + public static int pixelToEMU(int pixels) { + return pixels*EMU_PER_PIXEL; + } + + /** + * Converts EMUs to points + * @param emu emu + * @return points + */ + public static double toPoints(long emu){ + return (double)emu/EMU_PER_POINT; + } + + /** + * Converts a value of type FixedPoint to a floating point + * + * @param fixedPoint value in fixed point notation + * @return floating point (double) + * + * @see [MS-OSHARED] - 2.2.1.6 FixedPoint + */ + public static double fixedPointToDouble(int fixedPoint) { + int i = (fixedPoint >> 16); + int f = fixedPoint & 0xFFFF; + return (i + f/65536d); + } + + /** + * Converts a value of type floating point to a FixedPoint + * + * @param floatPoint value in floating point notation + * @return fixedPoint value in fixed points notation + * + * @see [MS-OSHARED] - 2.2.1.6 FixedPoint + */ + public static int doubleToFixedPoint(double floatPoint) { + double fractionalPart = floatPoint % 1d; + double integralPart = floatPoint - fractionalPart; + int i = (int)Math.floor(integralPart); + int f = (int)Math.rint(fractionalPart*65536d); + return (i << 16) | (f & 0xFFFF); + } + + public static double masterToPoints(int masterDPI) { + double points = masterDPI; + points *= POINT_DPI; + points /= MASTER_DPI; + return points; + } + + public static int pointsToMaster(double points) { + points *= MASTER_DPI; + points /= POINT_DPI; + return (int)Math.rint(points); + } + + public static int pointsToPixel(double points) { + points *= PIXEL_DPI; + points /= POINT_DPI; + return (int)Math.rint(points); + } + + public static double pixelToPoints(int pixel) { + double points = pixel; + points *= POINT_DPI; + points /= PIXEL_DPI; + return points; + } +} diff --git a/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java b/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java index eeed5f7c8d..f11b2d88b5 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java +++ b/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java @@ -1,174 +1,174 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; -import java.lang.ref.WeakReference; -import java.net.URL; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.stream.XMLStreamReader; - -import org.apache.poi.util.DocumentHelper; -import org.apache.xmlbeans.SchemaType; -import org.apache.xmlbeans.SchemaTypeLoader; -import org.apache.xmlbeans.XmlBeans; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.apache.xmlbeans.xml.stream.XMLInputStream; -import org.apache.xmlbeans.xml.stream.XMLStreamException; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -@SuppressWarnings("deprecation") -public class POIXMLTypeLoader { - - private static ThreadLocal classLoader = new ThreadLocal(); - - public static final XmlOptions DEFAULT_XML_OPTIONS; - static { - DEFAULT_XML_OPTIONS = new XmlOptions(); - DEFAULT_XML_OPTIONS.setSaveOuter(); - DEFAULT_XML_OPTIONS.setUseDefaultNamespace(); - DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces(); - DEFAULT_XML_OPTIONS.setCharacterEncoding("UTF-8"); - // Piccolo is disabled for POI builts, i.e. JAXP is used for parsing - // so only user code using XmlObject/XmlToken.Factory.parse - // directly can bypass the entity check, which is probably unlikely (... and not within our responsibility :)) - // DEFAULT_XML_OPTIONS.setLoadEntityBytesLimit(4096); - - Map map = new HashMap(); - map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a"); - map.put("http://schemas.openxmlformats.org/drawingml/2006/chart", "c"); - map.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp"); - map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve"); - map.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m"); - map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); - map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt"); - map.put("http://schemas.openxmlformats.org/presentationml/2006/main", "p"); - map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w"); - map.put("http://schemas.microsoft.com/office/word/2006/wordml", "wne"); - map.put("urn:schemas-microsoft-com:office:office", "o"); - map.put("urn:schemas-microsoft-com:office:excel", "x"); - map.put("urn:schemas-microsoft-com:office:word", "w10"); - map.put("urn:schemas-microsoft-com:vml", "v"); - DEFAULT_XML_OPTIONS.setSaveSuggestedPrefixes(Collections.unmodifiableMap(map)); - } - - private static XmlOptions getXmlOptions(XmlOptions options) { - return options == null ? DEFAULT_XML_OPTIONS : options; - } - - /** - * Sets the {@link ClassLoader} which is used, when XmlBeans are dynamically instantiated - - * opposed to being loaded by the factory class which is accompanied by each generated XmlBeans interface. - *

- * This is especially necessary in a context which doesn't guarantee that the current (thread) context - * cassloader has access to all XmlBeans schema definitions (*.xsb) - which is typically in OSGI the case. - *

- * The classloader will be only set for the current thread in a {@link ThreadLocal}. Although the - * ThreadLocal is implemented via a {@link WeakReference}, it's good style to {@code null} the classloader - * when the user code is finalized. - * - * @param cl the classloader to be used when XmlBeans classes and definitions are looked up - */ - public static void setClassLoader(ClassLoader cl) { - classLoader.set(cl); - } - - private static SchemaTypeLoader getTypeLoader() { - ClassLoader cl = classLoader.get(); - return (cl == null) - ? XmlBeans.getContextTypeLoader() - : XmlBeans.typeLoaderForClassLoader(cl); - } - - public static XmlObject newInstance(SchemaType type, XmlOptions options) { - return getTypeLoader().newInstance(type, getXmlOptions(options)); - } - - public static XmlObject parse(String xmlText, SchemaType type, XmlOptions options) throws XmlException { - try { - return parse(new StringReader(xmlText), type, options); - } catch (IOException e) { - throw new XmlException("Unable to parse xml bean", e); - } - } - - public static XmlObject parse(File file, SchemaType type, XmlOptions options) throws XmlException, IOException { - InputStream is = new FileInputStream(file); - try { - return parse(is, type, options); - } finally { - is.close(); - } - } - - public static XmlObject parse(URL file, SchemaType type, XmlOptions options) throws XmlException, IOException { - InputStream is = file.openStream(); - try { - return parse(is, type, options); - } finally { - is.close(); - } - } - - public static XmlObject parse(InputStream jiois, SchemaType type, XmlOptions options) throws XmlException, IOException { - try { - Document doc = DocumentHelper.readDocument(jiois); - return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); - } catch (SAXException e) { - throw new IOException("Unable to parse xml bean", e); - } - } - - public static XmlObject parse(XMLStreamReader xsr, SchemaType type, XmlOptions options) throws XmlException { - return getTypeLoader().parse(xsr, type, getXmlOptions(options)); - } - - public static XmlObject parse(Reader jior, SchemaType type, XmlOptions options) throws XmlException, IOException { - try { - Document doc = DocumentHelper.readDocument(new InputSource(jior)); - return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); - } catch (SAXException e) { - throw new XmlException("Unable to parse xml bean", e); - } - } - - public static XmlObject parse(Node node, SchemaType type, XmlOptions options) throws XmlException { - return getTypeLoader().parse(node, type, getXmlOptions(options)); - } - - public static XmlObject parse(XMLInputStream xis, SchemaType type, XmlOptions options) throws XmlException, XMLStreamException { - return getTypeLoader().parse(xis, type, getXmlOptions(options)); - } - - public static XMLInputStream newValidatingXMLInputStream ( XMLInputStream xis, SchemaType type, XmlOptions options ) throws XmlException, XMLStreamException { - return getTypeLoader().newValidatingXMLInputStream(xis, type, getXmlOptions(options)); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.lang.ref.WeakReference; +import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.poi.util.DocumentHelper; +import org.apache.xmlbeans.SchemaType; +import org.apache.xmlbeans.SchemaTypeLoader; +import org.apache.xmlbeans.XmlBeans; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlOptions; +import org.apache.xmlbeans.xml.stream.XMLInputStream; +import org.apache.xmlbeans.xml.stream.XMLStreamException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +@SuppressWarnings("deprecation") +public class POIXMLTypeLoader { + + private static ThreadLocal classLoader = new ThreadLocal(); + + public static final XmlOptions DEFAULT_XML_OPTIONS; + static { + DEFAULT_XML_OPTIONS = new XmlOptions(); + DEFAULT_XML_OPTIONS.setSaveOuter(); + DEFAULT_XML_OPTIONS.setUseDefaultNamespace(); + DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces(); + DEFAULT_XML_OPTIONS.setCharacterEncoding("UTF-8"); + // Piccolo is disabled for POI builts, i.e. JAXP is used for parsing + // so only user code using XmlObject/XmlToken.Factory.parse + // directly can bypass the entity check, which is probably unlikely (... and not within our responsibility :)) + // DEFAULT_XML_OPTIONS.setLoadEntityBytesLimit(4096); + + Map map = new HashMap(); + map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a"); + map.put("http://schemas.openxmlformats.org/drawingml/2006/chart", "c"); + map.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp"); + map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve"); + map.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m"); + map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); + map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt"); + map.put("http://schemas.openxmlformats.org/presentationml/2006/main", "p"); + map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w"); + map.put("http://schemas.microsoft.com/office/word/2006/wordml", "wne"); + map.put("urn:schemas-microsoft-com:office:office", "o"); + map.put("urn:schemas-microsoft-com:office:excel", "x"); + map.put("urn:schemas-microsoft-com:office:word", "w10"); + map.put("urn:schemas-microsoft-com:vml", "v"); + DEFAULT_XML_OPTIONS.setSaveSuggestedPrefixes(Collections.unmodifiableMap(map)); + } + + private static XmlOptions getXmlOptions(XmlOptions options) { + return options == null ? DEFAULT_XML_OPTIONS : options; + } + + /** + * Sets the {@link ClassLoader} which is used, when XmlBeans are dynamically instantiated - + * opposed to being loaded by the factory class which is accompanied by each generated XmlBeans interface. + *

+ * This is especially necessary in a context which doesn't guarantee that the current (thread) context + * cassloader has access to all XmlBeans schema definitions (*.xsb) - which is typically in OSGI the case. + *

+ * The classloader will be only set for the current thread in a {@link ThreadLocal}. Although the + * ThreadLocal is implemented via a {@link WeakReference}, it's good style to {@code null} the classloader + * when the user code is finalized. + * + * @param cl the classloader to be used when XmlBeans classes and definitions are looked up + */ + public static void setClassLoader(ClassLoader cl) { + classLoader.set(cl); + } + + private static SchemaTypeLoader getTypeLoader() { + ClassLoader cl = classLoader.get(); + return (cl == null) + ? XmlBeans.getContextTypeLoader() + : XmlBeans.typeLoaderForClassLoader(cl); + } + + public static XmlObject newInstance(SchemaType type, XmlOptions options) { + return getTypeLoader().newInstance(type, getXmlOptions(options)); + } + + public static XmlObject parse(String xmlText, SchemaType type, XmlOptions options) throws XmlException { + try { + return parse(new StringReader(xmlText), type, options); + } catch (IOException e) { + throw new XmlException("Unable to parse xml bean", e); + } + } + + public static XmlObject parse(File file, SchemaType type, XmlOptions options) throws XmlException, IOException { + InputStream is = new FileInputStream(file); + try { + return parse(is, type, options); + } finally { + is.close(); + } + } + + public static XmlObject parse(URL file, SchemaType type, XmlOptions options) throws XmlException, IOException { + InputStream is = file.openStream(); + try { + return parse(is, type, options); + } finally { + is.close(); + } + } + + public static XmlObject parse(InputStream jiois, SchemaType type, XmlOptions options) throws XmlException, IOException { + try { + Document doc = DocumentHelper.readDocument(jiois); + return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); + } catch (SAXException e) { + throw new IOException("Unable to parse xml bean", e); + } + } + + public static XmlObject parse(XMLStreamReader xsr, SchemaType type, XmlOptions options) throws XmlException { + return getTypeLoader().parse(xsr, type, getXmlOptions(options)); + } + + public static XmlObject parse(Reader jior, SchemaType type, XmlOptions options) throws XmlException, IOException { + try { + Document doc = DocumentHelper.readDocument(new InputSource(jior)); + return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); + } catch (SAXException e) { + throw new XmlException("Unable to parse xml bean", e); + } + } + + public static XmlObject parse(Node node, SchemaType type, XmlOptions options) throws XmlException { + return getTypeLoader().parse(node, type, getXmlOptions(options)); + } + + public static XmlObject parse(XMLInputStream xis, SchemaType type, XmlOptions options) throws XmlException, XMLStreamException { + return getTypeLoader().parse(xis, type, getXmlOptions(options)); + } + + public static XMLInputStream newValidatingXMLInputStream ( XMLInputStream xis, SchemaType type, XmlOptions options ) throws XmlException, XMLStreamException { + return getTypeLoader().newValidatingXMLInputStream(xis, type, getXmlOptions(options)); + } +} diff --git a/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java b/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java index 1a7a9d6c58..7d80b7ac28 100644 --- a/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java +++ b/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java @@ -1,143 +1,143 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.dev; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Result; -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.apache.poi.openxml4j.opc.internal.ZipHelper; -import org.apache.poi.openxml4j.util.ZipSecureFile; -import org.apache.poi.util.IOUtils; -import org.w3c.dom.Document; -import org.xml.sax.InputSource; - -/** - * Reads a zipped OOXML file and produces a copy with the included - * pretty-printed XML files. - * - * This is useful for comparing OOXML files produced by different tools as the often - * use different formatting of the XML. - */ -public class OOXMLPrettyPrint { - private final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - private final DocumentBuilder documentBuilder; - - public OOXMLPrettyPrint() throws ParserConfigurationException { - // allow files with much lower inflation rate here as there is no risk of Zip Bomb attacks in this developer tool - ZipSecureFile.setMinInflateRatio(0.00001); - - documentBuilder = documentBuilderFactory.newDocumentBuilder(); - } - - public static void main(String[] args) throws Exception { - if(args.length <= 1 || args.length % 2 != 0) { - System.err.println("Use:"); - System.err.println("\tjava OOXMLPrettyPrint [ ] ..."); - System.exit(1); - } - - for(int i = 0;i < args.length;i+=2) { - File f = new File(args[i]); - if(! f.exists()) { - System.err.println("Error, file not found!"); - System.err.println("\t" + f.toString()); - System.exit(2); - } - - handleFile(f, new File(args[i+1])); - } - System.out.println("Done."); - } - - private static void handleFile(File file, File outFile) throws ZipException, - IOException, TransformerException, ParserConfigurationException { - System.out.println("Reading zip-file " + file + " and writing pretty-printed XML to " + outFile); - - ZipFile zipFile = ZipHelper.openZipFile(file); - try { - ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile))); - try { - new OOXMLPrettyPrint().handle(zipFile, out); - } finally { - out.close(); - } - } finally { - zipFile.close(); - - System.out.println(); - } - } - - private void handle(ZipFile file, ZipOutputStream out) throws IOException, TransformerException { - Enumeration entries = file.entries(); - while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - - String name = entry.getName(); - out.putNextEntry(new ZipEntry(name)); - try { - if(name.endsWith(".xml") || name.endsWith(".rels")) { - Document document = documentBuilder.parse(new InputSource(file.getInputStream(entry))); - document.setXmlStandalone(true); - pretty(document, out, 2); - } else { - System.out.println("Not pretty-printing non-XML file " + name); - IOUtils.copy(file.getInputStream(entry), out); - } - } catch (Exception e) { - throw new IOException("While handling entry " + name, e); - } finally { - out.closeEntry(); - } - System.out.print("."); - } - } - - private static void pretty(Document document, OutputStream outputStream, int indent) throws TransformerException { - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - if (indent > 0) { - // set properties to indent the resulting XML nicely - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", Integer.toString(indent)); - } - Result result = new StreamResult(outputStream); - Source source = new DOMSource(document); - transformer.transform(source, result); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.dev; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.poi.openxml4j.opc.internal.ZipHelper; +import org.apache.poi.openxml4j.util.ZipSecureFile; +import org.apache.poi.util.IOUtils; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +/** + * Reads a zipped OOXML file and produces a copy with the included + * pretty-printed XML files. + * + * This is useful for comparing OOXML files produced by different tools as the often + * use different formatting of the XML. + */ +public class OOXMLPrettyPrint { + private final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + private final DocumentBuilder documentBuilder; + + public OOXMLPrettyPrint() throws ParserConfigurationException { + // allow files with much lower inflation rate here as there is no risk of Zip Bomb attacks in this developer tool + ZipSecureFile.setMinInflateRatio(0.00001); + + documentBuilder = documentBuilderFactory.newDocumentBuilder(); + } + + public static void main(String[] args) throws Exception { + if(args.length <= 1 || args.length % 2 != 0) { + System.err.println("Use:"); + System.err.println("\tjava OOXMLPrettyPrint [ ] ..."); + System.exit(1); + } + + for(int i = 0;i < args.length;i+=2) { + File f = new File(args[i]); + if(! f.exists()) { + System.err.println("Error, file not found!"); + System.err.println("\t" + f.toString()); + System.exit(2); + } + + handleFile(f, new File(args[i+1])); + } + System.out.println("Done."); + } + + private static void handleFile(File file, File outFile) throws ZipException, + IOException, TransformerException, ParserConfigurationException { + System.out.println("Reading zip-file " + file + " and writing pretty-printed XML to " + outFile); + + ZipFile zipFile = ZipHelper.openZipFile(file); + try { + ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile))); + try { + new OOXMLPrettyPrint().handle(zipFile, out); + } finally { + out.close(); + } + } finally { + zipFile.close(); + + System.out.println(); + } + } + + private void handle(ZipFile file, ZipOutputStream out) throws IOException, TransformerException { + Enumeration entries = file.entries(); + while(entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + + String name = entry.getName(); + out.putNextEntry(new ZipEntry(name)); + try { + if(name.endsWith(".xml") || name.endsWith(".rels")) { + Document document = documentBuilder.parse(new InputSource(file.getInputStream(entry))); + document.setXmlStandalone(true); + pretty(document, out, 2); + } else { + System.out.println("Not pretty-printing non-XML file " + name); + IOUtils.copy(file.getInputStream(entry), out); + } + } catch (Exception e) { + throw new IOException("While handling entry " + name, e); + } finally { + out.closeEntry(); + } + System.out.print("."); + } + } + + private static void pretty(Document document, OutputStream outputStream, int indent) throws TransformerException { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + if (indent > 0) { + // set properties to indent the resulting XML nicely + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", Integer.toString(indent)); + } + Result result = new StreamResult(outputStream); + Source source = new DOMSource(document); + transformer.transform(source, result); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java index 7a34c379b1..ef5c5378e8 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java @@ -1,309 +1,309 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.util; - -import java.io.File; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PushbackInputStream; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.zip.InflaterInputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; - -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.SuppressForbidden; - -/** - * This class wraps a {@link ZipFile} in order to check the - * entries for zip bombs - * while reading the archive. - * If a {@link ZipInputStream} is directly used, the wrapper - * can be applied via {@link #addThreshold(InputStream)}. - * The alert limits can be globally defined via {@link #setMaxEntrySize(long)} - * and {@link #setMinInflateRatio(double)}. - */ -public class ZipSecureFile extends ZipFile { - private static final POILogger LOG = POILogFactory.getLogger(ZipSecureFile.class); - - private static double MIN_INFLATE_RATIO = 0.01d; - private static long MAX_ENTRY_SIZE = 0xFFFFFFFFL; - - // don't alert for expanded sizes smaller than 100k - private final static long GRACE_ENTRY_SIZE = 100*1024L; - - // The default maximum size of extracted text - private static long MAX_TEXT_SIZE = 10*1024*1024L; - - /** - * Sets the ratio between de- and inflated bytes to detect zipbomb. - * It defaults to 1% (= 0.01d), i.e. when the compression is better than - * 1% for any given read package part, the parsing will fail indicating a - * Zip-Bomb. - * - * @param ratio the ratio between de- and inflated bytes to detect zipbomb - */ - public static void setMinInflateRatio(double ratio) { - MIN_INFLATE_RATIO = ratio; - } - - /** - * Returns the current minimum compression rate that is used. - * - * See setMinInflateRatio() for details. - * - * @return The min accepted compression-ratio. - */ - public static double getMinInflateRatio() { - return MIN_INFLATE_RATIO; - } - - /** - * Sets the maximum file size of a single zip entry. It defaults to 4GB, - * i.e. the 32-bit zip format maximum. - * - * This can be used to limit memory consumption and protect against - * security vulnerabilities when documents are provided by users. - * - * @param maxEntrySize the max. file size of a single zip entry - */ - public static void setMaxEntrySize(long maxEntrySize) { - if (maxEntrySize < 0 || maxEntrySize > 0xFFFFFFFFL) { // don't use MAX_ENTRY_SIZE here! - throw new IllegalArgumentException("Max entry size is bounded [0-4GB], but had " + maxEntrySize); - } - MAX_ENTRY_SIZE = maxEntrySize; - } - - /** - * Returns the current maximum allowed uncompressed file size. - * - * See setMaxEntrySize() for details. - * - * @return The max accepted uncompressed file size. - */ - public static long getMaxEntrySize() { - return MAX_ENTRY_SIZE; - } - - /** - * Sets the maximum number of characters of text that are - * extracted before an exception is thrown during extracting - * text from documents. - * - * This can be used to limit memory consumption and protect against - * security vulnerabilities when documents are provided by users. - * - * @param maxTextSize the max. file size of a single zip entry - */ - public static void setMaxTextSize(long maxTextSize) { - if (maxTextSize < 0 || maxTextSize > 0xFFFFFFFFL) { // don't use MAX_ENTRY_SIZE here! - throw new IllegalArgumentException("Max text size is bounded [0-4GB], but had " + maxTextSize); - } - MAX_TEXT_SIZE = maxTextSize; - } - - /** - * Returns the current maximum allowed text size. - * - * See setMaxTextSize() for details. - * - * @return The max accepted text size. - */ - public static long getMaxTextSize() { - return MAX_TEXT_SIZE; - } - - public ZipSecureFile(File file, int mode) throws ZipException, IOException { - super(file, mode); - } - - public ZipSecureFile(File file) throws ZipException, IOException { - super(file); - } - - public ZipSecureFile(String name) throws ZipException, IOException { - super(name); - } - - /** - * Returns an input stream for reading the contents of the specified - * zip file entry. - * - *

Closing this ZIP file will, in turn, close all input - * streams that have been returned by invocations of this method. - * - * @param entry the zip file entry - * @return the input stream for reading the contents of the specified - * zip file entry. - * @throws ZipException if a ZIP format error has occurred - * @throws IOException if an I/O error has occurred - * @throws IllegalStateException if the zip file has been closed - */ - @SuppressWarnings("resource") - public InputStream getInputStream(ZipEntry entry) throws IOException { - InputStream zipIS = super.getInputStream(entry); - return addThreshold(zipIS); - } - - public static ThresholdInputStream addThreshold(final InputStream zipIS) throws IOException { - ThresholdInputStream newInner; - if (zipIS instanceof InflaterInputStream) { - newInner = AccessController.doPrivileged(new PrivilegedAction() { // NOSONAR - @SuppressForbidden("TODO: Fix this to not use reflection (it will break in Java 9)! " + - "Better would be to wrap *before* instead of trying to insert wrapper afterwards.") - public ThresholdInputStream run() { - try { - Field f = FilterInputStream.class.getDeclaredField("in"); - f.setAccessible(true); - InputStream oldInner = (InputStream)f.get(zipIS); - ThresholdInputStream newInner = new ThresholdInputStream(oldInner, null); - f.set(zipIS, newInner); - return newInner; - } catch (Exception ex) { - LOG.log(POILogger.WARN, "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream", ex); - } - return null; - } - }); - } else { - // the inner stream is a ZipFileInputStream, i.e. the data wasn't compressed - newInner = null; - } - - return new ThresholdInputStream(zipIS, newInner); - } - - public static class ThresholdInputStream extends PushbackInputStream { - long counter = 0; - ThresholdInputStream cis; - - public ThresholdInputStream(InputStream is, ThresholdInputStream cis) { - super(is,1); - this.cis = cis; - } - - public int read() throws IOException { - int b = in.read(); - if (b > -1) advance(1); - return b; - } - - public int read(byte b[], int off, int len) throws IOException { - int cnt = in.read(b, off, len); - if (cnt > -1) advance(cnt); - return cnt; - - } - - public long skip(long n) throws IOException { - counter = 0; - return in.skip(n); - } - - public synchronized void reset() throws IOException { - counter = 0; - in.reset(); - } - - public void advance(int advance) throws IOException { - counter += advance; - - // check the file size first, in case we are working on uncompressed streams - if(counter > MAX_ENTRY_SIZE) { - throw new IOException("Zip bomb detected! The file would exceed the max size of the expanded data in the zip-file. " - + "This may indicates that the file is used to inflate memory usage and thus could pose a security risk. " - + "You can adjust this limit via ZipSecureFile.setMaxEntrySize() if you need to work with files which are very large. " - + "Counter: " + counter + ", cis.counter: " + (cis == null ? 0 : cis.counter) - + "Limits: MAX_ENTRY_SIZE: " + MAX_ENTRY_SIZE); - } - - // no expanded size? - if (cis == null) { - return; - } - - // don't alert for small expanded size - if (counter <= GRACE_ENTRY_SIZE) { - return; - } - - double ratio = (double)cis.counter/(double)counter; - if (ratio >= MIN_INFLATE_RATIO) { - return; - } - - // one of the limits was reached, report it - throw new IOException("Zip bomb detected! The file would exceed the max. ratio of compressed file size to the size of the expanded data. " - + "This may indicate that the file is used to inflate memory usage and thus could pose a security risk. " - + "You can adjust this limit via ZipSecureFile.setMinInflateRatio() if you need to work with files which exceed this limit. " - + "Counter: " + counter + ", cis.counter: " + cis.counter + ", ratio: " + (((double)cis.counter)/counter) - + "Limits: MIN_INFLATE_RATIO: " + MIN_INFLATE_RATIO); - } - - public ZipEntry getNextEntry() throws IOException { - if (!(in instanceof ZipInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); - } - counter = 0; - return ((ZipInputStream)in).getNextEntry(); - } - - public void closeEntry() throws IOException { - if (!(in instanceof ZipInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); - } - counter = 0; - ((ZipInputStream)in).closeEntry(); - } - - public void unread(int b) throws IOException { - if (!(in instanceof PushbackInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); - } - if (--counter < 0) counter = 0; - ((PushbackInputStream)in).unread(b); - } - - public void unread(byte[] b, int off, int len) throws IOException { - if (!(in instanceof PushbackInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); - } - counter -= len; - if (--counter < 0) counter = 0; - ((PushbackInputStream)in).unread(b, off, len); - } - - public int available() throws IOException { - return in.available(); - } - - public boolean markSupported() { - return in.markSupported(); - } - - public synchronized void mark(int readlimit) { - in.mark(readlimit); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.util; + +import java.io.File; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.zip.InflaterInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.SuppressForbidden; + +/** + * This class wraps a {@link ZipFile} in order to check the + * entries for zip bombs + * while reading the archive. + * If a {@link ZipInputStream} is directly used, the wrapper + * can be applied via {@link #addThreshold(InputStream)}. + * The alert limits can be globally defined via {@link #setMaxEntrySize(long)} + * and {@link #setMinInflateRatio(double)}. + */ +public class ZipSecureFile extends ZipFile { + private static final POILogger LOG = POILogFactory.getLogger(ZipSecureFile.class); + + private static double MIN_INFLATE_RATIO = 0.01d; + private static long MAX_ENTRY_SIZE = 0xFFFFFFFFL; + + // don't alert for expanded sizes smaller than 100k + private final static long GRACE_ENTRY_SIZE = 100*1024L; + + // The default maximum size of extracted text + private static long MAX_TEXT_SIZE = 10*1024*1024L; + + /** + * Sets the ratio between de- and inflated bytes to detect zipbomb. + * It defaults to 1% (= 0.01d), i.e. when the compression is better than + * 1% for any given read package part, the parsing will fail indicating a + * Zip-Bomb. + * + * @param ratio the ratio between de- and inflated bytes to detect zipbomb + */ + public static void setMinInflateRatio(double ratio) { + MIN_INFLATE_RATIO = ratio; + } + + /** + * Returns the current minimum compression rate that is used. + * + * See setMinInflateRatio() for details. + * + * @return The min accepted compression-ratio. + */ + public static double getMinInflateRatio() { + return MIN_INFLATE_RATIO; + } + + /** + * Sets the maximum file size of a single zip entry. It defaults to 4GB, + * i.e. the 32-bit zip format maximum. + * + * This can be used to limit memory consumption and protect against + * security vulnerabilities when documents are provided by users. + * + * @param maxEntrySize the max. file size of a single zip entry + */ + public static void setMaxEntrySize(long maxEntrySize) { + if (maxEntrySize < 0 || maxEntrySize > 0xFFFFFFFFL) { // don't use MAX_ENTRY_SIZE here! + throw new IllegalArgumentException("Max entry size is bounded [0-4GB], but had " + maxEntrySize); + } + MAX_ENTRY_SIZE = maxEntrySize; + } + + /** + * Returns the current maximum allowed uncompressed file size. + * + * See setMaxEntrySize() for details. + * + * @return The max accepted uncompressed file size. + */ + public static long getMaxEntrySize() { + return MAX_ENTRY_SIZE; + } + + /** + * Sets the maximum number of characters of text that are + * extracted before an exception is thrown during extracting + * text from documents. + * + * This can be used to limit memory consumption and protect against + * security vulnerabilities when documents are provided by users. + * + * @param maxTextSize the max. file size of a single zip entry + */ + public static void setMaxTextSize(long maxTextSize) { + if (maxTextSize < 0 || maxTextSize > 0xFFFFFFFFL) { // don't use MAX_ENTRY_SIZE here! + throw new IllegalArgumentException("Max text size is bounded [0-4GB], but had " + maxTextSize); + } + MAX_TEXT_SIZE = maxTextSize; + } + + /** + * Returns the current maximum allowed text size. + * + * See setMaxTextSize() for details. + * + * @return The max accepted text size. + */ + public static long getMaxTextSize() { + return MAX_TEXT_SIZE; + } + + public ZipSecureFile(File file, int mode) throws ZipException, IOException { + super(file, mode); + } + + public ZipSecureFile(File file) throws ZipException, IOException { + super(file); + } + + public ZipSecureFile(String name) throws ZipException, IOException { + super(name); + } + + /** + * Returns an input stream for reading the contents of the specified + * zip file entry. + * + *

Closing this ZIP file will, in turn, close all input + * streams that have been returned by invocations of this method. + * + * @param entry the zip file entry + * @return the input stream for reading the contents of the specified + * zip file entry. + * @throws ZipException if a ZIP format error has occurred + * @throws IOException if an I/O error has occurred + * @throws IllegalStateException if the zip file has been closed + */ + @SuppressWarnings("resource") + public InputStream getInputStream(ZipEntry entry) throws IOException { + InputStream zipIS = super.getInputStream(entry); + return addThreshold(zipIS); + } + + public static ThresholdInputStream addThreshold(final InputStream zipIS) throws IOException { + ThresholdInputStream newInner; + if (zipIS instanceof InflaterInputStream) { + newInner = AccessController.doPrivileged(new PrivilegedAction() { // NOSONAR + @SuppressForbidden("TODO: Fix this to not use reflection (it will break in Java 9)! " + + "Better would be to wrap *before* instead of trying to insert wrapper afterwards.") + public ThresholdInputStream run() { + try { + Field f = FilterInputStream.class.getDeclaredField("in"); + f.setAccessible(true); + InputStream oldInner = (InputStream)f.get(zipIS); + ThresholdInputStream newInner = new ThresholdInputStream(oldInner, null); + f.set(zipIS, newInner); + return newInner; + } catch (Exception ex) { + LOG.log(POILogger.WARN, "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream", ex); + } + return null; + } + }); + } else { + // the inner stream is a ZipFileInputStream, i.e. the data wasn't compressed + newInner = null; + } + + return new ThresholdInputStream(zipIS, newInner); + } + + public static class ThresholdInputStream extends PushbackInputStream { + long counter = 0; + ThresholdInputStream cis; + + public ThresholdInputStream(InputStream is, ThresholdInputStream cis) { + super(is,1); + this.cis = cis; + } + + public int read() throws IOException { + int b = in.read(); + if (b > -1) advance(1); + return b; + } + + public int read(byte b[], int off, int len) throws IOException { + int cnt = in.read(b, off, len); + if (cnt > -1) advance(cnt); + return cnt; + + } + + public long skip(long n) throws IOException { + counter = 0; + return in.skip(n); + } + + public synchronized void reset() throws IOException { + counter = 0; + in.reset(); + } + + public void advance(int advance) throws IOException { + counter += advance; + + // check the file size first, in case we are working on uncompressed streams + if(counter > MAX_ENTRY_SIZE) { + throw new IOException("Zip bomb detected! The file would exceed the max size of the expanded data in the zip-file. " + + "This may indicates that the file is used to inflate memory usage and thus could pose a security risk. " + + "You can adjust this limit via ZipSecureFile.setMaxEntrySize() if you need to work with files which are very large. " + + "Counter: " + counter + ", cis.counter: " + (cis == null ? 0 : cis.counter) + + "Limits: MAX_ENTRY_SIZE: " + MAX_ENTRY_SIZE); + } + + // no expanded size? + if (cis == null) { + return; + } + + // don't alert for small expanded size + if (counter <= GRACE_ENTRY_SIZE) { + return; + } + + double ratio = (double)cis.counter/(double)counter; + if (ratio >= MIN_INFLATE_RATIO) { + return; + } + + // one of the limits was reached, report it + throw new IOException("Zip bomb detected! The file would exceed the max. ratio of compressed file size to the size of the expanded data. " + + "This may indicate that the file is used to inflate memory usage and thus could pose a security risk. " + + "You can adjust this limit via ZipSecureFile.setMinInflateRatio() if you need to work with files which exceed this limit. " + + "Counter: " + counter + ", cis.counter: " + cis.counter + ", ratio: " + (((double)cis.counter)/counter) + + "Limits: MIN_INFLATE_RATIO: " + MIN_INFLATE_RATIO); + } + + public ZipEntry getNextEntry() throws IOException { + if (!(in instanceof ZipInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); + } + counter = 0; + return ((ZipInputStream)in).getNextEntry(); + } + + public void closeEntry() throws IOException { + if (!(in instanceof ZipInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); + } + counter = 0; + ((ZipInputStream)in).closeEntry(); + } + + public void unread(int b) throws IOException { + if (!(in instanceof PushbackInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); + } + if (--counter < 0) counter = 0; + ((PushbackInputStream)in).unread(b); + } + + public void unread(byte[] b, int off, int len) throws IOException { + if (!(in instanceof PushbackInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); + } + counter -= len; + if (--counter < 0) counter = 0; + ((PushbackInputStream)in).unread(b, off, len); + } + + public int available() throws IOException { + return in.available(); + } + + public boolean markSupported() { + return in.markSupported(); + } + + public synchronized void mark(int readlimit) { + in.mark(readlimit); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java index ebb64cb5be..9e8d7c05c3 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java @@ -1,134 +1,134 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt.agile; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.ChainingMode; -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.EncryptionHeader; -import org.apache.poi.poifs.crypt.HashAlgorithm; - -import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity; -import com.microsoft.schemas.office.x2006.encryption.CTKeyData; -import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; -import com.microsoft.schemas.office.x2006.encryption.STCipherChaining; - -public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable { - private byte encryptedHmacKey[], encryptedHmacValue[]; - - public AgileEncryptionHeader(String descriptor) { - this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor)); - } - - protected AgileEncryptionHeader(EncryptionDocument ed) { - CTKeyData keyData; - try { - keyData = ed.getEncryption().getKeyData(); - if (keyData == null) { - throw new NullPointerException("keyData not set"); - } - } catch (Exception e) { - throw new EncryptedDocumentException("Unable to parse keyData"); - } - - int keyBits = (int)keyData.getKeyBits(); - - CipherAlgorithm ca = CipherAlgorithm.fromXmlId(keyData.getCipherAlgorithm().toString(), keyBits); - setCipherAlgorithm(ca); - setCipherProvider(ca.provider); - - setKeySize(keyBits); - setFlags(0); - setSizeExtra(0); - setCspName(null); - setBlockSize(keyData.getBlockSize()); - - switch (keyData.getCipherChaining().intValue()) { - case STCipherChaining.INT_CHAINING_MODE_CBC: - setChainingMode(ChainingMode.cbc); - break; - case STCipherChaining.INT_CHAINING_MODE_CFB: - setChainingMode(ChainingMode.cfb); - break; - default: - throw new EncryptedDocumentException("Unsupported chaining mode - "+keyData.getCipherChaining().toString()); - } - - int hashSize = keyData.getHashSize(); - - HashAlgorithm ha = HashAlgorithm.fromEcmaId(keyData.getHashAlgorithm().toString()); - setHashAlgorithm(ha); - - if (getHashAlgorithm().hashSize != hashSize) { - throw new EncryptedDocumentException("Unsupported hash algorithm: " + - keyData.getHashAlgorithm() + " @ " + hashSize + " bytes"); - } - - int saltLength = keyData.getSaltSize(); - setKeySalt(keyData.getSaltValue()); - if (getKeySalt().length != saltLength) { - throw new EncryptedDocumentException("Invalid salt length"); - } - - CTDataIntegrity di = ed.getEncryption().getDataIntegrity(); - setEncryptedHmacKey(di.getEncryptedHmacKey()); - setEncryptedHmacValue(di.getEncryptedHmacValue()); - } - - - public AgileEncryptionHeader(CipherAlgorithm algorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { - setCipherAlgorithm(algorithm); - setHashAlgorithm(hashAlgorithm); - setKeySize(keyBits); - setBlockSize(blockSize); - setChainingMode(chainingMode); - } - - // make method visible for this package - @Override - protected void setKeySalt(byte salt[]) { - if (salt == null || salt.length != getBlockSize()) { - throw new EncryptedDocumentException("invalid verifier salt"); - } - super.setKeySalt(salt); - } - - public byte[] getEncryptedHmacKey() { - return encryptedHmacKey; - } - - protected void setEncryptedHmacKey(byte[] encryptedHmacKey) { - this.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone(); - } - - public byte[] getEncryptedHmacValue() { - return encryptedHmacValue; - } - - protected void setEncryptedHmacValue(byte[] encryptedHmacValue) { - this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone(); - } - - @Override - public AgileEncryptionHeader clone() throws CloneNotSupportedException { - AgileEncryptionHeader other = (AgileEncryptionHeader)super.clone(); - other.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone(); - other.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone(); - return other; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt.agile; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.ChainingMode; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.EncryptionHeader; +import org.apache.poi.poifs.crypt.HashAlgorithm; + +import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity; +import com.microsoft.schemas.office.x2006.encryption.CTKeyData; +import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; +import com.microsoft.schemas.office.x2006.encryption.STCipherChaining; + +public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable { + private byte encryptedHmacKey[], encryptedHmacValue[]; + + public AgileEncryptionHeader(String descriptor) { + this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor)); + } + + protected AgileEncryptionHeader(EncryptionDocument ed) { + CTKeyData keyData; + try { + keyData = ed.getEncryption().getKeyData(); + if (keyData == null) { + throw new NullPointerException("keyData not set"); + } + } catch (Exception e) { + throw new EncryptedDocumentException("Unable to parse keyData"); + } + + int keyBits = (int)keyData.getKeyBits(); + + CipherAlgorithm ca = CipherAlgorithm.fromXmlId(keyData.getCipherAlgorithm().toString(), keyBits); + setCipherAlgorithm(ca); + setCipherProvider(ca.provider); + + setKeySize(keyBits); + setFlags(0); + setSizeExtra(0); + setCspName(null); + setBlockSize(keyData.getBlockSize()); + + switch (keyData.getCipherChaining().intValue()) { + case STCipherChaining.INT_CHAINING_MODE_CBC: + setChainingMode(ChainingMode.cbc); + break; + case STCipherChaining.INT_CHAINING_MODE_CFB: + setChainingMode(ChainingMode.cfb); + break; + default: + throw new EncryptedDocumentException("Unsupported chaining mode - "+keyData.getCipherChaining().toString()); + } + + int hashSize = keyData.getHashSize(); + + HashAlgorithm ha = HashAlgorithm.fromEcmaId(keyData.getHashAlgorithm().toString()); + setHashAlgorithm(ha); + + if (getHashAlgorithm().hashSize != hashSize) { + throw new EncryptedDocumentException("Unsupported hash algorithm: " + + keyData.getHashAlgorithm() + " @ " + hashSize + " bytes"); + } + + int saltLength = keyData.getSaltSize(); + setKeySalt(keyData.getSaltValue()); + if (getKeySalt().length != saltLength) { + throw new EncryptedDocumentException("Invalid salt length"); + } + + CTDataIntegrity di = ed.getEncryption().getDataIntegrity(); + setEncryptedHmacKey(di.getEncryptedHmacKey()); + setEncryptedHmacValue(di.getEncryptedHmacValue()); + } + + + public AgileEncryptionHeader(CipherAlgorithm algorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { + setCipherAlgorithm(algorithm); + setHashAlgorithm(hashAlgorithm); + setKeySize(keyBits); + setBlockSize(blockSize); + setChainingMode(chainingMode); + } + + // make method visible for this package + @Override + protected void setKeySalt(byte salt[]) { + if (salt == null || salt.length != getBlockSize()) { + throw new EncryptedDocumentException("invalid verifier salt"); + } + super.setKeySalt(salt); + } + + public byte[] getEncryptedHmacKey() { + return encryptedHmacKey; + } + + protected void setEncryptedHmacKey(byte[] encryptedHmacKey) { + this.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone(); + } + + public byte[] getEncryptedHmacValue() { + return encryptedHmacValue; + } + + protected void setEncryptedHmacValue(byte[] encryptedHmacValue) { + this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone(); + } + + @Override + public AgileEncryptionHeader clone() throws CloneNotSupportedException { + AgileEncryptionHeader other = (AgileEncryptionHeader)super.clone(); + other.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone(); + other.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone(); + return other; + } + +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java index acfa01581d..15ec609b4a 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java @@ -1,109 +1,109 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt.agile; - -import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.ChainingMode; -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.EncryptionInfoBuilder; -import org.apache.poi.poifs.crypt.EncryptionMode; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.util.LittleEndianInput; -import org.apache.xmlbeans.XmlException; - -import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; - -public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder { - - @Override - public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException { - EncryptionDocument ed = parseDescriptor((InputStream)dis); - info.setHeader(new AgileEncryptionHeader(ed)); - info.setVerifier(new AgileEncryptionVerifier(ed)); - if (info.getVersionMajor() == EncryptionMode.agile.versionMajor - && info.getVersionMinor() == EncryptionMode.agile.versionMinor) { - AgileDecryptor dec = new AgileDecryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - AgileEncryptor enc = new AgileEncryptor(); - enc.setEncryptionInfo(info); - info.setEncryptor(enc); - } - } - - @Override - public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { - if (cipherAlgorithm == null) { - cipherAlgorithm = CipherAlgorithm.aes128; - } - if (cipherAlgorithm == CipherAlgorithm.rc4) { - throw new EncryptedDocumentException("RC4 must not be used with agile encryption."); - } - if (hashAlgorithm == null) { - hashAlgorithm = HashAlgorithm.sha1; - } - if (chainingMode == null) { - chainingMode = ChainingMode.cbc; - } - if (!(chainingMode == ChainingMode.cbc || chainingMode == ChainingMode.cfb)) { - throw new EncryptedDocumentException("Agile encryption only supports CBC/CFB chaining."); - } - if (keyBits == -1) { - keyBits = cipherAlgorithm.defaultKeySize; - } - if (blockSize == -1) { - blockSize = cipherAlgorithm.blockSize; - } - boolean found = false; - for (int ks : cipherAlgorithm.allowedKeySize) { - found |= (ks == keyBits); - } - if (!found) { - throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+cipherAlgorithm.toString()); - } - info.setHeader(new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); - info.setVerifier(new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); - AgileDecryptor dec = new AgileDecryptor(); - dec.setEncryptionInfo(info); - info.setDecryptor(dec); - AgileEncryptor enc = new AgileEncryptor(); - enc.setEncryptionInfo(info); - info.setEncryptor(enc); - } - - protected static EncryptionDocument parseDescriptor(String descriptor) { - try { - return EncryptionDocument.Factory.parse(descriptor, DEFAULT_XML_OPTIONS); - } catch (XmlException e) { - throw new EncryptedDocumentException("Unable to parse encryption descriptor", e); - } - } - - protected static EncryptionDocument parseDescriptor(InputStream descriptor) { - try { - return EncryptionDocument.Factory.parse(descriptor, DEFAULT_XML_OPTIONS); - } catch (Exception e) { - throw new EncryptedDocumentException("Unable to parse encryption descriptor", e); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt.agile; + +import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.ChainingMode; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionInfoBuilder; +import org.apache.poi.poifs.crypt.EncryptionMode; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.util.LittleEndianInput; +import org.apache.xmlbeans.XmlException; + +import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; + +public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder { + + @Override + public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException { + EncryptionDocument ed = parseDescriptor((InputStream)dis); + info.setHeader(new AgileEncryptionHeader(ed)); + info.setVerifier(new AgileEncryptionVerifier(ed)); + if (info.getVersionMajor() == EncryptionMode.agile.versionMajor + && info.getVersionMinor() == EncryptionMode.agile.versionMinor) { + AgileDecryptor dec = new AgileDecryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + AgileEncryptor enc = new AgileEncryptor(); + enc.setEncryptionInfo(info); + info.setEncryptor(enc); + } + } + + @Override + public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { + if (cipherAlgorithm == null) { + cipherAlgorithm = CipherAlgorithm.aes128; + } + if (cipherAlgorithm == CipherAlgorithm.rc4) { + throw new EncryptedDocumentException("RC4 must not be used with agile encryption."); + } + if (hashAlgorithm == null) { + hashAlgorithm = HashAlgorithm.sha1; + } + if (chainingMode == null) { + chainingMode = ChainingMode.cbc; + } + if (!(chainingMode == ChainingMode.cbc || chainingMode == ChainingMode.cfb)) { + throw new EncryptedDocumentException("Agile encryption only supports CBC/CFB chaining."); + } + if (keyBits == -1) { + keyBits = cipherAlgorithm.defaultKeySize; + } + if (blockSize == -1) { + blockSize = cipherAlgorithm.blockSize; + } + boolean found = false; + for (int ks : cipherAlgorithm.allowedKeySize) { + found |= (ks == keyBits); + } + if (!found) { + throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+cipherAlgorithm.toString()); + } + info.setHeader(new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); + info.setVerifier(new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode)); + AgileDecryptor dec = new AgileDecryptor(); + dec.setEncryptionInfo(info); + info.setDecryptor(dec); + AgileEncryptor enc = new AgileEncryptor(); + enc.setEncryptionInfo(info); + info.setEncryptor(enc); + } + + protected static EncryptionDocument parseDescriptor(String descriptor) { + try { + return EncryptionDocument.Factory.parse(descriptor, DEFAULT_XML_OPTIONS); + } catch (XmlException e) { + throw new EncryptedDocumentException("Unable to parse encryption descriptor", e); + } + } + + protected static EncryptionDocument parseDescriptor(InputStream descriptor) { + try { + return EncryptionDocument.Factory.parse(descriptor, DEFAULT_XML_OPTIONS); + } catch (Exception e) { + throw new EncryptedDocumentException("Unable to parse encryption descriptor", e); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java index 96aa9b5f9f..3ffb810030 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java @@ -1,460 +1,460 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt.agile; - -import static org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0; -import static org.apache.poi.poifs.crypt.CryptoFunctions.getCipher; -import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest; -import static org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword; -import static org.apache.poi.poifs.crypt.DataSpaceMapUtils.createEncryptionEntry; -import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.getNextBlockSize; -import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.hashInput; -import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kCryptoKeyBlock; -import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kHashedVerifierBlock; -import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityKeyBlock; -import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityValueBlock; -import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kVerifierInputBlock; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.SecureRandom; -import java.security.cert.CertificateEncodingException; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; - -import javax.crypto.Cipher; -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.DataSpaceMapUtils; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.Encryptor; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry; -import org.apache.poi.poifs.crypt.standard.EncryptionRecord; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianByteArrayOutputStream; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.xmlbeans.XmlOptions; - -import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity; -import com.microsoft.schemas.office.x2006.encryption.CTEncryption; -import com.microsoft.schemas.office.x2006.encryption.CTKeyData; -import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor; -import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptors; -import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; -import com.microsoft.schemas.office.x2006.encryption.STCipherAlgorithm; -import com.microsoft.schemas.office.x2006.encryption.STCipherChaining; -import com.microsoft.schemas.office.x2006.encryption.STHashAlgorithm; -import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor; -import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor; - -public class AgileEncryptor extends Encryptor implements Cloneable { - private byte integritySalt[]; - private byte pwHash[]; - - protected AgileEncryptor() { - } - - @Override - public void confirmPassword(String password) { - // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier - Random r = new SecureRandom(); - AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); - int blockSize = header.getBlockSize(); - int keySize = header.getKeySize()/8; - int hashSize = header.getHashAlgorithm().hashSize; - - byte[] newVerifierSalt = new byte[blockSize] - , newVerifier = new byte[blockSize] - , newKeySalt = new byte[blockSize] - , newKeySpec = new byte[keySize] - , newIntegritySalt = new byte[hashSize]; - r.nextBytes(newVerifierSalt); // blocksize - r.nextBytes(newVerifier); // blocksize - r.nextBytes(newKeySalt); // blocksize - r.nextBytes(newKeySpec); // keysize - r.nextBytes(newIntegritySalt); // hashsize - - confirmPassword(password, newKeySpec, newKeySalt, newVerifierSalt, newVerifier, newIntegritySalt); - } - - @Override - public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) { - AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier(); - AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); - - ver.setSalt(verifierSalt); - header.setKeySalt(keySalt); - - int blockSize = header.getBlockSize(); - - pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount()); - - /** - * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps: - * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize - * attribute. - * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password, - * the binary byte array used to create the saltValue attribute, and a blockKey byte array - * consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79. - * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue - * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an - * integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of - * blockSize bytes. - * 4. Use base64 to encode the result of step 3. - */ - byte encryptedVerifier[] = hashInput(ver, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE); - ver.setEncryptedVerifier(encryptedVerifier); - - - /** - * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps: - * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for - * encryptedVerifierHashInput. - * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password, - * the binary byte array used to create the saltValue attribute, and a blockKey byte array - * consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e. - * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as - * an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of - * blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes. - * 4. Use base64 to encode the result of step 3. - */ - MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm()); - byte[] hashedVerifier = hashMD.digest(verifier); - byte encryptedVerifierHash[] = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE); - ver.setEncryptedVerifierHash(encryptedVerifierHash); - - /** - * encryptedKeyValue: This attribute MUST be generated by using the following steps: - * 1. Generate a random array of bytes that is the same size as specified by the - * Encryptor.KeyData.keyBits attribute of the parent element. - * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password, - * the binary byte array used to create the saltValue attribute, and a blockKey byte array - * consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6. - * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue - * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an - * integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of - * blockSize bytes. - * 4. Use base64 to encode the result of step 3. - */ - byte encryptedKey[] = hashInput(ver, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE); - ver.setEncryptedKey(encryptedKey); - - SecretKey secretKey = new SecretKeySpec(keySpec, header.getCipherAlgorithm().jceId); - setSecretKey(secretKey); - - /* - * 2.3.4.14 DataIntegrity Generation (Agile Encryption) - * - * The DataIntegrity element contained within an Encryption element MUST be generated by using - * the following steps: - * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor - * contained within the KeyEncryptors sequence. Use this key for encryption operations in the - * remaining steps of this section. - * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the - * KeyData.hashSize attribute. - * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the - * KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes: - * 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as - * specified in section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize - * bytes, pad the array with 0x00 to the next integral multiple of blockSize bytes. - * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3. - * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message), - * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key. - * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be - * used as the message. - * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes: - * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33. - * 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6. - */ - this.integritySalt = integritySalt.clone(); - - try { - byte vec[] = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, header.getBlockSize()); - Cipher cipher = getCipher(secretKey, header.getCipherAlgorithm(), header.getChainingMode(), vec, Cipher.ENCRYPT_MODE); - byte hmacKey[] = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize)); - byte encryptedHmacKey[] = cipher.doFinal(hmacKey); - header.setEncryptedHmacKey(encryptedHmacKey); - - cipher = Cipher.getInstance("RSA"); - for (AgileCertificateEntry ace : ver.getCertificates()) { - cipher.init(Cipher.ENCRYPT_MODE, ace.x509.getPublicKey()); - ace.encryptedKey = cipher.doFinal(getSecretKey().getEncoded()); - Mac x509Hmac = CryptoFunctions.getMac(header.getHashAlgorithm()); - x509Hmac.init(getSecretKey()); - ace.certVerifier = x509Hmac.doFinal(ace.x509.getEncoded()); - } - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException(e); - } - } - - @Override - public OutputStream getDataStream(DirectoryNode dir) - throws IOException, GeneralSecurityException { - // TODO: initialize headers - AgileCipherOutputStream countStream = new AgileCipherOutputStream(dir); - return countStream; - } - - /** - * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message), - * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key. - * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be - * used as the message. - * - * Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes: - * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33. - **/ - protected void updateIntegrityHMAC(File tmpFile, int oleStreamSize) throws GeneralSecurityException, IOException { - // as the integrity hmac needs to contain the StreamSize, - // it's not possible to calculate it on-the-fly while buffering - // TODO: add stream size parameter to getDataStream() - AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); - int blockSize = header.getBlockSize(); - HashAlgorithm hashAlgo = header.getHashAlgorithm(); - Mac integrityMD = CryptoFunctions.getMac(hashAlgo); - byte hmacKey[] = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize)); - integrityMD.init(new SecretKeySpec(hmacKey, hashAlgo.jceHmacId)); - - byte buf[] = new byte[1024]; - LittleEndian.putLong(buf, 0, oleStreamSize); - integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE); - - InputStream fis = new FileInputStream(tmpFile); - try { - int readBytes; - while ((readBytes = fis.read(buf)) != -1) { - integrityMD.update(buf, 0, readBytes); - } - } finally { - fis.close(); - } - - byte hmacValue[] = integrityMD.doFinal(); - byte hmacValueFilled[] = getBlock0(hmacValue, getNextBlockSize(hmacValue.length, blockSize)); - - byte iv[] = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize); - Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE); - byte encryptedHmacValue[] = cipher.doFinal(hmacValueFilled); - - header.setEncryptedHmacValue(encryptedHmacValue); - } - - private final CTKeyEncryptor.Uri.Enum passwordUri = - CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_PASSWORD; - private final CTKeyEncryptor.Uri.Enum certificateUri = - CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE; - - protected EncryptionDocument createEncryptionDocument() { - AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier(); - AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); - - EncryptionDocument ed = EncryptionDocument.Factory.newInstance(); - CTEncryption edRoot = ed.addNewEncryption(); - - CTKeyData keyData = edRoot.addNewKeyData(); - CTKeyEncryptors keyEncList = edRoot.addNewKeyEncryptors(); - CTKeyEncryptor keyEnc = keyEncList.addNewKeyEncryptor(); - keyEnc.setUri(passwordUri); - CTPasswordKeyEncryptor keyPass = keyEnc.addNewEncryptedPasswordKey(); - - keyPass.setSpinCount(ver.getSpinCount()); - - keyData.setSaltSize(header.getBlockSize()); - keyPass.setSaltSize(ver.getBlockSize()); - - keyData.setBlockSize(header.getBlockSize()); - keyPass.setBlockSize(ver.getBlockSize()); - - keyData.setKeyBits(header.getKeySize()); - keyPass.setKeyBits(ver.getKeySize()); - - keyData.setHashSize(header.getHashAlgorithm().hashSize); - keyPass.setHashSize(ver.getHashAlgorithm().hashSize); - - // header and verifier have to have the same cipher algorithm - if (!header.getCipherAlgorithm().xmlId.equals(ver.getCipherAlgorithm().xmlId)) { - throw new EncryptedDocumentException("Cipher algorithm of header and verifier have to match"); - } - STCipherAlgorithm.Enum xmlCipherAlgo = STCipherAlgorithm.Enum.forString(header.getCipherAlgorithm().xmlId); - if (xmlCipherAlgo == null) { - throw new EncryptedDocumentException("CipherAlgorithm "+header.getCipherAlgorithm()+" not supported."); - } - keyData.setCipherAlgorithm(xmlCipherAlgo); - keyPass.setCipherAlgorithm(xmlCipherAlgo); - - switch (header.getChainingMode()) { - case cbc: - keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC); - keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC); - break; - case cfb: - keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB); - keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB); - break; - default: - throw new EncryptedDocumentException("ChainingMode "+header.getChainingMode()+" not supported."); - } - - keyData.setHashAlgorithm(mapHashAlgorithm(header.getHashAlgorithm())); - keyPass.setHashAlgorithm(mapHashAlgorithm(ver.getHashAlgorithm())); - - keyData.setSaltValue(header.getKeySalt()); - keyPass.setSaltValue(ver.getSalt()); - keyPass.setEncryptedVerifierHashInput(ver.getEncryptedVerifier()); - keyPass.setEncryptedVerifierHashValue(ver.getEncryptedVerifierHash()); - keyPass.setEncryptedKeyValue(ver.getEncryptedKey()); - - CTDataIntegrity hmacData = edRoot.addNewDataIntegrity(); - hmacData.setEncryptedHmacKey(header.getEncryptedHmacKey()); - hmacData.setEncryptedHmacValue(header.getEncryptedHmacValue()); - - for (AgileCertificateEntry ace : ver.getCertificates()) { - keyEnc = keyEncList.addNewKeyEncryptor(); - keyEnc.setUri(certificateUri); - CTCertificateKeyEncryptor certData = keyEnc.addNewEncryptedCertificateKey(); - try { - certData.setX509Certificate(ace.x509.getEncoded()); - } catch (CertificateEncodingException e) { - throw new EncryptedDocumentException(e); - } - certData.setEncryptedKeyValue(ace.encryptedKey); - certData.setCertVerifier(ace.certVerifier); - } - - return ed; - } - - private static STHashAlgorithm.Enum mapHashAlgorithm(HashAlgorithm hashAlgo) { - STHashAlgorithm.Enum xmlHashAlgo = STHashAlgorithm.Enum.forString(hashAlgo.ecmaString); - if (xmlHashAlgo == null) { - throw new EncryptedDocumentException("HashAlgorithm "+hashAlgo+" not supported."); - } - return xmlHashAlgo; - } - - protected void marshallEncryptionDocument(EncryptionDocument ed, LittleEndianByteArrayOutputStream os) { - XmlOptions xo = new XmlOptions(); - xo.setCharacterEncoding("UTF-8"); - Map nsMap = new HashMap(); - nsMap.put(passwordUri.toString(),"p"); - nsMap.put(certificateUri.toString(), "c"); - xo.setUseDefaultNamespace(); - xo.setSaveSuggestedPrefixes(nsMap); - xo.setSaveNamespacesFirst(); - xo.setSaveAggressiveNamespaces(); - - // setting standalone doesn't work with xmlbeans-2.3 & 2.6 - // ed.documentProperties().setStandalone(true); - xo.setSaveNoXmlDecl(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - try { - bos.write("\r\n".getBytes("UTF-8")); - ed.save(bos, xo); - bos.writeTo(os); - } catch (IOException e) { - throw new EncryptedDocumentException("error marshalling encryption info document", e); - } - } - - protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) - throws IOException, GeneralSecurityException { - DataSpaceMapUtils.addDefaultDataSpace(dir); - - final EncryptionInfo info = getEncryptionInfo(); - - EncryptionRecord er = new EncryptionRecord(){ - @Override - public void write(LittleEndianByteArrayOutputStream bos) { - // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where - // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004 - bos.writeShort(info.getVersionMajor()); - bos.writeShort(info.getVersionMinor()); - // Reserved (4 bytes): A value that MUST be 0x00000040 - bos.writeInt(info.getEncryptionFlags()); - - EncryptionDocument ed = createEncryptionDocument(); - marshallEncryptionDocument(ed, bos); - } - }; - - createEncryptionEntry(dir, "EncryptionInfo", er); - } - - - /** - * 2.3.4.15 Data Encryption (Agile Encryption) - * - * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly - * random access while allowing CBC modes to be used in the encryption process. - * The initialization vector for the encryption process MUST be obtained by using the zero-based - * segment number as a blockKey and the binary form of the KeyData.saltValue as specified in - * section 2.3.4.12. The block number MUST be represented as a 32-bit unsigned integer. - * Data blocks MUST then be encrypted by using the initialization vector and the intermediate key - * obtained by decrypting the encryptedKeyValue from a KeyEncryptor contained within the - * KeyEncryptors sequence as specified in section 2.3.4.10. The final data block MUST be padded to - * the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used. Note - * that the StreamSize field of the EncryptedPackage field specifies the number of bytes of - * unencrypted data as specified in section 2.3.4.4. - */ - private class AgileCipherOutputStream extends ChunkedCipherOutputStream { - public AgileCipherOutputStream(DirectoryNode dir) throws IOException, GeneralSecurityException { - super(dir, 4096); - } - - @Override - protected Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk) - throws GeneralSecurityException { - return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); - } - - @Override - protected void calculateChecksum(File fileOut, int oleStreamSize) - throws GeneralSecurityException, IOException { - // integrityHMAC needs to be updated before the encryption document is created - updateIntegrityHMAC(fileOut, oleStreamSize); - } - - @Override - protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) - throws IOException, GeneralSecurityException { - AgileEncryptor.this.createEncryptionInfoEntry(dir, tmpFile); - } - } - - @Override - public AgileEncryptor clone() throws CloneNotSupportedException { - AgileEncryptor other = (AgileEncryptor)super.clone(); - other.integritySalt = (integritySalt == null) ? null : integritySalt.clone(); - other.pwHash = (pwHash == null) ? null : pwHash.clone(); - return other; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt.agile; + +import static org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0; +import static org.apache.poi.poifs.crypt.CryptoFunctions.getCipher; +import static org.apache.poi.poifs.crypt.CryptoFunctions.getMessageDigest; +import static org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword; +import static org.apache.poi.poifs.crypt.DataSpaceMapUtils.createEncryptionEntry; +import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.getNextBlockSize; +import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.hashInput; +import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kCryptoKeyBlock; +import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kHashedVerifierBlock; +import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityKeyBlock; +import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kIntegrityValueBlock; +import static org.apache.poi.poifs.crypt.agile.AgileDecryptor.kVerifierInputBlock; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.security.cert.CertificateEncodingException; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import javax.crypto.Cipher; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.DataSpaceMapUtils; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry; +import org.apache.poi.poifs.crypt.standard.EncryptionRecord; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianByteArrayOutputStream; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.xmlbeans.XmlOptions; + +import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity; +import com.microsoft.schemas.office.x2006.encryption.CTEncryption; +import com.microsoft.schemas.office.x2006.encryption.CTKeyData; +import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor; +import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptors; +import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; +import com.microsoft.schemas.office.x2006.encryption.STCipherAlgorithm; +import com.microsoft.schemas.office.x2006.encryption.STCipherChaining; +import com.microsoft.schemas.office.x2006.encryption.STHashAlgorithm; +import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor; +import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor; + +public class AgileEncryptor extends Encryptor implements Cloneable { + private byte integritySalt[]; + private byte pwHash[]; + + protected AgileEncryptor() { + } + + @Override + public void confirmPassword(String password) { + // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier + Random r = new SecureRandom(); + AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); + int blockSize = header.getBlockSize(); + int keySize = header.getKeySize()/8; + int hashSize = header.getHashAlgorithm().hashSize; + + byte[] newVerifierSalt = new byte[blockSize] + , newVerifier = new byte[blockSize] + , newKeySalt = new byte[blockSize] + , newKeySpec = new byte[keySize] + , newIntegritySalt = new byte[hashSize]; + r.nextBytes(newVerifierSalt); // blocksize + r.nextBytes(newVerifier); // blocksize + r.nextBytes(newKeySalt); // blocksize + r.nextBytes(newKeySpec); // keysize + r.nextBytes(newIntegritySalt); // hashsize + + confirmPassword(password, newKeySpec, newKeySalt, newVerifierSalt, newVerifier, newIntegritySalt); + } + + @Override + public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) { + AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier(); + AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); + + ver.setSalt(verifierSalt); + header.setKeySalt(keySalt); + + int blockSize = header.getBlockSize(); + + pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount()); + + /** + * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps: + * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize + * attribute. + * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password, + * the binary byte array used to create the saltValue attribute, and a blockKey byte array + * consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79. + * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue + * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an + * integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of + * blockSize bytes. + * 4. Use base64 to encode the result of step 3. + */ + byte encryptedVerifier[] = hashInput(ver, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE); + ver.setEncryptedVerifier(encryptedVerifier); + + + /** + * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps: + * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for + * encryptedVerifierHashInput. + * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password, + * the binary byte array used to create the saltValue attribute, and a blockKey byte array + * consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e. + * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as + * an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of + * blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes. + * 4. Use base64 to encode the result of step 3. + */ + MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm()); + byte[] hashedVerifier = hashMD.digest(verifier); + byte encryptedVerifierHash[] = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE); + ver.setEncryptedVerifierHash(encryptedVerifierHash); + + /** + * encryptedKeyValue: This attribute MUST be generated by using the following steps: + * 1. Generate a random array of bytes that is the same size as specified by the + * Encryptor.KeyData.keyBits attribute of the parent element. + * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password, + * the binary byte array used to create the saltValue attribute, and a blockKey byte array + * consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6. + * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue + * attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an + * integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of + * blockSize bytes. + * 4. Use base64 to encode the result of step 3. + */ + byte encryptedKey[] = hashInput(ver, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE); + ver.setEncryptedKey(encryptedKey); + + SecretKey secretKey = new SecretKeySpec(keySpec, header.getCipherAlgorithm().jceId); + setSecretKey(secretKey); + + /* + * 2.3.4.14 DataIntegrity Generation (Agile Encryption) + * + * The DataIntegrity element contained within an Encryption element MUST be generated by using + * the following steps: + * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor + * contained within the KeyEncryptors sequence. Use this key for encryption operations in the + * remaining steps of this section. + * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the + * KeyData.hashSize attribute. + * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the + * KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes: + * 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as + * specified in section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize + * bytes, pad the array with 0x00 to the next integral multiple of blockSize bytes. + * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3. + * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message), + * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key. + * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be + * used as the message. + * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes: + * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33. + * 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6. + */ + this.integritySalt = integritySalt.clone(); + + try { + byte vec[] = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, header.getBlockSize()); + Cipher cipher = getCipher(secretKey, header.getCipherAlgorithm(), header.getChainingMode(), vec, Cipher.ENCRYPT_MODE); + byte hmacKey[] = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize)); + byte encryptedHmacKey[] = cipher.doFinal(hmacKey); + header.setEncryptedHmacKey(encryptedHmacKey); + + cipher = Cipher.getInstance("RSA"); + for (AgileCertificateEntry ace : ver.getCertificates()) { + cipher.init(Cipher.ENCRYPT_MODE, ace.x509.getPublicKey()); + ace.encryptedKey = cipher.doFinal(getSecretKey().getEncoded()); + Mac x509Hmac = CryptoFunctions.getMac(header.getHashAlgorithm()); + x509Hmac.init(getSecretKey()); + ace.certVerifier = x509Hmac.doFinal(ace.x509.getEncoded()); + } + } catch (GeneralSecurityException e) { + throw new EncryptedDocumentException(e); + } + } + + @Override + public OutputStream getDataStream(DirectoryNode dir) + throws IOException, GeneralSecurityException { + // TODO: initialize headers + AgileCipherOutputStream countStream = new AgileCipherOutputStream(dir); + return countStream; + } + + /** + * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message), + * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key. + * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be + * used as the message. + * + * Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes: + * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33. + **/ + protected void updateIntegrityHMAC(File tmpFile, int oleStreamSize) throws GeneralSecurityException, IOException { + // as the integrity hmac needs to contain the StreamSize, + // it's not possible to calculate it on-the-fly while buffering + // TODO: add stream size parameter to getDataStream() + AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); + int blockSize = header.getBlockSize(); + HashAlgorithm hashAlgo = header.getHashAlgorithm(); + Mac integrityMD = CryptoFunctions.getMac(hashAlgo); + byte hmacKey[] = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize)); + integrityMD.init(new SecretKeySpec(hmacKey, hashAlgo.jceHmacId)); + + byte buf[] = new byte[1024]; + LittleEndian.putLong(buf, 0, oleStreamSize); + integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE); + + InputStream fis = new FileInputStream(tmpFile); + try { + int readBytes; + while ((readBytes = fis.read(buf)) != -1) { + integrityMD.update(buf, 0, readBytes); + } + } finally { + fis.close(); + } + + byte hmacValue[] = integrityMD.doFinal(); + byte hmacValueFilled[] = getBlock0(hmacValue, getNextBlockSize(hmacValue.length, blockSize)); + + byte iv[] = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize); + Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE); + byte encryptedHmacValue[] = cipher.doFinal(hmacValueFilled); + + header.setEncryptedHmacValue(encryptedHmacValue); + } + + private final CTKeyEncryptor.Uri.Enum passwordUri = + CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_PASSWORD; + private final CTKeyEncryptor.Uri.Enum certificateUri = + CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE; + + protected EncryptionDocument createEncryptionDocument() { + AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier(); + AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); + + EncryptionDocument ed = EncryptionDocument.Factory.newInstance(); + CTEncryption edRoot = ed.addNewEncryption(); + + CTKeyData keyData = edRoot.addNewKeyData(); + CTKeyEncryptors keyEncList = edRoot.addNewKeyEncryptors(); + CTKeyEncryptor keyEnc = keyEncList.addNewKeyEncryptor(); + keyEnc.setUri(passwordUri); + CTPasswordKeyEncryptor keyPass = keyEnc.addNewEncryptedPasswordKey(); + + keyPass.setSpinCount(ver.getSpinCount()); + + keyData.setSaltSize(header.getBlockSize()); + keyPass.setSaltSize(ver.getBlockSize()); + + keyData.setBlockSize(header.getBlockSize()); + keyPass.setBlockSize(ver.getBlockSize()); + + keyData.setKeyBits(header.getKeySize()); + keyPass.setKeyBits(ver.getKeySize()); + + keyData.setHashSize(header.getHashAlgorithm().hashSize); + keyPass.setHashSize(ver.getHashAlgorithm().hashSize); + + // header and verifier have to have the same cipher algorithm + if (!header.getCipherAlgorithm().xmlId.equals(ver.getCipherAlgorithm().xmlId)) { + throw new EncryptedDocumentException("Cipher algorithm of header and verifier have to match"); + } + STCipherAlgorithm.Enum xmlCipherAlgo = STCipherAlgorithm.Enum.forString(header.getCipherAlgorithm().xmlId); + if (xmlCipherAlgo == null) { + throw new EncryptedDocumentException("CipherAlgorithm "+header.getCipherAlgorithm()+" not supported."); + } + keyData.setCipherAlgorithm(xmlCipherAlgo); + keyPass.setCipherAlgorithm(xmlCipherAlgo); + + switch (header.getChainingMode()) { + case cbc: + keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC); + keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC); + break; + case cfb: + keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB); + keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB); + break; + default: + throw new EncryptedDocumentException("ChainingMode "+header.getChainingMode()+" not supported."); + } + + keyData.setHashAlgorithm(mapHashAlgorithm(header.getHashAlgorithm())); + keyPass.setHashAlgorithm(mapHashAlgorithm(ver.getHashAlgorithm())); + + keyData.setSaltValue(header.getKeySalt()); + keyPass.setSaltValue(ver.getSalt()); + keyPass.setEncryptedVerifierHashInput(ver.getEncryptedVerifier()); + keyPass.setEncryptedVerifierHashValue(ver.getEncryptedVerifierHash()); + keyPass.setEncryptedKeyValue(ver.getEncryptedKey()); + + CTDataIntegrity hmacData = edRoot.addNewDataIntegrity(); + hmacData.setEncryptedHmacKey(header.getEncryptedHmacKey()); + hmacData.setEncryptedHmacValue(header.getEncryptedHmacValue()); + + for (AgileCertificateEntry ace : ver.getCertificates()) { + keyEnc = keyEncList.addNewKeyEncryptor(); + keyEnc.setUri(certificateUri); + CTCertificateKeyEncryptor certData = keyEnc.addNewEncryptedCertificateKey(); + try { + certData.setX509Certificate(ace.x509.getEncoded()); + } catch (CertificateEncodingException e) { + throw new EncryptedDocumentException(e); + } + certData.setEncryptedKeyValue(ace.encryptedKey); + certData.setCertVerifier(ace.certVerifier); + } + + return ed; + } + + private static STHashAlgorithm.Enum mapHashAlgorithm(HashAlgorithm hashAlgo) { + STHashAlgorithm.Enum xmlHashAlgo = STHashAlgorithm.Enum.forString(hashAlgo.ecmaString); + if (xmlHashAlgo == null) { + throw new EncryptedDocumentException("HashAlgorithm "+hashAlgo+" not supported."); + } + return xmlHashAlgo; + } + + protected void marshallEncryptionDocument(EncryptionDocument ed, LittleEndianByteArrayOutputStream os) { + XmlOptions xo = new XmlOptions(); + xo.setCharacterEncoding("UTF-8"); + Map nsMap = new HashMap(); + nsMap.put(passwordUri.toString(),"p"); + nsMap.put(certificateUri.toString(), "c"); + xo.setUseDefaultNamespace(); + xo.setSaveSuggestedPrefixes(nsMap); + xo.setSaveNamespacesFirst(); + xo.setSaveAggressiveNamespaces(); + + // setting standalone doesn't work with xmlbeans-2.3 & 2.6 + // ed.documentProperties().setStandalone(true); + xo.setSaveNoXmlDecl(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + bos.write("\r\n".getBytes("UTF-8")); + ed.save(bos, xo); + bos.writeTo(os); + } catch (IOException e) { + throw new EncryptedDocumentException("error marshalling encryption info document", e); + } + } + + protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) + throws IOException, GeneralSecurityException { + DataSpaceMapUtils.addDefaultDataSpace(dir); + + final EncryptionInfo info = getEncryptionInfo(); + + EncryptionRecord er = new EncryptionRecord(){ + @Override + public void write(LittleEndianByteArrayOutputStream bos) { + // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where + // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004 + bos.writeShort(info.getVersionMajor()); + bos.writeShort(info.getVersionMinor()); + // Reserved (4 bytes): A value that MUST be 0x00000040 + bos.writeInt(info.getEncryptionFlags()); + + EncryptionDocument ed = createEncryptionDocument(); + marshallEncryptionDocument(ed, bos); + } + }; + + createEncryptionEntry(dir, "EncryptionInfo", er); + } + + + /** + * 2.3.4.15 Data Encryption (Agile Encryption) + * + * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly + * random access while allowing CBC modes to be used in the encryption process. + * The initialization vector for the encryption process MUST be obtained by using the zero-based + * segment number as a blockKey and the binary form of the KeyData.saltValue as specified in + * section 2.3.4.12. The block number MUST be represented as a 32-bit unsigned integer. + * Data blocks MUST then be encrypted by using the initialization vector and the intermediate key + * obtained by decrypting the encryptedKeyValue from a KeyEncryptor contained within the + * KeyEncryptors sequence as specified in section 2.3.4.10. The final data block MUST be padded to + * the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used. Note + * that the StreamSize field of the EncryptedPackage field specifies the number of bytes of + * unencrypted data as specified in section 2.3.4.4. + */ + private class AgileCipherOutputStream extends ChunkedCipherOutputStream { + public AgileCipherOutputStream(DirectoryNode dir) throws IOException, GeneralSecurityException { + super(dir, 4096); + } + + @Override + protected Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk) + throws GeneralSecurityException { + return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE); + } + + @Override + protected void calculateChecksum(File fileOut, int oleStreamSize) + throws GeneralSecurityException, IOException { + // integrityHMAC needs to be updated before the encryption document is created + updateIntegrityHMAC(fileOut, oleStreamSize); + } + + @Override + protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) + throws IOException, GeneralSecurityException { + AgileEncryptor.this.createEncryptionInfoEntry(dir, tmpFile); + } + } + + @Override + public AgileEncryptor clone() throws CloneNotSupportedException { + AgileEncryptor other = (AgileEncryptor)super.clone(); + other.integritySalt = (integritySalt == null) ? null : integritySalt.clone(); + other.pwHash = (pwHash == null) ? null : pwHash.clone(); + return other; + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/CertificateSecurityException.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/CertificateSecurityException.java index 707ad758a8..fab6592777 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/CertificateSecurityException.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/CertificateSecurityException.java @@ -1,38 +1,38 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig; - -/** - * Exception thrown in case there is something wrong with the incoming eID - * certificate. - * - * @author Frank Cornelis - * - */ -public class CertificateSecurityException extends SecurityException { - - private static final long serialVersionUID = 1L; - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig; + +/** + * Exception thrown in case there is something wrong with the incoming eID + * certificate. + * + * @author Frank Cornelis + * + */ +public class CertificateSecurityException extends SecurityException { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/DigestInfo.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/DigestInfo.java index 33ae03c68d..3771053a05 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/DigestInfo.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/DigestInfo.java @@ -1,56 +1,56 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig; - -import java.io.Serializable; - -import org.apache.poi.poifs.crypt.HashAlgorithm; - -/** - * Digest Information data transfer class. - */ -public class DigestInfo implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * Main constructor. - * - * @param digestValue - * @param hashAlgo - * @param description - */ - public DigestInfo(byte[] digestValue, HashAlgorithm hashAlgo, String description) { - this.digestValue = digestValue.clone(); - this.hashAlgo = hashAlgo; - this.description = description; - } - - public final byte[] digestValue; - - public final String description; - - public final HashAlgorithm hashAlgo; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig; + +import java.io.Serializable; + +import org.apache.poi.poifs.crypt.HashAlgorithm; + +/** + * Digest Information data transfer class. + */ +public class DigestInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Main constructor. + * + * @param digestValue + * @param hashAlgo + * @param description + */ + public DigestInfo(byte[] digestValue, HashAlgorithm hashAlgo, String description) { + this.digestValue = digestValue.clone(); + this.hashAlgo = hashAlgo; + this.description = description; + } + + public final byte[] digestValue; + + public final String description; + + public final HashAlgorithm hashAlgo; +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/ExpiredCertificateSecurityException.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/ExpiredCertificateSecurityException.java index adbcfdb35e..fddede242b 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/ExpiredCertificateSecurityException.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/ExpiredCertificateSecurityException.java @@ -1,38 +1,38 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig; - -/** - * Exception thrown in case the incoming eID certificate is expired. - * - * @author Frank Cornelis - * - */ -public class ExpiredCertificateSecurityException extends - CertificateSecurityException { - - private static final long serialVersionUID = 1L; - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig; + +/** + * Exception thrown in case the incoming eID certificate is expired. + * + * @author Frank Cornelis + * + */ +public class ExpiredCertificateSecurityException extends + CertificateSecurityException { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java index 90294105e0..f4402dcc81 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java @@ -1,103 +1,103 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig; - -import java.security.Key; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.crypto.AlgorithmMethod; -import javax.xml.crypto.KeySelector; -import javax.xml.crypto.KeySelectorException; -import javax.xml.crypto.KeySelectorResult; -import javax.xml.crypto.XMLCryptoContext; -import javax.xml.crypto.XMLStructure; -import javax.xml.crypto.dsig.keyinfo.KeyInfo; -import javax.xml.crypto.dsig.keyinfo.X509Data; - -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * JSR105 key selector implementation using the ds:KeyInfo data of the signature - * itself. - */ -public class KeyInfoKeySelector extends KeySelector implements KeySelectorResult { - - private static final POILogger LOG = POILogFactory.getLogger(KeyInfoKeySelector.class); - - private List certChain = new ArrayList(); - - @SuppressWarnings("unchecked") - @Override - public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException { - LOG.log(POILogger.DEBUG, "select key"); - if (null == keyInfo) { - throw new KeySelectorException("no ds:KeyInfo present"); - } - List keyInfoContent = keyInfo.getContent(); - certChain.clear(); - for (XMLStructure keyInfoStructure : keyInfoContent) { - if (!(keyInfoStructure instanceof X509Data)) { - continue; - } - X509Data x509Data = (X509Data) keyInfoStructure; - List x509DataList = x509Data.getContent(); - for (Object x509DataObject : x509DataList) { - if (!(x509DataObject instanceof X509Certificate)) { - continue; - } - X509Certificate certificate = (X509Certificate) x509DataObject; - LOG.log(POILogger.DEBUG, "certificate", certificate.getSubjectX500Principal()); - certChain.add(certificate); - } - } - if (certChain.isEmpty()) { - throw new KeySelectorException("No key found!"); - } - return this; - } - - public Key getKey() { - // The first certificate is presumably the signer. - return certChain.isEmpty() ? null : certChain.get(0).getPublicKey(); - } - - /** - * Gives back the X509 certificate used during the last signature - * verification operation. - * - * @return the certificate which was used to sign the xml content - */ - public X509Certificate getSigner() { - // The first certificate is presumably the signer. - return certChain.isEmpty() ? null : certChain.get(0); - } - - public List getCertChain() { - return certChain; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig; + +import java.security.Key; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.crypto.AlgorithmMethod; +import javax.xml.crypto.KeySelector; +import javax.xml.crypto.KeySelectorException; +import javax.xml.crypto.KeySelectorResult; +import javax.xml.crypto.XMLCryptoContext; +import javax.xml.crypto.XMLStructure; +import javax.xml.crypto.dsig.keyinfo.KeyInfo; +import javax.xml.crypto.dsig.keyinfo.X509Data; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * JSR105 key selector implementation using the ds:KeyInfo data of the signature + * itself. + */ +public class KeyInfoKeySelector extends KeySelector implements KeySelectorResult { + + private static final POILogger LOG = POILogFactory.getLogger(KeyInfoKeySelector.class); + + private List certChain = new ArrayList(); + + @SuppressWarnings("unchecked") + @Override + public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException { + LOG.log(POILogger.DEBUG, "select key"); + if (null == keyInfo) { + throw new KeySelectorException("no ds:KeyInfo present"); + } + List keyInfoContent = keyInfo.getContent(); + certChain.clear(); + for (XMLStructure keyInfoStructure : keyInfoContent) { + if (!(keyInfoStructure instanceof X509Data)) { + continue; + } + X509Data x509Data = (X509Data) keyInfoStructure; + List x509DataList = x509Data.getContent(); + for (Object x509DataObject : x509DataList) { + if (!(x509DataObject instanceof X509Certificate)) { + continue; + } + X509Certificate certificate = (X509Certificate) x509DataObject; + LOG.log(POILogger.DEBUG, "certificate", certificate.getSubjectX500Principal()); + certChain.add(certificate); + } + } + if (certChain.isEmpty()) { + throw new KeySelectorException("No key found!"); + } + return this; + } + + public Key getKey() { + // The first certificate is presumably the signer. + return certChain.isEmpty() ? null : certChain.get(0).getPublicKey(); + } + + /** + * Gives back the X509 certificate used during the last signature + * verification operation. + * + * @return the certificate which was used to sign the xml content + */ + public X509Certificate getSigner() { + // The first certificate is presumably the signer. + return certChain.isEmpty() ? null : certChain.get(0); + } + + public List getCertChain() { + return certChain; + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/OOXMLURIDereferencer.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/OOXMLURIDereferencer.java index 64eb53d6f8..07711d2b84 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/OOXMLURIDereferencer.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/OOXMLURIDereferencer.java @@ -1,130 +1,130 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; - -import javax.xml.crypto.Data; -import javax.xml.crypto.OctetStreamData; -import javax.xml.crypto.URIDereferencer; -import javax.xml.crypto.URIReference; -import javax.xml.crypto.URIReferenceException; -import javax.xml.crypto.XMLCryptoContext; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * JSR105 URI dereferencer for Office Open XML documents. - */ -public class OOXMLURIDereferencer implements URIDereferencer, SignatureConfigurable { - - private static final POILogger LOG = POILogFactory.getLogger(OOXMLURIDereferencer.class); - - private SignatureConfig signatureConfig; - private URIDereferencer baseUriDereferencer; - - public void setSignatureConfig(SignatureConfig signatureConfig) { - this.signatureConfig = signatureConfig; - } - - public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException { - if (baseUriDereferencer == null) { - baseUriDereferencer = signatureConfig.getSignatureFactory().getURIDereferencer(); - } - - if (null == uriReference) { - throw new NullPointerException("URIReference cannot be null"); - } - if (null == context) { - throw new NullPointerException("XMLCrytoContext cannot be null"); - } - - URI uri; - try { - uri = new URI(uriReference.getURI()); - } catch (URISyntaxException e) { - throw new URIReferenceException("could not URL decode the uri: "+uriReference.getURI(), e); - } - - PackagePart part = findPart(uri); - if (part == null) { - LOG.log(POILogger.DEBUG, "cannot resolve, delegating to base DOM URI dereferencer", uri); - return this.baseUriDereferencer.dereference(uriReference, context); - } - - InputStream dataStream; - try { - dataStream = part.getInputStream(); - - // workaround for office 2007 pretty-printed .rels files - if (part.getPartName().toString().endsWith(".rels")) { - // although xmlsec has an option to ignore line breaks, currently this - // only affects .rels files, so we only modify these - // http://stackoverflow.com/questions/4728300 - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - for (int ch; (ch = dataStream.read()) != -1; ) { - if (ch == 10 || ch == 13) continue; - bos.write(ch); - } - dataStream = new ByteArrayInputStream(bos.toByteArray()); - } - } catch (IOException e) { - throw new URIReferenceException("I/O error: " + e.getMessage(), e); - } - - return new OctetStreamData(dataStream, uri.toString(), null); - } - - private PackagePart findPart(URI uri) { - LOG.log(POILogger.DEBUG, "dereference", uri); - - String path = uri.getPath(); - if (path == null || "".equals(path)) { - LOG.log(POILogger.DEBUG, "illegal part name (expected)", uri); - return null; - } - - PackagePartName ppn; - try { - ppn = PackagingURIHelper.createPartName(path); - } catch (InvalidFormatException e) { - LOG.log(POILogger.WARN, "illegal part name (not expected)", uri); - return null; - } - - return signatureConfig.getOpcPackage().getPart(ppn); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.xml.crypto.Data; +import javax.xml.crypto.OctetStreamData; +import javax.xml.crypto.URIDereferencer; +import javax.xml.crypto.URIReference; +import javax.xml.crypto.URIReferenceException; +import javax.xml.crypto.XMLCryptoContext; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * JSR105 URI dereferencer for Office Open XML documents. + */ +public class OOXMLURIDereferencer implements URIDereferencer, SignatureConfigurable { + + private static final POILogger LOG = POILogFactory.getLogger(OOXMLURIDereferencer.class); + + private SignatureConfig signatureConfig; + private URIDereferencer baseUriDereferencer; + + public void setSignatureConfig(SignatureConfig signatureConfig) { + this.signatureConfig = signatureConfig; + } + + public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException { + if (baseUriDereferencer == null) { + baseUriDereferencer = signatureConfig.getSignatureFactory().getURIDereferencer(); + } + + if (null == uriReference) { + throw new NullPointerException("URIReference cannot be null"); + } + if (null == context) { + throw new NullPointerException("XMLCrytoContext cannot be null"); + } + + URI uri; + try { + uri = new URI(uriReference.getURI()); + } catch (URISyntaxException e) { + throw new URIReferenceException("could not URL decode the uri: "+uriReference.getURI(), e); + } + + PackagePart part = findPart(uri); + if (part == null) { + LOG.log(POILogger.DEBUG, "cannot resolve, delegating to base DOM URI dereferencer", uri); + return this.baseUriDereferencer.dereference(uriReference, context); + } + + InputStream dataStream; + try { + dataStream = part.getInputStream(); + + // workaround for office 2007 pretty-printed .rels files + if (part.getPartName().toString().endsWith(".rels")) { + // although xmlsec has an option to ignore line breaks, currently this + // only affects .rels files, so we only modify these + // http://stackoverflow.com/questions/4728300 + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + for (int ch; (ch = dataStream.read()) != -1; ) { + if (ch == 10 || ch == 13) continue; + bos.write(ch); + } + dataStream = new ByteArrayInputStream(bos.toByteArray()); + } + } catch (IOException e) { + throw new URIReferenceException("I/O error: " + e.getMessage(), e); + } + + return new OctetStreamData(dataStream, uri.toString(), null); + } + + private PackagePart findPart(URI uri) { + LOG.log(POILogger.DEBUG, "dereference", uri); + + String path = uri.getPath(); + if (path == null || "".equals(path)) { + LOG.log(POILogger.DEBUG, "illegal part name (expected)", uri); + return null; + } + + PackagePartName ppn; + try { + ppn = PackagingURIHelper.createPartName(path); + } catch (InvalidFormatException e) { + LOG.log(POILogger.WARN, "illegal part name (not expected)", uri); + return null; + } + + return signatureConfig.getOpcPackage().getPart(ppn); + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/RevokedCertificateSecurityException.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/RevokedCertificateSecurityException.java index fa4fee7370..58b64dce48 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/RevokedCertificateSecurityException.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/RevokedCertificateSecurityException.java @@ -1,38 +1,38 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig; - -/** - * Exception thrown in case the incoming eID certificate has been revoked. - * - * @author Frank Cornelis - * - */ -public class RevokedCertificateSecurityException extends - CertificateSecurityException { - - private static final long serialVersionUID = 1L; - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig; + +/** + * Exception thrown in case the incoming eID certificate has been revoked. + * + * @author Frank Cornelis + * + */ +public class RevokedCertificateSecurityException extends + CertificateSecurityException { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java index 6779d8a210..fa87be191a 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java @@ -1,897 +1,897 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.dsig; - -import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS; -import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XADES_132_NS; - -import java.security.PrivateKey; -import java.security.Provider; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.xml.crypto.URIDereferencer; -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.DigestMethod; -import javax.xml.crypto.dsig.XMLSignatureFactory; -import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet; -import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet; -import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet; -import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet; -import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet; -import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService; -import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService; -import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService; -import org.apache.poi.poifs.crypt.dsig.services.TimeStampService; -import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.xml.security.signature.XMLSignature; -import org.w3c.dom.events.EventListener; - -/** - * This class bundles the configuration options used for the existing - * signature facets. - * Apart of the thread local members (e.g. opc-package) most values will probably be constant, so - * it might be configured centrally (e.g. by spring) - */ -public class SignatureConfig { - - private static final POILogger LOG = POILogFactory.getLogger(SignatureConfig.class); - - public interface SignatureConfigurable { - void setSignatureConfig(SignatureConfig signatureConfig); - } - - private ThreadLocal opcPackage = new ThreadLocal(); - private ThreadLocal signatureFactory = new ThreadLocal(); - private ThreadLocal keyInfoFactory = new ThreadLocal(); - private ThreadLocal provider = new ThreadLocal(); - - private List signatureFacets = new ArrayList(); - private HashAlgorithm digestAlgo = HashAlgorithm.sha1; - private Date executionTime = new Date(); - private PrivateKey key; - private List signingCertificateChain; - - /** - * the optional signature policy service used for XAdES-EPES. - */ - private SignaturePolicyService signaturePolicyService; - private URIDereferencer uriDereferencer = null; - private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE; - - private boolean includeEntireCertificateChain = true; - private boolean includeIssuerSerial = false; - private boolean includeKeyValue = false; - - /** - * the time-stamp service used for XAdES-T and XAdES-X. - */ - private TimeStampService tspService = new TSPTimeStampService(); - /** - * timestamp service provider URL - */ - private String tspUrl; - private boolean tspOldProtocol = false; - /** - * if not defined, it's the same as the main digest - */ - private HashAlgorithm tspDigestAlgo = null; - private String tspUser; - private String tspPass; - private TimeStampServiceValidator tspValidator; - /** - * the optional TSP request policy OID. - */ - private String tspRequestPolicy = "1.3.6.1.4.1.13762.3"; - private String userAgent = "POI XmlSign Service TSP Client"; - private String proxyUrl; - - /** - * the optional revocation data service used for XAdES-C and XAdES-X-L. - * When null the signature will be limited to XAdES-T only. - */ - private RevocationDataService revocationDataService; - /** - * if not defined, it's the same as the main digest - */ - private HashAlgorithm xadesDigestAlgo = null; - private String xadesRole = null; - private String xadesSignatureId = "idSignedProperties"; - private boolean xadesSignaturePolicyImplied = true; - private String xadesCanonicalizationMethod = CanonicalizationMethod.EXCLUSIVE; - - /** - * Work-around for Office 2010 IssuerName encoding. - */ - private boolean xadesIssuerNameNoReverseOrder = true; - - /** - * The signature Id attribute value used to create the XML signature. A - * null value will trigger an automatically generated signature Id. - */ - private String packageSignatureId = "idPackageSignature"; - - /** - * Gives back the human-readable description of what the citizen will be - * signing. The default value is "Office OpenXML Document". - */ - private String signatureDescription = "Office OpenXML Document"; - - /** - * The process of signing includes the marshalling of xml structures. - * This also includes the canonicalization. Currently this leads to problems - * with certain namespaces, so this EventListener is used to interfere - * with the marshalling process. - */ - EventListener signatureMarshalListener = null; - - /** - * Map of namespace uris to prefix - * If a mapping is specified, the corresponding elements will be prefixed - */ - Map namespacePrefixes = new HashMap(); - - /** - * Inits and checks the config object. - * If not set previously, complex configuration properties also get - * created/initialized via this initialization call. - * - * @param onlyValidation if true, only a subset of the properties - * is initialized, which are necessary for validation. If false, - * also the other properties needed for signing are been taken care of - */ - protected void init(boolean onlyValidation) { - if (opcPackage == null) { - throw new EncryptedDocumentException("opcPackage is null"); - } - if (uriDereferencer == null) { - uriDereferencer = new OOXMLURIDereferencer(); - } - if (uriDereferencer instanceof SignatureConfigurable) { - ((SignatureConfigurable)uriDereferencer).setSignatureConfig(this); - } - if (namespacePrefixes.isEmpty()) { - /* - * OOo doesn't like ds namespaces so per default prefixing is off. - */ - // namespacePrefixes.put(XML_DIGSIG_NS, ""); - namespacePrefixes.put(OO_DIGSIG_NS, "mdssi"); - namespacePrefixes.put(XADES_132_NS, "xd"); - } - - if (onlyValidation) return; - - if (signatureMarshalListener == null) { - signatureMarshalListener = new SignatureMarshalListener(); - } - - if (signatureMarshalListener instanceof SignatureConfigurable) { - ((SignatureConfigurable)signatureMarshalListener).setSignatureConfig(this); - } - - if (tspService != null) { - tspService.setSignatureConfig(this); - } - - if (signatureFacets.isEmpty()) { - addSignatureFacet(new OOXMLSignatureFacet()); - addSignatureFacet(new KeyInfoSignatureFacet()); - addSignatureFacet(new XAdESSignatureFacet()); - addSignatureFacet(new Office2010SignatureFacet()); - } - - for (SignatureFacet sf : signatureFacets) { - sf.setSignatureConfig(this); - } - } - - /** - * @param signatureFacet the signature facet is appended to facet list - */ - public void addSignatureFacet(SignatureFacet signatureFacet) { - signatureFacets.add(signatureFacet); - } - - /** - * @return the list of facets, may be empty when the config object is not initialized - */ - public List getSignatureFacets() { - return signatureFacets; - } - - /** - * @param signatureFacets the new list of facets - */ - public void setSignatureFacets(List signatureFacets) { - this.signatureFacets = signatureFacets; - } - - /** - * @return the main digest algorithm, defaults to sha-1 - */ - public HashAlgorithm getDigestAlgo() { - return digestAlgo; - } - - /** - * @param digestAlgo the main digest algorithm - */ - public void setDigestAlgo(HashAlgorithm digestAlgo) { - this.digestAlgo = digestAlgo; - } - - /** - * @return the opc package to be used by this thread, stored as thread-local - */ - public OPCPackage getOpcPackage() { - return opcPackage.get(); - } - - /** - * @param opcPackage the opc package to be handled by this thread, stored as thread-local - */ - public void setOpcPackage(OPCPackage opcPackage) { - this.opcPackage.set(opcPackage); - } - - /** - * @return the private key - */ - public PrivateKey getKey() { - return key; - } - - /** - * @param key the private key - */ - public void setKey(PrivateKey key) { - this.key = key; - } - - /** - * @return the certificate chain, index 0 is usually the certificate matching - * the private key - */ - public List getSigningCertificateChain() { - return signingCertificateChain; - } - - /** - * @param signingCertificateChain the certificate chain, index 0 should be - * the certificate matching the private key - */ - public void setSigningCertificateChain( - List signingCertificateChain) { - this.signingCertificateChain = signingCertificateChain; - } - - /** - * @return the time at which the document is signed, also used for the timestamp service. - * defaults to now - */ - public Date getExecutionTime() { - return executionTime; - } - - /** - * @param executionTime sets the time at which the document ought to be signed - */ - public void setExecutionTime(Date executionTime) { - this.executionTime = executionTime; - } - - /** - * @return the service to be used for XAdES-EPES properties. There's no default implementation - */ - public SignaturePolicyService getSignaturePolicyService() { - return signaturePolicyService; - } - - /** - * @param signaturePolicyService the service to be used for XAdES-EPES properties - */ - public void setSignaturePolicyService(SignaturePolicyService signaturePolicyService) { - this.signaturePolicyService = signaturePolicyService; - } - - /** - * @return the dereferencer used for Reference/@URI attributes, defaults to {@link OOXMLURIDereferencer} - */ - public URIDereferencer getUriDereferencer() { - return uriDereferencer; - } - - /** - * @param uriDereferencer the dereferencer used for Reference/@URI attributes - */ - public void setUriDereferencer(URIDereferencer uriDereferencer) { - this.uriDereferencer = uriDereferencer; - } - - /** - * @return Gives back the human-readable description of what the citizen - * will be signing. The default value is "Office OpenXML Document". - */ - public String getSignatureDescription() { - return signatureDescription; - } - - /** - * @param signatureDescription the human-readable description of - * what the citizen will be signing. - */ - public void setSignatureDescription(String signatureDescription) { - this.signatureDescription = signatureDescription; - } - - /** - * @return the default canonicalization method, defaults to INCLUSIVE - */ - public String getCanonicalizationMethod() { - return canonicalizationMethod; - } - - /** - * @param canonicalizationMethod the default canonicalization method - */ - public void setCanonicalizationMethod(String canonicalizationMethod) { - this.canonicalizationMethod = canonicalizationMethod; - } - - /** - * @return The signature Id attribute value used to create the XML signature. - * Defaults to "idPackageSignature" - */ - public String getPackageSignatureId() { - return packageSignatureId; - } - - /** - * @param packageSignatureId The signature Id attribute value used to create the XML signature. - * A null value will trigger an automatically generated signature Id. - */ - public void setPackageSignatureId(String packageSignatureId) { - this.packageSignatureId = nvl(packageSignatureId,"xmldsig-"+UUID.randomUUID()); - } - - /** - * @return the url of the timestamp provider (TSP) - */ - public String getTspUrl() { - return tspUrl; - } - - /** - * @param tspUrl the url of the timestamp provider (TSP) - */ - public void setTspUrl(String tspUrl) { - this.tspUrl = tspUrl; - } - - /** - * @return if true, uses timestamp-request/response mimetype, - * if false, timestamp-query/reply mimetype - */ - public boolean isTspOldProtocol() { - return tspOldProtocol; - } - - /** - * @param tspOldProtocol defines the timestamp-protocol mimetype - * @see #isTspOldProtocol - */ - public void setTspOldProtocol(boolean tspOldProtocol) { - this.tspOldProtocol = tspOldProtocol; - } - - /** - * @return the hash algorithm to be used for the timestamp entry. - * Defaults to the hash algorithm of the main entry - */ - public HashAlgorithm getTspDigestAlgo() { - return nvl(tspDigestAlgo,digestAlgo); - } - - /** - * @param tspDigestAlgo the algorithm to be used for the timestamp entry. - * if null, the hash algorithm of the main entry - */ - public void setTspDigestAlgo(HashAlgorithm tspDigestAlgo) { - this.tspDigestAlgo = tspDigestAlgo; - } - - /** - * @return the proxy url to be used for all communications. - * Currently this affects the timestamp service - */ - public String getProxyUrl() { - return proxyUrl; - } - - /** - * @param proxyUrl the proxy url to be used for all communications. - * Currently this affects the timestamp service - */ - public void setProxyUrl(String proxyUrl) { - this.proxyUrl = proxyUrl; - } - - /** - * @return the timestamp service. Defaults to {@link TSPTimeStampService} - */ - public TimeStampService getTspService() { - return tspService; - } - - /** - * @param tspService the timestamp service - */ - public void setTspService(TimeStampService tspService) { - this.tspService = tspService; - } - - /** - * @return the user id for the timestamp service - currently only basic authorization is supported - */ - public String getTspUser() { - return tspUser; - } - - /** - * @param tspUser the user id for the timestamp service - currently only basic authorization is supported - */ - public void setTspUser(String tspUser) { - this.tspUser = tspUser; - } - - /** - * @return the password for the timestamp service - */ - public String getTspPass() { - return tspPass; - } - - /** - * @param tspPass the password for the timestamp service - */ - public void setTspPass(String tspPass) { - this.tspPass = tspPass; - } - - /** - * @return the validator for the timestamp service (certificate) - */ - public TimeStampServiceValidator getTspValidator() { - return tspValidator; - } - - /** - * @param tspValidator the validator for the timestamp service (certificate) - */ - public void setTspValidator(TimeStampServiceValidator tspValidator) { - this.tspValidator = tspValidator; - } - - /** - * @return the optional revocation data service used for XAdES-C and XAdES-X-L. - * When null the signature will be limited to XAdES-T only. - */ - public RevocationDataService getRevocationDataService() { - return revocationDataService; - } - - /** - * @param revocationDataService the optional revocation data service used for XAdES-C and XAdES-X-L. - * When null the signature will be limited to XAdES-T only. - */ - public void setRevocationDataService(RevocationDataService revocationDataService) { - this.revocationDataService = revocationDataService; - } - - /** - * @return hash algorithm used for XAdES. Defaults to the {@link #getDigestAlgo()} - */ - public HashAlgorithm getXadesDigestAlgo() { - return nvl(xadesDigestAlgo,digestAlgo); - } - - /** - * @param xadesDigestAlgo hash algorithm used for XAdES. - * When null, defaults to {@link #getDigestAlgo()} - */ - public void setXadesDigestAlgo(HashAlgorithm xadesDigestAlgo) { - this.xadesDigestAlgo = xadesDigestAlgo; - } - - /** - * @return the user agent used for http communication (e.g. to the TSP) - */ - public String getUserAgent() { - return userAgent; - } - - /** - * @param userAgent the user agent used for http communication (e.g. to the TSP) - */ - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; - } - - /** - * @return the asn.1 object id for the tsp request policy. - * Defaults to 1.3.6.1.4.1.13762.3 - */ - public String getTspRequestPolicy() { - return tspRequestPolicy; - } - - /** - * @param tspRequestPolicy the asn.1 object id for the tsp request policy. - */ - public void setTspRequestPolicy(String tspRequestPolicy) { - this.tspRequestPolicy = tspRequestPolicy; - } - - /** - * @return true, if the whole certificate chain is included in the signature. - * When false, only the signer cert will be included - */ - public boolean isIncludeEntireCertificateChain() { - return includeEntireCertificateChain; - } - - /** - * @param includeEntireCertificateChain if true, include the whole certificate chain. - * If false, only include the signer cert - */ - public void setIncludeEntireCertificateChain(boolean includeEntireCertificateChain) { - this.includeEntireCertificateChain = includeEntireCertificateChain; - } - - /** - * @return if true, issuer serial number is included - */ - public boolean isIncludeIssuerSerial() { - return includeIssuerSerial; - } - - /** - * @param includeIssuerSerial if true, issuer serial number is included - */ - public void setIncludeIssuerSerial(boolean includeIssuerSerial) { - this.includeIssuerSerial = includeIssuerSerial; - } - - /** - * @return if true, the key value of the public key (certificate) is included - */ - public boolean isIncludeKeyValue() { - return includeKeyValue; - } - - /** - * @param includeKeyValue if true, the key value of the public key (certificate) is included - */ - public void setIncludeKeyValue(boolean includeKeyValue) { - this.includeKeyValue = includeKeyValue; - } - - /** - * @return the xades role element. If null the claimed role element is omitted. - * Defaults to null - */ - public String getXadesRole() { - return xadesRole; - } - - /** - * @param xadesRole the xades role element. If null the claimed role element is omitted. - */ - public void setXadesRole(String xadesRole) { - this.xadesRole = xadesRole; - } - - /** - * @return the Id for the XAdES SignedProperties element. - * Defaults to idSignedProperties - */ - public String getXadesSignatureId() { - return nvl(xadesSignatureId, "idSignedProperties"); - } - - /** - * @param xadesSignatureId the Id for the XAdES SignedProperties element. - * When null defaults to idSignedProperties - */ - public void setXadesSignatureId(String xadesSignatureId) { - this.xadesSignatureId = xadesSignatureId; - } - - /** - * @return when true, include the policy-implied block. - * Defaults to true - */ - public boolean isXadesSignaturePolicyImplied() { - return xadesSignaturePolicyImplied; - } - - /** - * @param xadesSignaturePolicyImplied when true, include the policy-implied block - */ - public void setXadesSignaturePolicyImplied(boolean xadesSignaturePolicyImplied) { - this.xadesSignaturePolicyImplied = xadesSignaturePolicyImplied; - } - - /** - * Make sure the DN is encoded using the same order as present - * within the certificate. This is an Office2010 work-around. - * Should be reverted back. - * - * XXX: not correct according to RFC 4514. - * - * @return when true, the issuer DN is used instead of the issuer X500 principal - */ - public boolean isXadesIssuerNameNoReverseOrder() { - return xadesIssuerNameNoReverseOrder; - } - - /** - * @param xadesIssuerNameNoReverseOrder when true, the issuer DN instead of the issuer X500 prinicpal is used - */ - public void setXadesIssuerNameNoReverseOrder(boolean xadesIssuerNameNoReverseOrder) { - this.xadesIssuerNameNoReverseOrder = xadesIssuerNameNoReverseOrder; - } - - - /** - * @return the event listener which is active while xml structure for - * the signature is created. - * Defaults to {@link SignatureMarshalListener} - */ - public EventListener getSignatureMarshalListener() { - return signatureMarshalListener; - } - - /** - * @param signatureMarshalListener the event listener watching the xml structure - * generation for the signature - */ - public void setSignatureMarshalListener(EventListener signatureMarshalListener) { - this.signatureMarshalListener = signatureMarshalListener; - } - - /** - * @return the map of namespace uri (key) to prefix (value) - */ - public Map getNamespacePrefixes() { - return namespacePrefixes; - } - - /** - * @param namespacePrefixes the map of namespace uri (key) to prefix (value) - */ - public void setNamespacePrefixes(Map namespacePrefixes) { - this.namespacePrefixes = namespacePrefixes; - } - - /** - * helper method for null/default value handling - * @param value - * @param defaultValue - * @return if value is not null, return value otherwise defaultValue - */ - protected static T nvl(T value, T defaultValue) { - return value == null ? defaultValue : value; - } - - /** - * Each digest method has its own IV (initial vector) - * - * @return the IV depending on the main digest method - */ - public byte[] getHashMagic() { - // see https://www.ietf.org/rfc/rfc3110.txt - // RSA/SHA1 SIG Resource Records - byte result[]; - switch (getDigestAlgo()) { - case sha1: result = new byte[] - { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e - , 0x03, 0x02, 0x1a, 0x04, 0x14 }; - break; - case sha224: result = new byte[] - { 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 - , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x04, 0x1c }; - break; - case sha256: result = new byte[] - { 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 - , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20 }; - break; - case sha384: result = new byte[] - { 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 - , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30 }; - break; - case sha512: result = new byte[] - { 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 - , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40 }; - break; - case ripemd128: result = new byte[] - { 0x30, 0x1b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24 - , 0x03, 0x02, 0x02, 0x04, 0x10 }; - break; - case ripemd160: result = new byte[] - { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24 - , 0x03, 0x02, 0x01, 0x04, 0x14 }; - break; - // case ripemd256: result = new byte[] - // { 0x30, 0x2b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24 - // , 0x03, 0x02, 0x03, 0x04, 0x20 }; - // break; - default: throw new EncryptedDocumentException("Hash algorithm " - +getDigestAlgo()+" not supported for signing."); - } - - return result; - } - - /** - * @return the uri for the signature method, i.e. currently only rsa is - * supported, so it's the rsa variant of the main digest - */ - public String getSignatureMethodUri() { - switch (getDigestAlgo()) { - case sha1: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1; - case sha224: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224; - case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256; - case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384; - case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512; - case ripemd160: return XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160; - default: throw new EncryptedDocumentException("Hash algorithm " - +getDigestAlgo()+" not supported for signing."); - } - } - - /** - * @return the uri for the main digest - */ - public String getDigestMethodUri() { - return getDigestMethodUri(getDigestAlgo()); - } - - /** - * @param digestAlgo the digest algo, currently only sha* and ripemd160 is supported - * @return the uri for the given digest - */ - public static String getDigestMethodUri(HashAlgorithm digestAlgo) { - switch (digestAlgo) { - case sha1: return DigestMethod.SHA1; - case sha224: return "http://www.w3.org/2001/04/xmldsig-more#sha224"; - case sha256: return DigestMethod.SHA256; - case sha384: return "http://www.w3.org/2001/04/xmldsig-more#sha384"; - case sha512: return DigestMethod.SHA512; - case ripemd160: return DigestMethod.RIPEMD160; - default: throw new EncryptedDocumentException("Hash algorithm " - +digestAlgo+" not supported for signing."); - } - } - - /** - * @param signatureFactory the xml signature factory, saved as thread-local - */ - public void setSignatureFactory(XMLSignatureFactory signatureFactory) { - this.signatureFactory.set(signatureFactory); - } - - /** - * @return the xml signature factory (thread-local) - */ - public XMLSignatureFactory getSignatureFactory() { - XMLSignatureFactory sigFac = signatureFactory.get(); - if (sigFac == null) { - sigFac = XMLSignatureFactory.getInstance("DOM", getProvider()); - setSignatureFactory(sigFac); - } - return sigFac; - } - - /** - * @param keyInfoFactory the key factory, saved as thread-local - */ - public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) { - this.keyInfoFactory.set(keyInfoFactory); - } - - /** - * @return the key factory (thread-local) - */ - public KeyInfoFactory getKeyInfoFactory() { - KeyInfoFactory keyFac = keyInfoFactory.get(); - if (keyFac == null) { - keyFac = KeyInfoFactory.getInstance("DOM", getProvider()); - setKeyInfoFactory(keyFac); - } - return keyFac; - } - - /** - * This method tests the existence of xml signature provider in the following order: - *

    - *
  • the class pointed to by the system property "jsr105Provider"
  • - *
  • the Santuario xmlsec provider
  • - *
  • the JDK xmlsec provider
  • - *
- * - * For signing the classes are linked against the Santuario xmlsec, so this might - * only work for validation (not tested). - * - * @return the xml dsig provider - */ - public Provider getProvider() { - Provider prov = provider.get(); - if (prov == null) { - String dsigProviderNames[] = { - System.getProperty("jsr105Provider"), - "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI", // Santuario xmlsec - "org.jcp.xml.dsig.internal.dom.XMLDSigRI" // JDK xmlsec - }; - for (String pn : dsigProviderNames) { - if (pn == null) continue; - try { - prov = (Provider)Class.forName(pn).newInstance(); - break; - } catch (Exception e) { - LOG.log(POILogger.DEBUG, "XMLDsig-Provider '"+pn+"' can't be found - trying next."); - } - } - } - - if (prov == null) { - throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!"); - } - - return prov; - } - - /** - * @return the cannonicalization method for XAdES-XL signing. - * Defaults to EXCLUSIVE - * @see javax.xml.crypto.dsig.CanonicalizationMethod - */ - public String getXadesCanonicalizationMethod() { - return xadesCanonicalizationMethod; - } - - /** - * @param xadesCanonicalizationMethod the cannonicalization method for XAdES-XL signing - * @see javax.xml.crypto.dsig.CanonicalizationMethod - */ - public void setXadesCanonicalizationMethod(String xadesCanonicalizationMethod) { - this.xadesCanonicalizationMethod = xadesCanonicalizationMethod; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.dsig; + +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XADES_132_NS; + +import java.security.PrivateKey; +import java.security.Provider; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.xml.crypto.URIDereferencer; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet; +import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet; +import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet; +import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet; +import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet; +import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService; +import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService; +import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService; +import org.apache.poi.poifs.crypt.dsig.services.TimeStampService; +import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.xml.security.signature.XMLSignature; +import org.w3c.dom.events.EventListener; + +/** + * This class bundles the configuration options used for the existing + * signature facets. + * Apart of the thread local members (e.g. opc-package) most values will probably be constant, so + * it might be configured centrally (e.g. by spring) + */ +public class SignatureConfig { + + private static final POILogger LOG = POILogFactory.getLogger(SignatureConfig.class); + + public interface SignatureConfigurable { + void setSignatureConfig(SignatureConfig signatureConfig); + } + + private ThreadLocal opcPackage = new ThreadLocal(); + private ThreadLocal signatureFactory = new ThreadLocal(); + private ThreadLocal keyInfoFactory = new ThreadLocal(); + private ThreadLocal provider = new ThreadLocal(); + + private List signatureFacets = new ArrayList(); + private HashAlgorithm digestAlgo = HashAlgorithm.sha1; + private Date executionTime = new Date(); + private PrivateKey key; + private List signingCertificateChain; + + /** + * the optional signature policy service used for XAdES-EPES. + */ + private SignaturePolicyService signaturePolicyService; + private URIDereferencer uriDereferencer = null; + private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE; + + private boolean includeEntireCertificateChain = true; + private boolean includeIssuerSerial = false; + private boolean includeKeyValue = false; + + /** + * the time-stamp service used for XAdES-T and XAdES-X. + */ + private TimeStampService tspService = new TSPTimeStampService(); + /** + * timestamp service provider URL + */ + private String tspUrl; + private boolean tspOldProtocol = false; + /** + * if not defined, it's the same as the main digest + */ + private HashAlgorithm tspDigestAlgo = null; + private String tspUser; + private String tspPass; + private TimeStampServiceValidator tspValidator; + /** + * the optional TSP request policy OID. + */ + private String tspRequestPolicy = "1.3.6.1.4.1.13762.3"; + private String userAgent = "POI XmlSign Service TSP Client"; + private String proxyUrl; + + /** + * the optional revocation data service used for XAdES-C and XAdES-X-L. + * When null the signature will be limited to XAdES-T only. + */ + private RevocationDataService revocationDataService; + /** + * if not defined, it's the same as the main digest + */ + private HashAlgorithm xadesDigestAlgo = null; + private String xadesRole = null; + private String xadesSignatureId = "idSignedProperties"; + private boolean xadesSignaturePolicyImplied = true; + private String xadesCanonicalizationMethod = CanonicalizationMethod.EXCLUSIVE; + + /** + * Work-around for Office 2010 IssuerName encoding. + */ + private boolean xadesIssuerNameNoReverseOrder = true; + + /** + * The signature Id attribute value used to create the XML signature. A + * null value will trigger an automatically generated signature Id. + */ + private String packageSignatureId = "idPackageSignature"; + + /** + * Gives back the human-readable description of what the citizen will be + * signing. The default value is "Office OpenXML Document". + */ + private String signatureDescription = "Office OpenXML Document"; + + /** + * The process of signing includes the marshalling of xml structures. + * This also includes the canonicalization. Currently this leads to problems + * with certain namespaces, so this EventListener is used to interfere + * with the marshalling process. + */ + EventListener signatureMarshalListener = null; + + /** + * Map of namespace uris to prefix + * If a mapping is specified, the corresponding elements will be prefixed + */ + Map namespacePrefixes = new HashMap(); + + /** + * Inits and checks the config object. + * If not set previously, complex configuration properties also get + * created/initialized via this initialization call. + * + * @param onlyValidation if true, only a subset of the properties + * is initialized, which are necessary for validation. If false, + * also the other properties needed for signing are been taken care of + */ + protected void init(boolean onlyValidation) { + if (opcPackage == null) { + throw new EncryptedDocumentException("opcPackage is null"); + } + if (uriDereferencer == null) { + uriDereferencer = new OOXMLURIDereferencer(); + } + if (uriDereferencer instanceof SignatureConfigurable) { + ((SignatureConfigurable)uriDereferencer).setSignatureConfig(this); + } + if (namespacePrefixes.isEmpty()) { + /* + * OOo doesn't like ds namespaces so per default prefixing is off. + */ + // namespacePrefixes.put(XML_DIGSIG_NS, ""); + namespacePrefixes.put(OO_DIGSIG_NS, "mdssi"); + namespacePrefixes.put(XADES_132_NS, "xd"); + } + + if (onlyValidation) return; + + if (signatureMarshalListener == null) { + signatureMarshalListener = new SignatureMarshalListener(); + } + + if (signatureMarshalListener instanceof SignatureConfigurable) { + ((SignatureConfigurable)signatureMarshalListener).setSignatureConfig(this); + } + + if (tspService != null) { + tspService.setSignatureConfig(this); + } + + if (signatureFacets.isEmpty()) { + addSignatureFacet(new OOXMLSignatureFacet()); + addSignatureFacet(new KeyInfoSignatureFacet()); + addSignatureFacet(new XAdESSignatureFacet()); + addSignatureFacet(new Office2010SignatureFacet()); + } + + for (SignatureFacet sf : signatureFacets) { + sf.setSignatureConfig(this); + } + } + + /** + * @param signatureFacet the signature facet is appended to facet list + */ + public void addSignatureFacet(SignatureFacet signatureFacet) { + signatureFacets.add(signatureFacet); + } + + /** + * @return the list of facets, may be empty when the config object is not initialized + */ + public List getSignatureFacets() { + return signatureFacets; + } + + /** + * @param signatureFacets the new list of facets + */ + public void setSignatureFacets(List signatureFacets) { + this.signatureFacets = signatureFacets; + } + + /** + * @return the main digest algorithm, defaults to sha-1 + */ + public HashAlgorithm getDigestAlgo() { + return digestAlgo; + } + + /** + * @param digestAlgo the main digest algorithm + */ + public void setDigestAlgo(HashAlgorithm digestAlgo) { + this.digestAlgo = digestAlgo; + } + + /** + * @return the opc package to be used by this thread, stored as thread-local + */ + public OPCPackage getOpcPackage() { + return opcPackage.get(); + } + + /** + * @param opcPackage the opc package to be handled by this thread, stored as thread-local + */ + public void setOpcPackage(OPCPackage opcPackage) { + this.opcPackage.set(opcPackage); + } + + /** + * @return the private key + */ + public PrivateKey getKey() { + return key; + } + + /** + * @param key the private key + */ + public void setKey(PrivateKey key) { + this.key = key; + } + + /** + * @return the certificate chain, index 0 is usually the certificate matching + * the private key + */ + public List getSigningCertificateChain() { + return signingCertificateChain; + } + + /** + * @param signingCertificateChain the certificate chain, index 0 should be + * the certificate matching the private key + */ + public void setSigningCertificateChain( + List signingCertificateChain) { + this.signingCertificateChain = signingCertificateChain; + } + + /** + * @return the time at which the document is signed, also used for the timestamp service. + * defaults to now + */ + public Date getExecutionTime() { + return executionTime; + } + + /** + * @param executionTime sets the time at which the document ought to be signed + */ + public void setExecutionTime(Date executionTime) { + this.executionTime = executionTime; + } + + /** + * @return the service to be used for XAdES-EPES properties. There's no default implementation + */ + public SignaturePolicyService getSignaturePolicyService() { + return signaturePolicyService; + } + + /** + * @param signaturePolicyService the service to be used for XAdES-EPES properties + */ + public void setSignaturePolicyService(SignaturePolicyService signaturePolicyService) { + this.signaturePolicyService = signaturePolicyService; + } + + /** + * @return the dereferencer used for Reference/@URI attributes, defaults to {@link OOXMLURIDereferencer} + */ + public URIDereferencer getUriDereferencer() { + return uriDereferencer; + } + + /** + * @param uriDereferencer the dereferencer used for Reference/@URI attributes + */ + public void setUriDereferencer(URIDereferencer uriDereferencer) { + this.uriDereferencer = uriDereferencer; + } + + /** + * @return Gives back the human-readable description of what the citizen + * will be signing. The default value is "Office OpenXML Document". + */ + public String getSignatureDescription() { + return signatureDescription; + } + + /** + * @param signatureDescription the human-readable description of + * what the citizen will be signing. + */ + public void setSignatureDescription(String signatureDescription) { + this.signatureDescription = signatureDescription; + } + + /** + * @return the default canonicalization method, defaults to INCLUSIVE + */ + public String getCanonicalizationMethod() { + return canonicalizationMethod; + } + + /** + * @param canonicalizationMethod the default canonicalization method + */ + public void setCanonicalizationMethod(String canonicalizationMethod) { + this.canonicalizationMethod = canonicalizationMethod; + } + + /** + * @return The signature Id attribute value used to create the XML signature. + * Defaults to "idPackageSignature" + */ + public String getPackageSignatureId() { + return packageSignatureId; + } + + /** + * @param packageSignatureId The signature Id attribute value used to create the XML signature. + * A null value will trigger an automatically generated signature Id. + */ + public void setPackageSignatureId(String packageSignatureId) { + this.packageSignatureId = nvl(packageSignatureId,"xmldsig-"+UUID.randomUUID()); + } + + /** + * @return the url of the timestamp provider (TSP) + */ + public String getTspUrl() { + return tspUrl; + } + + /** + * @param tspUrl the url of the timestamp provider (TSP) + */ + public void setTspUrl(String tspUrl) { + this.tspUrl = tspUrl; + } + + /** + * @return if true, uses timestamp-request/response mimetype, + * if false, timestamp-query/reply mimetype + */ + public boolean isTspOldProtocol() { + return tspOldProtocol; + } + + /** + * @param tspOldProtocol defines the timestamp-protocol mimetype + * @see #isTspOldProtocol + */ + public void setTspOldProtocol(boolean tspOldProtocol) { + this.tspOldProtocol = tspOldProtocol; + } + + /** + * @return the hash algorithm to be used for the timestamp entry. + * Defaults to the hash algorithm of the main entry + */ + public HashAlgorithm getTspDigestAlgo() { + return nvl(tspDigestAlgo,digestAlgo); + } + + /** + * @param tspDigestAlgo the algorithm to be used for the timestamp entry. + * if null, the hash algorithm of the main entry + */ + public void setTspDigestAlgo(HashAlgorithm tspDigestAlgo) { + this.tspDigestAlgo = tspDigestAlgo; + } + + /** + * @return the proxy url to be used for all communications. + * Currently this affects the timestamp service + */ + public String getProxyUrl() { + return proxyUrl; + } + + /** + * @param proxyUrl the proxy url to be used for all communications. + * Currently this affects the timestamp service + */ + public void setProxyUrl(String proxyUrl) { + this.proxyUrl = proxyUrl; + } + + /** + * @return the timestamp service. Defaults to {@link TSPTimeStampService} + */ + public TimeStampService getTspService() { + return tspService; + } + + /** + * @param tspService the timestamp service + */ + public void setTspService(TimeStampService tspService) { + this.tspService = tspService; + } + + /** + * @return the user id for the timestamp service - currently only basic authorization is supported + */ + public String getTspUser() { + return tspUser; + } + + /** + * @param tspUser the user id for the timestamp service - currently only basic authorization is supported + */ + public void setTspUser(String tspUser) { + this.tspUser = tspUser; + } + + /** + * @return the password for the timestamp service + */ + public String getTspPass() { + return tspPass; + } + + /** + * @param tspPass the password for the timestamp service + */ + public void setTspPass(String tspPass) { + this.tspPass = tspPass; + } + + /** + * @return the validator for the timestamp service (certificate) + */ + public TimeStampServiceValidator getTspValidator() { + return tspValidator; + } + + /** + * @param tspValidator the validator for the timestamp service (certificate) + */ + public void setTspValidator(TimeStampServiceValidator tspValidator) { + this.tspValidator = tspValidator; + } + + /** + * @return the optional revocation data service used for XAdES-C and XAdES-X-L. + * When null the signature will be limited to XAdES-T only. + */ + public RevocationDataService getRevocationDataService() { + return revocationDataService; + } + + /** + * @param revocationDataService the optional revocation data service used for XAdES-C and XAdES-X-L. + * When null the signature will be limited to XAdES-T only. + */ + public void setRevocationDataService(RevocationDataService revocationDataService) { + this.revocationDataService = revocationDataService; + } + + /** + * @return hash algorithm used for XAdES. Defaults to the {@link #getDigestAlgo()} + */ + public HashAlgorithm getXadesDigestAlgo() { + return nvl(xadesDigestAlgo,digestAlgo); + } + + /** + * @param xadesDigestAlgo hash algorithm used for XAdES. + * When null, defaults to {@link #getDigestAlgo()} + */ + public void setXadesDigestAlgo(HashAlgorithm xadesDigestAlgo) { + this.xadesDigestAlgo = xadesDigestAlgo; + } + + /** + * @return the user agent used for http communication (e.g. to the TSP) + */ + public String getUserAgent() { + return userAgent; + } + + /** + * @param userAgent the user agent used for http communication (e.g. to the TSP) + */ + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + /** + * @return the asn.1 object id for the tsp request policy. + * Defaults to 1.3.6.1.4.1.13762.3 + */ + public String getTspRequestPolicy() { + return tspRequestPolicy; + } + + /** + * @param tspRequestPolicy the asn.1 object id for the tsp request policy. + */ + public void setTspRequestPolicy(String tspRequestPolicy) { + this.tspRequestPolicy = tspRequestPolicy; + } + + /** + * @return true, if the whole certificate chain is included in the signature. + * When false, only the signer cert will be included + */ + public boolean isIncludeEntireCertificateChain() { + return includeEntireCertificateChain; + } + + /** + * @param includeEntireCertificateChain if true, include the whole certificate chain. + * If false, only include the signer cert + */ + public void setIncludeEntireCertificateChain(boolean includeEntireCertificateChain) { + this.includeEntireCertificateChain = includeEntireCertificateChain; + } + + /** + * @return if true, issuer serial number is included + */ + public boolean isIncludeIssuerSerial() { + return includeIssuerSerial; + } + + /** + * @param includeIssuerSerial if true, issuer serial number is included + */ + public void setIncludeIssuerSerial(boolean includeIssuerSerial) { + this.includeIssuerSerial = includeIssuerSerial; + } + + /** + * @return if true, the key value of the public key (certificate) is included + */ + public boolean isIncludeKeyValue() { + return includeKeyValue; + } + + /** + * @param includeKeyValue if true, the key value of the public key (certificate) is included + */ + public void setIncludeKeyValue(boolean includeKeyValue) { + this.includeKeyValue = includeKeyValue; + } + + /** + * @return the xades role element. If null the claimed role element is omitted. + * Defaults to null + */ + public String getXadesRole() { + return xadesRole; + } + + /** + * @param xadesRole the xades role element. If null the claimed role element is omitted. + */ + public void setXadesRole(String xadesRole) { + this.xadesRole = xadesRole; + } + + /** + * @return the Id for the XAdES SignedProperties element. + * Defaults to idSignedProperties + */ + public String getXadesSignatureId() { + return nvl(xadesSignatureId, "idSignedProperties"); + } + + /** + * @param xadesSignatureId the Id for the XAdES SignedProperties element. + * When null defaults to idSignedProperties + */ + public void setXadesSignatureId(String xadesSignatureId) { + this.xadesSignatureId = xadesSignatureId; + } + + /** + * @return when true, include the policy-implied block. + * Defaults to true + */ + public boolean isXadesSignaturePolicyImplied() { + return xadesSignaturePolicyImplied; + } + + /** + * @param xadesSignaturePolicyImplied when true, include the policy-implied block + */ + public void setXadesSignaturePolicyImplied(boolean xadesSignaturePolicyImplied) { + this.xadesSignaturePolicyImplied = xadesSignaturePolicyImplied; + } + + /** + * Make sure the DN is encoded using the same order as present + * within the certificate. This is an Office2010 work-around. + * Should be reverted back. + * + * XXX: not correct according to RFC 4514. + * + * @return when true, the issuer DN is used instead of the issuer X500 principal + */ + public boolean isXadesIssuerNameNoReverseOrder() { + return xadesIssuerNameNoReverseOrder; + } + + /** + * @param xadesIssuerNameNoReverseOrder when true, the issuer DN instead of the issuer X500 prinicpal is used + */ + public void setXadesIssuerNameNoReverseOrder(boolean xadesIssuerNameNoReverseOrder) { + this.xadesIssuerNameNoReverseOrder = xadesIssuerNameNoReverseOrder; + } + + + /** + * @return the event listener which is active while xml structure for + * the signature is created. + * Defaults to {@link SignatureMarshalListener} + */ + public EventListener getSignatureMarshalListener() { + return signatureMarshalListener; + } + + /** + * @param signatureMarshalListener the event listener watching the xml structure + * generation for the signature + */ + public void setSignatureMarshalListener(EventListener signatureMarshalListener) { + this.signatureMarshalListener = signatureMarshalListener; + } + + /** + * @return the map of namespace uri (key) to prefix (value) + */ + public Map getNamespacePrefixes() { + return namespacePrefixes; + } + + /** + * @param namespacePrefixes the map of namespace uri (key) to prefix (value) + */ + public void setNamespacePrefixes(Map namespacePrefixes) { + this.namespacePrefixes = namespacePrefixes; + } + + /** + * helper method for null/default value handling + * @param value + * @param defaultValue + * @return if value is not null, return value otherwise defaultValue + */ + protected static T nvl(T value, T defaultValue) { + return value == null ? defaultValue : value; + } + + /** + * Each digest method has its own IV (initial vector) + * + * @return the IV depending on the main digest method + */ + public byte[] getHashMagic() { + // see https://www.ietf.org/rfc/rfc3110.txt + // RSA/SHA1 SIG Resource Records + byte result[]; + switch (getDigestAlgo()) { + case sha1: result = new byte[] + { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e + , 0x03, 0x02, 0x1a, 0x04, 0x14 }; + break; + case sha224: result = new byte[] + { 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 + , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x04, 0x1c }; + break; + case sha256: result = new byte[] + { 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 + , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20 }; + break; + case sha384: result = new byte[] + { 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 + , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30 }; + break; + case sha512: result = new byte[] + { 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86 + , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40 }; + break; + case ripemd128: result = new byte[] + { 0x30, 0x1b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24 + , 0x03, 0x02, 0x02, 0x04, 0x10 }; + break; + case ripemd160: result = new byte[] + { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24 + , 0x03, 0x02, 0x01, 0x04, 0x14 }; + break; + // case ripemd256: result = new byte[] + // { 0x30, 0x2b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24 + // , 0x03, 0x02, 0x03, 0x04, 0x20 }; + // break; + default: throw new EncryptedDocumentException("Hash algorithm " + +getDigestAlgo()+" not supported for signing."); + } + + return result; + } + + /** + * @return the uri for the signature method, i.e. currently only rsa is + * supported, so it's the rsa variant of the main digest + */ + public String getSignatureMethodUri() { + switch (getDigestAlgo()) { + case sha1: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1; + case sha224: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224; + case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256; + case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384; + case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512; + case ripemd160: return XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160; + default: throw new EncryptedDocumentException("Hash algorithm " + +getDigestAlgo()+" not supported for signing."); + } + } + + /** + * @return the uri for the main digest + */ + public String getDigestMethodUri() { + return getDigestMethodUri(getDigestAlgo()); + } + + /** + * @param digestAlgo the digest algo, currently only sha* and ripemd160 is supported + * @return the uri for the given digest + */ + public static String getDigestMethodUri(HashAlgorithm digestAlgo) { + switch (digestAlgo) { + case sha1: return DigestMethod.SHA1; + case sha224: return "http://www.w3.org/2001/04/xmldsig-more#sha224"; + case sha256: return DigestMethod.SHA256; + case sha384: return "http://www.w3.org/2001/04/xmldsig-more#sha384"; + case sha512: return DigestMethod.SHA512; + case ripemd160: return DigestMethod.RIPEMD160; + default: throw new EncryptedDocumentException("Hash algorithm " + +digestAlgo+" not supported for signing."); + } + } + + /** + * @param signatureFactory the xml signature factory, saved as thread-local + */ + public void setSignatureFactory(XMLSignatureFactory signatureFactory) { + this.signatureFactory.set(signatureFactory); + } + + /** + * @return the xml signature factory (thread-local) + */ + public XMLSignatureFactory getSignatureFactory() { + XMLSignatureFactory sigFac = signatureFactory.get(); + if (sigFac == null) { + sigFac = XMLSignatureFactory.getInstance("DOM", getProvider()); + setSignatureFactory(sigFac); + } + return sigFac; + } + + /** + * @param keyInfoFactory the key factory, saved as thread-local + */ + public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) { + this.keyInfoFactory.set(keyInfoFactory); + } + + /** + * @return the key factory (thread-local) + */ + public KeyInfoFactory getKeyInfoFactory() { + KeyInfoFactory keyFac = keyInfoFactory.get(); + if (keyFac == null) { + keyFac = KeyInfoFactory.getInstance("DOM", getProvider()); + setKeyInfoFactory(keyFac); + } + return keyFac; + } + + /** + * This method tests the existence of xml signature provider in the following order: + *
    + *
  • the class pointed to by the system property "jsr105Provider"
  • + *
  • the Santuario xmlsec provider
  • + *
  • the JDK xmlsec provider
  • + *
+ * + * For signing the classes are linked against the Santuario xmlsec, so this might + * only work for validation (not tested). + * + * @return the xml dsig provider + */ + public Provider getProvider() { + Provider prov = provider.get(); + if (prov == null) { + String dsigProviderNames[] = { + System.getProperty("jsr105Provider"), + "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI", // Santuario xmlsec + "org.jcp.xml.dsig.internal.dom.XMLDSigRI" // JDK xmlsec + }; + for (String pn : dsigProviderNames) { + if (pn == null) continue; + try { + prov = (Provider)Class.forName(pn).newInstance(); + break; + } catch (Exception e) { + LOG.log(POILogger.DEBUG, "XMLDsig-Provider '"+pn+"' can't be found - trying next."); + } + } + } + + if (prov == null) { + throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!"); + } + + return prov; + } + + /** + * @return the cannonicalization method for XAdES-XL signing. + * Defaults to EXCLUSIVE + * @see javax.xml.crypto.dsig.CanonicalizationMethod + */ + public String getXadesCanonicalizationMethod() { + return xadesCanonicalizationMethod; + } + + /** + * @param xadesCanonicalizationMethod the cannonicalization method for XAdES-XL signing + * @see javax.xml.crypto.dsig.CanonicalizationMethod + */ + public void setXadesCanonicalizationMethod(String xadesCanonicalizationMethod) { + this.xadesCanonicalizationMethod = xadesCanonicalizationMethod; + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java index f0f43c674d..3b21eb8658 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java @@ -1,92 +1,92 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt.dsig; - -import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS; -import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_NS; - -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.events.Event; -import org.w3c.dom.events.EventListener; -import org.w3c.dom.events.EventTarget; -import org.w3c.dom.events.MutationEvent; - -/** - * This listener class is used, to modify the to be digested xml document, - * e.g. to register id attributes or set prefixes for registered namespaces - */ -public class SignatureMarshalListener implements EventListener, SignatureConfigurable { - ThreadLocal target = new ThreadLocal(); - SignatureConfig signatureConfig; - public void setEventTarget(EventTarget target) { - this.target.set(target); - } - - public void handleEvent(Event e) { - if (!(e instanceof MutationEvent)) return; - MutationEvent mutEvt = (MutationEvent)e; - EventTarget et = mutEvt.getTarget(); - if (!(et instanceof Element)) return; - handleElement((Element)et); - } - - public void handleElement(Element el) { - EventTarget target = this.target.get(); - String packageId = signatureConfig.getPackageSignatureId(); - if (el.hasAttribute("Id")) { - el.setIdAttribute("Id", true); - } - - setListener(target, this, false); - if (packageId.equals(el.getAttribute("Id"))) { - el.setAttributeNS(XML_NS, "xmlns:mdssi", OO_DIGSIG_NS); - } - setPrefix(el); - setListener(target, this, true); - } - - // helper method to keep it in one place - public static void setListener(EventTarget target, EventListener listener, boolean enabled) { - String type = "DOMSubtreeModified"; - boolean useCapture = false; - if (enabled) { - target.addEventListener(type, listener, useCapture); - } else { - target.removeEventListener(type, listener, useCapture); - } - } - - protected void setPrefix(Node el) { - String prefix = signatureConfig.getNamespacePrefixes().get(el.getNamespaceURI()); - if (prefix != null && el.getPrefix() == null) { - el.setPrefix(prefix); - } - - NodeList nl = el.getChildNodes(); - for (int i=0; i target = new ThreadLocal(); + SignatureConfig signatureConfig; + public void setEventTarget(EventTarget target) { + this.target.set(target); + } + + public void handleEvent(Event e) { + if (!(e instanceof MutationEvent)) return; + MutationEvent mutEvt = (MutationEvent)e; + EventTarget et = mutEvt.getTarget(); + if (!(et instanceof Element)) return; + handleElement((Element)et); + } + + public void handleElement(Element el) { + EventTarget target = this.target.get(); + String packageId = signatureConfig.getPackageSignatureId(); + if (el.hasAttribute("Id")) { + el.setIdAttribute("Id", true); + } + + setListener(target, this, false); + if (packageId.equals(el.getAttribute("Id"))) { + el.setAttributeNS(XML_NS, "xmlns:mdssi", OO_DIGSIG_NS); + } + setPrefix(el); + setListener(target, this, true); + } + + // helper method to keep it in one place + public static void setListener(EventTarget target, EventListener listener, boolean enabled) { + String type = "DOMSubtreeModified"; + boolean useCapture = false; + if (enabled) { + target.addEventListener(type, listener, useCapture); + } else { + target.removeEventListener(type, listener, useCapture); + } + } + + protected void setPrefix(Node el) { + String prefix = signatureConfig.getNamespacePrefixes().get(el.getNamespaceURI()); + if (prefix != null && el.getPrefix() == null) { + el.setPrefix(prefix); + } + + NodeList nl = el.getChildNodes(); + for (int i=0; i references - , List objects) - throws XMLSignatureException { - List transforms = new ArrayList(); - Transform envelopedTransform = newTransform(CanonicalizationMethod.ENVELOPED); - transforms.add(envelopedTransform); - Transform exclusiveTransform = newTransform(CanonicalizationMethod.EXCLUSIVE); - transforms.add(exclusiveTransform); - - Reference reference = newReference("", transforms, null, null, null); - references.add(reference); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureException; + +import org.w3c.dom.Document; + +/** + * Signature Facet implementation to create enveloped signatures. + * + * @author Frank Cornelis + * + */ +public class EnvelopedSignatureFacet extends SignatureFacet { + + @Override + public void preSign(Document document + , List references + , List objects) + throws XMLSignatureException { + List transforms = new ArrayList(); + Transform envelopedTransform = newTransform(CanonicalizationMethod.ENVELOPED); + transforms.add(envelopedTransform); + Transform exclusiveTransform = newTransform(CanonicalizationMethod.EXCLUSIVE); + transforms.add(exclusiveTransform); + + Reference reference = newReference("", transforms, null, null, null); + references.add(reference); + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java index 93f0f5b8b6..67d18dd28b 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java @@ -1,148 +1,148 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.facets; - -import java.security.Key; -import java.security.KeyException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.xml.crypto.MarshalException; -import javax.xml.crypto.XMLStructure; -import javax.xml.crypto.dom.DOMStructure; -import javax.xml.crypto.dsig.dom.DOMSignContext; -import javax.xml.crypto.dsig.keyinfo.KeyInfo; -import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; -import javax.xml.crypto.dsig.keyinfo.KeyValue; -import javax.xml.crypto.dsig.keyinfo.X509Data; - -import org.apache.jcp.xml.dsig.internal.dom.DOMKeyInfo; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Signature Facet implementation that adds ds:KeyInfo to the XML signature. - * - * @author Frank Cornelis - * - */ -public class KeyInfoSignatureFacet extends SignatureFacet { - - private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class); - - @Override - public void postSign(Document document) - throws MarshalException { - LOG.log(POILogger.DEBUG, "postSign"); - - NodeList nl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "Object"); - - /* - * Make sure we insert right after the ds:SignatureValue element, just - * before the first ds:Object element. - */ - Node nextSibling = (nl.getLength() == 0) ? null : nl.item(0); - - /* - * Construct the ds:KeyInfo element using JSR 105. - */ - KeyInfoFactory keyInfoFactory = signatureConfig.getKeyInfoFactory(); - List x509DataObjects = new ArrayList(); - X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0); - - List keyInfoContent = new ArrayList(); - - if (signatureConfig.isIncludeKeyValue()) { - KeyValue keyValue; - try { - keyValue = keyInfoFactory.newKeyValue(signingCertificate.getPublicKey()); - } catch (KeyException e) { - throw new RuntimeException("key exception: " + e.getMessage(), e); - } - keyInfoContent.add(keyValue); - } - - if (signatureConfig.isIncludeIssuerSerial()) { - x509DataObjects.add(keyInfoFactory.newX509IssuerSerial( - signingCertificate.getIssuerX500Principal().toString(), - signingCertificate.getSerialNumber())); - } - - if (signatureConfig.isIncludeEntireCertificateChain()) { - x509DataObjects.addAll(signatureConfig.getSigningCertificateChain()); - } else { - x509DataObjects.add(signingCertificate); - } - - if (!x509DataObjects.isEmpty()) { - X509Data x509Data = keyInfoFactory.newX509Data(x509DataObjects); - keyInfoContent.add(x509Data); - } - KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent); - DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo; - - Key key = new Key() { - private static final long serialVersionUID = 1L; - - public String getAlgorithm() { - return null; - } - - public byte[] getEncoded() { - return null; - } - - public String getFormat() { - return null; - } - }; - - Element n = document.getDocumentElement(); - DOMSignContext domSignContext = (nextSibling == null) - ? new DOMSignContext(key, n) - : new DOMSignContext(key, n, nextSibling); - for (Map.Entry me : signatureConfig.getNamespacePrefixes().entrySet()) { - domSignContext.putNamespacePrefix(me.getKey(), me.getValue()); - } - - DOMStructure domStructure = new DOMStructure(n); - domKeyInfo.marshal(domStructure, domSignContext); - - // move keyinfo into the right place - if (nextSibling != null) { - NodeList kiNl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "KeyInfo"); - if (kiNl.getLength() != 1) { - throw new RuntimeException("KeyInfo wasn't set"); - } - nextSibling.getParentNode().insertBefore(kiNl.item(0), nextSibling); - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.security.Key; +import java.security.KeyException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.XMLStructure; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.dom.DOMSignContext; +import javax.xml.crypto.dsig.keyinfo.KeyInfo; +import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; +import javax.xml.crypto.dsig.keyinfo.KeyValue; +import javax.xml.crypto.dsig.keyinfo.X509Data; + +import org.apache.jcp.xml.dsig.internal.dom.DOMKeyInfo; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Signature Facet implementation that adds ds:KeyInfo to the XML signature. + * + * @author Frank Cornelis + * + */ +public class KeyInfoSignatureFacet extends SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class); + + @Override + public void postSign(Document document) + throws MarshalException { + LOG.log(POILogger.DEBUG, "postSign"); + + NodeList nl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "Object"); + + /* + * Make sure we insert right after the ds:SignatureValue element, just + * before the first ds:Object element. + */ + Node nextSibling = (nl.getLength() == 0) ? null : nl.item(0); + + /* + * Construct the ds:KeyInfo element using JSR 105. + */ + KeyInfoFactory keyInfoFactory = signatureConfig.getKeyInfoFactory(); + List x509DataObjects = new ArrayList(); + X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0); + + List keyInfoContent = new ArrayList(); + + if (signatureConfig.isIncludeKeyValue()) { + KeyValue keyValue; + try { + keyValue = keyInfoFactory.newKeyValue(signingCertificate.getPublicKey()); + } catch (KeyException e) { + throw new RuntimeException("key exception: " + e.getMessage(), e); + } + keyInfoContent.add(keyValue); + } + + if (signatureConfig.isIncludeIssuerSerial()) { + x509DataObjects.add(keyInfoFactory.newX509IssuerSerial( + signingCertificate.getIssuerX500Principal().toString(), + signingCertificate.getSerialNumber())); + } + + if (signatureConfig.isIncludeEntireCertificateChain()) { + x509DataObjects.addAll(signatureConfig.getSigningCertificateChain()); + } else { + x509DataObjects.add(signingCertificate); + } + + if (!x509DataObjects.isEmpty()) { + X509Data x509Data = keyInfoFactory.newX509Data(x509DataObjects); + keyInfoContent.add(x509Data); + } + KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent); + DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo; + + Key key = new Key() { + private static final long serialVersionUID = 1L; + + public String getAlgorithm() { + return null; + } + + public byte[] getEncoded() { + return null; + } + + public String getFormat() { + return null; + } + }; + + Element n = document.getDocumentElement(); + DOMSignContext domSignContext = (nextSibling == null) + ? new DOMSignContext(key, n) + : new DOMSignContext(key, n, nextSibling); + for (Map.Entry me : signatureConfig.getNamespacePrefixes().entrySet()) { + domSignContext.putNamespacePrefix(me.getKey(), me.getValue()); + } + + DOMStructure domStructure = new DOMStructure(n); + domKeyInfo.marshal(domStructure, domSignContext); + + // move keyinfo into the right place + if (nextSibling != null) { + NodeList kiNl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "KeyInfo"); + if (kiNl.getLength() != 1) { + throw new RuntimeException("KeyInfo wasn't set"); + } + nextSibling.getParentNode().insertBefore(kiNl.item(0), nextSibling); + } + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java index 9e094a6415..5affefc07d 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java @@ -1,475 +1,475 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.facets; - -import java.net.URI; -import java.net.URISyntaxException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -import javax.xml.XMLConstants; -import javax.xml.crypto.XMLStructure; -import javax.xml.crypto.dom.DOMStructure; -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.Manifest; -import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.SignatureProperties; -import javax.xml.crypto.dsig.SignatureProperty; -import javax.xml.crypto.dsig.Transform; -import javax.xml.crypto.dsig.XMLObject; -import javax.xml.crypto.dsig.XMLSignatureException; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.ContentTypes; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService; -import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec; -import org.apache.poi.util.LocaleUtil; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime; -import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1; -import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document; - -/** - * Office OpenXML Signature Facet implementation. - * - * @author fcorneli - * @see [MS-OFFCRYPTO]: Office Document Cryptography Structure - */ -public class OOXMLSignatureFacet extends SignatureFacet { - - private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class); - - @Override - public void preSign( - Document document - , List references - , List objects) - throws XMLSignatureException { - LOG.log(POILogger.DEBUG, "pre sign"); - addManifestObject(document, references, objects); - addSignatureInfo(document, references, objects); - } - - protected void addManifestObject( - Document document - , List references - , List objects) - throws XMLSignatureException { - - List manifestReferences = new ArrayList(); - addManifestReferences(manifestReferences); - Manifest manifest = getSignatureFactory().newManifest(manifestReferences); - - String objectId = "idPackageObject"; // really has to be this value. - List objectContent = new ArrayList(); - objectContent.add(manifest); - - addSignatureTime(document, objectContent); - - XMLObject xo = getSignatureFactory().newXMLObject(objectContent, objectId, null, null); - objects.add(xo); - - Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); - references.add(reference); - } - - @SuppressWarnings("resource") - protected void addManifestReferences(List manifestReferences) - throws XMLSignatureException { - - OPCPackage ooxml = signatureConfig.getOpcPackage(); - List relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART); - - Set digestedPartNames = new HashSet(); - for (PackagePart pp : relsEntryNames) { - String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1"); - - PackageRelationshipCollection prc; - try { - prc = new PackageRelationshipCollection(ooxml); - prc.parseRelationshipsPart(pp); - } catch (InvalidFormatException e) { - throw new XMLSignatureException("Invalid relationship descriptor: "+pp.getPartName().getName(), e); - } - - RelationshipTransformParameterSpec parameterSpec = new RelationshipTransformParameterSpec(); - for (PackageRelationship relationship : prc) { - String relationshipType = relationship.getRelationshipType(); - - /* - * ECMA-376 Part 2 - 3rd edition - * 13.2.4.16 Manifest Element - * "The producer shall not create a Manifest element that references any data outside of the package." - */ - if (TargetMode.EXTERNAL == relationship.getTargetMode()) { - continue; - } - - if (!isSignedRelationship(relationshipType)) continue; - - parameterSpec.addRelationshipReference(relationship.getId()); - - // TODO: find a better way ... - String partName = relationship.getTargetURI().toString(); - if (!partName.startsWith(baseUri)) { - partName = baseUri + partName; - } - try { - partName = new URI(partName).normalize().getPath().replace('\\', '/'); - LOG.log(POILogger.DEBUG, "part name: " + partName); - } catch (URISyntaxException e) { - throw new XMLSignatureException(e); - } - - String contentType; - try { - PackagePartName relName = PackagingURIHelper.createPartName(partName); - PackagePart pp2 = ooxml.getPart(relName); - contentType = pp2.getContentType(); - } catch (InvalidFormatException e) { - throw new XMLSignatureException(e); - } - - if (relationshipType.endsWith("customXml") - && !(contentType.equals("inkml+xml") || contentType.equals("text/xml"))) { - LOG.log(POILogger.DEBUG, "skipping customXml with content type: " + contentType); - continue; - } - - if (!digestedPartNames.contains(partName)) { - // We only digest a part once. - String uri = partName + "?ContentType=" + contentType; - Reference reference = newReference(uri, null, null, null, null); - manifestReferences.add(reference); - digestedPartNames.add(partName); - } - } - - if (parameterSpec.hasSourceIds()) { - List transforms = new ArrayList(); - transforms.add(newTransform(RelationshipTransformService.TRANSFORM_URI, parameterSpec)); - transforms.add(newTransform(CanonicalizationMethod.INCLUSIVE)); - String uri = pp.getPartName().getName() - + "?ContentType=application/vnd.openxmlformats-package.relationships+xml"; - Reference reference = newReference(uri, transforms, null, null, null); - manifestReferences.add(reference); - } - } - } - - - protected void addSignatureTime(Document document, List objectContent) { - /* - * SignatureTime - */ - DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT); - fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC); - String nowStr = fmt.format(signatureConfig.getExecutionTime()); - LOG.log(POILogger.DEBUG, "now: " + nowStr); - - SignatureTimeDocument sigTime = SignatureTimeDocument.Factory.newInstance(); - CTSignatureTime ctTime = sigTime.addNewSignatureTime(); - ctTime.setFormat("YYYY-MM-DDThh:mm:ssTZD"); - ctTime.setValue(nowStr); - - Element n = (Element)document.importNode(ctTime.getDomNode(),true); - List signatureTimeContent = new ArrayList(); - signatureTimeContent.add(new DOMStructure(n)); - SignatureProperty signatureTimeSignatureProperty = getSignatureFactory() - .newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(), - "idSignatureTime"); - List signaturePropertyContent = new ArrayList(); - signaturePropertyContent.add(signatureTimeSignatureProperty); - SignatureProperties signatureProperties = getSignatureFactory() - .newSignatureProperties(signaturePropertyContent, - "id-signature-time-" + signatureConfig.getExecutionTime()); - objectContent.add(signatureProperties); - } - - protected void addSignatureInfo(Document document, - List references, - List objects) - throws XMLSignatureException { - List objectContent = new ArrayList(); - - SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance(); - CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1(); - ctSigV1.setManifestHashAlgorithm(signatureConfig.getDigestMethodUri()); - Element n = (Element)document.importNode(ctSigV1.getDomNode(), true); - n.setAttributeNS(XML_NS, XMLConstants.XMLNS_ATTRIBUTE, MS_DIGSIG_NS); - - List signatureInfoContent = new ArrayList(); - signatureInfoContent.add(new DOMStructure(n)); - SignatureProperty signatureInfoSignatureProperty = getSignatureFactory() - .newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(), - "idOfficeV1Details"); - - List signaturePropertyContent = new ArrayList(); - signaturePropertyContent.add(signatureInfoSignatureProperty); - SignatureProperties signatureProperties = getSignatureFactory() - .newSignatureProperties(signaturePropertyContent, null); - objectContent.add(signatureProperties); - - String objectId = "idOfficeObject"; - objects.add(getSignatureFactory().newXMLObject(objectContent, objectId, null, null)); - - Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); - references.add(reference); - } - - protected static String getRelationshipReferenceURI(String zipEntryName) { - return "/" - + zipEntryName - + "?ContentType=application/vnd.openxmlformats-package.relationships+xml"; - } - - protected static String getResourceReferenceURI(String resourceName, String contentType) { - return "/" + resourceName + "?ContentType=" + contentType; - } - - protected static boolean isSignedRelationship(String relationshipType) { - LOG.log(POILogger.DEBUG, "relationship type: " + relationshipType); - for (String signedTypeExtension : signed) { - if (relationshipType.endsWith(signedTypeExtension)) { - return true; - } - } - if (relationshipType.endsWith("customXml")) { - LOG.log(POILogger.DEBUG, "customXml relationship type"); - return true; - } - return false; - } - - public static final String[] contentTypes = { - /* - * Word - */ - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", - "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", - "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", - "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", - "application/vnd.openxmlformats-officedocument.theme+xml", - "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", - "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", - - /* - * Word 2010 - */ - "application/vnd.ms-word.stylesWithEffects+xml", - - /* - * Excel - */ - "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", - "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml", - "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", - - /* - * Powerpoint - */ - "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml", - "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml", - "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml", - "application/vnd.openxmlformats-officedocument.presentationml.slide+xml", - "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml", - - /* - * Powerpoint 2010 - */ - "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml", - "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml" - }; - - /** - * Office 2010 list of signed types (extensions). - */ - public static final String[] signed = { - "powerPivotData", // - "activeXControlBinary", // - "attachedToolbars", // - "connectorXml", // - "downRev", // - "functionPrototypes", // - "graphicFrameDoc", // - "groupShapeXml", // - "ink", // - "keyMapCustomizations", // - "legacyDiagramText", // - "legacyDocTextInfo", // - "officeDocument", // - "pictureXml", // - "shapeXml", // - "smartTags", // - "ui/altText", // - "ui/buttonSize", // - "ui/controlID", // - "ui/description", // - "ui/enabled", // - "ui/extensibility", // - "ui/helperText", // - "ui/imageID", // - "ui/imageMso", // - "ui/keyTip", // - "ui/label", // - "ui/lcid", // - "ui/loud", // - "ui/pressed", // - "ui/progID", // - "ui/ribbonID", // - "ui/showImage", // - "ui/showLabel", // - "ui/supertip", // - "ui/target", // - "ui/text", // - "ui/title", // - "ui/tooltip", // - "ui/userCustomization", // - "ui/visible", // - "userXmlData", // - "vbaProject", // - "wordVbaData", // - "wsSortMap", // - "xlBinaryIndex", // - "xlExternalLinkPath/xlAlternateStartup", // - "xlExternalLinkPath/xlLibrary", // - "xlExternalLinkPath/xlPathMissing", // - "xlExternalLinkPath/xlStartup", // - "xlIntlMacrosheet", // - "xlMacrosheet", // - "customData", // - "diagramDrawing", // - "hdphoto", // - "inkXml", // - "media", // - "slicer", // - "slicerCache", // - "stylesWithEffects", // - "ui/extensibility", // - "chartColorStyle", // - "chartLayout", // - "chartStyle", // - "dictionary", // - "timeline", // - "timelineCache", // - "aFChunk", // - "attachedTemplate", // - "audio", // - "calcChain", // - "chart", // - "chartsheet", // - "chartUserShapes", // - "commentAuthors", // - "comments", // - "connections", // - "control", // - "customProperty", // - "customXml", // - "diagramColors", // - "diagramData", // - "diagramLayout", // - "diagramQuickStyle", // - "dialogsheet", // - "drawing", // - "endnotes", // - "externalLink", // - "externalLinkPath", // - "font", // - "fontTable", // - "footer", // - "footnotes", // - "glossaryDocument", // - "handoutMaster", // - "header", // - "hyperlink", // - "image", // - "mailMergeHeaderSource", // - "mailMergeRecipientData", // - "mailMergeSource", // - "notesMaster", // - "notesSlide", // - "numbering", // - "officeDocument", // - "oleObject", // - "package", // - "pivotCacheDefinition", // - "pivotCacheRecords", // - "pivotTable", // - "presProps", // - "printerSettings", // - "queryTable", // - "recipientData", // - "settings", // - "sharedStrings", // - "sheetMetadata", // - "slide", // - "slideLayout", // - "slideMaster", // - "slideUpdateInfo", // - "slideUpdateUrl", // - "styles", // - "table", // - "tableSingleCells", // - "tableStyles", // - "tags", // - "theme", // - "themeOverride", // - "transform", // - "video", // - "viewProps", // - "volatileDependencies", // - "webSettings", // - "worksheet", // - "xmlMaps", // - "ctrlProp", // - "customData", // - "diagram", // - "diagramColorsHeader", // - "diagramLayoutHeader", // - "diagramQuickStyleHeader", // - "documentParts", // - "slicer", // - "slicerCache", // - "vmlDrawing" // - }; +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.net.URI; +import java.net.URISyntaxException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.xml.XMLConstants; +import javax.xml.crypto.XMLStructure; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.Manifest; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.SignatureProperties; +import javax.xml.crypto.dsig.SignatureProperty; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureException; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService; +import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec; +import org.apache.poi.util.LocaleUtil; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime; +import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1; +import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document; + +/** + * Office OpenXML Signature Facet implementation. + * + * @author fcorneli + * @see [MS-OFFCRYPTO]: Office Document Cryptography Structure + */ +public class OOXMLSignatureFacet extends SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class); + + @Override + public void preSign( + Document document + , List references + , List objects) + throws XMLSignatureException { + LOG.log(POILogger.DEBUG, "pre sign"); + addManifestObject(document, references, objects); + addSignatureInfo(document, references, objects); + } + + protected void addManifestObject( + Document document + , List references + , List objects) + throws XMLSignatureException { + + List manifestReferences = new ArrayList(); + addManifestReferences(manifestReferences); + Manifest manifest = getSignatureFactory().newManifest(manifestReferences); + + String objectId = "idPackageObject"; // really has to be this value. + List objectContent = new ArrayList(); + objectContent.add(manifest); + + addSignatureTime(document, objectContent); + + XMLObject xo = getSignatureFactory().newXMLObject(objectContent, objectId, null, null); + objects.add(xo); + + Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); + references.add(reference); + } + + @SuppressWarnings("resource") + protected void addManifestReferences(List manifestReferences) + throws XMLSignatureException { + + OPCPackage ooxml = signatureConfig.getOpcPackage(); + List relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART); + + Set digestedPartNames = new HashSet(); + for (PackagePart pp : relsEntryNames) { + String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1"); + + PackageRelationshipCollection prc; + try { + prc = new PackageRelationshipCollection(ooxml); + prc.parseRelationshipsPart(pp); + } catch (InvalidFormatException e) { + throw new XMLSignatureException("Invalid relationship descriptor: "+pp.getPartName().getName(), e); + } + + RelationshipTransformParameterSpec parameterSpec = new RelationshipTransformParameterSpec(); + for (PackageRelationship relationship : prc) { + String relationshipType = relationship.getRelationshipType(); + + /* + * ECMA-376 Part 2 - 3rd edition + * 13.2.4.16 Manifest Element + * "The producer shall not create a Manifest element that references any data outside of the package." + */ + if (TargetMode.EXTERNAL == relationship.getTargetMode()) { + continue; + } + + if (!isSignedRelationship(relationshipType)) continue; + + parameterSpec.addRelationshipReference(relationship.getId()); + + // TODO: find a better way ... + String partName = relationship.getTargetURI().toString(); + if (!partName.startsWith(baseUri)) { + partName = baseUri + partName; + } + try { + partName = new URI(partName).normalize().getPath().replace('\\', '/'); + LOG.log(POILogger.DEBUG, "part name: " + partName); + } catch (URISyntaxException e) { + throw new XMLSignatureException(e); + } + + String contentType; + try { + PackagePartName relName = PackagingURIHelper.createPartName(partName); + PackagePart pp2 = ooxml.getPart(relName); + contentType = pp2.getContentType(); + } catch (InvalidFormatException e) { + throw new XMLSignatureException(e); + } + + if (relationshipType.endsWith("customXml") + && !(contentType.equals("inkml+xml") || contentType.equals("text/xml"))) { + LOG.log(POILogger.DEBUG, "skipping customXml with content type: " + contentType); + continue; + } + + if (!digestedPartNames.contains(partName)) { + // We only digest a part once. + String uri = partName + "?ContentType=" + contentType; + Reference reference = newReference(uri, null, null, null, null); + manifestReferences.add(reference); + digestedPartNames.add(partName); + } + } + + if (parameterSpec.hasSourceIds()) { + List transforms = new ArrayList(); + transforms.add(newTransform(RelationshipTransformService.TRANSFORM_URI, parameterSpec)); + transforms.add(newTransform(CanonicalizationMethod.INCLUSIVE)); + String uri = pp.getPartName().getName() + + "?ContentType=application/vnd.openxmlformats-package.relationships+xml"; + Reference reference = newReference(uri, transforms, null, null, null); + manifestReferences.add(reference); + } + } + } + + + protected void addSignatureTime(Document document, List objectContent) { + /* + * SignatureTime + */ + DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT); + fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC); + String nowStr = fmt.format(signatureConfig.getExecutionTime()); + LOG.log(POILogger.DEBUG, "now: " + nowStr); + + SignatureTimeDocument sigTime = SignatureTimeDocument.Factory.newInstance(); + CTSignatureTime ctTime = sigTime.addNewSignatureTime(); + ctTime.setFormat("YYYY-MM-DDThh:mm:ssTZD"); + ctTime.setValue(nowStr); + + Element n = (Element)document.importNode(ctTime.getDomNode(),true); + List signatureTimeContent = new ArrayList(); + signatureTimeContent.add(new DOMStructure(n)); + SignatureProperty signatureTimeSignatureProperty = getSignatureFactory() + .newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(), + "idSignatureTime"); + List signaturePropertyContent = new ArrayList(); + signaturePropertyContent.add(signatureTimeSignatureProperty); + SignatureProperties signatureProperties = getSignatureFactory() + .newSignatureProperties(signaturePropertyContent, + "id-signature-time-" + signatureConfig.getExecutionTime()); + objectContent.add(signatureProperties); + } + + protected void addSignatureInfo(Document document, + List references, + List objects) + throws XMLSignatureException { + List objectContent = new ArrayList(); + + SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance(); + CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1(); + ctSigV1.setManifestHashAlgorithm(signatureConfig.getDigestMethodUri()); + Element n = (Element)document.importNode(ctSigV1.getDomNode(), true); + n.setAttributeNS(XML_NS, XMLConstants.XMLNS_ATTRIBUTE, MS_DIGSIG_NS); + + List signatureInfoContent = new ArrayList(); + signatureInfoContent.add(new DOMStructure(n)); + SignatureProperty signatureInfoSignatureProperty = getSignatureFactory() + .newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(), + "idOfficeV1Details"); + + List signaturePropertyContent = new ArrayList(); + signaturePropertyContent.add(signatureInfoSignatureProperty); + SignatureProperties signatureProperties = getSignatureFactory() + .newSignatureProperties(signaturePropertyContent, null); + objectContent.add(signatureProperties); + + String objectId = "idOfficeObject"; + objects.add(getSignatureFactory().newXMLObject(objectContent, objectId, null, null)); + + Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); + references.add(reference); + } + + protected static String getRelationshipReferenceURI(String zipEntryName) { + return "/" + + zipEntryName + + "?ContentType=application/vnd.openxmlformats-package.relationships+xml"; + } + + protected static String getResourceReferenceURI(String resourceName, String contentType) { + return "/" + resourceName + "?ContentType=" + contentType; + } + + protected static boolean isSignedRelationship(String relationshipType) { + LOG.log(POILogger.DEBUG, "relationship type: " + relationshipType); + for (String signedTypeExtension : signed) { + if (relationshipType.endsWith(signedTypeExtension)) { + return true; + } + } + if (relationshipType.endsWith("customXml")) { + LOG.log(POILogger.DEBUG, "customXml relationship type"); + return true; + } + return false; + } + + public static final String[] contentTypes = { + /* + * Word + */ + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", + "application/vnd.openxmlformats-officedocument.theme+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", + + /* + * Word 2010 + */ + "application/vnd.ms-word.stylesWithEffects+xml", + + /* + * Excel + */ + "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", + + /* + * Powerpoint + */ + "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slide+xml", + "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml", + + /* + * Powerpoint 2010 + */ + "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml", + "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml" + }; + + /** + * Office 2010 list of signed types (extensions). + */ + public static final String[] signed = { + "powerPivotData", // + "activeXControlBinary", // + "attachedToolbars", // + "connectorXml", // + "downRev", // + "functionPrototypes", // + "graphicFrameDoc", // + "groupShapeXml", // + "ink", // + "keyMapCustomizations", // + "legacyDiagramText", // + "legacyDocTextInfo", // + "officeDocument", // + "pictureXml", // + "shapeXml", // + "smartTags", // + "ui/altText", // + "ui/buttonSize", // + "ui/controlID", // + "ui/description", // + "ui/enabled", // + "ui/extensibility", // + "ui/helperText", // + "ui/imageID", // + "ui/imageMso", // + "ui/keyTip", // + "ui/label", // + "ui/lcid", // + "ui/loud", // + "ui/pressed", // + "ui/progID", // + "ui/ribbonID", // + "ui/showImage", // + "ui/showLabel", // + "ui/supertip", // + "ui/target", // + "ui/text", // + "ui/title", // + "ui/tooltip", // + "ui/userCustomization", // + "ui/visible", // + "userXmlData", // + "vbaProject", // + "wordVbaData", // + "wsSortMap", // + "xlBinaryIndex", // + "xlExternalLinkPath/xlAlternateStartup", // + "xlExternalLinkPath/xlLibrary", // + "xlExternalLinkPath/xlPathMissing", // + "xlExternalLinkPath/xlStartup", // + "xlIntlMacrosheet", // + "xlMacrosheet", // + "customData", // + "diagramDrawing", // + "hdphoto", // + "inkXml", // + "media", // + "slicer", // + "slicerCache", // + "stylesWithEffects", // + "ui/extensibility", // + "chartColorStyle", // + "chartLayout", // + "chartStyle", // + "dictionary", // + "timeline", // + "timelineCache", // + "aFChunk", // + "attachedTemplate", // + "audio", // + "calcChain", // + "chart", // + "chartsheet", // + "chartUserShapes", // + "commentAuthors", // + "comments", // + "connections", // + "control", // + "customProperty", // + "customXml", // + "diagramColors", // + "diagramData", // + "diagramLayout", // + "diagramQuickStyle", // + "dialogsheet", // + "drawing", // + "endnotes", // + "externalLink", // + "externalLinkPath", // + "font", // + "fontTable", // + "footer", // + "footnotes", // + "glossaryDocument", // + "handoutMaster", // + "header", // + "hyperlink", // + "image", // + "mailMergeHeaderSource", // + "mailMergeRecipientData", // + "mailMergeSource", // + "notesMaster", // + "notesSlide", // + "numbering", // + "officeDocument", // + "oleObject", // + "package", // + "pivotCacheDefinition", // + "pivotCacheRecords", // + "pivotTable", // + "presProps", // + "printerSettings", // + "queryTable", // + "recipientData", // + "settings", // + "sharedStrings", // + "sheetMetadata", // + "slide", // + "slideLayout", // + "slideMaster", // + "slideUpdateInfo", // + "slideUpdateUrl", // + "styles", // + "table", // + "tableSingleCells", // + "tableStyles", // + "tags", // + "theme", // + "themeOverride", // + "transform", // + "video", // + "viewProps", // + "volatileDependencies", // + "webSettings", // + "worksheet", // + "xmlMaps", // + "ctrlProp", // + "customData", // + "diagram", // + "diagramColorsHeader", // + "diagramLayoutHeader", // + "diagramQuickStyleHeader", // + "documentParts", // + "slicer", // + "slicerCache", // + "vmlDrawing" // + }; } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java index c6dc2491e6..1cd1c6acce 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java @@ -1,79 +1,79 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.facets; - -import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import javax.xml.crypto.MarshalException; - -import org.apache.xmlbeans.XmlException; -import org.etsi.uri.x01903.v13.QualifyingPropertiesType; -import org.etsi.uri.x01903.v13.UnsignedPropertiesType; -import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Work-around for Office2010 to accept the XAdES-BES/EPES signature. - * - * xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be - * present. - * - * @author Frank Cornelis - * - */ -public class Office2010SignatureFacet extends SignatureFacet { - - @Override - public void postSign(Document document) - throws MarshalException { - // check for XAdES-BES - NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties"); - if (nl.getLength() != 1) { - throw new MarshalException("no XAdES-BES extension present"); - } - - QualifyingPropertiesType qualProps; - try { - qualProps = QualifyingPropertiesType.Factory.parse(nl.item(0), DEFAULT_XML_OPTIONS); - } catch (XmlException e) { - throw new MarshalException(e); - } - - // create basic XML container structure - UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); - if (unsignedProps == null) { - unsignedProps = qualProps.addNewUnsignedProperties(); - } - UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties(); - if (unsignedSigProps == null) { - /* unsignedSigProps = */ unsignedProps.addNewUnsignedSignatureProperties(); - } - - Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true); - nl.item(0).getParentNode().replaceChild(n, nl.item(0)); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; + +import javax.xml.crypto.MarshalException; + +import org.apache.xmlbeans.XmlException; +import org.etsi.uri.x01903.v13.QualifyingPropertiesType; +import org.etsi.uri.x01903.v13.UnsignedPropertiesType; +import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Work-around for Office2010 to accept the XAdES-BES/EPES signature. + * + * xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be + * present. + * + * @author Frank Cornelis + * + */ +public class Office2010SignatureFacet extends SignatureFacet { + + @Override + public void postSign(Document document) + throws MarshalException { + // check for XAdES-BES + NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties"); + if (nl.getLength() != 1) { + throw new MarshalException("no XAdES-BES extension present"); + } + + QualifyingPropertiesType qualProps; + try { + qualProps = QualifyingPropertiesType.Factory.parse(nl.item(0), DEFAULT_XML_OPTIONS); + } catch (XmlException e) { + throw new MarshalException(e); + } + + // create basic XML container structure + UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); + if (unsignedProps == null) { + unsignedProps = qualProps.addNewUnsignedProperties(); + } + UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties(); + if (unsignedSigProps == null) { + /* unsignedSigProps = */ unsignedProps.addNewUnsignedSignatureProperties(); + } + + Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true); + nl.item(0).getParentNode().replaceChild(n, nl.item(0)); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java index 43bef872fd..eec02ad4d5 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java @@ -1,190 +1,190 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.facets; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.PrivilegedAction; -import java.security.Provider; -import java.security.Security; -import java.util.List; - -import javax.xml.XMLConstants; -import javax.xml.crypto.MarshalException; -import javax.xml.crypto.dsig.DigestMethod; -import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.Transform; -import javax.xml.crypto.dsig.XMLObject; -import javax.xml.crypto.dsig.XMLSignature; -import javax.xml.crypto.dsig.XMLSignatureException; -import javax.xml.crypto.dsig.XMLSignatureFactory; -import javax.xml.crypto.dsig.spec.TransformParameterSpec; - -import org.apache.jcp.xml.dsig.internal.dom.DOMDigestMethod; -import org.apache.jcp.xml.dsig.internal.dom.DOMReference; -import org.apache.poi.openxml4j.opc.PackageNamespaces; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.SuppressForbidden; -import org.w3c.dom.Document; - -/** - * JSR105 Signature Facet base class. - */ -public abstract class SignatureFacet implements SignatureConfigurable { - - private static final POILogger LOG = POILogFactory.getLogger(SignatureFacet.class); - - public static final String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; - public static final String XML_DIGSIG_NS = XMLSignature.XMLNS; - public static final String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE; - public static final String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig"; - public static final String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#"; - public static final String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#"; - - protected SignatureConfig signatureConfig; - - public void setSignatureConfig(SignatureConfig signatureConfig) { - this.signatureConfig = signatureConfig; - } - - /** - * This method is being invoked by the XML signature service engine during - * pre-sign phase. Via this method a signature facet implementation can add - * signature facets to an XML signature. - * - * @param document the signature document to be used for imports - * @param references list of reference definitions - * @param objects objects to be signed/included in the signature document - * @throws XMLSignatureException - */ - public void preSign( - Document document - , List references - , List objects - ) throws XMLSignatureException { - // empty - } - - /** - * This method is being invoked by the XML signature service engine during - * the post-sign phase. Via this method a signature facet can extend the XML - * signatures with for example key information. - * - * @param document the signature document to be modified - * @throws MarshalException - */ - public void postSign(Document document) throws MarshalException { - // empty - } - - protected XMLSignatureFactory getSignatureFactory() { - return signatureConfig.getSignatureFactory(); - } - - protected Transform newTransform(String canonicalizationMethod) throws XMLSignatureException { - return newTransform(canonicalizationMethod, null); - } - - protected Transform newTransform(String canonicalizationMethod, TransformParameterSpec paramSpec) - throws XMLSignatureException { - try { - return getSignatureFactory().newTransform(canonicalizationMethod, paramSpec); - } catch (GeneralSecurityException e) { - throw new XMLSignatureException("unknown canonicalization method: "+canonicalizationMethod, e); - } - } - - protected Reference newReference(String uri, List transforms, String type, String id, byte digestValue[]) - throws XMLSignatureException { - return newReference(uri, transforms, type, id, digestValue, signatureConfig); - } - - public static Reference newReference( - String uri - , List transforms - , String type - , String id - , byte digestValue[] - , SignatureConfig signatureConfig) - throws XMLSignatureException { - // the references appear in the package signature or the package object - // so we can use the default digest algorithm - String digestMethodUri = signatureConfig.getDigestMethodUri(); - XMLSignatureFactory sigFac = signatureConfig.getSignatureFactory(); - DigestMethod digestMethod; - try { - digestMethod = sigFac.newDigestMethod(digestMethodUri, null); - } catch (GeneralSecurityException e) { - throw new XMLSignatureException("unknown digest method uri: "+digestMethodUri, e); - } - - Reference reference; - if (digestValue == null) { - reference = sigFac.newReference(uri, digestMethod, transforms, type, id); - } else { - reference = sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue); - } - - brokenJvmWorkaround(reference); - - return reference; - } - - // helper method ... will be removed soon - public static void brokenJvmWorkaround(final Reference reference) { - final DigestMethod digestMethod = reference.getDigestMethod(); - final String digestMethodUri = digestMethod.getAlgorithm(); - - final Provider bcProv = Security.getProvider("BC"); - if (bcProv != null && !DigestMethod.SHA1.equals(digestMethodUri)) { - // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012 - // overwrite standard message digest, if a digest <> SHA1 is used - AccessController.doPrivileged(new PrivilegedAction() { - @Override - @SuppressForbidden("Workaround for a bug, needs access to private JDK members (may fail in Java 9): https://bugzilla.redhat.com/show_bug.cgi?id=1155012") - public Void run() { - try { - Method m = DOMDigestMethod.class.getDeclaredMethod("getMessageDigestAlgorithm"); - m.setAccessible(true); - String mdAlgo = (String)m.invoke(digestMethod); - MessageDigest md = MessageDigest.getInstance(mdAlgo, bcProv); - Field f = DOMReference.class.getDeclaredField("md"); - f.setAccessible(true); - f.set(reference, md); - } catch (Exception e) { - LOG.log(POILogger.WARN, "Can't overwrite message digest (workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012)", e); - } - return null; // Void - } - }); - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.PrivilegedAction; +import java.security.Provider; +import java.security.Security; +import java.util.List; + +import javax.xml.XMLConstants; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignature; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; + +import org.apache.jcp.xml.dsig.internal.dom.DOMDigestMethod; +import org.apache.jcp.xml.dsig.internal.dom.DOMReference; +import org.apache.poi.openxml4j.opc.PackageNamespaces; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.SuppressForbidden; +import org.w3c.dom.Document; + +/** + * JSR105 Signature Facet base class. + */ +public abstract class SignatureFacet implements SignatureConfigurable { + + private static final POILogger LOG = POILogFactory.getLogger(SignatureFacet.class); + + public static final String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + public static final String XML_DIGSIG_NS = XMLSignature.XMLNS; + public static final String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE; + public static final String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig"; + public static final String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#"; + public static final String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#"; + + protected SignatureConfig signatureConfig; + + public void setSignatureConfig(SignatureConfig signatureConfig) { + this.signatureConfig = signatureConfig; + } + + /** + * This method is being invoked by the XML signature service engine during + * pre-sign phase. Via this method a signature facet implementation can add + * signature facets to an XML signature. + * + * @param document the signature document to be used for imports + * @param references list of reference definitions + * @param objects objects to be signed/included in the signature document + * @throws XMLSignatureException + */ + public void preSign( + Document document + , List references + , List objects + ) throws XMLSignatureException { + // empty + } + + /** + * This method is being invoked by the XML signature service engine during + * the post-sign phase. Via this method a signature facet can extend the XML + * signatures with for example key information. + * + * @param document the signature document to be modified + * @throws MarshalException + */ + public void postSign(Document document) throws MarshalException { + // empty + } + + protected XMLSignatureFactory getSignatureFactory() { + return signatureConfig.getSignatureFactory(); + } + + protected Transform newTransform(String canonicalizationMethod) throws XMLSignatureException { + return newTransform(canonicalizationMethod, null); + } + + protected Transform newTransform(String canonicalizationMethod, TransformParameterSpec paramSpec) + throws XMLSignatureException { + try { + return getSignatureFactory().newTransform(canonicalizationMethod, paramSpec); + } catch (GeneralSecurityException e) { + throw new XMLSignatureException("unknown canonicalization method: "+canonicalizationMethod, e); + } + } + + protected Reference newReference(String uri, List transforms, String type, String id, byte digestValue[]) + throws XMLSignatureException { + return newReference(uri, transforms, type, id, digestValue, signatureConfig); + } + + public static Reference newReference( + String uri + , List transforms + , String type + , String id + , byte digestValue[] + , SignatureConfig signatureConfig) + throws XMLSignatureException { + // the references appear in the package signature or the package object + // so we can use the default digest algorithm + String digestMethodUri = signatureConfig.getDigestMethodUri(); + XMLSignatureFactory sigFac = signatureConfig.getSignatureFactory(); + DigestMethod digestMethod; + try { + digestMethod = sigFac.newDigestMethod(digestMethodUri, null); + } catch (GeneralSecurityException e) { + throw new XMLSignatureException("unknown digest method uri: "+digestMethodUri, e); + } + + Reference reference; + if (digestValue == null) { + reference = sigFac.newReference(uri, digestMethod, transforms, type, id); + } else { + reference = sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue); + } + + brokenJvmWorkaround(reference); + + return reference; + } + + // helper method ... will be removed soon + public static void brokenJvmWorkaround(final Reference reference) { + final DigestMethod digestMethod = reference.getDigestMethod(); + final String digestMethodUri = digestMethod.getAlgorithm(); + + final Provider bcProv = Security.getProvider("BC"); + if (bcProv != null && !DigestMethod.SHA1.equals(digestMethodUri)) { + // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012 + // overwrite standard message digest, if a digest <> SHA1 is used + AccessController.doPrivileged(new PrivilegedAction() { + @Override + @SuppressForbidden("Workaround for a bug, needs access to private JDK members (may fail in Java 9): https://bugzilla.redhat.com/show_bug.cgi?id=1155012") + public Void run() { + try { + Method m = DOMDigestMethod.class.getDeclaredMethod("getMessageDigestAlgorithm"); + m.setAccessible(true); + String mdAlgo = (String)m.invoke(digestMethod); + MessageDigest md = MessageDigest.getInstance(mdAlgo, bcProv); + Field f = DOMReference.class.getDeclaredField("md"); + f.setAccessible(true); + f.set(reference, md); + } catch (Exception e) { + LOG.log(POILogger.WARN, "Can't overwrite message digest (workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012)", e); + } + return null; // Void + } + }); + } + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java index 5441d58bbc..a556f1f794 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java @@ -1,286 +1,286 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.facets; - -import java.security.MessageDigest; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; - -import javax.xml.crypto.XMLStructure; -import javax.xml.crypto.dom.DOMStructure; -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.Transform; -import javax.xml.crypto.dsig.XMLObject; -import javax.xml.crypto.dsig.XMLSignatureException; - -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig; -import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlString; -import org.etsi.uri.x01903.v13.AnyType; -import org.etsi.uri.x01903.v13.CertIDListType; -import org.etsi.uri.x01903.v13.CertIDType; -import org.etsi.uri.x01903.v13.ClaimedRolesListType; -import org.etsi.uri.x01903.v13.DataObjectFormatType; -import org.etsi.uri.x01903.v13.DigestAlgAndValueType; -import org.etsi.uri.x01903.v13.IdentifierType; -import org.etsi.uri.x01903.v13.ObjectIdentifierType; -import org.etsi.uri.x01903.v13.QualifyingPropertiesDocument; -import org.etsi.uri.x01903.v13.QualifyingPropertiesType; -import org.etsi.uri.x01903.v13.SigPolicyQualifiersListType; -import org.etsi.uri.x01903.v13.SignaturePolicyIdType; -import org.etsi.uri.x01903.v13.SignaturePolicyIdentifierType; -import org.etsi.uri.x01903.v13.SignedDataObjectPropertiesType; -import org.etsi.uri.x01903.v13.SignedPropertiesType; -import org.etsi.uri.x01903.v13.SignedSignaturePropertiesType; -import org.etsi.uri.x01903.v13.SignerRoleType; -import org.w3.x2000.x09.xmldsig.DigestMethodType; -import org.w3.x2000.x09.xmldsig.X509IssuerSerialType; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * XAdES Signature Facet. Implements XAdES v1.4.1 which is compatible with XAdES - * v1.3.2. The implemented XAdES format is XAdES-BES/EPES. It's up to another - * part of the signature service to upgrade the XAdES-BES to a XAdES-X-L. - * - * This implementation has been tested against an implementation that - * participated multiple ETSI XAdES plugtests. - * - * @author Frank Cornelis - * @see XAdES - * - */ -public class XAdESSignatureFacet extends SignatureFacet { - - private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class); - - private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties"; - - private Map dataObjectFormatMimeTypes = new HashMap(); - - - @Override - public void preSign( - Document document - , List references - , List objects) - throws XMLSignatureException { - LOG.log(POILogger.DEBUG, "preSign"); - - // QualifyingProperties - QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance(); - QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties(); - qualifyingProperties.setTarget("#" + signatureConfig.getPackageSignatureId()); - - // SignedProperties - SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties(); - signedProperties.setId(signatureConfig.getXadesSignatureId()); - - // SignedSignatureProperties - SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties(); - - // SigningTime - Calendar xmlGregorianCalendar = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); - xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime()); - xmlGregorianCalendar.clear(Calendar.MILLISECOND); - signedSignatureProperties.setSigningTime(xmlGregorianCalendar); - - // SigningCertificate - if (signatureConfig.getSigningCertificateChain() == null - || signatureConfig.getSigningCertificateChain().isEmpty()) { - throw new RuntimeException("no signing certificate chain available"); - } - CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate(); - CertIDType certId = signingCertificates.addNewCert(); - X509Certificate certificate = signatureConfig.getSigningCertificateChain().get(0); - setCertID(certId, signatureConfig, signatureConfig.isXadesIssuerNameNoReverseOrder(), certificate); - - // ClaimedRole - String role = signatureConfig.getXadesRole(); - if (role != null && !role.isEmpty()) { - SignerRoleType signerRole = signedSignatureProperties.addNewSignerRole(); - signedSignatureProperties.setSignerRole(signerRole); - ClaimedRolesListType claimedRolesList = signerRole.addNewClaimedRoles(); - AnyType claimedRole = claimedRolesList.addNewClaimedRole(); - XmlString roleString = XmlString.Factory.newInstance(); - roleString.setStringValue(role); - insertXChild(claimedRole, roleString); - } - - // XAdES-EPES - SignaturePolicyService policyService = signatureConfig.getSignaturePolicyService(); - if (policyService != null) { - SignaturePolicyIdentifierType signaturePolicyIdentifier = - signedSignatureProperties.addNewSignaturePolicyIdentifier(); - - SignaturePolicyIdType signaturePolicyId = signaturePolicyIdentifier.addNewSignaturePolicyId(); - - ObjectIdentifierType objectIdentifier = signaturePolicyId.addNewSigPolicyId(); - objectIdentifier.setDescription(policyService.getSignaturePolicyDescription()); - - IdentifierType identifier = objectIdentifier.addNewIdentifier(); - identifier.setStringValue(policyService.getSignaturePolicyIdentifier()); - - byte[] signaturePolicyDocumentData = policyService.getSignaturePolicyDocument(); - DigestAlgAndValueType sigPolicyHash = signaturePolicyId.addNewSigPolicyHash(); - setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, signatureConfig.getDigestAlgo()); - - String signaturePolicyDownloadUrl = policyService.getSignaturePolicyDownloadUrl(); - if (null != signaturePolicyDownloadUrl) { - SigPolicyQualifiersListType sigPolicyQualifiers = signaturePolicyId.addNewSigPolicyQualifiers(); - AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier(); - XmlString spUriElement = XmlString.Factory.newInstance(); - spUriElement.setStringValue(signaturePolicyDownloadUrl); - insertXChild(sigPolicyQualifier, spUriElement); - } - } else if (signatureConfig.isXadesSignaturePolicyImplied()) { - SignaturePolicyIdentifierType signaturePolicyIdentifier = - signedSignatureProperties.addNewSignaturePolicyIdentifier(); - signaturePolicyIdentifier.addNewSignaturePolicyImplied(); - } - - // DataObjectFormat - if (!dataObjectFormatMimeTypes.isEmpty()) { - SignedDataObjectPropertiesType signedDataObjectProperties = - signedProperties.addNewSignedDataObjectProperties(); - - List dataObjectFormats = signedDataObjectProperties - .getDataObjectFormatList(); - for (Map.Entry dataObjectFormatMimeType : this.dataObjectFormatMimeTypes - .entrySet()) { - DataObjectFormatType dataObjectFormat = DataObjectFormatType.Factory.newInstance(); - dataObjectFormat.setObjectReference("#" + dataObjectFormatMimeType.getKey()); - dataObjectFormat.setMimeType(dataObjectFormatMimeType.getValue()); - dataObjectFormats.add(dataObjectFormat); - } - } - - // add XAdES ds:Object - List xadesObjectContent = new ArrayList(); - Element qualDocElSrc = (Element)qualifyingProperties.getDomNode(); - Element qualDocEl = (Element)document.importNode(qualDocElSrc, true); - xadesObjectContent.add(new DOMStructure(qualDocEl)); - XMLObject xadesObject = getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null); - objects.add(xadesObject); - - // add XAdES ds:Reference - List transforms = new ArrayList(); - Transform exclusiveTransform = newTransform(CanonicalizationMethod.INCLUSIVE); - transforms.add(exclusiveTransform); - Reference reference = newReference - ("#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null); - references.add(reference); - } - - /** - * Gives back the JAXB DigestAlgAndValue data structure. - * - * @param digestAlgAndValue the parent for the new digest element - * @param data the data to be digested - * @param digestAlgo the digest algorithm - */ - protected static void setDigestAlgAndValue( - DigestAlgAndValueType digestAlgAndValue, - byte[] data, - HashAlgorithm digestAlgo) { - DigestMethodType digestMethod = digestAlgAndValue.addNewDigestMethod(); - digestMethod.setAlgorithm(SignatureConfig.getDigestMethodUri(digestAlgo)); - - MessageDigest messageDigest = CryptoFunctions.getMessageDigest(digestAlgo); - byte[] digestValue = messageDigest.digest(data); - digestAlgAndValue.setDigestValue(digestValue); - } - - /** - * Gives back the JAXB CertID data structure. - */ - protected static void setCertID - (CertIDType certId, SignatureConfig signatureConfig, boolean issuerNameNoReverseOrder, X509Certificate certificate) { - X509IssuerSerialType issuerSerial = certId.addNewIssuerSerial(); - String issuerName; - if (issuerNameNoReverseOrder) { - /* - * Make sure the DN is encoded using the same order as present - * within the certificate. This is an Office2010 work-around. - * Should be reverted back. - * - * XXX: not correct according to RFC 4514. - */ - // TODO: check if issuerName is different on getTBSCertificate - // issuerName = PrincipalUtil.getIssuerX509Principal(certificate).getName().replace(",", ", "); - issuerName = certificate.getIssuerDN().getName().replace(",", ", "); - } else { - issuerName = certificate.getIssuerX500Principal().toString(); - } - issuerSerial.setX509IssuerName(issuerName); - issuerSerial.setX509SerialNumber(certificate.getSerialNumber()); - - byte[] encodedCertificate; - try { - encodedCertificate = certificate.getEncoded(); - } catch (CertificateEncodingException e) { - throw new RuntimeException("certificate encoding error: " - + e.getMessage(), e); - } - DigestAlgAndValueType certDigest = certId.addNewCertDigest(); - setDigestAlgAndValue(certDigest, encodedCertificate, signatureConfig.getXadesDigestAlgo()); - } - - /** - * Adds a mime-type for the given ds:Reference (referred via its @URI). This - * information is added via the xades:DataObjectFormat element. - * - * @param dsReferenceUri - * @param mimetype - */ - public void addMimeType(String dsReferenceUri, String mimetype) { - this.dataObjectFormatMimeTypes.put(dsReferenceUri, mimetype); - } - - protected static void insertXChild(XmlObject root, XmlObject child) { - XmlCursor rootCursor = root.newCursor(); - rootCursor.toEndToken(); - XmlCursor childCursor = child.newCursor(); - childCursor.toNextToken(); - childCursor.moveXml(rootCursor); - childCursor.dispose(); - rootCursor.dispose(); - } - +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.security.MessageDigest; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; + +import javax.xml.crypto.XMLStructure; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureException; + +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlString; +import org.etsi.uri.x01903.v13.AnyType; +import org.etsi.uri.x01903.v13.CertIDListType; +import org.etsi.uri.x01903.v13.CertIDType; +import org.etsi.uri.x01903.v13.ClaimedRolesListType; +import org.etsi.uri.x01903.v13.DataObjectFormatType; +import org.etsi.uri.x01903.v13.DigestAlgAndValueType; +import org.etsi.uri.x01903.v13.IdentifierType; +import org.etsi.uri.x01903.v13.ObjectIdentifierType; +import org.etsi.uri.x01903.v13.QualifyingPropertiesDocument; +import org.etsi.uri.x01903.v13.QualifyingPropertiesType; +import org.etsi.uri.x01903.v13.SigPolicyQualifiersListType; +import org.etsi.uri.x01903.v13.SignaturePolicyIdType; +import org.etsi.uri.x01903.v13.SignaturePolicyIdentifierType; +import org.etsi.uri.x01903.v13.SignedDataObjectPropertiesType; +import org.etsi.uri.x01903.v13.SignedPropertiesType; +import org.etsi.uri.x01903.v13.SignedSignaturePropertiesType; +import org.etsi.uri.x01903.v13.SignerRoleType; +import org.w3.x2000.x09.xmldsig.DigestMethodType; +import org.w3.x2000.x09.xmldsig.X509IssuerSerialType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * XAdES Signature Facet. Implements XAdES v1.4.1 which is compatible with XAdES + * v1.3.2. The implemented XAdES format is XAdES-BES/EPES. It's up to another + * part of the signature service to upgrade the XAdES-BES to a XAdES-X-L. + * + * This implementation has been tested against an implementation that + * participated multiple ETSI XAdES plugtests. + * + * @author Frank Cornelis + * @see XAdES + * + */ +public class XAdESSignatureFacet extends SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class); + + private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties"; + + private Map dataObjectFormatMimeTypes = new HashMap(); + + + @Override + public void preSign( + Document document + , List references + , List objects) + throws XMLSignatureException { + LOG.log(POILogger.DEBUG, "preSign"); + + // QualifyingProperties + QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance(); + QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties(); + qualifyingProperties.setTarget("#" + signatureConfig.getPackageSignatureId()); + + // SignedProperties + SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties(); + signedProperties.setId(signatureConfig.getXadesSignatureId()); + + // SignedSignatureProperties + SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties(); + + // SigningTime + Calendar xmlGregorianCalendar = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); + xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime()); + xmlGregorianCalendar.clear(Calendar.MILLISECOND); + signedSignatureProperties.setSigningTime(xmlGregorianCalendar); + + // SigningCertificate + if (signatureConfig.getSigningCertificateChain() == null + || signatureConfig.getSigningCertificateChain().isEmpty()) { + throw new RuntimeException("no signing certificate chain available"); + } + CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate(); + CertIDType certId = signingCertificates.addNewCert(); + X509Certificate certificate = signatureConfig.getSigningCertificateChain().get(0); + setCertID(certId, signatureConfig, signatureConfig.isXadesIssuerNameNoReverseOrder(), certificate); + + // ClaimedRole + String role = signatureConfig.getXadesRole(); + if (role != null && !role.isEmpty()) { + SignerRoleType signerRole = signedSignatureProperties.addNewSignerRole(); + signedSignatureProperties.setSignerRole(signerRole); + ClaimedRolesListType claimedRolesList = signerRole.addNewClaimedRoles(); + AnyType claimedRole = claimedRolesList.addNewClaimedRole(); + XmlString roleString = XmlString.Factory.newInstance(); + roleString.setStringValue(role); + insertXChild(claimedRole, roleString); + } + + // XAdES-EPES + SignaturePolicyService policyService = signatureConfig.getSignaturePolicyService(); + if (policyService != null) { + SignaturePolicyIdentifierType signaturePolicyIdentifier = + signedSignatureProperties.addNewSignaturePolicyIdentifier(); + + SignaturePolicyIdType signaturePolicyId = signaturePolicyIdentifier.addNewSignaturePolicyId(); + + ObjectIdentifierType objectIdentifier = signaturePolicyId.addNewSigPolicyId(); + objectIdentifier.setDescription(policyService.getSignaturePolicyDescription()); + + IdentifierType identifier = objectIdentifier.addNewIdentifier(); + identifier.setStringValue(policyService.getSignaturePolicyIdentifier()); + + byte[] signaturePolicyDocumentData = policyService.getSignaturePolicyDocument(); + DigestAlgAndValueType sigPolicyHash = signaturePolicyId.addNewSigPolicyHash(); + setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, signatureConfig.getDigestAlgo()); + + String signaturePolicyDownloadUrl = policyService.getSignaturePolicyDownloadUrl(); + if (null != signaturePolicyDownloadUrl) { + SigPolicyQualifiersListType sigPolicyQualifiers = signaturePolicyId.addNewSigPolicyQualifiers(); + AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier(); + XmlString spUriElement = XmlString.Factory.newInstance(); + spUriElement.setStringValue(signaturePolicyDownloadUrl); + insertXChild(sigPolicyQualifier, spUriElement); + } + } else if (signatureConfig.isXadesSignaturePolicyImplied()) { + SignaturePolicyIdentifierType signaturePolicyIdentifier = + signedSignatureProperties.addNewSignaturePolicyIdentifier(); + signaturePolicyIdentifier.addNewSignaturePolicyImplied(); + } + + // DataObjectFormat + if (!dataObjectFormatMimeTypes.isEmpty()) { + SignedDataObjectPropertiesType signedDataObjectProperties = + signedProperties.addNewSignedDataObjectProperties(); + + List dataObjectFormats = signedDataObjectProperties + .getDataObjectFormatList(); + for (Map.Entry dataObjectFormatMimeType : this.dataObjectFormatMimeTypes + .entrySet()) { + DataObjectFormatType dataObjectFormat = DataObjectFormatType.Factory.newInstance(); + dataObjectFormat.setObjectReference("#" + dataObjectFormatMimeType.getKey()); + dataObjectFormat.setMimeType(dataObjectFormatMimeType.getValue()); + dataObjectFormats.add(dataObjectFormat); + } + } + + // add XAdES ds:Object + List xadesObjectContent = new ArrayList(); + Element qualDocElSrc = (Element)qualifyingProperties.getDomNode(); + Element qualDocEl = (Element)document.importNode(qualDocElSrc, true); + xadesObjectContent.add(new DOMStructure(qualDocEl)); + XMLObject xadesObject = getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null); + objects.add(xadesObject); + + // add XAdES ds:Reference + List transforms = new ArrayList(); + Transform exclusiveTransform = newTransform(CanonicalizationMethod.INCLUSIVE); + transforms.add(exclusiveTransform); + Reference reference = newReference + ("#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null); + references.add(reference); + } + + /** + * Gives back the JAXB DigestAlgAndValue data structure. + * + * @param digestAlgAndValue the parent for the new digest element + * @param data the data to be digested + * @param digestAlgo the digest algorithm + */ + protected static void setDigestAlgAndValue( + DigestAlgAndValueType digestAlgAndValue, + byte[] data, + HashAlgorithm digestAlgo) { + DigestMethodType digestMethod = digestAlgAndValue.addNewDigestMethod(); + digestMethod.setAlgorithm(SignatureConfig.getDigestMethodUri(digestAlgo)); + + MessageDigest messageDigest = CryptoFunctions.getMessageDigest(digestAlgo); + byte[] digestValue = messageDigest.digest(data); + digestAlgAndValue.setDigestValue(digestValue); + } + + /** + * Gives back the JAXB CertID data structure. + */ + protected static void setCertID + (CertIDType certId, SignatureConfig signatureConfig, boolean issuerNameNoReverseOrder, X509Certificate certificate) { + X509IssuerSerialType issuerSerial = certId.addNewIssuerSerial(); + String issuerName; + if (issuerNameNoReverseOrder) { + /* + * Make sure the DN is encoded using the same order as present + * within the certificate. This is an Office2010 work-around. + * Should be reverted back. + * + * XXX: not correct according to RFC 4514. + */ + // TODO: check if issuerName is different on getTBSCertificate + // issuerName = PrincipalUtil.getIssuerX509Principal(certificate).getName().replace(",", ", "); + issuerName = certificate.getIssuerDN().getName().replace(",", ", "); + } else { + issuerName = certificate.getIssuerX500Principal().toString(); + } + issuerSerial.setX509IssuerName(issuerName); + issuerSerial.setX509SerialNumber(certificate.getSerialNumber()); + + byte[] encodedCertificate; + try { + encodedCertificate = certificate.getEncoded(); + } catch (CertificateEncodingException e) { + throw new RuntimeException("certificate encoding error: " + + e.getMessage(), e); + } + DigestAlgAndValueType certDigest = certId.addNewCertDigest(); + setDigestAlgAndValue(certDigest, encodedCertificate, signatureConfig.getXadesDigestAlgo()); + } + + /** + * Adds a mime-type for the given ds:Reference (referred via its @URI). This + * information is added via the xades:DataObjectFormat element. + * + * @param dsReferenceUri + * @param mimetype + */ + public void addMimeType(String dsReferenceUri, String mimetype) { + this.dataObjectFormatMimeTypes.put(dsReferenceUri, mimetype); + } + + protected static void insertXChild(XmlObject root, XmlObject child) { + XmlCursor rootCursor = root.newCursor(); + rootCursor.toEndToken(); + XmlCursor childCursor = child.newCursor(); + childCursor.toNextToken(); + childCursor.moveXml(rootCursor); + childCursor.dispose(); + rootCursor.dispose(); + } + } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java index 783b16cfd2..e7d17b0b1a 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java @@ -1,389 +1,389 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.facets; - -import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; -import static org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet.insertXChild; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; -import java.security.cert.CRLException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; -import java.util.UUID; - -import javax.xml.crypto.MarshalException; - -import org.apache.poi.poifs.crypt.dsig.services.RevocationData; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.xml.security.c14n.Canonicalizer; -import org.apache.xmlbeans.XmlException; -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.ASN1Integer; -import org.bouncycastle.asn1.ASN1OctetString; -import org.bouncycastle.asn1.DERTaggedObject; -import org.bouncycastle.asn1.ocsp.ResponderID; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.cert.ocsp.BasicOCSPResp; -import org.bouncycastle.cert.ocsp.OCSPResp; -import org.bouncycastle.cert.ocsp.RespID; -import org.etsi.uri.x01903.v13.*; -import org.etsi.uri.x01903.v14.ValidationDataType; -import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * XAdES-X-L v1.4.1 signature facet. This signature facet implementation will - * upgrade a given XAdES-BES/EPES signature to XAdES-X-L. - * - * We don't inherit from XAdESSignatureFacet as we also want to be able to use - * this facet out of the context of a signature creation. This signature facet - * assumes that the signature is already XAdES-BES/EPES compliant. - * - * This implementation has been tested against an implementation that - * participated multiple ETSI XAdES plugtests. - * - * @author Frank Cornelis - * @see XAdESSignatureFacet - */ -public class XAdESXLSignatureFacet extends SignatureFacet { - - private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class); - - private final CertificateFactory certificateFactory; - - public XAdESXLSignatureFacet() { - try { - this.certificateFactory = CertificateFactory.getInstance("X.509"); - } catch (CertificateException e) { - throw new RuntimeException("X509 JCA error: " + e.getMessage(), e); - } - } - - @Override - public void postSign(Document document) throws MarshalException { - LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase"); - - QualifyingPropertiesDocument qualDoc = null; - QualifyingPropertiesType qualProps = null; - - // check for XAdES-BES - NodeList qualNl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties"); - if (qualNl.getLength() == 1) { - try { - qualDoc = QualifyingPropertiesDocument.Factory.parse(qualNl.item(0), DEFAULT_XML_OPTIONS); - } catch (XmlException e) { - throw new MarshalException(e); - } - qualProps = qualDoc.getQualifyingProperties(); - } else { - throw new MarshalException("no XAdES-BES extension present"); - } - - // create basic XML container structure - UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); - if (unsignedProps == null) { - unsignedProps = qualProps.addNewUnsignedProperties(); - } - UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties(); - if (unsignedSigProps == null) { - unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties(); - } - - - // create the XAdES-T time-stamp - NodeList nlSigVal = document.getElementsByTagNameNS(XML_DIGSIG_NS, "SignatureValue"); - if (nlSigVal.getLength() != 1) { - throw new IllegalArgumentException("SignatureValue is not set."); - } - - RevocationData tsaRevocationDataXadesT = new RevocationData(); - LOG.log(POILogger.DEBUG, "creating XAdES-T time-stamp"); - XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp - (Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT); - - // marshal the XAdES-T extension - unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp); - - // xadesv141::TimeStampValidationData - if (tsaRevocationDataXadesT.hasRevocationDataEntries()) { - ValidationDataType validationData = createValidationData(tsaRevocationDataXadesT); - insertXChild(unsignedSigProps, validationData); - } - - if (signatureConfig.getRevocationDataService() == null) { - /* - * Without revocation data service we cannot construct the XAdES-C - * extension. - */ - return; - } - - // XAdES-C: complete certificate refs - CompleteCertificateRefsType completeCertificateRefs = - unsignedSigProps.addNewCompleteCertificateRefs(); - - CertIDListType certIdList = completeCertificateRefs.addNewCertRefs(); - /* - * We skip the signing certificate itself according to section - * 4.4.3.2 of the XAdES 1.4.1 specification. - */ - List certChain = signatureConfig.getSigningCertificateChain(); - int chainSize = certChain.size(); - if (chainSize > 1) { - for (X509Certificate cert : certChain.subList(1, chainSize)) { - CertIDType certId = certIdList.addNewCert(); - XAdESSignatureFacet.setCertID(certId, signatureConfig, false, cert); - } - } - - // XAdES-C: complete revocation refs - CompleteRevocationRefsType completeRevocationRefs = - unsignedSigProps.addNewCompleteRevocationRefs(); - RevocationData revocationData = signatureConfig.getRevocationDataService() - .getRevocationData(certChain); - if (revocationData.hasCRLs()) { - CRLRefsType crlRefs = completeRevocationRefs.addNewCRLRefs(); - completeRevocationRefs.setCRLRefs(crlRefs); - - for (byte[] encodedCrl : revocationData.getCRLs()) { - CRLRefType crlRef = crlRefs.addNewCRLRef(); - X509CRL crl; - try { - crl = (X509CRL) this.certificateFactory - .generateCRL(new ByteArrayInputStream(encodedCrl)); - } catch (CRLException e) { - throw new RuntimeException("CRL parse error: " - + e.getMessage(), e); - } - - CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier(); - String issuerName = crl.getIssuerDN().getName().replace(",", ", "); - crlIdentifier.setIssuer(issuerName); - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); - cal.setTime(crl.getThisUpdate()); - crlIdentifier.setIssueTime(cal); - crlIdentifier.setNumber(getCrlNumber(crl)); - - DigestAlgAndValueType digestAlgAndValue = crlRef.addNewDigestAlgAndValue(); - XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, encodedCrl, signatureConfig.getDigestAlgo()); - } - } - if (revocationData.hasOCSPs()) { - OCSPRefsType ocspRefs = completeRevocationRefs.addNewOCSPRefs(); - for (byte[] ocsp : revocationData.getOCSPs()) { - try { - OCSPRefType ocspRef = ocspRefs.addNewOCSPRef(); - - DigestAlgAndValueType digestAlgAndValue = ocspRef.addNewDigestAlgAndValue(); - XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, ocsp, signatureConfig.getDigestAlgo()); - - OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier(); - - OCSPResp ocspResp = new OCSPResp(ocsp); - - BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject(); - - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); - cal.setTime(basicOcspResp.getProducedAt()); - ocspIdentifier.setProducedAt(cal); - - ResponderIDType responderId = ocspIdentifier.addNewResponderID(); - - RespID respId = basicOcspResp.getResponderId(); - ResponderID ocspResponderId = respId.toASN1Primitive(); - DERTaggedObject derTaggedObject = (DERTaggedObject)ocspResponderId.toASN1Primitive(); - if (2 == derTaggedObject.getTagNo()) { - ASN1OctetString keyHashOctetString = (ASN1OctetString)derTaggedObject.getObject(); - byte key[] = keyHashOctetString.getOctets(); - responderId.setByKey(key); - } else { - X500Name name = X500Name.getInstance(derTaggedObject.getObject()); - String nameStr = name.toString(); - responderId.setByName(nameStr); - } - } catch (Exception e) { - throw new RuntimeException("OCSP decoding error: " + e.getMessage(), e); - } - } - } - - // marshal XAdES-C - - // XAdES-X Type 1 timestamp - List timeStampNodesXadesX1 = new ArrayList(); - timeStampNodesXadesX1.add(nlSigVal.item(0)); - timeStampNodesXadesX1.add(signatureTimeStamp.getDomNode()); - timeStampNodesXadesX1.add(completeCertificateRefs.getDomNode()); - timeStampNodesXadesX1.add(completeRevocationRefs.getDomNode()); - - RevocationData tsaRevocationDataXadesX1 = new RevocationData(); - LOG.log(POILogger.DEBUG, "creating XAdES-X time-stamp"); - XAdESTimeStampType timeStampXadesX1 = createXAdESTimeStamp - (timeStampNodesXadesX1, tsaRevocationDataXadesX1); - if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) { - ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1); - insertXChild(unsignedSigProps, timeStampXadesX1ValidationData); - } - - // marshal XAdES-X - unsignedSigProps.addNewSigAndRefsTimeStamp().set(timeStampXadesX1); - - // XAdES-X-L - CertificateValuesType certificateValues = unsignedSigProps.addNewCertificateValues(); - for (X509Certificate certificate : certChain) { - EncapsulatedPKIDataType encapsulatedPKIDataType = certificateValues.addNewEncapsulatedX509Certificate(); - try { - encapsulatedPKIDataType.setByteArrayValue(certificate.getEncoded()); - } catch (CertificateEncodingException e) { - throw new RuntimeException("certificate encoding error: " + e.getMessage(), e); - } - } - - RevocationValuesType revocationValues = unsignedSigProps.addNewRevocationValues(); - createRevocationValues(revocationValues, revocationData); - - // marshal XAdES-X-L - Node n = document.importNode(qualProps.getDomNode(), true); - qualNl.item(0).getParentNode().replaceChild(n, qualNl.item(0)); - } - - public static byte[] getC14nValue(List nodeList, String c14nAlgoId) { - ByteArrayOutputStream c14nValue = new ByteArrayOutputStream(); - try { - for (Node node : nodeList) { - /* - * Re-initialize the c14n else the namespaces will get cached - * and will be missing from the c14n resulting nodes. - */ - Canonicalizer c14n = Canonicalizer.getInstance(c14nAlgoId); - c14nValue.write(c14n.canonicalizeSubtree(node)); - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException("c14n error: " + e.getMessage(), e); - } - return c14nValue.toByteArray(); - } - - private BigInteger getCrlNumber(X509CRL crl) { - byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId()); - if (null == crlNumberExtensionValue) { - return null; - } - - try { - ASN1InputStream asn1IS1 = null, asn1IS2 = null; - try { - asn1IS1 = new ASN1InputStream(crlNumberExtensionValue); - ASN1OctetString octetString = (ASN1OctetString)asn1IS1.readObject(); - byte[] octets = octetString.getOctets(); - asn1IS2 = new ASN1InputStream(octets); - ASN1Integer integer = (ASN1Integer)asn1IS2.readObject(); - return integer.getPositiveValue(); - } finally { - IOUtils.closeQuietly(asn1IS2); - IOUtils.closeQuietly(asn1IS1); - } - } catch (IOException e) { - throw new RuntimeException("I/O error: " + e.getMessage(), e); - } - } - - private XAdESTimeStampType createXAdESTimeStamp( - List nodeList, - RevocationData revocationData) { - byte[] c14nSignatureValueElement = getC14nValue(nodeList, signatureConfig.getXadesCanonicalizationMethod()); - - return createXAdESTimeStamp(c14nSignatureValueElement, revocationData); - } - - private XAdESTimeStampType createXAdESTimeStamp(byte[] data, RevocationData revocationData) { - // create the time-stamp - byte[] timeStampToken; - try { - timeStampToken = signatureConfig.getTspService().timeStamp(data, revocationData); - } catch (Exception e) { - throw new RuntimeException("error while creating a time-stamp: " - + e.getMessage(), e); - } - - // create a XAdES time-stamp container - XAdESTimeStampType xadesTimeStamp = XAdESTimeStampType.Factory.newInstance(); - xadesTimeStamp.setId("time-stamp-" + UUID.randomUUID().toString()); - CanonicalizationMethodType c14nMethod = xadesTimeStamp.addNewCanonicalizationMethod(); - c14nMethod.setAlgorithm(signatureConfig.getXadesCanonicalizationMethod()); - - // embed the time-stamp - EncapsulatedPKIDataType encapsulatedTimeStamp = xadesTimeStamp.addNewEncapsulatedTimeStamp(); - encapsulatedTimeStamp.setByteArrayValue(timeStampToken); - encapsulatedTimeStamp.setId("time-stamp-token-" + UUID.randomUUID().toString()); - - return xadesTimeStamp; - } - - private ValidationDataType createValidationData( - RevocationData revocationData) { - ValidationDataType validationData = ValidationDataType.Factory.newInstance(); - RevocationValuesType revocationValues = validationData.addNewRevocationValues(); - createRevocationValues(revocationValues, revocationData); - return validationData; - } - - private void createRevocationValues( - RevocationValuesType revocationValues, RevocationData revocationData) { - if (revocationData.hasCRLs()) { - CRLValuesType crlValues = revocationValues.addNewCRLValues(); - for (byte[] crl : revocationData.getCRLs()) { - EncapsulatedPKIDataType encapsulatedCrlValue = crlValues.addNewEncapsulatedCRLValue(); - encapsulatedCrlValue.setByteArrayValue(crl); - } - } - if (revocationData.hasOCSPs()) { - OCSPValuesType ocspValues = revocationValues.addNewOCSPValues(); - for (byte[] ocsp : revocationData.getOCSPs()) { - EncapsulatedPKIDataType encapsulatedOcspValue = ocspValues.addNewEncapsulatedOCSPValue(); - encapsulatedOcspValue.setByteArrayValue(ocsp); - } - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; +import static org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet.insertXChild; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRLException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; +import java.util.UUID; + +import javax.xml.crypto.MarshalException; + +import org.apache.poi.poifs.crypt.dsig.services.RevocationData; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.xml.security.c14n.Canonicalizer; +import org.apache.xmlbeans.XmlException; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.ocsp.ResponderID; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.cert.ocsp.BasicOCSPResp; +import org.bouncycastle.cert.ocsp.OCSPResp; +import org.bouncycastle.cert.ocsp.RespID; +import org.etsi.uri.x01903.v13.*; +import org.etsi.uri.x01903.v14.ValidationDataType; +import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * XAdES-X-L v1.4.1 signature facet. This signature facet implementation will + * upgrade a given XAdES-BES/EPES signature to XAdES-X-L. + * + * We don't inherit from XAdESSignatureFacet as we also want to be able to use + * this facet out of the context of a signature creation. This signature facet + * assumes that the signature is already XAdES-BES/EPES compliant. + * + * This implementation has been tested against an implementation that + * participated multiple ETSI XAdES plugtests. + * + * @author Frank Cornelis + * @see XAdESSignatureFacet + */ +public class XAdESXLSignatureFacet extends SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class); + + private final CertificateFactory certificateFactory; + + public XAdESXLSignatureFacet() { + try { + this.certificateFactory = CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + throw new RuntimeException("X509 JCA error: " + e.getMessage(), e); + } + } + + @Override + public void postSign(Document document) throws MarshalException { + LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase"); + + QualifyingPropertiesDocument qualDoc = null; + QualifyingPropertiesType qualProps = null; + + // check for XAdES-BES + NodeList qualNl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties"); + if (qualNl.getLength() == 1) { + try { + qualDoc = QualifyingPropertiesDocument.Factory.parse(qualNl.item(0), DEFAULT_XML_OPTIONS); + } catch (XmlException e) { + throw new MarshalException(e); + } + qualProps = qualDoc.getQualifyingProperties(); + } else { + throw new MarshalException("no XAdES-BES extension present"); + } + + // create basic XML container structure + UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); + if (unsignedProps == null) { + unsignedProps = qualProps.addNewUnsignedProperties(); + } + UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties(); + if (unsignedSigProps == null) { + unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties(); + } + + + // create the XAdES-T time-stamp + NodeList nlSigVal = document.getElementsByTagNameNS(XML_DIGSIG_NS, "SignatureValue"); + if (nlSigVal.getLength() != 1) { + throw new IllegalArgumentException("SignatureValue is not set."); + } + + RevocationData tsaRevocationDataXadesT = new RevocationData(); + LOG.log(POILogger.DEBUG, "creating XAdES-T time-stamp"); + XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp + (Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT); + + // marshal the XAdES-T extension + unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp); + + // xadesv141::TimeStampValidationData + if (tsaRevocationDataXadesT.hasRevocationDataEntries()) { + ValidationDataType validationData = createValidationData(tsaRevocationDataXadesT); + insertXChild(unsignedSigProps, validationData); + } + + if (signatureConfig.getRevocationDataService() == null) { + /* + * Without revocation data service we cannot construct the XAdES-C + * extension. + */ + return; + } + + // XAdES-C: complete certificate refs + CompleteCertificateRefsType completeCertificateRefs = + unsignedSigProps.addNewCompleteCertificateRefs(); + + CertIDListType certIdList = completeCertificateRefs.addNewCertRefs(); + /* + * We skip the signing certificate itself according to section + * 4.4.3.2 of the XAdES 1.4.1 specification. + */ + List certChain = signatureConfig.getSigningCertificateChain(); + int chainSize = certChain.size(); + if (chainSize > 1) { + for (X509Certificate cert : certChain.subList(1, chainSize)) { + CertIDType certId = certIdList.addNewCert(); + XAdESSignatureFacet.setCertID(certId, signatureConfig, false, cert); + } + } + + // XAdES-C: complete revocation refs + CompleteRevocationRefsType completeRevocationRefs = + unsignedSigProps.addNewCompleteRevocationRefs(); + RevocationData revocationData = signatureConfig.getRevocationDataService() + .getRevocationData(certChain); + if (revocationData.hasCRLs()) { + CRLRefsType crlRefs = completeRevocationRefs.addNewCRLRefs(); + completeRevocationRefs.setCRLRefs(crlRefs); + + for (byte[] encodedCrl : revocationData.getCRLs()) { + CRLRefType crlRef = crlRefs.addNewCRLRef(); + X509CRL crl; + try { + crl = (X509CRL) this.certificateFactory + .generateCRL(new ByteArrayInputStream(encodedCrl)); + } catch (CRLException e) { + throw new RuntimeException("CRL parse error: " + + e.getMessage(), e); + } + + CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier(); + String issuerName = crl.getIssuerDN().getName().replace(",", ", "); + crlIdentifier.setIssuer(issuerName); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); + cal.setTime(crl.getThisUpdate()); + crlIdentifier.setIssueTime(cal); + crlIdentifier.setNumber(getCrlNumber(crl)); + + DigestAlgAndValueType digestAlgAndValue = crlRef.addNewDigestAlgAndValue(); + XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, encodedCrl, signatureConfig.getDigestAlgo()); + } + } + if (revocationData.hasOCSPs()) { + OCSPRefsType ocspRefs = completeRevocationRefs.addNewOCSPRefs(); + for (byte[] ocsp : revocationData.getOCSPs()) { + try { + OCSPRefType ocspRef = ocspRefs.addNewOCSPRef(); + + DigestAlgAndValueType digestAlgAndValue = ocspRef.addNewDigestAlgAndValue(); + XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, ocsp, signatureConfig.getDigestAlgo()); + + OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier(); + + OCSPResp ocspResp = new OCSPResp(ocsp); + + BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject(); + + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); + cal.setTime(basicOcspResp.getProducedAt()); + ocspIdentifier.setProducedAt(cal); + + ResponderIDType responderId = ocspIdentifier.addNewResponderID(); + + RespID respId = basicOcspResp.getResponderId(); + ResponderID ocspResponderId = respId.toASN1Primitive(); + DERTaggedObject derTaggedObject = (DERTaggedObject)ocspResponderId.toASN1Primitive(); + if (2 == derTaggedObject.getTagNo()) { + ASN1OctetString keyHashOctetString = (ASN1OctetString)derTaggedObject.getObject(); + byte key[] = keyHashOctetString.getOctets(); + responderId.setByKey(key); + } else { + X500Name name = X500Name.getInstance(derTaggedObject.getObject()); + String nameStr = name.toString(); + responderId.setByName(nameStr); + } + } catch (Exception e) { + throw new RuntimeException("OCSP decoding error: " + e.getMessage(), e); + } + } + } + + // marshal XAdES-C + + // XAdES-X Type 1 timestamp + List timeStampNodesXadesX1 = new ArrayList(); + timeStampNodesXadesX1.add(nlSigVal.item(0)); + timeStampNodesXadesX1.add(signatureTimeStamp.getDomNode()); + timeStampNodesXadesX1.add(completeCertificateRefs.getDomNode()); + timeStampNodesXadesX1.add(completeRevocationRefs.getDomNode()); + + RevocationData tsaRevocationDataXadesX1 = new RevocationData(); + LOG.log(POILogger.DEBUG, "creating XAdES-X time-stamp"); + XAdESTimeStampType timeStampXadesX1 = createXAdESTimeStamp + (timeStampNodesXadesX1, tsaRevocationDataXadesX1); + if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) { + ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1); + insertXChild(unsignedSigProps, timeStampXadesX1ValidationData); + } + + // marshal XAdES-X + unsignedSigProps.addNewSigAndRefsTimeStamp().set(timeStampXadesX1); + + // XAdES-X-L + CertificateValuesType certificateValues = unsignedSigProps.addNewCertificateValues(); + for (X509Certificate certificate : certChain) { + EncapsulatedPKIDataType encapsulatedPKIDataType = certificateValues.addNewEncapsulatedX509Certificate(); + try { + encapsulatedPKIDataType.setByteArrayValue(certificate.getEncoded()); + } catch (CertificateEncodingException e) { + throw new RuntimeException("certificate encoding error: " + e.getMessage(), e); + } + } + + RevocationValuesType revocationValues = unsignedSigProps.addNewRevocationValues(); + createRevocationValues(revocationValues, revocationData); + + // marshal XAdES-X-L + Node n = document.importNode(qualProps.getDomNode(), true); + qualNl.item(0).getParentNode().replaceChild(n, qualNl.item(0)); + } + + public static byte[] getC14nValue(List nodeList, String c14nAlgoId) { + ByteArrayOutputStream c14nValue = new ByteArrayOutputStream(); + try { + for (Node node : nodeList) { + /* + * Re-initialize the c14n else the namespaces will get cached + * and will be missing from the c14n resulting nodes. + */ + Canonicalizer c14n = Canonicalizer.getInstance(c14nAlgoId); + c14nValue.write(c14n.canonicalizeSubtree(node)); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException("c14n error: " + e.getMessage(), e); + } + return c14nValue.toByteArray(); + } + + private BigInteger getCrlNumber(X509CRL crl) { + byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId()); + if (null == crlNumberExtensionValue) { + return null; + } + + try { + ASN1InputStream asn1IS1 = null, asn1IS2 = null; + try { + asn1IS1 = new ASN1InputStream(crlNumberExtensionValue); + ASN1OctetString octetString = (ASN1OctetString)asn1IS1.readObject(); + byte[] octets = octetString.getOctets(); + asn1IS2 = new ASN1InputStream(octets); + ASN1Integer integer = (ASN1Integer)asn1IS2.readObject(); + return integer.getPositiveValue(); + } finally { + IOUtils.closeQuietly(asn1IS2); + IOUtils.closeQuietly(asn1IS1); + } + } catch (IOException e) { + throw new RuntimeException("I/O error: " + e.getMessage(), e); + } + } + + private XAdESTimeStampType createXAdESTimeStamp( + List nodeList, + RevocationData revocationData) { + byte[] c14nSignatureValueElement = getC14nValue(nodeList, signatureConfig.getXadesCanonicalizationMethod()); + + return createXAdESTimeStamp(c14nSignatureValueElement, revocationData); + } + + private XAdESTimeStampType createXAdESTimeStamp(byte[] data, RevocationData revocationData) { + // create the time-stamp + byte[] timeStampToken; + try { + timeStampToken = signatureConfig.getTspService().timeStamp(data, revocationData); + } catch (Exception e) { + throw new RuntimeException("error while creating a time-stamp: " + + e.getMessage(), e); + } + + // create a XAdES time-stamp container + XAdESTimeStampType xadesTimeStamp = XAdESTimeStampType.Factory.newInstance(); + xadesTimeStamp.setId("time-stamp-" + UUID.randomUUID().toString()); + CanonicalizationMethodType c14nMethod = xadesTimeStamp.addNewCanonicalizationMethod(); + c14nMethod.setAlgorithm(signatureConfig.getXadesCanonicalizationMethod()); + + // embed the time-stamp + EncapsulatedPKIDataType encapsulatedTimeStamp = xadesTimeStamp.addNewEncapsulatedTimeStamp(); + encapsulatedTimeStamp.setByteArrayValue(timeStampToken); + encapsulatedTimeStamp.setId("time-stamp-token-" + UUID.randomUUID().toString()); + + return xadesTimeStamp; + } + + private ValidationDataType createValidationData( + RevocationData revocationData) { + ValidationDataType validationData = ValidationDataType.Factory.newInstance(); + RevocationValuesType revocationValues = validationData.addNewRevocationValues(); + createRevocationValues(revocationValues, revocationData); + return validationData; + } + + private void createRevocationValues( + RevocationValuesType revocationValues, RevocationData revocationData) { + if (revocationData.hasCRLs()) { + CRLValuesType crlValues = revocationValues.addNewCRLValues(); + for (byte[] crl : revocationData.getCRLs()) { + EncapsulatedPKIDataType encapsulatedCrlValue = crlValues.addNewEncapsulatedCRLValue(); + encapsulatedCrlValue.setByteArrayValue(crl); + } + } + if (revocationData.hasOCSPs()) { + OCSPValuesType ocspValues = revocationValues.addNewOCSPValues(); + for (byte[] ocsp : revocationData.getOCSPs()) { + EncapsulatedPKIDataType encapsulatedOcspValue = ocspValues.addNewEncapsulatedOCSPValue(); + encapsulatedOcspValue.setByteArrayValue(ocsp); + } + } + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java index 495d843b4c..55518772fa 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java @@ -1,248 +1,248 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.services; - -import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.InvalidAlgorithmParameterException; -import java.security.Provider; -import java.security.Security; -import java.security.spec.AlgorithmParameterSpec; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -import javax.xml.crypto.Data; -import javax.xml.crypto.MarshalException; -import javax.xml.crypto.OctetStreamData; -import javax.xml.crypto.XMLCryptoContext; -import javax.xml.crypto.XMLStructure; -import javax.xml.crypto.dom.DOMStructure; -import javax.xml.crypto.dsig.TransformException; -import javax.xml.crypto.dsig.TransformService; -import javax.xml.crypto.dsig.spec.TransformParameterSpec; - -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.XmlSort; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTRelationshipReference; -import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.RelationshipReferenceDocument; -import org.openxmlformats.schemas.xpackage.x2006.relationships.CTRelationship; -import org.openxmlformats.schemas.xpackage.x2006.relationships.CTRelationships; -import org.openxmlformats.schemas.xpackage.x2006.relationships.RelationshipsDocument; -import org.openxmlformats.schemas.xpackage.x2006.relationships.STTargetMode; -import org.w3.x2000.x09.xmldsig.TransformDocument; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * JSR105 implementation of the RelationshipTransform transformation. - * - *

- * Specs: http://openiso.org/Ecma/376/Part2/12.2.4#26 - *

- */ -public class RelationshipTransformService extends TransformService { - - public static final String TRANSFORM_URI = "http://schemas.openxmlformats.org/package/2006/RelationshipTransform"; - - private final List sourceIds; - - private static final POILogger LOG = POILogFactory.getLogger(RelationshipTransformService.class); - - /** - * Relationship Transform parameter specification class. - */ - public static class RelationshipTransformParameterSpec implements TransformParameterSpec { - List sourceIds = new ArrayList(); - public void addRelationshipReference(String relationshipId) { - sourceIds.add(relationshipId); - } - public boolean hasSourceIds() { - return !sourceIds.isEmpty(); - } - } - - - public RelationshipTransformService() { - super(); - LOG.log(POILogger.DEBUG, "constructor"); - this.sourceIds = new ArrayList(); - } - - /** - * Register the provider for this TransformService - * - * @see javax.xml.crypto.dsig.TransformService - */ - public static synchronized void registerDsigProvider() { - // the xml signature classes will try to find a special TransformerService, - // which is ofcourse unknown to JCE before ... - final String dsigProvider = "POIXmlDsigProvider"; - if (Security.getProperty(dsigProvider) == null) { - Provider p = new Provider(dsigProvider, 1.0, dsigProvider){ - static final long serialVersionUID = 1L; - }; - p.put("TransformService." + TRANSFORM_URI, RelationshipTransformService.class.getName()); - p.put("TransformService." + TRANSFORM_URI + " MechanismType", "DOM"); - Security.addProvider(p); - } - } - - - @Override - public void init(TransformParameterSpec params) throws InvalidAlgorithmParameterException { - LOG.log(POILogger.DEBUG, "init(params)"); - if (!(params instanceof RelationshipTransformParameterSpec)) { - throw new InvalidAlgorithmParameterException(); - } - RelationshipTransformParameterSpec relParams = (RelationshipTransformParameterSpec) params; - for (String sourceId : relParams.sourceIds) { - this.sourceIds.add(sourceId); - } - } - - @Override - public void init(XMLStructure parent, XMLCryptoContext context) throws InvalidAlgorithmParameterException { - LOG.log(POILogger.DEBUG, "init(parent,context)"); - LOG.log(POILogger.DEBUG, "parent java type: " + parent.getClass().getName()); - DOMStructure domParent = (DOMStructure) parent; - Node parentNode = domParent.getNode(); - - try { - TransformDocument transDoc = TransformDocument.Factory.parse(parentNode, DEFAULT_XML_OPTIONS); - XmlObject xoList[] = transDoc.getTransform().selectChildren(RelationshipReferenceDocument.type.getDocumentElementName()); - if (xoList.length == 0) { - LOG.log(POILogger.WARN, "no RelationshipReference/@SourceId parameters present"); - } - for (XmlObject xo : xoList) { - String sourceId = ((CTRelationshipReference)xo).getSourceId(); - LOG.log(POILogger.DEBUG, "sourceId: ", sourceId); - this.sourceIds.add(sourceId); - } - } catch (XmlException e) { - throw new InvalidAlgorithmParameterException(e); - } - } - - @Override - public void marshalParams(XMLStructure parent, XMLCryptoContext context) throws MarshalException { - LOG.log(POILogger.DEBUG, "marshallParams(parent,context)"); - DOMStructure domParent = (DOMStructure) parent; - Element parentNode = (Element)domParent.getNode(); - // parentNode.setAttributeNS(XML_NS, "xmlns:mdssi", XML_DIGSIG_NS); - Document doc = parentNode.getOwnerDocument(); - - for (String sourceId : this.sourceIds) { - RelationshipReferenceDocument relRef = RelationshipReferenceDocument.Factory.newInstance(); - relRef.addNewRelationshipReference().setSourceId(sourceId); - Node n = relRef.getRelationshipReference().getDomNode(); - n = doc.importNode(n, true); - parentNode.appendChild(n); - } - } - - public AlgorithmParameterSpec getParameterSpec() { - LOG.log(POILogger.DEBUG, "getParameterSpec"); - return null; - } - - public Data transform(Data data, XMLCryptoContext context) throws TransformException { - LOG.log(POILogger.DEBUG, "transform(data,context)"); - LOG.log(POILogger.DEBUG, "data java type: " + data.getClass().getName()); - OctetStreamData octetStreamData = (OctetStreamData) data; - LOG.log(POILogger.DEBUG, "URI: " + octetStreamData.getURI()); - InputStream octetStream = octetStreamData.getOctetStream(); - - RelationshipsDocument relDoc; - try { - relDoc = RelationshipsDocument.Factory.parse(octetStream, DEFAULT_XML_OPTIONS); - } catch (Exception e) { - throw new TransformException(e.getMessage(), e); - } - LOG.log(POILogger.DEBUG, "relationships document", relDoc); - - CTRelationships rels = relDoc.getRelationships(); - List relList = rels.getRelationshipList(); - Iterator relIter = rels.getRelationshipList().iterator(); - while (relIter.hasNext()) { - CTRelationship rel = relIter.next(); - /* - * See: ISO/IEC 29500-2:2008(E) - 13.2.4.24 Relationships Transform - * Algorithm. - */ - if (!this.sourceIds.contains(rel.getId())) { - LOG.log(POILogger.DEBUG, "removing element: " + rel.getId()); - relIter.remove(); - } else { - if (!rel.isSetTargetMode()) { - rel.setTargetMode(STTargetMode.INTERNAL); - } - } - } - - // TODO: remove non element nodes ??? - LOG.log(POILogger.DEBUG, "# Relationship elements", relList.size()); - - XmlSort.sort(rels, new Comparator(){ - public int compare(XmlCursor c1, XmlCursor c2) { - String id1 = ((CTRelationship)c1.getObject()).getId(); - String id2 = ((CTRelationship)c2.getObject()).getId(); - return id1.compareTo(id2); - } - }); - - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - XmlOptions xo = new XmlOptions(); - xo.setSaveNoXmlDecl(); - relDoc.save(bos, xo); - return new OctetStreamData(new ByteArrayInputStream(bos.toByteArray())); - } catch (IOException e) { - throw new TransformException(e.getMessage(), e); - } - } - - public Data transform(Data data, XMLCryptoContext context, OutputStream os) throws TransformException { - LOG.log(POILogger.DEBUG, "transform(data,context,os)"); - return null; - } - - public boolean isFeatureSupported(String feature) { - LOG.log(POILogger.DEBUG, "isFeatureSupported(feature)"); - return false; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.services; + +import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.InvalidAlgorithmParameterException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import javax.xml.crypto.Data; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.OctetStreamData; +import javax.xml.crypto.XMLCryptoContext; +import javax.xml.crypto.XMLStructure; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.TransformException; +import javax.xml.crypto.dsig.TransformService; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.XmlSort; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlOptions; +import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTRelationshipReference; +import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.RelationshipReferenceDocument; +import org.openxmlformats.schemas.xpackage.x2006.relationships.CTRelationship; +import org.openxmlformats.schemas.xpackage.x2006.relationships.CTRelationships; +import org.openxmlformats.schemas.xpackage.x2006.relationships.RelationshipsDocument; +import org.openxmlformats.schemas.xpackage.x2006.relationships.STTargetMode; +import org.w3.x2000.x09.xmldsig.TransformDocument; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * JSR105 implementation of the RelationshipTransform transformation. + * + *

+ * Specs: http://openiso.org/Ecma/376/Part2/12.2.4#26 + *

+ */ +public class RelationshipTransformService extends TransformService { + + public static final String TRANSFORM_URI = "http://schemas.openxmlformats.org/package/2006/RelationshipTransform"; + + private final List sourceIds; + + private static final POILogger LOG = POILogFactory.getLogger(RelationshipTransformService.class); + + /** + * Relationship Transform parameter specification class. + */ + public static class RelationshipTransformParameterSpec implements TransformParameterSpec { + List sourceIds = new ArrayList(); + public void addRelationshipReference(String relationshipId) { + sourceIds.add(relationshipId); + } + public boolean hasSourceIds() { + return !sourceIds.isEmpty(); + } + } + + + public RelationshipTransformService() { + super(); + LOG.log(POILogger.DEBUG, "constructor"); + this.sourceIds = new ArrayList(); + } + + /** + * Register the provider for this TransformService + * + * @see javax.xml.crypto.dsig.TransformService + */ + public static synchronized void registerDsigProvider() { + // the xml signature classes will try to find a special TransformerService, + // which is ofcourse unknown to JCE before ... + final String dsigProvider = "POIXmlDsigProvider"; + if (Security.getProperty(dsigProvider) == null) { + Provider p = new Provider(dsigProvider, 1.0, dsigProvider){ + static final long serialVersionUID = 1L; + }; + p.put("TransformService." + TRANSFORM_URI, RelationshipTransformService.class.getName()); + p.put("TransformService." + TRANSFORM_URI + " MechanismType", "DOM"); + Security.addProvider(p); + } + } + + + @Override + public void init(TransformParameterSpec params) throws InvalidAlgorithmParameterException { + LOG.log(POILogger.DEBUG, "init(params)"); + if (!(params instanceof RelationshipTransformParameterSpec)) { + throw new InvalidAlgorithmParameterException(); + } + RelationshipTransformParameterSpec relParams = (RelationshipTransformParameterSpec) params; + for (String sourceId : relParams.sourceIds) { + this.sourceIds.add(sourceId); + } + } + + @Override + public void init(XMLStructure parent, XMLCryptoContext context) throws InvalidAlgorithmParameterException { + LOG.log(POILogger.DEBUG, "init(parent,context)"); + LOG.log(POILogger.DEBUG, "parent java type: " + parent.getClass().getName()); + DOMStructure domParent = (DOMStructure) parent; + Node parentNode = domParent.getNode(); + + try { + TransformDocument transDoc = TransformDocument.Factory.parse(parentNode, DEFAULT_XML_OPTIONS); + XmlObject xoList[] = transDoc.getTransform().selectChildren(RelationshipReferenceDocument.type.getDocumentElementName()); + if (xoList.length == 0) { + LOG.log(POILogger.WARN, "no RelationshipReference/@SourceId parameters present"); + } + for (XmlObject xo : xoList) { + String sourceId = ((CTRelationshipReference)xo).getSourceId(); + LOG.log(POILogger.DEBUG, "sourceId: ", sourceId); + this.sourceIds.add(sourceId); + } + } catch (XmlException e) { + throw new InvalidAlgorithmParameterException(e); + } + } + + @Override + public void marshalParams(XMLStructure parent, XMLCryptoContext context) throws MarshalException { + LOG.log(POILogger.DEBUG, "marshallParams(parent,context)"); + DOMStructure domParent = (DOMStructure) parent; + Element parentNode = (Element)domParent.getNode(); + // parentNode.setAttributeNS(XML_NS, "xmlns:mdssi", XML_DIGSIG_NS); + Document doc = parentNode.getOwnerDocument(); + + for (String sourceId : this.sourceIds) { + RelationshipReferenceDocument relRef = RelationshipReferenceDocument.Factory.newInstance(); + relRef.addNewRelationshipReference().setSourceId(sourceId); + Node n = relRef.getRelationshipReference().getDomNode(); + n = doc.importNode(n, true); + parentNode.appendChild(n); + } + } + + public AlgorithmParameterSpec getParameterSpec() { + LOG.log(POILogger.DEBUG, "getParameterSpec"); + return null; + } + + public Data transform(Data data, XMLCryptoContext context) throws TransformException { + LOG.log(POILogger.DEBUG, "transform(data,context)"); + LOG.log(POILogger.DEBUG, "data java type: " + data.getClass().getName()); + OctetStreamData octetStreamData = (OctetStreamData) data; + LOG.log(POILogger.DEBUG, "URI: " + octetStreamData.getURI()); + InputStream octetStream = octetStreamData.getOctetStream(); + + RelationshipsDocument relDoc; + try { + relDoc = RelationshipsDocument.Factory.parse(octetStream, DEFAULT_XML_OPTIONS); + } catch (Exception e) { + throw new TransformException(e.getMessage(), e); + } + LOG.log(POILogger.DEBUG, "relationships document", relDoc); + + CTRelationships rels = relDoc.getRelationships(); + List relList = rels.getRelationshipList(); + Iterator relIter = rels.getRelationshipList().iterator(); + while (relIter.hasNext()) { + CTRelationship rel = relIter.next(); + /* + * See: ISO/IEC 29500-2:2008(E) - 13.2.4.24 Relationships Transform + * Algorithm. + */ + if (!this.sourceIds.contains(rel.getId())) { + LOG.log(POILogger.DEBUG, "removing element: " + rel.getId()); + relIter.remove(); + } else { + if (!rel.isSetTargetMode()) { + rel.setTargetMode(STTargetMode.INTERNAL); + } + } + } + + // TODO: remove non element nodes ??? + LOG.log(POILogger.DEBUG, "# Relationship elements", relList.size()); + + XmlSort.sort(rels, new Comparator(){ + public int compare(XmlCursor c1, XmlCursor c2) { + String id1 = ((CTRelationship)c1.getObject()).getId(); + String id2 = ((CTRelationship)c2.getObject()).getId(); + return id1.compareTo(id2); + } + }); + + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + XmlOptions xo = new XmlOptions(); + xo.setSaveNoXmlDecl(); + relDoc.save(bos, xo); + return new OctetStreamData(new ByteArrayInputStream(bos.toByteArray())); + } catch (IOException e) { + throw new TransformException(e.getMessage(), e); + } + } + + public Data transform(Data data, XMLCryptoContext context, OutputStream os) throws TransformException { + LOG.log(POILogger.DEBUG, "transform(data,context,os)"); + return null; + } + + public boolean isFeatureSupported(String feature) { + LOG.log(POILogger.DEBUG, "isFeatureSupported(feature)"); + return false; + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java index 22e667bf17..66a78e396d 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java @@ -1,132 +1,132 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.services; - -import java.security.cert.CRLException; -import java.security.cert.X509CRL; -import java.util.ArrayList; -import java.util.List; - -/** - * Container class for PKI revocation data. - * - * @author Frank Cornelis - * - */ -public class RevocationData { - - private final List crls; - - private final List ocsps; - - /** - * Default constructor. - */ - public RevocationData() { - this.crls = new ArrayList(); - this.ocsps = new ArrayList(); - } - - /** - * Adds a CRL to this revocation data set. - * - * @param encodedCrl - */ - public void addCRL(byte[] encodedCrl) { - this.crls.add(encodedCrl); - } - - /** - * Adds a CRL to this revocation data set. - * - * @param crl - */ - public void addCRL(X509CRL crl) { - byte[] encodedCrl; - try { - encodedCrl = crl.getEncoded(); - } catch (CRLException e) { - throw new IllegalArgumentException("CRL coding error: " - + e.getMessage(), e); - } - addCRL(encodedCrl); - } - - /** - * Adds an OCSP response to this revocation data set. - * - * @param encodedOcsp - */ - public void addOCSP(byte[] encodedOcsp) { - this.ocsps.add(encodedOcsp); - } - - /** - * Gives back a list of all CRLs. - * - * @return a list of all CRLs - */ - public List getCRLs() { - return this.crls; - } - - /** - * Gives back a list of all OCSP responses. - * - * @return a list of all OCSP response - */ - public List getOCSPs() { - return this.ocsps; - } - - /** - * Returns true if this revocation data set holds OCSP - * responses. - * - * @return true if this revocation data set holds OCSP - * responses. - */ - public boolean hasOCSPs() { - return false == this.ocsps.isEmpty(); - } - - /** - * Returns true if this revocation data set holds CRLs. - * - * @return true if this revocation data set holds CRLs. - */ - public boolean hasCRLs() { - return false == this.crls.isEmpty(); - } - - /** - * Returns true if this revocation data is not empty. - * - * @return true if this revocation data is not empty. - */ - public boolean hasRevocationDataEntries() { - return hasOCSPs() || hasCRLs(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.services; + +import java.security.cert.CRLException; +import java.security.cert.X509CRL; +import java.util.ArrayList; +import java.util.List; + +/** + * Container class for PKI revocation data. + * + * @author Frank Cornelis + * + */ +public class RevocationData { + + private final List crls; + + private final List ocsps; + + /** + * Default constructor. + */ + public RevocationData() { + this.crls = new ArrayList(); + this.ocsps = new ArrayList(); + } + + /** + * Adds a CRL to this revocation data set. + * + * @param encodedCrl + */ + public void addCRL(byte[] encodedCrl) { + this.crls.add(encodedCrl); + } + + /** + * Adds a CRL to this revocation data set. + * + * @param crl + */ + public void addCRL(X509CRL crl) { + byte[] encodedCrl; + try { + encodedCrl = crl.getEncoded(); + } catch (CRLException e) { + throw new IllegalArgumentException("CRL coding error: " + + e.getMessage(), e); + } + addCRL(encodedCrl); + } + + /** + * Adds an OCSP response to this revocation data set. + * + * @param encodedOcsp + */ + public void addOCSP(byte[] encodedOcsp) { + this.ocsps.add(encodedOcsp); + } + + /** + * Gives back a list of all CRLs. + * + * @return a list of all CRLs + */ + public List getCRLs() { + return this.crls; + } + + /** + * Gives back a list of all OCSP responses. + * + * @return a list of all OCSP response + */ + public List getOCSPs() { + return this.ocsps; + } + + /** + * Returns true if this revocation data set holds OCSP + * responses. + * + * @return true if this revocation data set holds OCSP + * responses. + */ + public boolean hasOCSPs() { + return false == this.ocsps.isEmpty(); + } + + /** + * Returns true if this revocation data set holds CRLs. + * + * @return true if this revocation data set holds CRLs. + */ + public boolean hasCRLs() { + return false == this.crls.isEmpty(); + } + + /** + * Returns true if this revocation data is not empty. + * + * @return true if this revocation data is not empty. + */ + public boolean hasRevocationDataEntries() { + return hasOCSPs() || hasCRLs(); + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationDataService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationDataService.java index 02bd6a0573..ed5ce29918 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationDataService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationDataService.java @@ -1,47 +1,47 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.services; - -import java.security.cert.X509Certificate; -import java.util.List; - -/** - * Interface for a service that retrieves revocation data about some given - * certificate chain. - * - * @author Frank Cornelis - * - */ -public interface RevocationDataService { - - /** - * Gives back the revocation data corresponding with the given certificate - * chain. - * - * @param certificateChain the certificate chain - * @return the revocation data corresponding with the given certificate chain. - */ - RevocationData getRevocationData(List certificateChain); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.services; + +import java.security.cert.X509Certificate; +import java.util.List; + +/** + * Interface for a service that retrieves revocation data about some given + * certificate chain. + * + * @author Frank Cornelis + * + */ +public interface RevocationDataService { + + /** + * Gives back the revocation data corresponding with the given certificate + * chain. + * + * @param certificateChain the certificate chain + * @return the revocation data corresponding with the given certificate chain. + */ + RevocationData getRevocationData(List certificateChain); +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignaturePolicyService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignaturePolicyService.java index 9716e63532..56fd9ba232 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignaturePolicyService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignaturePolicyService.java @@ -1,65 +1,65 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.services; - -/** - * Interface for the signature policy service. - * - * @author Frank Cornelis - * - */ -public interface SignaturePolicyService { - - /** - * Gives back the signature policy identifier URI. - * - * @return the signature policy identifier URI. - */ - String getSignaturePolicyIdentifier(); - - /** - * Gives back the short description of the signature policy or - * null if a description is not available. - * - * @return the description, or null. - */ - String getSignaturePolicyDescription(); - - /** - * Gives back the download URL where the signature policy document can be - * found. Can be null in case such a download location does not - * exist. - * - * @return the download URL, or null. - */ - String getSignaturePolicyDownloadUrl(); - - /** - * Gives back the signature policy document. - * - * @return the bytes of the signature policy document. - */ - byte[] getSignaturePolicyDocument(); +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.services; + +/** + * Interface for the signature policy service. + * + * @author Frank Cornelis + * + */ +public interface SignaturePolicyService { + + /** + * Gives back the signature policy identifier URI. + * + * @return the signature policy identifier URI. + */ + String getSignaturePolicyIdentifier(); + + /** + * Gives back the short description of the signature policy or + * null if a description is not available. + * + * @return the description, or null. + */ + String getSignaturePolicyDescription(); + + /** + * Gives back the download URL where the signature policy document can be + * found. Can be null in case such a download location does not + * exist. + * + * @return the download URL, or null. + */ + String getSignaturePolicyDownloadUrl(); + + /** + * Gives back the signature policy document. + * + * @return the bytes of the signature policy document. + */ + byte[] getSignaturePolicyDocument(); } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java index cc1c4c4a96..bc3e744559 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java @@ -1,261 +1,261 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.services; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.math.BigInteger; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.URL; -import java.nio.charset.Charset; -import java.security.MessageDigest; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.bind.DatatypeConverter; - -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig; -import org.apache.poi.util.HexDump; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.cmp.PKIFailureInfo; -import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; -import org.bouncycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator; -import org.bouncycastle.cms.SignerId; -import org.bouncycastle.cms.SignerInformationVerifier; -import org.bouncycastle.cms.bc.BcRSASignerInfoVerifierBuilder; -import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; -import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; -import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; -import org.bouncycastle.tsp.TimeStampRequest; -import org.bouncycastle.tsp.TimeStampRequestGenerator; -import org.bouncycastle.tsp.TimeStampResponse; -import org.bouncycastle.tsp.TimeStampToken; - -/** - * A TSP time-stamp service implementation. - * - * @author Frank Cornelis - * - */ -public class TSPTimeStampService implements TimeStampService { - - private static final POILogger LOG = POILogFactory.getLogger(TSPTimeStampService.class); - - private SignatureConfig signatureConfig; - - /** - * Maps the digest algorithm to corresponding OID value. - */ - public ASN1ObjectIdentifier mapDigestAlgoToOID(HashAlgorithm digestAlgo) { - switch (digestAlgo) { - case sha1: return X509ObjectIdentifiers.id_SHA1; - case sha256: return NISTObjectIdentifiers.id_sha256; - case sha384: return NISTObjectIdentifiers.id_sha384; - case sha512: return NISTObjectIdentifiers.id_sha512; - default: - throw new IllegalArgumentException("unsupported digest algo: " + digestAlgo); - } - } - - @SuppressWarnings("unchecked") - public byte[] timeStamp(byte[] data, RevocationData revocationData) - throws Exception { - // digest the message - MessageDigest messageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getTspDigestAlgo()); - byte[] digest = messageDigest.digest(data); - - // generate the TSP request - BigInteger nonce = new BigInteger(128, new SecureRandom()); - TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator(); - requestGenerator.setCertReq(true); - String requestPolicy = signatureConfig.getTspRequestPolicy(); - if (requestPolicy != null) { - requestGenerator.setReqPolicy(new ASN1ObjectIdentifier(requestPolicy)); - } - ASN1ObjectIdentifier digestAlgoOid = mapDigestAlgoToOID(signatureConfig.getTspDigestAlgo()); - TimeStampRequest request = requestGenerator.generate(digestAlgoOid, digest, nonce); - byte[] encodedRequest = request.getEncoded(); - - // create the HTTP POST request - Proxy proxy = Proxy.NO_PROXY; - if (signatureConfig.getProxyUrl() != null) { - URL proxyUrl = new URL(signatureConfig.getProxyUrl()); - String host = proxyUrl.getHost(); - int port = proxyUrl.getPort(); - proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(InetAddress.getByName(host), (port == -1 ? 80 : port))); - } - - HttpURLConnection huc = (HttpURLConnection)new URL(signatureConfig.getTspUrl()).openConnection(proxy); - - if (signatureConfig.getTspUser() != null) { - String userPassword = signatureConfig.getTspUser() + ":" + signatureConfig.getTspPass(); - String encoding = DatatypeConverter.printBase64Binary(userPassword.getBytes(Charset.forName("iso-8859-1"))); - huc.setRequestProperty("Authorization", "Basic " + encoding); - } - - huc.setRequestMethod("POST"); - huc.setConnectTimeout(20000); - huc.setReadTimeout(20000); - huc.setDoOutput(true); // also sets method to POST. - huc.setRequestProperty("User-Agent", signatureConfig.getUserAgent()); - huc.setRequestProperty("Content-Type", signatureConfig.isTspOldProtocol() - ? "application/timestamp-request" - : "application/timestamp-query"); // "; charset=ISO-8859-1"); - - OutputStream hucOut = huc.getOutputStream(); - hucOut.write(encodedRequest); - - // invoke TSP service - huc.connect(); - - int statusCode = huc.getResponseCode(); - if (statusCode != 200) { - LOG.log(POILogger.ERROR, "Error contacting TSP server ", signatureConfig.getTspUrl() + - ", had status code " + statusCode + "/" + huc.getResponseMessage()); - throw new IOException("Error contacting TSP server " + signatureConfig.getTspUrl() + - ", had status code " + statusCode + "/" + huc.getResponseMessage()); - } - - // HTTP input validation - String contentType = huc.getHeaderField("Content-Type"); - if (null == contentType) { - throw new RuntimeException("missing Content-Type header"); - } - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - IOUtils.copy(huc.getInputStream(), bos); - LOG.log(POILogger.DEBUG, "response content: ", HexDump.dump(bos.toByteArray(), 0, 0)); - - if (!contentType.startsWith(signatureConfig.isTspOldProtocol() - ? "application/timestamp-response" - : "application/timestamp-reply" - )) { - throw new RuntimeException("invalid Content-Type: " + contentType + - // dump the first few bytes - ": " + HexDump.dump(bos.toByteArray(), 0, 0, 200)); - } - - if (bos.size() == 0) { - throw new RuntimeException("Content-Length is zero"); - } - - // TSP response parsing and validation - TimeStampResponse timeStampResponse = new TimeStampResponse(bos.toByteArray()); - timeStampResponse.validate(request); - - if (0 != timeStampResponse.getStatus()) { - LOG.log(POILogger.DEBUG, "status: " + timeStampResponse.getStatus()); - LOG.log(POILogger.DEBUG, "status string: " + timeStampResponse.getStatusString()); - PKIFailureInfo failInfo = timeStampResponse.getFailInfo(); - if (null != failInfo) { - LOG.log(POILogger.DEBUG, "fail info int value: " + failInfo.intValue()); - if (/*PKIFailureInfo.unacceptedPolicy*/(1 << 8) == failInfo.intValue()) { - LOG.log(POILogger.DEBUG, "unaccepted policy"); - } - } - throw new RuntimeException("timestamp response status != 0: " - + timeStampResponse.getStatus()); - } - TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken(); - SignerId signerId = timeStampToken.getSID(); - BigInteger signerCertSerialNumber = signerId.getSerialNumber(); - X500Name signerCertIssuer = signerId.getIssuer(); - LOG.log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber); - LOG.log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer); - - // TSP signer certificates retrieval - Collection certificates = timeStampToken.getCertificates().getMatches(null); - - X509CertificateHolder signerCert = null; - Map certificateMap = new HashMap(); - for (X509CertificateHolder certificate : certificates) { - if (signerCertIssuer.equals(certificate.getIssuer()) - && signerCertSerialNumber.equals(certificate.getSerialNumber())) { - signerCert = certificate; - } - certificateMap.put(certificate.getSubject(), certificate); - } - - // TSP signer cert path building - if (signerCert == null) { - throw new RuntimeException("TSP response token has no signer certificate"); - } - List tspCertificateChain = new ArrayList(); - JcaX509CertificateConverter x509converter = new JcaX509CertificateConverter(); - x509converter.setProvider("BC"); - X509CertificateHolder certificate = signerCert; - do { - LOG.log(POILogger.DEBUG, "adding to certificate chain: " + certificate.getSubject()); - tspCertificateChain.add(x509converter.getCertificate(certificate)); - if (certificate.getSubject().equals(certificate.getIssuer())) { - break; - } - certificate = certificateMap.get(certificate.getIssuer()); - } while (null != certificate); - - // verify TSP signer signature - X509CertificateHolder holder = new X509CertificateHolder(tspCertificateChain.get(0).getEncoded()); - DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator(); - DefaultSignatureAlgorithmIdentifierFinder sigAlgoFinder = new DefaultSignatureAlgorithmIdentifierFinder(); - DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder(); - BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider(); - BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator); - SignerInformationVerifier verifier = verifierBuilder.build(holder); - - timeStampToken.validate(verifier); - - // verify TSP signer certificate - if (signatureConfig.getTspValidator() != null) { - signatureConfig.getTspValidator().validate(tspCertificateChain, revocationData); - } - - LOG.log(POILogger.DEBUG, "time-stamp token time: " - + timeStampToken.getTimeStampInfo().getGenTime()); - - return timeStampToken.getEncoded(); - } - - public void setSignatureConfig(SignatureConfig signatureConfig) { - this.signatureConfig = signatureConfig; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.services; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.DatatypeConverter; + +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.cmp.PKIFailureInfo; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator; +import org.bouncycastle.cms.SignerId; +import org.bouncycastle.cms.SignerInformationVerifier; +import org.bouncycastle.cms.bc.BcRSASignerInfoVerifierBuilder; +import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; +import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; +import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; +import org.bouncycastle.tsp.TimeStampRequest; +import org.bouncycastle.tsp.TimeStampRequestGenerator; +import org.bouncycastle.tsp.TimeStampResponse; +import org.bouncycastle.tsp.TimeStampToken; + +/** + * A TSP time-stamp service implementation. + * + * @author Frank Cornelis + * + */ +public class TSPTimeStampService implements TimeStampService { + + private static final POILogger LOG = POILogFactory.getLogger(TSPTimeStampService.class); + + private SignatureConfig signatureConfig; + + /** + * Maps the digest algorithm to corresponding OID value. + */ + public ASN1ObjectIdentifier mapDigestAlgoToOID(HashAlgorithm digestAlgo) { + switch (digestAlgo) { + case sha1: return X509ObjectIdentifiers.id_SHA1; + case sha256: return NISTObjectIdentifiers.id_sha256; + case sha384: return NISTObjectIdentifiers.id_sha384; + case sha512: return NISTObjectIdentifiers.id_sha512; + default: + throw new IllegalArgumentException("unsupported digest algo: " + digestAlgo); + } + } + + @SuppressWarnings("unchecked") + public byte[] timeStamp(byte[] data, RevocationData revocationData) + throws Exception { + // digest the message + MessageDigest messageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getTspDigestAlgo()); + byte[] digest = messageDigest.digest(data); + + // generate the TSP request + BigInteger nonce = new BigInteger(128, new SecureRandom()); + TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator(); + requestGenerator.setCertReq(true); + String requestPolicy = signatureConfig.getTspRequestPolicy(); + if (requestPolicy != null) { + requestGenerator.setReqPolicy(new ASN1ObjectIdentifier(requestPolicy)); + } + ASN1ObjectIdentifier digestAlgoOid = mapDigestAlgoToOID(signatureConfig.getTspDigestAlgo()); + TimeStampRequest request = requestGenerator.generate(digestAlgoOid, digest, nonce); + byte[] encodedRequest = request.getEncoded(); + + // create the HTTP POST request + Proxy proxy = Proxy.NO_PROXY; + if (signatureConfig.getProxyUrl() != null) { + URL proxyUrl = new URL(signatureConfig.getProxyUrl()); + String host = proxyUrl.getHost(); + int port = proxyUrl.getPort(); + proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(InetAddress.getByName(host), (port == -1 ? 80 : port))); + } + + HttpURLConnection huc = (HttpURLConnection)new URL(signatureConfig.getTspUrl()).openConnection(proxy); + + if (signatureConfig.getTspUser() != null) { + String userPassword = signatureConfig.getTspUser() + ":" + signatureConfig.getTspPass(); + String encoding = DatatypeConverter.printBase64Binary(userPassword.getBytes(Charset.forName("iso-8859-1"))); + huc.setRequestProperty("Authorization", "Basic " + encoding); + } + + huc.setRequestMethod("POST"); + huc.setConnectTimeout(20000); + huc.setReadTimeout(20000); + huc.setDoOutput(true); // also sets method to POST. + huc.setRequestProperty("User-Agent", signatureConfig.getUserAgent()); + huc.setRequestProperty("Content-Type", signatureConfig.isTspOldProtocol() + ? "application/timestamp-request" + : "application/timestamp-query"); // "; charset=ISO-8859-1"); + + OutputStream hucOut = huc.getOutputStream(); + hucOut.write(encodedRequest); + + // invoke TSP service + huc.connect(); + + int statusCode = huc.getResponseCode(); + if (statusCode != 200) { + LOG.log(POILogger.ERROR, "Error contacting TSP server ", signatureConfig.getTspUrl() + + ", had status code " + statusCode + "/" + huc.getResponseMessage()); + throw new IOException("Error contacting TSP server " + signatureConfig.getTspUrl() + + ", had status code " + statusCode + "/" + huc.getResponseMessage()); + } + + // HTTP input validation + String contentType = huc.getHeaderField("Content-Type"); + if (null == contentType) { + throw new RuntimeException("missing Content-Type header"); + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + IOUtils.copy(huc.getInputStream(), bos); + LOG.log(POILogger.DEBUG, "response content: ", HexDump.dump(bos.toByteArray(), 0, 0)); + + if (!contentType.startsWith(signatureConfig.isTspOldProtocol() + ? "application/timestamp-response" + : "application/timestamp-reply" + )) { + throw new RuntimeException("invalid Content-Type: " + contentType + + // dump the first few bytes + ": " + HexDump.dump(bos.toByteArray(), 0, 0, 200)); + } + + if (bos.size() == 0) { + throw new RuntimeException("Content-Length is zero"); + } + + // TSP response parsing and validation + TimeStampResponse timeStampResponse = new TimeStampResponse(bos.toByteArray()); + timeStampResponse.validate(request); + + if (0 != timeStampResponse.getStatus()) { + LOG.log(POILogger.DEBUG, "status: " + timeStampResponse.getStatus()); + LOG.log(POILogger.DEBUG, "status string: " + timeStampResponse.getStatusString()); + PKIFailureInfo failInfo = timeStampResponse.getFailInfo(); + if (null != failInfo) { + LOG.log(POILogger.DEBUG, "fail info int value: " + failInfo.intValue()); + if (/*PKIFailureInfo.unacceptedPolicy*/(1 << 8) == failInfo.intValue()) { + LOG.log(POILogger.DEBUG, "unaccepted policy"); + } + } + throw new RuntimeException("timestamp response status != 0: " + + timeStampResponse.getStatus()); + } + TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken(); + SignerId signerId = timeStampToken.getSID(); + BigInteger signerCertSerialNumber = signerId.getSerialNumber(); + X500Name signerCertIssuer = signerId.getIssuer(); + LOG.log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber); + LOG.log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer); + + // TSP signer certificates retrieval + Collection certificates = timeStampToken.getCertificates().getMatches(null); + + X509CertificateHolder signerCert = null; + Map certificateMap = new HashMap(); + for (X509CertificateHolder certificate : certificates) { + if (signerCertIssuer.equals(certificate.getIssuer()) + && signerCertSerialNumber.equals(certificate.getSerialNumber())) { + signerCert = certificate; + } + certificateMap.put(certificate.getSubject(), certificate); + } + + // TSP signer cert path building + if (signerCert == null) { + throw new RuntimeException("TSP response token has no signer certificate"); + } + List tspCertificateChain = new ArrayList(); + JcaX509CertificateConverter x509converter = new JcaX509CertificateConverter(); + x509converter.setProvider("BC"); + X509CertificateHolder certificate = signerCert; + do { + LOG.log(POILogger.DEBUG, "adding to certificate chain: " + certificate.getSubject()); + tspCertificateChain.add(x509converter.getCertificate(certificate)); + if (certificate.getSubject().equals(certificate.getIssuer())) { + break; + } + certificate = certificateMap.get(certificate.getIssuer()); + } while (null != certificate); + + // verify TSP signer signature + X509CertificateHolder holder = new X509CertificateHolder(tspCertificateChain.get(0).getEncoded()); + DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator(); + DefaultSignatureAlgorithmIdentifierFinder sigAlgoFinder = new DefaultSignatureAlgorithmIdentifierFinder(); + DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder(); + BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider(); + BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator); + SignerInformationVerifier verifier = verifierBuilder.build(holder); + + timeStampToken.validate(verifier); + + // verify TSP signer certificate + if (signatureConfig.getTspValidator() != null) { + signatureConfig.getTspValidator().validate(tspCertificateChain, revocationData); + } + + LOG.log(POILogger.DEBUG, "time-stamp token time: " + + timeStampToken.getTimeStampInfo().getGenTime()); + + return timeStampToken.getEncoded(); + } + + public void setSignatureConfig(SignatureConfig signatureConfig) { + this.signatureConfig = signatureConfig; + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java index 84cde92377..ede39ac357 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampService.java @@ -1,54 +1,54 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.services; - -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; - - -/** - * Interface for a time-stamp service. - * - * @author Frank Cornelis - * - */ -public interface TimeStampService extends SignatureConfigurable { - - /** - * Gives back the encoded time-stamp token for the given array of data - * bytes. We assume that the time-stamp token itself contains its full - * certificate chain required for proper validation. - * - * @param data - * the data to be time-stamped. - * @param revocationData - * the optional container that needs to be filled up with the - * revocation data used to validate the TSA certificate chain. - * @return the DER encoded time-stamp token. - * @throws Exception - * in case something went wrong. - */ - byte[] timeStamp(byte[] data, RevocationData revocationData) - throws Exception; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.services; + +import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; + + +/** + * Interface for a time-stamp service. + * + * @author Frank Cornelis + * + */ +public interface TimeStampService extends SignatureConfigurable { + + /** + * Gives back the encoded time-stamp token for the given array of data + * bytes. We assume that the time-stamp token itself contains its full + * certificate chain required for proper validation. + * + * @param data + * the data to be time-stamped. + * @param revocationData + * the optional container that needs to be filled up with the + * revocation data used to validate the TSA certificate chain. + * @return the DER encoded time-stamp token. + * @throws Exception + * in case something went wrong. + */ + byte[] timeStamp(byte[] data, RevocationData revocationData) + throws Exception; +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampServiceValidator.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampServiceValidator.java index 4d36be9ec5..0ea5bbdc1d 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampServiceValidator.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TimeStampServiceValidator.java @@ -1,51 +1,51 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.services; - -import java.security.cert.X509Certificate; -import java.util.List; - -/** - * Interface for trust validator of a TSP. - * - * @author Frank Cornelis - * - */ -public interface TimeStampServiceValidator { - - /** - * Validates the given certificate chain. - * - * @param certificateChain - * @param revocationData - * the optional data container that should be filled with - * revocation data that was used to validate the given - * certificate chain. - * @throws Exception - * in case the certificate chain is invalid. - */ - void validate(List certificateChain, - RevocationData revocationData) throws Exception; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.services; + +import java.security.cert.X509Certificate; +import java.util.List; + +/** + * Interface for trust validator of a TSP. + * + * @author Frank Cornelis + * + */ +public interface TimeStampServiceValidator { + + /** + * Validates the given certificate chain. + * + * @param certificateChain + * @param revocationData + * the optional data container that should be filled with + * revocation data that was used to validate the given + * certificate chain. + * @throws Exception + * in case the certificate chain is invalid. + */ + void validate(List certificateChain, + RevocationData revocationData) throws Exception; +} diff --git a/src/ooxml/java/org/apache/poi/util/IdentifierManager.java b/src/ooxml/java/org/apache/poi/util/IdentifierManager.java index 4b57e77707..88822351f0 100644 --- a/src/ooxml/java/org/apache/poi/util/IdentifierManager.java +++ b/src/ooxml/java/org/apache/poi/util/IdentifierManager.java @@ -1,266 +1,266 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.util; - -import java.util.LinkedList; -import java.util.ListIterator; - -/** - *

- * 24.08.2009
- *

- * - * @author Stefan Stern
- */ - -public class IdentifierManager { - - public static final long MAX_ID = Long.MAX_VALUE - 1; - - public static final long MIN_ID = 0L; - - /** - * - */ - private final long upperbound; - - /** - * - */ - private final long lowerbound; - - /** - * List of segments of available identifiers - */ - private LinkedList segments; - - /** - * @param lowerbound the lower limit of the id-range to manage. Must be greater than or equal to {@link #MIN_ID}. - * @param upperbound the upper limit of the id-range to manage. Must be less then or equal {@link #MAX_ID}. - */ - public IdentifierManager(long lowerbound, long upperbound) { - if (lowerbound > upperbound) { - throw new IllegalArgumentException("lowerbound must not be greater than upperbound, had " + lowerbound + " and " + upperbound); - } - else if (lowerbound < MIN_ID) { - String message = "lowerbound must be greater than or equal to " + Long.toString(MIN_ID); - throw new IllegalArgumentException(message); - } - else if (upperbound > MAX_ID) { - /* - * while MAX_ID is Long.MAX_VALUE, this check is pointless. But if - * someone subclasses / tweaks the limits, this check is fine. - */ - throw new IllegalArgumentException("upperbound must be less than or equal to " + Long.toString(MAX_ID) + " but had " + upperbound); - } - this.lowerbound = lowerbound; - this.upperbound = upperbound; - this.segments = new LinkedList(); - segments.add(new Segment(lowerbound, upperbound)); - } - - public long reserve(long id) { - if (id < lowerbound || id > upperbound) { - throw new IllegalArgumentException("Value for parameter 'id' was out of bounds, had " + id + ", but should be within [" + lowerbound + ":" + upperbound + "]"); - } - verifyIdentifiersLeft(); - - if (id == upperbound) { - Segment lastSegment = segments.getLast(); - if (lastSegment.end == upperbound) { - lastSegment.end = upperbound - 1; - if (lastSegment.start > lastSegment.end) { - segments.removeLast(); - } - return id; - } - return reserveNew(); - } - - if (id == lowerbound) { - Segment firstSegment = segments.getFirst(); - if (firstSegment.start == lowerbound) { - firstSegment.start = lowerbound + 1; - if (firstSegment.end < firstSegment.start) { - segments.removeFirst(); - } - return id; - } - return reserveNew(); - } - - ListIterator iter = segments.listIterator(); - while (iter.hasNext()) { - Segment segment = iter.next(); - if (segment.end < id) { - continue; - } - else if (segment.start > id) { - break; - } - else if (segment.start == id) { - segment.start = id + 1; - if (segment.end < segment.start) { - iter.remove(); - } - return id; - } - else if (segment.end == id) { - segment.end = id - 1; - if (segment.start > segment.end) { - iter.remove(); - } - return id; - } - else { - iter.add(new Segment(id + 1, segment.end)); - segment.end = id - 1; - return id; - } - } - return reserveNew(); - } - - /** - * @return a new identifier. - * @throws IllegalStateException if no more identifiers are available, then an Exception is raised. - */ - public long reserveNew() { - verifyIdentifiersLeft(); - Segment segment = segments.getFirst(); - long result = segment.start; - segment.start += 1; - if (segment.start > segment.end) { - segments.removeFirst(); - } - return result; - } - - /** - * @param id - * the identifier to release. Must be greater than or equal to - * {@link #lowerbound} and must be less than or equal to {@link #upperbound} - * @return true, if the identifier was reserved and has been successfully - * released, false, if the identifier was not reserved. - */ - public boolean release(long id) { - if (id < lowerbound || id > upperbound) { - throw new IllegalArgumentException("Value for parameter 'id' was out of bounds, had " + id + ", but should be within [" + lowerbound + ":" + upperbound + "]"); - } - - if (id == upperbound) { - Segment lastSegment = segments.getLast(); - if (lastSegment.end == upperbound - 1) { - lastSegment.end = upperbound; - return true; - } else if (lastSegment.end == upperbound) { - return false; - } else { - segments.add(new Segment(upperbound, upperbound)); - return true; - } - } - - if (id == lowerbound) { - Segment firstSegment = segments.getFirst(); - if (firstSegment.start == lowerbound + 1) { - firstSegment.start = lowerbound; - return true; - } else if (firstSegment.start == lowerbound) { - return false; - } else { - segments.addFirst(new Segment(lowerbound, lowerbound)); - return true; - } - } - - long higher = id + 1; - long lower = id - 1; - ListIterator iter = segments.listIterator(); - - while (iter.hasNext()) { - Segment segment = iter.next(); - if (segment.end < lower) { - continue; - } - if (segment.start > higher) { - iter.previous(); - iter.add(new Segment(id, id)); - return true; - } - if (segment.start == higher) { - segment.start = id; - return true; - } - else if (segment.end == lower) { - segment.end = id; - /* check if releasing this elements glues two segments into one */ - if (iter.hasNext()) { - Segment next = iter.next(); - if (next.start == segment.end + 1) { - segment.end = next.end; - iter.remove(); - } - } - return true; - } - else { - /* id was not reserved, return false */ - break; - } - } - return false; - } - - public long getRemainingIdentifiers() { - long result = 0; - for (Segment segment : segments) { - result = result - segment.start; - result = result + segment.end + 1; - } - return result; - } - - /** - * - */ - private void verifyIdentifiersLeft() { - if (segments.isEmpty()) { - throw new IllegalStateException("No identifiers left"); - } - } - - private static class Segment { - - public Segment(long start, long end) { - this.start = start; - this.end = end; - } - - public long start; - public long end; - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - public String toString() { - return "[" + start + "; " + end + "]"; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.util; + +import java.util.LinkedList; +import java.util.ListIterator; + +/** + *

+ * 24.08.2009
+ *

+ * + * @author Stefan Stern
+ */ + +public class IdentifierManager { + + public static final long MAX_ID = Long.MAX_VALUE - 1; + + public static final long MIN_ID = 0L; + + /** + * + */ + private final long upperbound; + + /** + * + */ + private final long lowerbound; + + /** + * List of segments of available identifiers + */ + private LinkedList segments; + + /** + * @param lowerbound the lower limit of the id-range to manage. Must be greater than or equal to {@link #MIN_ID}. + * @param upperbound the upper limit of the id-range to manage. Must be less then or equal {@link #MAX_ID}. + */ + public IdentifierManager(long lowerbound, long upperbound) { + if (lowerbound > upperbound) { + throw new IllegalArgumentException("lowerbound must not be greater than upperbound, had " + lowerbound + " and " + upperbound); + } + else if (lowerbound < MIN_ID) { + String message = "lowerbound must be greater than or equal to " + Long.toString(MIN_ID); + throw new IllegalArgumentException(message); + } + else if (upperbound > MAX_ID) { + /* + * while MAX_ID is Long.MAX_VALUE, this check is pointless. But if + * someone subclasses / tweaks the limits, this check is fine. + */ + throw new IllegalArgumentException("upperbound must be less than or equal to " + Long.toString(MAX_ID) + " but had " + upperbound); + } + this.lowerbound = lowerbound; + this.upperbound = upperbound; + this.segments = new LinkedList(); + segments.add(new Segment(lowerbound, upperbound)); + } + + public long reserve(long id) { + if (id < lowerbound || id > upperbound) { + throw new IllegalArgumentException("Value for parameter 'id' was out of bounds, had " + id + ", but should be within [" + lowerbound + ":" + upperbound + "]"); + } + verifyIdentifiersLeft(); + + if (id == upperbound) { + Segment lastSegment = segments.getLast(); + if (lastSegment.end == upperbound) { + lastSegment.end = upperbound - 1; + if (lastSegment.start > lastSegment.end) { + segments.removeLast(); + } + return id; + } + return reserveNew(); + } + + if (id == lowerbound) { + Segment firstSegment = segments.getFirst(); + if (firstSegment.start == lowerbound) { + firstSegment.start = lowerbound + 1; + if (firstSegment.end < firstSegment.start) { + segments.removeFirst(); + } + return id; + } + return reserveNew(); + } + + ListIterator iter = segments.listIterator(); + while (iter.hasNext()) { + Segment segment = iter.next(); + if (segment.end < id) { + continue; + } + else if (segment.start > id) { + break; + } + else if (segment.start == id) { + segment.start = id + 1; + if (segment.end < segment.start) { + iter.remove(); + } + return id; + } + else if (segment.end == id) { + segment.end = id - 1; + if (segment.start > segment.end) { + iter.remove(); + } + return id; + } + else { + iter.add(new Segment(id + 1, segment.end)); + segment.end = id - 1; + return id; + } + } + return reserveNew(); + } + + /** + * @return a new identifier. + * @throws IllegalStateException if no more identifiers are available, then an Exception is raised. + */ + public long reserveNew() { + verifyIdentifiersLeft(); + Segment segment = segments.getFirst(); + long result = segment.start; + segment.start += 1; + if (segment.start > segment.end) { + segments.removeFirst(); + } + return result; + } + + /** + * @param id + * the identifier to release. Must be greater than or equal to + * {@link #lowerbound} and must be less than or equal to {@link #upperbound} + * @return true, if the identifier was reserved and has been successfully + * released, false, if the identifier was not reserved. + */ + public boolean release(long id) { + if (id < lowerbound || id > upperbound) { + throw new IllegalArgumentException("Value for parameter 'id' was out of bounds, had " + id + ", but should be within [" + lowerbound + ":" + upperbound + "]"); + } + + if (id == upperbound) { + Segment lastSegment = segments.getLast(); + if (lastSegment.end == upperbound - 1) { + lastSegment.end = upperbound; + return true; + } else if (lastSegment.end == upperbound) { + return false; + } else { + segments.add(new Segment(upperbound, upperbound)); + return true; + } + } + + if (id == lowerbound) { + Segment firstSegment = segments.getFirst(); + if (firstSegment.start == lowerbound + 1) { + firstSegment.start = lowerbound; + return true; + } else if (firstSegment.start == lowerbound) { + return false; + } else { + segments.addFirst(new Segment(lowerbound, lowerbound)); + return true; + } + } + + long higher = id + 1; + long lower = id - 1; + ListIterator iter = segments.listIterator(); + + while (iter.hasNext()) { + Segment segment = iter.next(); + if (segment.end < lower) { + continue; + } + if (segment.start > higher) { + iter.previous(); + iter.add(new Segment(id, id)); + return true; + } + if (segment.start == higher) { + segment.start = id; + return true; + } + else if (segment.end == lower) { + segment.end = id; + /* check if releasing this elements glues two segments into one */ + if (iter.hasNext()) { + Segment next = iter.next(); + if (next.start == segment.end + 1) { + segment.end = next.end; + iter.remove(); + } + } + return true; + } + else { + /* id was not reserved, return false */ + break; + } + } + return false; + } + + public long getRemainingIdentifiers() { + long result = 0; + for (Segment segment : segments) { + result = result - segment.start; + result = result + segment.end + 1; + } + return result; + } + + /** + * + */ + private void verifyIdentifiersLeft() { + if (segments.isEmpty()) { + throw new IllegalStateException("No identifiers left"); + } + } + + private static class Segment { + + public Segment(long start, long end) { + this.start = start; + this.end = end; + } + + public long start; + public long end; + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + public String toString() { + return "[" + start + "; " + end + "]"; + } + } +} diff --git a/src/ooxml/java/org/apache/poi/util/XmlSort.java b/src/ooxml/java/org/apache/poi/util/XmlSort.java index e6be797029..09f05fb463 100644 --- a/src/ooxml/java/org/apache/poi/util/XmlSort.java +++ b/src/ooxml/java/org/apache/poi/util/XmlSort.java @@ -1,88 +1,88 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.util; - -import java.util.Comparator; - -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; - -public final class XmlSort { - /** - * Sorts the children of element according to the order indicated by the - * comparator. - * @param element the element whose content is to be sorted. Only element children are sorted, - * attributes are not touched. When elements are reordered, all the text, comments and PIs - * follow the element that they come immediately after. - * @param comp a comparator that is to be used when comparing the QNames of two - * elements. - * @throws IllegalArgumentException if the input XmlObject does not represent - * an element - */ - public static void sort(XmlObject element, Comparator comp) { - XmlCursor headCursor = element.newCursor(); - if (!headCursor.isStart()) { - throw new IllegalStateException("The element parameter must point to a STARTDOC"); - } - // We use insertion sort to minimize the number of swaps, because each swap means - // moving a part of the document - /* headCursor points to the beginning of the list of the already sorted items and - listCursor points to the beginning of the list of unsorted items - At the beginning, headCursor points to the first element and listCursor points to the - second element. The algorithm ends when listCursor cannot be moved to the "next" - element in the unsorted list, i.e. the unsorted list becomes empty */ - boolean moved = headCursor.toFirstChild(); - if (!moved) { - // Cursor was not moved, which means that the given element has no children and - // therefore there is nothing to sort - return; - } - XmlCursor listCursor = headCursor.newCursor(); - boolean moreElements = listCursor.toNextSibling(); - while (moreElements) { - moved = false; - // While we can move the head of the unsorted list, it means that there are still - // items (elements) that need to be sorted - while (headCursor.comparePosition(listCursor) < 0) { - if (comp.compare(headCursor, listCursor) > 0) { - // We have found the position in the sorted list, insert the element and the - // text following the element in the current position - // Move the element - listCursor.moveXml(headCursor); - // Move the text following the element - while (!listCursor.isStart() && !listCursor.isEnd()) - listCursor.moveXml(headCursor); - moreElements = listCursor.isStart(); - moved = true; - break; - } - headCursor.toNextSibling(); - } - if (!moved) { - // Because during the move of a fragment of XML, the listCursor is also moved, in - // case we didn't need to move XML (the new element to be inserted happened to - // be the last one in order), we need to move this cursor - moreElements = listCursor.toNextSibling(); - } - // Reposition the head of the sorted list - headCursor.toParent(); - headCursor.toFirstChild(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.util; + +import java.util.Comparator; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; + +public final class XmlSort { + /** + * Sorts the children of element according to the order indicated by the + * comparator. + * @param element the element whose content is to be sorted. Only element children are sorted, + * attributes are not touched. When elements are reordered, all the text, comments and PIs + * follow the element that they come immediately after. + * @param comp a comparator that is to be used when comparing the QNames of two + * elements. + * @throws IllegalArgumentException if the input XmlObject does not represent + * an element + */ + public static void sort(XmlObject element, Comparator comp) { + XmlCursor headCursor = element.newCursor(); + if (!headCursor.isStart()) { + throw new IllegalStateException("The element parameter must point to a STARTDOC"); + } + // We use insertion sort to minimize the number of swaps, because each swap means + // moving a part of the document + /* headCursor points to the beginning of the list of the already sorted items and + listCursor points to the beginning of the list of unsorted items + At the beginning, headCursor points to the first element and listCursor points to the + second element. The algorithm ends when listCursor cannot be moved to the "next" + element in the unsorted list, i.e. the unsorted list becomes empty */ + boolean moved = headCursor.toFirstChild(); + if (!moved) { + // Cursor was not moved, which means that the given element has no children and + // therefore there is nothing to sort + return; + } + XmlCursor listCursor = headCursor.newCursor(); + boolean moreElements = listCursor.toNextSibling(); + while (moreElements) { + moved = false; + // While we can move the head of the unsorted list, it means that there are still + // items (elements) that need to be sorted + while (headCursor.comparePosition(listCursor) < 0) { + if (comp.compare(headCursor, listCursor) > 0) { + // We have found the position in the sorted list, insert the element and the + // text following the element in the current position + // Move the element + listCursor.moveXml(headCursor); + // Move the text following the element + while (!listCursor.isStart() && !listCursor.isEnd()) + listCursor.moveXml(headCursor); + moreElements = listCursor.isStart(); + moved = true; + break; + } + headCursor.toNextSibling(); + } + if (!moved) { + // Because during the move of a fragment of XML, the listCursor is also moved, in + // case we didn't need to move XML (the new element to be inserted happened to + // be the last one in order), we need to move this cursor + moreElements = listCursor.toNextSibling(); + } + // Reposition the head of the sorted list + headCursor.toParent(); + headCursor.toFirstChild(); + } + } +} \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java index 3358a72774..fd8b40fc09 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java @@ -1,40 +1,40 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.model; - -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; - -public abstract class CharacterPropertyFetcher extends ParagraphPropertyFetcher { - public CharacterPropertyFetcher(int level) { - super(level); - } - - public boolean fetch(CTTextParagraphProperties props) { - if (props != null && props.isSetDefRPr()) { - return fetch(props.getDefRPr()); - } - - return false; - } - - public abstract boolean fetch(CTTextCharacterProperties props); - +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.model; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; + +public abstract class CharacterPropertyFetcher extends ParagraphPropertyFetcher { + public CharacterPropertyFetcher(int level) { + super(level); + } + + public boolean fetch(CTTextParagraphProperties props) { + if (props != null && props.isSetDefRPr()) { + return fetch(props.getDefRPr()); + } + + return false; + } + + public abstract boolean fetch(CTTextCharacterProperties props); + } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java index c6c583616c..6085b9d80b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java @@ -1,52 +1,52 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.model; - -import org.apache.poi.xslf.usermodel.XSLFShape; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; - -/** - * - * @author Yegor Kozlov - */ -public abstract class ParagraphPropertyFetcher extends PropertyFetcher { - int _level; - - public ParagraphPropertyFetcher(int level) { - _level = level; - } - - public boolean fetch(XSLFShape shape) { - - XmlObject[] o = shape.getXmlObject().selectPath( - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + - "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + - ".//p:txBody/a:lstStyle/a:lvl" + (_level + 1) + "pPr" - ); - if (o.length == 1) { - CTTextParagraphProperties props = (CTTextParagraphProperties) o[0]; - return fetch(props); - } - return false; - } - - public abstract boolean fetch(CTTextParagraphProperties props); +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.model; + +import org.apache.poi.xslf.usermodel.XSLFShape; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; + +/** + * + * @author Yegor Kozlov + */ +public abstract class ParagraphPropertyFetcher extends PropertyFetcher { + int _level; + + public ParagraphPropertyFetcher(int level) { + _level = level; + } + + public boolean fetch(XSLFShape shape) { + + XmlObject[] o = shape.getXmlObject().selectPath( + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + + "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + + ".//p:txBody/a:lstStyle/a:lvl" + (_level + 1) + "pPr" + ); + if (o.length == 1) { + CTTextParagraphProperties props = (CTTextParagraphProperties) o[0]; + return fetch(props); + } + return false; + } + + public abstract boolean fetch(CTTextParagraphProperties props); } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java index f9e8a780da..2875e0345e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java @@ -1,48 +1,48 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.model; - -import org.apache.poi.util.Internal; -import org.apache.poi.xslf.usermodel.XSLFShape; - -/** - * Used internally to navigate the PresentationML text style hierarchy and fetch properties - * - * @author Yegor Kozlov -*/ -@Internal -public abstract class PropertyFetcher { - private T _value; - - /** - * - * @param shape the shape being examined - * @return true if the desired property was fetched - */ - public abstract boolean fetch(XSLFShape shape); - - public T getValue(){ - return _value; - } - - public void setValue(T val){ - _value = val; - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.model; + +import org.apache.poi.util.Internal; +import org.apache.poi.xslf.usermodel.XSLFShape; + +/** + * Used internally to navigate the PresentationML text style hierarchy and fetch properties + * + * @author Yegor Kozlov +*/ +@Internal +public abstract class PropertyFetcher { + private T _value; + + /** + * + * @param shape the shape being examined + * @return true if the desired property was fetched + */ + public abstract boolean fetch(XSLFShape shape); + + public T getValue(){ + return _value; + } + + public void setValue(T val){ + _value = val; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/TextBodyPropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/TextBodyPropertyFetcher.java index cc8486a33c..4b1d546e75 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/TextBodyPropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/TextBodyPropertyFetcher.java @@ -1,52 +1,52 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.model; - -import org.apache.poi.xslf.usermodel.XSLFShape; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; - -/** - * Created by IntelliJ IDEA. - * User: yegor - * Date: Oct 21, 2011 - * Time: 1:18:52 PM - * To change this template use File | Settings | File Templates. - */ -public abstract class TextBodyPropertyFetcher extends PropertyFetcher { - - public boolean fetch(XSLFShape shape) { - - XmlObject[] o = shape.getXmlObject().selectPath( - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + - "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + - ".//p:txBody/a:bodyPr" - ); - if (o.length == 1) { - CTTextBodyProperties props = (CTTextBodyProperties) o[0]; - return fetch(props); - } - - return false; - } - - public abstract boolean fetch(CTTextBodyProperties props); - +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.model; + +import org.apache.poi.xslf.usermodel.XSLFShape; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; + +/** + * Created by IntelliJ IDEA. + * User: yegor + * Date: Oct 21, 2011 + * Time: 1:18:52 PM + * To change this template use File | Settings | File Templates. + */ +public abstract class TextBodyPropertyFetcher extends PropertyFetcher { + + public boolean fetch(XSLFShape shape) { + + XmlObject[] o = shape.getXmlObject().selectPath( + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + + "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + + ".//p:txBody/a:bodyPr" + ); + if (o.length == 1) { + CTTextBodyProperties props = (CTTextBodyProperties) o[0]; + return fetch(props); + } + + return false; + } + + public abstract boolean fetch(CTTextBodyProperties props); + } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java index e45df5ee29..9dfa62fa04 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFAutoShape.java @@ -1,108 +1,108 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import org.apache.poi.sl.usermodel.AutoShape; -import org.apache.poi.util.Beta; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; - - -/** - * Represents a shape with a preset geometry. - * - * @author Yegor Kozlov - */ -@Beta -public class XSLFAutoShape extends XSLFTextShape - implements AutoShape { - - /*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) { - super(shape, sheet); - } - - /*package*/ - static XSLFAutoShape create(CTShape shape, XSLFSheet sheet) { - if (shape.getSpPr().isSetCustGeom()) { - return new XSLFFreeformShape(shape, sheet); - } else if (shape.getNvSpPr().getCNvSpPr().isSetTxBox()) { - return new XSLFTextBox(shape, sheet); - } else { - return new XSLFAutoShape(shape, sheet); - } - } - - /** - * @param shapeId 1-based shapeId - */ - static CTShape prototype(int shapeId) { - CTShape ct = CTShape.Factory.newInstance(); - CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); - CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); - cnv.setName("AutoShape " + shapeId); - cnv.setId(shapeId + 1); - nvSpPr.addNewCNvSpPr(); - nvSpPr.addNewNvPr(); - CTShapeProperties spPr = ct.addNewSpPr(); - CTPresetGeometry2D prst = spPr.addNewPrstGeom(); - prst.setPrst(STShapeType.RECT); - prst.addNewAvLst(); - return ct; - } - - protected static void initTextBody(CTTextBody txBody) { - CTTextBodyProperties bodypr = txBody.addNewBodyPr(); - bodypr.setAnchor(STTextAnchoringType.T); - bodypr.setRtlCol(false); - CTTextParagraph p = txBody.addNewP(); - p.addNewPPr().setAlgn(STTextAlignType.L); - CTTextCharacterProperties endPr = p.addNewEndParaRPr(); - endPr.setLang("en-US"); - endPr.setSz(1100); - p.addNewR().setT(""); - txBody.addNewLstStyle(); - } - - protected CTTextBody getTextBody(boolean create){ - CTShape shape = (CTShape)getXmlObject(); - CTTextBody txBody = shape.getTxBody(); - if (txBody == null && create) { - txBody = shape.addNewTxBody(); - initTextBody(txBody); - } - return txBody; - } - - @Override - public String toString(){ - return "[" + getClass().getSimpleName() + "] " + getShapeName(); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.sl.usermodel.AutoShape; +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; + + +/** + * Represents a shape with a preset geometry. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFAutoShape extends XSLFTextShape + implements AutoShape { + + /*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) { + super(shape, sheet); + } + + /*package*/ + static XSLFAutoShape create(CTShape shape, XSLFSheet sheet) { + if (shape.getSpPr().isSetCustGeom()) { + return new XSLFFreeformShape(shape, sheet); + } else if (shape.getNvSpPr().getCNvSpPr().isSetTxBox()) { + return new XSLFTextBox(shape, sheet); + } else { + return new XSLFAutoShape(shape, sheet); + } + } + + /** + * @param shapeId 1-based shapeId + */ + static CTShape prototype(int shapeId) { + CTShape ct = CTShape.Factory.newInstance(); + CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("AutoShape " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvSpPr(); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.RECT); + prst.addNewAvLst(); + return ct; + } + + protected static void initTextBody(CTTextBody txBody) { + CTTextBodyProperties bodypr = txBody.addNewBodyPr(); + bodypr.setAnchor(STTextAnchoringType.T); + bodypr.setRtlCol(false); + CTTextParagraph p = txBody.addNewP(); + p.addNewPPr().setAlgn(STTextAlignType.L); + CTTextCharacterProperties endPr = p.addNewEndParaRPr(); + endPr.setLang("en-US"); + endPr.setSz(1100); + p.addNewR().setT(""); + txBody.addNewLstStyle(); + } + + protected CTTextBody getTextBody(boolean create){ + CTShape shape = (CTShape)getXmlObject(); + CTTextBody txBody = shape.getTxBody(); + if (txBody == null && create) { + txBody = shape.addNewTxBody(); + initTextBody(txBody); + } + return txBody; + } + + @Override + public String toString(){ + return "[" + getClass().getSimpleName() + "] " + getShapeName(); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java index 1eac4b2770..343f33baeb 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java @@ -1,112 +1,112 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.geom.Rectangle2D; - -import org.apache.poi.POIXMLException; -import org.apache.poi.sl.usermodel.Background; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground; -import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties; - -/** - * Background shape - */ -public class XSLFBackground extends XSLFSimpleShape - implements Background { - - /* package */XSLFBackground(CTBackground shape, XSLFSheet sheet) { - super(shape, sheet); - } - - @Override - public Rectangle2D getAnchor(){ - Dimension pg = getSheet().getSlideShow().getPageSize(); - return new Rectangle2D.Double(0, 0, pg.getWidth(), pg.getHeight()); - } - - /** - * background does not have a associated transform, therefore we return null - * - * @param create ignored - * - * @return null - */ - @Override - protected CTTransform2D getXfrm(boolean create) { - return null; - } - - @Override - public void setPlaceholder(Placeholder placeholder) { - // extending XSLFSimpleShape is a bit unlucky ... - throw new POIXMLException("Can't set a placeholder for a background"); - } - - protected CTBackgroundProperties getBgPr(boolean create) { - CTBackground bg = (CTBackground)getXmlObject(); - if (!bg.isSetBgPr() && create) { - if (bg.isSetBgRef()) { - bg.unsetBgRef(); - } - return bg.addNewBgPr(); - } - return bg.getBgPr(); - } - - public void setFillColor(Color color) { - CTBackgroundProperties bgPr = getBgPr(true); - - if (color == null) { - if (bgPr.isSetSolidFill()) { - bgPr.unsetSolidFill(); - } - - if (!bgPr.isSetNoFill()) { - bgPr.addNewNoFill(); - } - } else { - if (bgPr.isSetNoFill()) { - bgPr.unsetNoFill(); - } - - CTSolidColorFillProperties fill = bgPr.isSetSolidFill() ? bgPr.getSolidFill() : bgPr.addNewSolidFill(); - - XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); - col.setColor(color); - } - } - - @Override - protected XmlObject getShapeProperties() { - CTBackground bg = (CTBackground)getXmlObject(); - if (bg.isSetBgPr()) { - return bg.getBgPr(); - } else if (bg.isSetBgRef()) { - return bg.getBgRef(); - } else { - return null; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.POIXMLException; +import org.apache.poi.sl.usermodel.Background; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground; +import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties; + +/** + * Background shape + */ +public class XSLFBackground extends XSLFSimpleShape + implements Background { + + /* package */XSLFBackground(CTBackground shape, XSLFSheet sheet) { + super(shape, sheet); + } + + @Override + public Rectangle2D getAnchor(){ + Dimension pg = getSheet().getSlideShow().getPageSize(); + return new Rectangle2D.Double(0, 0, pg.getWidth(), pg.getHeight()); + } + + /** + * background does not have a associated transform, therefore we return null + * + * @param create ignored + * + * @return null + */ + @Override + protected CTTransform2D getXfrm(boolean create) { + return null; + } + + @Override + public void setPlaceholder(Placeholder placeholder) { + // extending XSLFSimpleShape is a bit unlucky ... + throw new POIXMLException("Can't set a placeholder for a background"); + } + + protected CTBackgroundProperties getBgPr(boolean create) { + CTBackground bg = (CTBackground)getXmlObject(); + if (!bg.isSetBgPr() && create) { + if (bg.isSetBgRef()) { + bg.unsetBgRef(); + } + return bg.addNewBgPr(); + } + return bg.getBgPr(); + } + + public void setFillColor(Color color) { + CTBackgroundProperties bgPr = getBgPr(true); + + if (color == null) { + if (bgPr.isSetSolidFill()) { + bgPr.unsetSolidFill(); + } + + if (!bgPr.isSetNoFill()) { + bgPr.addNewNoFill(); + } + } else { + if (bgPr.isSetNoFill()) { + bgPr.unsetNoFill(); + } + + CTSolidColorFillProperties fill = bgPr.isSetSolidFill() ? bgPr.getSolidFill() : bgPr.addNewSolidFill(); + + XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); + col.setColor(color); + } + } + + @Override + protected XmlObject getShapeProperties() { + CTBackground bg = (CTBackground)getXmlObject(); + if (bg.isSetBgPr()) { + return bg.getBgPr(); + } else if (bg.isSetBgRef()) { + return bg.getBgRef(); + } else { + return null; + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java index bff6e0140a..30f353811c 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java @@ -1,484 +1,484 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; - -import org.apache.poi.sl.draw.DrawPaint; -import org.apache.poi.sl.usermodel.ColorStyle; -import org.apache.poi.sl.usermodel.PresetColor; -import org.apache.poi.util.Beta; -import org.apache.poi.util.Internal; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference; -import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveFixedPercentage; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTScRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSystemColor; -import org.w3c.dom.Node; - -/** - * Encapsulates logic to read color definitions from DrawingML and convert them to java.awt.Color - */ -@Beta -@Internal -public class XSLFColor { - private final static POILogger LOGGER = POILogFactory.getLogger(XSLFColor.class); - - private XmlObject _xmlObject; - private Color _color; - private CTSchemeColor _phClr; - - public XSLFColor(XmlObject obj, XSLFTheme theme, CTSchemeColor phClr) { - _xmlObject = obj; - _phClr = phClr; - _color = toColor(obj, theme); - } - - @Internal - public XmlObject getXmlObject() { - return _xmlObject; - } - - /** - * - * @return the displayed color as a Java Color. - * If not color information was found in the supplied xml object then a null is returned. - */ - public Color getColor() { - return DrawPaint.applyColorTransform(getColorStyle()); - } - - public ColorStyle getColorStyle() { - return new ColorStyle() { - public Color getColor() { - return _color; - } - - public int getAlpha() { - return getRawValue("alpha"); - } - - public int getHueOff() { - return getRawValue("hueOff"); - } - - public int getHueMod() { - return getRawValue("hueMod"); - } - - public int getSatOff() { - return getRawValue("satOff"); - } - - public int getSatMod() { - return getRawValue("satMod"); - } - - public int getLumOff() { - return getRawValue("lumOff"); - } - - public int getLumMod() { - return getRawValue("lumMod"); - } - - public int getShade() { - return getRawValue("shade"); - } - - public int getTint() { - return getRawValue("tint"); - } - }; - } - - Color toColor(XmlObject obj, XSLFTheme theme) { - Color color = null; - for (XmlObject ch : obj.selectPath("*")) { - if (ch instanceof CTHslColor) { - CTHslColor hsl = (CTHslColor)ch; - int h = hsl.getHue2(); - int s = hsl.getSat2(); - int l = hsl.getLum2(); - color = DrawPaint.HSL2RGB(h / 60000d, s / 1000d, l / 1000d, 1d); - } else if (ch instanceof CTPresetColor) { - CTPresetColor prst = (CTPresetColor)ch; - String colorName = prst.getVal().toString(); - PresetColor pc = PresetColor.valueOfOoxmlId(colorName); - if (pc != null) { - color = pc.color; - } - } else if (ch instanceof CTSchemeColor) { - CTSchemeColor schemeColor = (CTSchemeColor)ch; - String colorRef = schemeColor.getVal().toString(); - if(_phClr != null) { - // context color overrides the theme - colorRef = _phClr.getVal().toString(); - } - // find referenced CTColor in the theme and convert it to java.awt.Color via a recursive call - CTColor ctColor = theme.getCTColor(colorRef); - if(ctColor != null) color = toColor(ctColor, null); - } else if (ch instanceof CTScRgbColor) { - // color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color - CTScRgbColor scrgb = (CTScRgbColor)ch; - color = new Color(DrawPaint.lin2srgb(scrgb.getR()), DrawPaint.lin2srgb(scrgb.getG()), DrawPaint.lin2srgb(scrgb.getB())); - } else if (ch instanceof CTSRgbColor) { - // color in sRGB color space, i.e. same as AWT Color - CTSRgbColor srgb = (CTSRgbColor)ch; - byte[] val = srgb.getVal(); - color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); - } else if (ch instanceof CTSystemColor) { - CTSystemColor sys = (CTSystemColor)ch; - if(sys.isSetLastClr()) { - byte[] val = sys.getLastClr(); - color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); - } else { - String colorName = sys.getVal().toString(); - PresetColor pc = PresetColor.valueOfOoxmlId(colorName); - if (pc != null) { - color = pc.color; - } - if (color == null) { - color = Color.black; - } - } - } else if (ch instanceof CTFontReference) { - // try next ... - continue; - } else { - throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass()); - } - } - return color; - } - - /** - * Sets the solid color - * - * @param color solid color - */ - @Internal - protected void setColor(Color color) { - if (!(_xmlObject instanceof CTSolidColorFillProperties)) { - LOGGER.log(POILogger.ERROR, "XSLFColor.setColor currently only supports CTSolidColorFillProperties"); - return; - } - CTSolidColorFillProperties fill = (CTSolidColorFillProperties)_xmlObject; - if (fill.isSetSrgbClr()) { - fill.unsetSrgbClr(); - } - - if (fill.isSetScrgbClr()) { - fill.unsetScrgbClr(); - } - - if (fill.isSetHslClr()) { - fill.unsetHslClr(); - } - - if (fill.isSetPrstClr()) { - fill.unsetPrstClr(); - } - - if (fill.isSetSchemeClr()) { - fill.unsetSchemeClr(); - } - - if (fill.isSetSysClr()) { - fill.unsetSysClr(); - } - - float[] rgbaf = color.getRGBComponents(null); - boolean addAlpha = (rgbaf.length == 4 && rgbaf[3] < 1f); - CTPositiveFixedPercentage alphaPct; - - // see office open xml part 4 - 5.1.2.2.30 and 5.1.2.2.32 - if (isInt(rgbaf[0]) && isInt(rgbaf[1]) && isInt(rgbaf[2])) { - // sRGB has a gamma of 2.2 - CTSRgbColor rgb = fill.addNewSrgbClr(); - - byte rgbBytes[] = { (byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue() }; - rgb.setVal(rgbBytes); - alphaPct = (addAlpha) ? rgb.addNewAlpha() : null; - } else { - CTScRgbColor rgb = fill.addNewScrgbClr(); - rgb.setR(DrawPaint.srgb2lin(rgbaf[0])); - rgb.setG(DrawPaint.srgb2lin(rgbaf[1])); - rgb.setB(DrawPaint.srgb2lin(rgbaf[2])); - alphaPct = (addAlpha) ? rgb.addNewAlpha() : null; - } - - // alpha (%) - if (alphaPct != null) { - alphaPct.setVal((int)(100000 * rgbaf[3])); - } - } - - /** - * @return true, if this is an integer color value - */ - private static boolean isInt(float f) { - return Math.abs((f*255f) - Math.rint(f*255f)) < 0.00001f; - } - - private int getRawValue(String elem) { - String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem; - - XmlObject[] obj; - - // first ask the context color and if not found, ask the actual color bean - if (_phClr != null){ - obj = _phClr.selectPath(query); - if (obj.length == 1){ - Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); - if(attr != null) { - return Integer.parseInt(attr.getNodeValue()); - } - } - } - - obj = _xmlObject.selectPath(query); - if (obj.length == 1){ - Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); - if(attr != null) { - return Integer.parseInt(attr.getNodeValue()); - } - } - - return -1; - } - - /** - * Read a perecentage value from the supplied xml bean. - * Example: - * - * - * the returned value is 45 - * - * @return the percentage value in the range [0 .. 100] - */ - private int getPercentageValue(String elem){ - int val = getRawValue(elem); - return (val == -1) ? val : (val / 1000); - } - - private int getAngleValue(String elem){ - int val = getRawValue(elem); - return (val == -1) ? val : (val / 60000); - } - - /** - * the opacity as expressed by a percentage value - * - * @return opacity in percents in the range [0..100] - * or -1 if the value is not set - */ - int getAlpha(){ - return getPercentageValue("alpha"); - } - - /** - * the opacity as expressed by a percentage relative to the input color - * - * @return opacity in percents in the range [0..100] - * or -1 if the value is not set - */ - int getAlphaMod(){ - return getPercentageValue("alphaMod"); - } - - /** - * the opacity as expressed by a percentage offset increase or decrease relative to - * the input color. Increases will never increase the opacity beyond 100%, decreases will - * never decrease the opacity below 0%. - * - * @return opacity shift in percents in the range [0..100] - * or -1 if the value is not set - */ - int getAlphaOff(){ - return getPercentageValue("alphaOff"); - } - - - int getHue(){ - return getAngleValue("hue"); - } - - int getHueMod(){ - return getPercentageValue("hueMod"); - } - - int getHueOff(){ - return getPercentageValue("hueOff"); - } - - /** - * specifies the input color with the specified luminance, - * but with its hue and saturation unchanged. - * - * @return luminance in percents in the range [0..100] - * or -1 if the value is not set - */ - int getLum(){ - return getPercentageValue("lum"); - } - - /** - * the luminance as expressed by a percentage relative to the input color - * - * @return luminance in percents in the range [0..100] - * or -1 if the value is not set - */ - int getLumMod(){ - return getPercentageValue("lumMod"); - } - - /** - * the luminance shift as expressed by a percentage relative to the input color - * - * @return luminance shift in percents in the range [0..100] - * or -1 if the value is not set - */ - int getLumOff(){ - return getPercentageValue("lumOff"); - } - - /** - * specifies the input color with the specified saturation, - * but with its hue and luminance unchanged. - * - * @return saturation in percents in the range [0..100] - * or -1 if the value is not set - */ - int getSat(){ - return getPercentageValue("sat"); - } - - /** - * the saturation as expressed by a percentage relative to the input color - * - * @return saturation in percents in the range [0..100] - * or -1 if the value is not set - */ - int getSatMod(){ - return getPercentageValue("satMod"); - } - - /** - * the saturation shift as expressed by a percentage relative to the input color - * - * @return saturation shift in percents in the range [0..100] - * or -1 if the value is not set - */ - int getSatOff(){ - return getPercentageValue("satOff"); - } - - /** - * specifies the input color with the specific red component, but with the blue and green color - * components unchanged - * - * @return the value of the red component specified as a - * percentage with 0% indicating minimal blue and 100% indicating maximum - * or -1 if the value is not set - */ - int getRed(){ - return getPercentageValue("red"); - } - - int getRedMod(){ - return getPercentageValue("redMod"); - } - - int getRedOff(){ - return getPercentageValue("redOff"); - } - - /** - * specifies the input color with the specific green component, but with the red and blue color - * components unchanged - * - * @return the value of the green component specified as a - * percentage with 0% indicating minimal blue and 100% indicating maximum - * or -1 if the value is not set - */ - int getGreen(){ - return getPercentageValue("green"); - } - - int getGreenMod(){ - return getPercentageValue("greenMod"); - } - - int getGreenOff(){ - return getPercentageValue("greenOff"); - } - - /** - * specifies the input color with the specific blue component, but with the red and green color - * components unchanged - * - * @return the value of the blue component specified as a - * percentage with 0% indicating minimal blue and 100% indicating maximum - * or -1 if the value is not set - */ - int getBlue(){ - return getPercentageValue("blue"); - } - - int getBlueMod(){ - return getPercentageValue("blueMod"); - } - - int getBlueOff(){ - return getPercentageValue("blueOff"); - } - - /** - * specifies a darker version of its input color. - * A 10% shade is 10% of the input color combined with 90% black. - * - * @return the value of the shade specified as a - * percentage with 0% indicating minimal shade and 100% indicating maximum - * or -1 if the value is not set - */ - public int getShade(){ - return getPercentageValue("shade"); - } - - /** - * specifies a lighter version of its input color. - * A 10% tint is 10% of the input color combined with 90% white. - * - * @return the value of the tint specified as a - * percentage with 0% indicating minimal tint and 100% indicating maximum - * or -1 if the value is not set - */ - public int getTint(){ - return getPercentageValue("tint"); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; + +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.ColorStyle; +import org.apache.poi.sl.usermodel.PresetColor; +import org.apache.poi.util.Beta; +import org.apache.poi.util.Internal; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference; +import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveFixedPercentage; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTScRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSystemColor; +import org.w3c.dom.Node; + +/** + * Encapsulates logic to read color definitions from DrawingML and convert them to java.awt.Color + */ +@Beta +@Internal +public class XSLFColor { + private final static POILogger LOGGER = POILogFactory.getLogger(XSLFColor.class); + + private XmlObject _xmlObject; + private Color _color; + private CTSchemeColor _phClr; + + public XSLFColor(XmlObject obj, XSLFTheme theme, CTSchemeColor phClr) { + _xmlObject = obj; + _phClr = phClr; + _color = toColor(obj, theme); + } + + @Internal + public XmlObject getXmlObject() { + return _xmlObject; + } + + /** + * + * @return the displayed color as a Java Color. + * If not color information was found in the supplied xml object then a null is returned. + */ + public Color getColor() { + return DrawPaint.applyColorTransform(getColorStyle()); + } + + public ColorStyle getColorStyle() { + return new ColorStyle() { + public Color getColor() { + return _color; + } + + public int getAlpha() { + return getRawValue("alpha"); + } + + public int getHueOff() { + return getRawValue("hueOff"); + } + + public int getHueMod() { + return getRawValue("hueMod"); + } + + public int getSatOff() { + return getRawValue("satOff"); + } + + public int getSatMod() { + return getRawValue("satMod"); + } + + public int getLumOff() { + return getRawValue("lumOff"); + } + + public int getLumMod() { + return getRawValue("lumMod"); + } + + public int getShade() { + return getRawValue("shade"); + } + + public int getTint() { + return getRawValue("tint"); + } + }; + } + + Color toColor(XmlObject obj, XSLFTheme theme) { + Color color = null; + for (XmlObject ch : obj.selectPath("*")) { + if (ch instanceof CTHslColor) { + CTHslColor hsl = (CTHslColor)ch; + int h = hsl.getHue2(); + int s = hsl.getSat2(); + int l = hsl.getLum2(); + color = DrawPaint.HSL2RGB(h / 60000d, s / 1000d, l / 1000d, 1d); + } else if (ch instanceof CTPresetColor) { + CTPresetColor prst = (CTPresetColor)ch; + String colorName = prst.getVal().toString(); + PresetColor pc = PresetColor.valueOfOoxmlId(colorName); + if (pc != null) { + color = pc.color; + } + } else if (ch instanceof CTSchemeColor) { + CTSchemeColor schemeColor = (CTSchemeColor)ch; + String colorRef = schemeColor.getVal().toString(); + if(_phClr != null) { + // context color overrides the theme + colorRef = _phClr.getVal().toString(); + } + // find referenced CTColor in the theme and convert it to java.awt.Color via a recursive call + CTColor ctColor = theme.getCTColor(colorRef); + if(ctColor != null) color = toColor(ctColor, null); + } else if (ch instanceof CTScRgbColor) { + // color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color + CTScRgbColor scrgb = (CTScRgbColor)ch; + color = new Color(DrawPaint.lin2srgb(scrgb.getR()), DrawPaint.lin2srgb(scrgb.getG()), DrawPaint.lin2srgb(scrgb.getB())); + } else if (ch instanceof CTSRgbColor) { + // color in sRGB color space, i.e. same as AWT Color + CTSRgbColor srgb = (CTSRgbColor)ch; + byte[] val = srgb.getVal(); + color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); + } else if (ch instanceof CTSystemColor) { + CTSystemColor sys = (CTSystemColor)ch; + if(sys.isSetLastClr()) { + byte[] val = sys.getLastClr(); + color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); + } else { + String colorName = sys.getVal().toString(); + PresetColor pc = PresetColor.valueOfOoxmlId(colorName); + if (pc != null) { + color = pc.color; + } + if (color == null) { + color = Color.black; + } + } + } else if (ch instanceof CTFontReference) { + // try next ... + continue; + } else { + throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass()); + } + } + return color; + } + + /** + * Sets the solid color + * + * @param color solid color + */ + @Internal + protected void setColor(Color color) { + if (!(_xmlObject instanceof CTSolidColorFillProperties)) { + LOGGER.log(POILogger.ERROR, "XSLFColor.setColor currently only supports CTSolidColorFillProperties"); + return; + } + CTSolidColorFillProperties fill = (CTSolidColorFillProperties)_xmlObject; + if (fill.isSetSrgbClr()) { + fill.unsetSrgbClr(); + } + + if (fill.isSetScrgbClr()) { + fill.unsetScrgbClr(); + } + + if (fill.isSetHslClr()) { + fill.unsetHslClr(); + } + + if (fill.isSetPrstClr()) { + fill.unsetPrstClr(); + } + + if (fill.isSetSchemeClr()) { + fill.unsetSchemeClr(); + } + + if (fill.isSetSysClr()) { + fill.unsetSysClr(); + } + + float[] rgbaf = color.getRGBComponents(null); + boolean addAlpha = (rgbaf.length == 4 && rgbaf[3] < 1f); + CTPositiveFixedPercentage alphaPct; + + // see office open xml part 4 - 5.1.2.2.30 and 5.1.2.2.32 + if (isInt(rgbaf[0]) && isInt(rgbaf[1]) && isInt(rgbaf[2])) { + // sRGB has a gamma of 2.2 + CTSRgbColor rgb = fill.addNewSrgbClr(); + + byte rgbBytes[] = { (byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue() }; + rgb.setVal(rgbBytes); + alphaPct = (addAlpha) ? rgb.addNewAlpha() : null; + } else { + CTScRgbColor rgb = fill.addNewScrgbClr(); + rgb.setR(DrawPaint.srgb2lin(rgbaf[0])); + rgb.setG(DrawPaint.srgb2lin(rgbaf[1])); + rgb.setB(DrawPaint.srgb2lin(rgbaf[2])); + alphaPct = (addAlpha) ? rgb.addNewAlpha() : null; + } + + // alpha (%) + if (alphaPct != null) { + alphaPct.setVal((int)(100000 * rgbaf[3])); + } + } + + /** + * @return true, if this is an integer color value + */ + private static boolean isInt(float f) { + return Math.abs((f*255f) - Math.rint(f*255f)) < 0.00001f; + } + + private int getRawValue(String elem) { + String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem; + + XmlObject[] obj; + + // first ask the context color and if not found, ask the actual color bean + if (_phClr != null){ + obj = _phClr.selectPath(query); + if (obj.length == 1){ + Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); + if(attr != null) { + return Integer.parseInt(attr.getNodeValue()); + } + } + } + + obj = _xmlObject.selectPath(query); + if (obj.length == 1){ + Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); + if(attr != null) { + return Integer.parseInt(attr.getNodeValue()); + } + } + + return -1; + } + + /** + * Read a perecentage value from the supplied xml bean. + * Example: + * + * + * the returned value is 45 + * + * @return the percentage value in the range [0 .. 100] + */ + private int getPercentageValue(String elem){ + int val = getRawValue(elem); + return (val == -1) ? val : (val / 1000); + } + + private int getAngleValue(String elem){ + int val = getRawValue(elem); + return (val == -1) ? val : (val / 60000); + } + + /** + * the opacity as expressed by a percentage value + * + * @return opacity in percents in the range [0..100] + * or -1 if the value is not set + */ + int getAlpha(){ + return getPercentageValue("alpha"); + } + + /** + * the opacity as expressed by a percentage relative to the input color + * + * @return opacity in percents in the range [0..100] + * or -1 if the value is not set + */ + int getAlphaMod(){ + return getPercentageValue("alphaMod"); + } + + /** + * the opacity as expressed by a percentage offset increase or decrease relative to + * the input color. Increases will never increase the opacity beyond 100%, decreases will + * never decrease the opacity below 0%. + * + * @return opacity shift in percents in the range [0..100] + * or -1 if the value is not set + */ + int getAlphaOff(){ + return getPercentageValue("alphaOff"); + } + + + int getHue(){ + return getAngleValue("hue"); + } + + int getHueMod(){ + return getPercentageValue("hueMod"); + } + + int getHueOff(){ + return getPercentageValue("hueOff"); + } + + /** + * specifies the input color with the specified luminance, + * but with its hue and saturation unchanged. + * + * @return luminance in percents in the range [0..100] + * or -1 if the value is not set + */ + int getLum(){ + return getPercentageValue("lum"); + } + + /** + * the luminance as expressed by a percentage relative to the input color + * + * @return luminance in percents in the range [0..100] + * or -1 if the value is not set + */ + int getLumMod(){ + return getPercentageValue("lumMod"); + } + + /** + * the luminance shift as expressed by a percentage relative to the input color + * + * @return luminance shift in percents in the range [0..100] + * or -1 if the value is not set + */ + int getLumOff(){ + return getPercentageValue("lumOff"); + } + + /** + * specifies the input color with the specified saturation, + * but with its hue and luminance unchanged. + * + * @return saturation in percents in the range [0..100] + * or -1 if the value is not set + */ + int getSat(){ + return getPercentageValue("sat"); + } + + /** + * the saturation as expressed by a percentage relative to the input color + * + * @return saturation in percents in the range [0..100] + * or -1 if the value is not set + */ + int getSatMod(){ + return getPercentageValue("satMod"); + } + + /** + * the saturation shift as expressed by a percentage relative to the input color + * + * @return saturation shift in percents in the range [0..100] + * or -1 if the value is not set + */ + int getSatOff(){ + return getPercentageValue("satOff"); + } + + /** + * specifies the input color with the specific red component, but with the blue and green color + * components unchanged + * + * @return the value of the red component specified as a + * percentage with 0% indicating minimal blue and 100% indicating maximum + * or -1 if the value is not set + */ + int getRed(){ + return getPercentageValue("red"); + } + + int getRedMod(){ + return getPercentageValue("redMod"); + } + + int getRedOff(){ + return getPercentageValue("redOff"); + } + + /** + * specifies the input color with the specific green component, but with the red and blue color + * components unchanged + * + * @return the value of the green component specified as a + * percentage with 0% indicating minimal blue and 100% indicating maximum + * or -1 if the value is not set + */ + int getGreen(){ + return getPercentageValue("green"); + } + + int getGreenMod(){ + return getPercentageValue("greenMod"); + } + + int getGreenOff(){ + return getPercentageValue("greenOff"); + } + + /** + * specifies the input color with the specific blue component, but with the red and green color + * components unchanged + * + * @return the value of the blue component specified as a + * percentage with 0% indicating minimal blue and 100% indicating maximum + * or -1 if the value is not set + */ + int getBlue(){ + return getPercentageValue("blue"); + } + + int getBlueMod(){ + return getPercentageValue("blueMod"); + } + + int getBlueOff(){ + return getPercentageValue("blueOff"); + } + + /** + * specifies a darker version of its input color. + * A 10% shade is 10% of the input color combined with 90% black. + * + * @return the value of the shade specified as a + * percentage with 0% indicating minimal shade and 100% indicating maximum + * or -1 if the value is not set + */ + public int getShade(){ + return getPercentageValue("shade"); + } + + /** + * specifies a lighter version of its input color. + * A 10% tint is 10% of the input color combined with 90% white. + * + * @return the value of the tint specified as a + * percentage with 0% indicating minimal tint and 100% indicating maximum + * or -1 if the value is not set + */ + public int getTint(){ + return getPercentageValue("tint"); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java index 0ca895efa8..c7bf948a91 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java @@ -1,78 +1,78 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import org.apache.poi.POIXMLException; -import org.apache.poi.sl.usermodel.ConnectorShape; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.util.Beta; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; -import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual; - -/** - * Specifies a connection shape. - * - * @author Yegor Kozlov - */ -@Beta -public class XSLFConnectorShape extends XSLFSimpleShape - implements ConnectorShape { - - /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet) { - super(shape, sheet); - } - - /** - * @param shapeId 1-based shapeId - */ - static CTConnector prototype(int shapeId) { - CTConnector ct = CTConnector.Factory.newInstance(); - CTConnectorNonVisual nvSpPr = ct.addNewNvCxnSpPr(); - CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); - cnv.setName("Connector " + shapeId); - cnv.setId(shapeId + 1); - nvSpPr.addNewCNvCxnSpPr(); - nvSpPr.addNewNvPr(); - CTShapeProperties spPr = ct.addNewSpPr(); - CTPresetGeometry2D prst = spPr.addNewPrstGeom(); - prst.setPrst(STShapeType.LINE); - prst.addNewAvLst(); - /* CTLineProperties ln = */ spPr.addNewLn(); - return ct; - } - - - /** - * YK: shadows of lines are suppressed for now. - */ - @Override - public XSLFShadow getShadow() { - return null; - } - - @Override - public void setPlaceholder(Placeholder placeholder) { - throw new POIXMLException("A connector shape can't be a placeholder."); - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.POIXMLException; +import org.apache.poi.sl.usermodel.ConnectorShape; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual; + +/** + * Specifies a connection shape. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFConnectorShape extends XSLFSimpleShape + implements ConnectorShape { + + /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet) { + super(shape, sheet); + } + + /** + * @param shapeId 1-based shapeId + */ + static CTConnector prototype(int shapeId) { + CTConnector ct = CTConnector.Factory.newInstance(); + CTConnectorNonVisual nvSpPr = ct.addNewNvCxnSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Connector " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvCxnSpPr(); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.LINE); + prst.addNewAvLst(); + /* CTLineProperties ln = */ spPr.addNewLn(); + return ct; + } + + + /** + * YK: shadows of lines are suppressed for now. + */ + @Override + public XSLFShadow getShadow() { + return null; + } + + @Override + public void setPlaceholder(Placeholder placeholder) { + throw new POIXMLException("A connector shape can't be a placeholder."); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java index ccf0c7b301..058507c01e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java @@ -1,113 +1,113 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; -import java.awt.geom.Rectangle2D; - -import org.apache.poi.util.Beta; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; - - -/** - * @author Yegor Kozlov - */ -@Beta -public class XSLFDrawing { - private XSLFSheet _sheet; - private int _shapeId = 1; - private CTGroupShape _spTree; - - /*package*/ XSLFDrawing(XSLFSheet sheet, CTGroupShape spTree){ - _sheet = sheet; - _spTree = spTree; - XmlObject[] cNvPr = sheet.getSpTree().selectPath( - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"); - for(XmlObject o : cNvPr) { - // powerpoint generates AlternateContent elements which cNvPr elements aren't recognized - // ignore them for now - if (o instanceof CTNonVisualDrawingProps) { - CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o; - _shapeId = (int)Math.max(_shapeId, p.getId()); - } - } - } - - public XSLFAutoShape createAutoShape(){ - CTShape sp = _spTree.addNewSp(); - sp.set(XSLFAutoShape.prototype(_shapeId++)); - XSLFAutoShape shape = new XSLFAutoShape(sp, _sheet); - shape.setAnchor(new Rectangle2D.Double()); - return shape; - } - - public XSLFFreeformShape createFreeform(){ - CTShape sp = _spTree.addNewSp(); - sp.set(XSLFFreeformShape.prototype(_shapeId++)); - XSLFFreeformShape shape = new XSLFFreeformShape(sp, _sheet); - shape.setAnchor(new Rectangle2D.Double()); - return shape; - } - - public XSLFTextBox createTextBox(){ - CTShape sp = _spTree.addNewSp(); - sp.set(XSLFTextBox.prototype(_shapeId++)); - XSLFTextBox shape = new XSLFTextBox(sp, _sheet); - shape.setAnchor(new Rectangle2D.Double()); - return shape; - } - - public XSLFConnectorShape createConnector(){ - CTConnector sp = _spTree.addNewCxnSp(); - sp.set(XSLFConnectorShape.prototype(_shapeId++)); - XSLFConnectorShape shape = new XSLFConnectorShape(sp, _sheet); - shape.setAnchor(new Rectangle2D.Double()); - shape.setLineColor(Color.black); - shape.setLineWidth(0.75); - return shape; - } - - public XSLFGroupShape createGroup(){ - CTGroupShape obj = _spTree.addNewGrpSp(); - obj.set(XSLFGroupShape.prototype(_shapeId++)); - XSLFGroupShape shape = new XSLFGroupShape(obj, _sheet); - shape.setAnchor(new Rectangle2D.Double()); - return shape; - } - - public XSLFPictureShape createPicture(String rel){ - CTPicture obj = _spTree.addNewPic(); - obj.set(XSLFPictureShape.prototype(_shapeId++, rel)); - XSLFPictureShape shape = new XSLFPictureShape(obj, _sheet); - shape.setAnchor(new Rectangle2D.Double()); - return shape; - } - - public XSLFTable createTable(){ - CTGraphicalObjectFrame obj = _spTree.addNewGraphicFrame(); - obj.set(XSLFTable.prototype(_shapeId++)); - XSLFTable shape = new XSLFTable(obj, _sheet); - shape.setAnchor(new Rectangle2D.Double()); - return shape; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.util.Beta; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; + + +/** + * @author Yegor Kozlov + */ +@Beta +public class XSLFDrawing { + private XSLFSheet _sheet; + private int _shapeId = 1; + private CTGroupShape _spTree; + + /*package*/ XSLFDrawing(XSLFSheet sheet, CTGroupShape spTree){ + _sheet = sheet; + _spTree = spTree; + XmlObject[] cNvPr = sheet.getSpTree().selectPath( + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"); + for(XmlObject o : cNvPr) { + // powerpoint generates AlternateContent elements which cNvPr elements aren't recognized + // ignore them for now + if (o instanceof CTNonVisualDrawingProps) { + CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o; + _shapeId = (int)Math.max(_shapeId, p.getId()); + } + } + } + + public XSLFAutoShape createAutoShape(){ + CTShape sp = _spTree.addNewSp(); + sp.set(XSLFAutoShape.prototype(_shapeId++)); + XSLFAutoShape shape = new XSLFAutoShape(sp, _sheet); + shape.setAnchor(new Rectangle2D.Double()); + return shape; + } + + public XSLFFreeformShape createFreeform(){ + CTShape sp = _spTree.addNewSp(); + sp.set(XSLFFreeformShape.prototype(_shapeId++)); + XSLFFreeformShape shape = new XSLFFreeformShape(sp, _sheet); + shape.setAnchor(new Rectangle2D.Double()); + return shape; + } + + public XSLFTextBox createTextBox(){ + CTShape sp = _spTree.addNewSp(); + sp.set(XSLFTextBox.prototype(_shapeId++)); + XSLFTextBox shape = new XSLFTextBox(sp, _sheet); + shape.setAnchor(new Rectangle2D.Double()); + return shape; + } + + public XSLFConnectorShape createConnector(){ + CTConnector sp = _spTree.addNewCxnSp(); + sp.set(XSLFConnectorShape.prototype(_shapeId++)); + XSLFConnectorShape shape = new XSLFConnectorShape(sp, _sheet); + shape.setAnchor(new Rectangle2D.Double()); + shape.setLineColor(Color.black); + shape.setLineWidth(0.75); + return shape; + } + + public XSLFGroupShape createGroup(){ + CTGroupShape obj = _spTree.addNewGrpSp(); + obj.set(XSLFGroupShape.prototype(_shapeId++)); + XSLFGroupShape shape = new XSLFGroupShape(obj, _sheet); + shape.setAnchor(new Rectangle2D.Double()); + return shape; + } + + public XSLFPictureShape createPicture(String rel){ + CTPicture obj = _spTree.addNewPic(); + obj.set(XSLFPictureShape.prototype(_shapeId++, rel)); + XSLFPictureShape shape = new XSLFPictureShape(obj, _sheet); + shape.setAnchor(new Rectangle2D.Double()); + return shape; + } + + public XSLFTable createTable(){ + CTGraphicalObjectFrame obj = _spTree.addNewGraphicFrame(); + obj.set(XSLFTable.prototype(_shapeId++)); + XSLFTable shape = new XSLFTable(obj, _sheet); + shape.setAnchor(new Rectangle2D.Double()); + return shape; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java index 3e482d3ea3..e4c02f58da 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java @@ -1,209 +1,209 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.geom.AffineTransform; -import java.awt.geom.Path2D; -import java.awt.geom.PathIterator; -import java.awt.geom.Rectangle2D; - -import org.apache.poi.sl.usermodel.FreeformShape; -import org.apache.poi.util.Beta; -import org.apache.poi.util.Units; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomRect; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DClose; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DCubicBezierTo; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DLineTo; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DMoveTo; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DQuadBezierTo; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; - -/** - * Represents a custom geometric shape. - * This shape will consist of a series of lines and curves described within a creation path. - */ -@Beta -public class XSLFFreeformShape extends XSLFAutoShape - implements FreeformShape { - - /*package*/ XSLFFreeformShape(CTShape shape, XSLFSheet sheet) { - super(shape, sheet); - } - - @Override - public int setPath(Path2D.Double path) { - CTPath2D ctPath = CTPath2D.Factory.newInstance(); - - Rectangle2D bounds = path.getBounds2D(); - int x0 = Units.toEMU(bounds.getX()); - int y0 = Units.toEMU(bounds.getY()); - PathIterator it = path.getPathIterator(new AffineTransform()); - int numPoints = 0; - ctPath.setH(Units.toEMU(bounds.getHeight())); - ctPath.setW(Units.toEMU(bounds.getWidth())); - while (!it.isDone()) { - double[] vals = new double[6]; - int type = it.currentSegment(vals); - switch (type) { - case PathIterator.SEG_MOVETO: - CTAdjPoint2D mv = ctPath.addNewMoveTo().addNewPt(); - mv.setX(Units.toEMU(vals[0]) - x0); - mv.setY(Units.toEMU(vals[1]) - y0); - numPoints++; - break; - case PathIterator.SEG_LINETO: - CTAdjPoint2D ln = ctPath.addNewLnTo().addNewPt(); - ln.setX(Units.toEMU(vals[0]) - x0); - ln.setY(Units.toEMU(vals[1]) - y0); - numPoints++; - break; - case PathIterator.SEG_QUADTO: - CTPath2DQuadBezierTo qbez = ctPath.addNewQuadBezTo(); - CTAdjPoint2D qp1 = qbez.addNewPt(); - qp1.setX(Units.toEMU(vals[0]) - x0); - qp1.setY(Units.toEMU(vals[1]) - y0); - CTAdjPoint2D qp2 = qbez.addNewPt(); - qp2.setX(Units.toEMU(vals[2]) - x0); - qp2.setY(Units.toEMU(vals[3]) - y0); - numPoints += 2; - break; - case PathIterator.SEG_CUBICTO: - CTPath2DCubicBezierTo bez = ctPath.addNewCubicBezTo(); - CTAdjPoint2D p1 = bez.addNewPt(); - p1.setX(Units.toEMU(vals[0]) - x0); - p1.setY(Units.toEMU(vals[1]) - y0); - CTAdjPoint2D p2 = bez.addNewPt(); - p2.setX(Units.toEMU(vals[2]) - x0); - p2.setY(Units.toEMU(vals[3]) - y0); - CTAdjPoint2D p3 = bez.addNewPt(); - p3.setX(Units.toEMU(vals[4]) - x0); - p3.setY(Units.toEMU(vals[5]) - y0); - numPoints += 3; - break; - case PathIterator.SEG_CLOSE: - numPoints++; - ctPath.addNewClose(); - break; - default: - throw new IllegalStateException("Unrecognized path segment type: " + type); - } - it.next(); - } - - XmlObject xo = getShapeProperties(); - if (!(xo instanceof CTShapeProperties)) { - return -1; - } - - ((CTShapeProperties)xo).getCustGeom().getPathLst().setPathArray(new CTPath2D[]{ctPath}); - setAnchor(bounds); - return numPoints; - } - - @Override - public Path2D.Double getPath() { - Path2D.Double path = new Path2D.Double(); - Rectangle2D bounds = getAnchor(); - - XmlObject xo = getShapeProperties(); - if (!(xo instanceof CTShapeProperties)) { - return null; - } - - CTCustomGeometry2D geom = ((CTShapeProperties)xo).getCustGeom(); - for(CTPath2D spPath : geom.getPathLst().getPathArray()){ - double scaleW = bounds.getWidth() / Units.toPoints(spPath.getW()); - double scaleH = bounds.getHeight() / Units.toPoints(spPath.getH()); - for(XmlObject ch : spPath.selectPath("*")){ - if(ch instanceof CTPath2DMoveTo){ - CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt(); - path.moveTo( - (float) (Units.toPoints((Long) pt.getX()) * scaleW), - (float) (Units.toPoints((Long) pt.getY()) * scaleH)); - } else if (ch instanceof CTPath2DLineTo){ - CTAdjPoint2D pt = ((CTPath2DLineTo)ch).getPt(); - path.lineTo((float)Units.toPoints((Long)pt.getX()), - (float)Units.toPoints((Long)pt.getY())); - } else if (ch instanceof CTPath2DQuadBezierTo){ - CTPath2DQuadBezierTo bez = ((CTPath2DQuadBezierTo)ch); - CTAdjPoint2D pt1 = bez.getPtArray(0); - CTAdjPoint2D pt2 = bez.getPtArray(1); - path.quadTo( - (float) (Units.toPoints((Long) pt1.getX()) * scaleW), - (float) (Units.toPoints((Long) pt1.getY()) * scaleH), - (float) (Units.toPoints((Long) pt2.getX()) * scaleW), - (float) (Units.toPoints((Long) pt2.getY()) * scaleH)); - } else if (ch instanceof CTPath2DCubicBezierTo){ - CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch); - CTAdjPoint2D pt1 = bez.getPtArray(0); - CTAdjPoint2D pt2 = bez.getPtArray(1); - CTAdjPoint2D pt3 = bez.getPtArray(2); - path.curveTo( - (float) (Units.toPoints((Long) pt1.getX()) * scaleW), - (float) (Units.toPoints((Long) pt1.getY()) * scaleH), - (float) (Units.toPoints((Long) pt2.getX()) * scaleW), - (float) (Units.toPoints((Long) pt2.getY()) * scaleH), - (float) (Units.toPoints((Long) pt3.getX()) * scaleW), - (float) (Units.toPoints((Long) pt3.getY()) * scaleH)); - } else if (ch instanceof CTPath2DClose){ - path.closePath(); - } - } - } - - // the created path starts at (x=0, y=0). - // The returned path should fit in the bounding rectangle - AffineTransform at = new AffineTransform(); - at.translate(bounds.getX(), bounds.getY()); - return new Path2D.Double(at.createTransformedShape(path)); - } - /** - * @param shapeId 1-based shapeId - */ - static CTShape prototype(int shapeId) { - CTShape ct = CTShape.Factory.newInstance(); - CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); - CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); - cnv.setName("Freeform " + shapeId); - cnv.setId(shapeId + 1); - nvSpPr.addNewCNvSpPr(); - nvSpPr.addNewNvPr(); - CTShapeProperties spPr = ct.addNewSpPr(); - CTCustomGeometry2D geom = spPr.addNewCustGeom(); - geom.addNewAvLst(); - geom.addNewGdLst(); - geom.addNewAhLst(); - geom.addNewCxnLst(); - CTGeomRect rect = geom.addNewRect(); - rect.setR("r"); - rect.setB("b"); - rect.setT("t"); - rect.setL("l"); - geom.addNewPathLst(); - return ct; - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.sl.usermodel.FreeformShape; +import org.apache.poi.util.Beta; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomRect; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DClose; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DCubicBezierTo; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DLineTo; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DMoveTo; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPath2DQuadBezierTo; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; + +/** + * Represents a custom geometric shape. + * This shape will consist of a series of lines and curves described within a creation path. + */ +@Beta +public class XSLFFreeformShape extends XSLFAutoShape + implements FreeformShape { + + /*package*/ XSLFFreeformShape(CTShape shape, XSLFSheet sheet) { + super(shape, sheet); + } + + @Override + public int setPath(Path2D.Double path) { + CTPath2D ctPath = CTPath2D.Factory.newInstance(); + + Rectangle2D bounds = path.getBounds2D(); + int x0 = Units.toEMU(bounds.getX()); + int y0 = Units.toEMU(bounds.getY()); + PathIterator it = path.getPathIterator(new AffineTransform()); + int numPoints = 0; + ctPath.setH(Units.toEMU(bounds.getHeight())); + ctPath.setW(Units.toEMU(bounds.getWidth())); + while (!it.isDone()) { + double[] vals = new double[6]; + int type = it.currentSegment(vals); + switch (type) { + case PathIterator.SEG_MOVETO: + CTAdjPoint2D mv = ctPath.addNewMoveTo().addNewPt(); + mv.setX(Units.toEMU(vals[0]) - x0); + mv.setY(Units.toEMU(vals[1]) - y0); + numPoints++; + break; + case PathIterator.SEG_LINETO: + CTAdjPoint2D ln = ctPath.addNewLnTo().addNewPt(); + ln.setX(Units.toEMU(vals[0]) - x0); + ln.setY(Units.toEMU(vals[1]) - y0); + numPoints++; + break; + case PathIterator.SEG_QUADTO: + CTPath2DQuadBezierTo qbez = ctPath.addNewQuadBezTo(); + CTAdjPoint2D qp1 = qbez.addNewPt(); + qp1.setX(Units.toEMU(vals[0]) - x0); + qp1.setY(Units.toEMU(vals[1]) - y0); + CTAdjPoint2D qp2 = qbez.addNewPt(); + qp2.setX(Units.toEMU(vals[2]) - x0); + qp2.setY(Units.toEMU(vals[3]) - y0); + numPoints += 2; + break; + case PathIterator.SEG_CUBICTO: + CTPath2DCubicBezierTo bez = ctPath.addNewCubicBezTo(); + CTAdjPoint2D p1 = bez.addNewPt(); + p1.setX(Units.toEMU(vals[0]) - x0); + p1.setY(Units.toEMU(vals[1]) - y0); + CTAdjPoint2D p2 = bez.addNewPt(); + p2.setX(Units.toEMU(vals[2]) - x0); + p2.setY(Units.toEMU(vals[3]) - y0); + CTAdjPoint2D p3 = bez.addNewPt(); + p3.setX(Units.toEMU(vals[4]) - x0); + p3.setY(Units.toEMU(vals[5]) - y0); + numPoints += 3; + break; + case PathIterator.SEG_CLOSE: + numPoints++; + ctPath.addNewClose(); + break; + default: + throw new IllegalStateException("Unrecognized path segment type: " + type); + } + it.next(); + } + + XmlObject xo = getShapeProperties(); + if (!(xo instanceof CTShapeProperties)) { + return -1; + } + + ((CTShapeProperties)xo).getCustGeom().getPathLst().setPathArray(new CTPath2D[]{ctPath}); + setAnchor(bounds); + return numPoints; + } + + @Override + public Path2D.Double getPath() { + Path2D.Double path = new Path2D.Double(); + Rectangle2D bounds = getAnchor(); + + XmlObject xo = getShapeProperties(); + if (!(xo instanceof CTShapeProperties)) { + return null; + } + + CTCustomGeometry2D geom = ((CTShapeProperties)xo).getCustGeom(); + for(CTPath2D spPath : geom.getPathLst().getPathArray()){ + double scaleW = bounds.getWidth() / Units.toPoints(spPath.getW()); + double scaleH = bounds.getHeight() / Units.toPoints(spPath.getH()); + for(XmlObject ch : spPath.selectPath("*")){ + if(ch instanceof CTPath2DMoveTo){ + CTAdjPoint2D pt = ((CTPath2DMoveTo)ch).getPt(); + path.moveTo( + (float) (Units.toPoints((Long) pt.getX()) * scaleW), + (float) (Units.toPoints((Long) pt.getY()) * scaleH)); + } else if (ch instanceof CTPath2DLineTo){ + CTAdjPoint2D pt = ((CTPath2DLineTo)ch).getPt(); + path.lineTo((float)Units.toPoints((Long)pt.getX()), + (float)Units.toPoints((Long)pt.getY())); + } else if (ch instanceof CTPath2DQuadBezierTo){ + CTPath2DQuadBezierTo bez = ((CTPath2DQuadBezierTo)ch); + CTAdjPoint2D pt1 = bez.getPtArray(0); + CTAdjPoint2D pt2 = bez.getPtArray(1); + path.quadTo( + (float) (Units.toPoints((Long) pt1.getX()) * scaleW), + (float) (Units.toPoints((Long) pt1.getY()) * scaleH), + (float) (Units.toPoints((Long) pt2.getX()) * scaleW), + (float) (Units.toPoints((Long) pt2.getY()) * scaleH)); + } else if (ch instanceof CTPath2DCubicBezierTo){ + CTPath2DCubicBezierTo bez = ((CTPath2DCubicBezierTo)ch); + CTAdjPoint2D pt1 = bez.getPtArray(0); + CTAdjPoint2D pt2 = bez.getPtArray(1); + CTAdjPoint2D pt3 = bez.getPtArray(2); + path.curveTo( + (float) (Units.toPoints((Long) pt1.getX()) * scaleW), + (float) (Units.toPoints((Long) pt1.getY()) * scaleH), + (float) (Units.toPoints((Long) pt2.getX()) * scaleW), + (float) (Units.toPoints((Long) pt2.getY()) * scaleH), + (float) (Units.toPoints((Long) pt3.getX()) * scaleW), + (float) (Units.toPoints((Long) pt3.getY()) * scaleH)); + } else if (ch instanceof CTPath2DClose){ + path.closePath(); + } + } + } + + // the created path starts at (x=0, y=0). + // The returned path should fit in the bounding rectangle + AffineTransform at = new AffineTransform(); + at.translate(bounds.getX(), bounds.getY()); + return new Path2D.Double(at.createTransformedShape(path)); + } + /** + * @param shapeId 1-based shapeId + */ + static CTShape prototype(int shapeId) { + CTShape ct = CTShape.Factory.newInstance(); + CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Freeform " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvSpPr(); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTCustomGeometry2D geom = spPr.addNewCustGeom(); + geom.addNewAvLst(); + geom.addNewGdLst(); + geom.addNewAhLst(); + geom.addNewCxnLst(); + CTGeomRect rect = geom.addNewRect(); + rect.setR("r"); + rect.setB("b"); + rect.setT("t"); + rect.setL("l"); + geom.addNewPathLst(); + return ct; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java index 1b5a9dcbd9..89aae95a2f 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java @@ -1,219 +1,219 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.geom.Rectangle2D; - -import javax.xml.namespace.QName; - -import org.apache.poi.POIXMLException; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.sl.usermodel.GraphicalFrame; -import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.util.Beta; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.Units; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; - -@Beta -public class XSLFGraphicFrame extends XSLFShape implements GraphicalFrame { - private static final POILogger LOG = POILogFactory.getLogger(XSLFGraphicFrame.class); - - /*package*/ XSLFGraphicFrame(CTGraphicalObjectFrame shape, XSLFSheet sheet){ - super(shape,sheet); - } - - public ShapeType getShapeType(){ - throw new UnsupportedOperationException(); - } - - @Override - public Rectangle2D getAnchor(){ - CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm(); - CTPoint2D off = xfrm.getOff(); - double x = Units.toPoints(off.getX()); - double y = Units.toPoints(off.getY()); - CTPositiveSize2D ext = xfrm.getExt(); - double cx = Units.toPoints(ext.getCx()); - double cy = Units.toPoints(ext.getCy()); - return new Rectangle2D.Double(x, y, cx, cy); - } - - @Override - public void setAnchor(Rectangle2D anchor){ - CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm(); - CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); - long x = Units.toEMU(anchor.getX()); - long y = Units.toEMU(anchor.getY()); - off.setX(x); - off.setY(y); - CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm - .addNewExt(); - long cx = Units.toEMU(anchor.getWidth()); - long cy = Units.toEMU(anchor.getHeight()); - ext.setCx(cx); - ext.setCy(cy); - } - - - static XSLFGraphicFrame create(CTGraphicalObjectFrame shape, XSLFSheet sheet){ - String uri = shape.getGraphic().getGraphicData().getUri(); - if(XSLFTable.TABLE_URI.equals(uri)){ - return new XSLFTable(shape, sheet); - } else { - return new XSLFGraphicFrame(shape, sheet); - } - } - - /** - * Rotate this shape. - *

- * Positive angles are clockwise (i.e., towards the positive y axis); - * negative angles are counter-clockwise (i.e., towards the negative y axis). - *

- * - * @param theta the rotation angle in degrees. - */ - public void setRotation(double theta){ - throw new IllegalArgumentException("Operation not supported"); - } - - /** - * Rotation angle in degrees - *

- * Positive angles are clockwise (i.e., towards the positive y axis); - * negative angles are counter-clockwise (i.e., towards the negative y axis). - *

- * - * @return rotation angle in degrees - */ - public double getRotation(){ - return 0; - } - - public void setFlipHorizontal(boolean flip){ - throw new IllegalArgumentException("Operation not supported"); - } - - public void setFlipVertical(boolean flip){ - throw new IllegalArgumentException("Operation not supported"); - } - - /** - * Whether the shape is horizontally flipped - * - * @return whether the shape is horizontally flipped - */ - public boolean getFlipHorizontal(){ - return false; - } - - public boolean getFlipVertical(){ - return false; - } - - @Override - void copy(XSLFShape sh){ - super.copy(sh); - - CTGraphicalObjectData data = ((CTGraphicalObjectFrame)getXmlObject()).getGraphic().getGraphicData(); - String uri = data.getUri(); - if(uri.equals("http://schemas.openxmlformats.org/drawingml/2006/diagram")){ - copyDiagram(data, (XSLFGraphicFrame)sh); - } else { - // TODO support other types of objects - - } - } - - // TODO should be moved to a sub-class - private void copyDiagram(CTGraphicalObjectData objData, XSLFGraphicFrame srcShape){ - String xpath = "declare namespace dgm='http://schemas.openxmlformats.org/drawingml/2006/diagram' $this//dgm:relIds"; - XmlObject[] obj = objData.selectPath(xpath); - if(obj != null && obj.length == 1){ - XmlCursor c = obj[0].newCursor(); - - XSLFSheet sheet = srcShape.getSheet(); - try { - String dm = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "dm")); - PackageRelationship dmRel = sheet.getPackagePart().getRelationship(dm); - PackagePart dmPart = sheet.getPackagePart().getRelatedPart(dmRel); - getSheet().importPart(dmRel, dmPart); - - String lo = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "lo")); - PackageRelationship loRel = sheet.getPackagePart().getRelationship(lo); - PackagePart loPart = sheet.getPackagePart().getRelatedPart(loRel); - getSheet().importPart(loRel, loPart); - - String qs = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "qs")); - PackageRelationship qsRel = sheet.getPackagePart().getRelationship(qs); - PackagePart qsPart = sheet.getPackagePart().getRelatedPart(qsRel); - getSheet().importPart(qsRel, qsPart); - - String cs = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "cs")); - PackageRelationship csRel = sheet.getPackagePart().getRelationship(cs); - PackagePart csPart = sheet.getPackagePart().getRelatedPart(csRel); - getSheet().importPart(csRel, csPart); - - } catch (InvalidFormatException e){ - throw new POIXMLException(e); - } - c.dispose(); - } - } - - @Override - public XSLFPictureShape getFallbackPicture() { - String xquery = - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main'; " - + "declare namespace mc='http://schemas.openxmlformats.org/markup-compatibility/2006' " - + ".//mc:Fallback/*/p:pic" - ; - XmlObject xo = selectProperty(XmlObject.class, xquery); - if (xo == null) { - return null; - } - - CTGroupShape gs; - try { - gs = CTGroupShape.Factory.parse(xo.newDomNode()); - } catch (XmlException e) { - LOG.log(POILogger.WARN, "Can't parse fallback picture stream of graphical frame", e); - return null; - } - - if (gs.sizeOfPicArray() == 0) { - return null; - } - - return new XSLFPictureShape(gs.getPicArray(0), getSheet()); - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.geom.Rectangle2D; + +import javax.xml.namespace.QName; + +import org.apache.poi.POIXMLException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.sl.usermodel.GraphicalFrame; +import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.util.Beta; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; + +@Beta +public class XSLFGraphicFrame extends XSLFShape implements GraphicalFrame { + private static final POILogger LOG = POILogFactory.getLogger(XSLFGraphicFrame.class); + + /*package*/ XSLFGraphicFrame(CTGraphicalObjectFrame shape, XSLFSheet sheet){ + super(shape,sheet); + } + + public ShapeType getShapeType(){ + throw new UnsupportedOperationException(); + } + + @Override + public Rectangle2D getAnchor(){ + CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm(); + CTPoint2D off = xfrm.getOff(); + double x = Units.toPoints(off.getX()); + double y = Units.toPoints(off.getY()); + CTPositiveSize2D ext = xfrm.getExt(); + double cx = Units.toPoints(ext.getCx()); + double cy = Units.toPoints(ext.getCy()); + return new Rectangle2D.Double(x, y, cx, cy); + } + + @Override + public void setAnchor(Rectangle2D anchor){ + CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm(); + CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); + long x = Units.toEMU(anchor.getX()); + long y = Units.toEMU(anchor.getY()); + off.setX(x); + off.setY(y); + CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm + .addNewExt(); + long cx = Units.toEMU(anchor.getWidth()); + long cy = Units.toEMU(anchor.getHeight()); + ext.setCx(cx); + ext.setCy(cy); + } + + + static XSLFGraphicFrame create(CTGraphicalObjectFrame shape, XSLFSheet sheet){ + String uri = shape.getGraphic().getGraphicData().getUri(); + if(XSLFTable.TABLE_URI.equals(uri)){ + return new XSLFTable(shape, sheet); + } else { + return new XSLFGraphicFrame(shape, sheet); + } + } + + /** + * Rotate this shape. + *

+ * Positive angles are clockwise (i.e., towards the positive y axis); + * negative angles are counter-clockwise (i.e., towards the negative y axis). + *

+ * + * @param theta the rotation angle in degrees. + */ + public void setRotation(double theta){ + throw new IllegalArgumentException("Operation not supported"); + } + + /** + * Rotation angle in degrees + *

+ * Positive angles are clockwise (i.e., towards the positive y axis); + * negative angles are counter-clockwise (i.e., towards the negative y axis). + *

+ * + * @return rotation angle in degrees + */ + public double getRotation(){ + return 0; + } + + public void setFlipHorizontal(boolean flip){ + throw new IllegalArgumentException("Operation not supported"); + } + + public void setFlipVertical(boolean flip){ + throw new IllegalArgumentException("Operation not supported"); + } + + /** + * Whether the shape is horizontally flipped + * + * @return whether the shape is horizontally flipped + */ + public boolean getFlipHorizontal(){ + return false; + } + + public boolean getFlipVertical(){ + return false; + } + + @Override + void copy(XSLFShape sh){ + super.copy(sh); + + CTGraphicalObjectData data = ((CTGraphicalObjectFrame)getXmlObject()).getGraphic().getGraphicData(); + String uri = data.getUri(); + if(uri.equals("http://schemas.openxmlformats.org/drawingml/2006/diagram")){ + copyDiagram(data, (XSLFGraphicFrame)sh); + } else { + // TODO support other types of objects + + } + } + + // TODO should be moved to a sub-class + private void copyDiagram(CTGraphicalObjectData objData, XSLFGraphicFrame srcShape){ + String xpath = "declare namespace dgm='http://schemas.openxmlformats.org/drawingml/2006/diagram' $this//dgm:relIds"; + XmlObject[] obj = objData.selectPath(xpath); + if(obj != null && obj.length == 1){ + XmlCursor c = obj[0].newCursor(); + + XSLFSheet sheet = srcShape.getSheet(); + try { + String dm = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "dm")); + PackageRelationship dmRel = sheet.getPackagePart().getRelationship(dm); + PackagePart dmPart = sheet.getPackagePart().getRelatedPart(dmRel); + getSheet().importPart(dmRel, dmPart); + + String lo = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "lo")); + PackageRelationship loRel = sheet.getPackagePart().getRelationship(lo); + PackagePart loPart = sheet.getPackagePart().getRelatedPart(loRel); + getSheet().importPart(loRel, loPart); + + String qs = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "qs")); + PackageRelationship qsRel = sheet.getPackagePart().getRelationship(qs); + PackagePart qsPart = sheet.getPackagePart().getRelatedPart(qsRel); + getSheet().importPart(qsRel, qsPart); + + String cs = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "cs")); + PackageRelationship csRel = sheet.getPackagePart().getRelationship(cs); + PackagePart csPart = sheet.getPackagePart().getRelatedPart(csRel); + getSheet().importPart(csRel, csPart); + + } catch (InvalidFormatException e){ + throw new POIXMLException(e); + } + c.dispose(); + } + } + + @Override + public XSLFPictureShape getFallbackPicture() { + String xquery = + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main'; " + + "declare namespace mc='http://schemas.openxmlformats.org/markup-compatibility/2006' " + + ".//mc:Fallback/*/p:pic" + ; + XmlObject xo = selectProperty(XmlObject.class, xquery); + if (xo == null) { + return null; + } + + CTGroupShape gs; + try { + gs = CTGroupShape.Factory.parse(xo.newDomNode()); + } catch (XmlException e) { + LOG.log(POILogger.WARN, "Can't parse fallback picture stream of graphical frame", e); + return null; + } + + if (gs.sizeOfPicArray() == 0) { + return null; + } + + return new XSLFPictureShape(gs.getPicArray(0), getSheet()); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java index bb904be56a..e5ee2b9d50 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java @@ -1,379 +1,379 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.sl.draw.DrawPictureShape; -import org.apache.poi.sl.usermodel.GroupShape; -import org.apache.poi.sl.usermodel.PictureData; -import org.apache.poi.util.Beta; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.Units; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; - -/** - * Represents a group shape that consists of many shapes grouped together. - * - * @author Yegor Kozlov - */ -@Beta -public class XSLFGroupShape extends XSLFShape -implements XSLFShapeContainer, GroupShape { - private final static POILogger _logger = POILogFactory.getLogger(XSLFGroupShape.class); - - private final List _shapes; - private final CTGroupShapeProperties _grpSpPr; - private XSLFDrawing _drawing; - - protected XSLFGroupShape(CTGroupShape shape, XSLFSheet sheet){ - super(shape,sheet); - _shapes = XSLFSheet.buildShapes(shape, sheet); - _grpSpPr = shape.getGrpSpPr(); - } - - protected CTGroupShapeProperties getGrpSpPr() { - return _grpSpPr; - } - - protected CTGroupTransform2D getSafeXfrm() { - CTGroupTransform2D xfrm = getXfrm(); - return (xfrm == null ? getGrpSpPr().addNewXfrm() : xfrm); - } - - protected CTGroupTransform2D getXfrm() { - return getGrpSpPr().getXfrm(); - } - - @Override - public Rectangle2D getAnchor(){ - CTGroupTransform2D xfrm = getXfrm(); - CTPoint2D off = xfrm.getOff(); - double x = Units.toPoints(off.getX()); - double y = Units.toPoints(off.getY()); - CTPositiveSize2D ext = xfrm.getExt(); - double cx = Units.toPoints(ext.getCx()); - double cy = Units.toPoints(ext.getCy()); - return new Rectangle2D.Double(x,y,cx,cy); - } - - @Override - public void setAnchor(Rectangle2D anchor){ - CTGroupTransform2D xfrm = getSafeXfrm(); - CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); - long x = Units.toEMU(anchor.getX()); - long y = Units.toEMU(anchor.getY()); - off.setX(x); - off.setY(y); - CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt(); - long cx = Units.toEMU(anchor.getWidth()); - long cy = Units.toEMU(anchor.getHeight()); - ext.setCx(cx); - ext.setCy(cy); - } - - /** - * - * @return the coordinates of the child extents rectangle - * used for calculations of grouping, scaling, and rotation - * behavior of shapes placed within a group. - */ - @Override - public Rectangle2D getInteriorAnchor(){ - CTGroupTransform2D xfrm = getXfrm(); - CTPoint2D off = xfrm.getChOff(); - double x = Units.toPoints(off.getX()); - double y = Units.toPoints(off.getY()); - CTPositiveSize2D ext = xfrm.getChExt(); - double cx = Units.toPoints(ext.getCx()); - double cy = Units.toPoints(ext.getCy()); - return new Rectangle2D.Double(x, y, cx, cy); - } - - /** - * - * @param anchor the coordinates of the child extents rectangle - * used for calculations of grouping, scaling, and rotation - * behavior of shapes placed within a group. - */ - @Override - public void setInteriorAnchor(Rectangle2D anchor) { - CTGroupTransform2D xfrm = getSafeXfrm(); - CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); - long x = Units.toEMU(anchor.getX()); - long y = Units.toEMU(anchor.getY()); - off.setX(x); - off.setY(y); - CTPositiveSize2D ext = xfrm.isSetChExt() ? xfrm.getChExt() : xfrm.addNewChExt(); - long cx = Units.toEMU(anchor.getWidth()); - long cy = Units.toEMU(anchor.getHeight()); - ext.setCx(cx); - ext.setCy(cy); - } - - /** - * @return child shapes contained within this group - */ - @Override - public List getShapes(){ - return _shapes; - } - - /** - * Returns an iterator over the shapes in this sheet - * - * @return an iterator over the shapes in this sheet - */ - public Iterator iterator(){ - return _shapes.iterator(); - } - - /** - * Remove the specified shape from this group - */ - public boolean removeShape(XSLFShape xShape) { - XmlObject obj = xShape.getXmlObject(); - CTGroupShape grpSp = (CTGroupShape)getXmlObject(); - if(obj instanceof CTShape){ - grpSp.getSpList().remove(obj); - } else if (obj instanceof CTGroupShape){ - grpSp.getGrpSpList().remove(obj); - } else if (obj instanceof CTConnector){ - grpSp.getCxnSpList().remove(obj); - } else if (obj instanceof CTGraphicalObjectFrame) { - grpSp.getGraphicFrameList().remove(obj); - } else if (obj instanceof CTPicture) { - XSLFPictureShape ps = (XSLFPictureShape)xShape; - XSLFSheet sh = getSheet(); - if (sh != null) { - sh.removePictureRelation(ps); - } - grpSp.getPicList().remove(obj); - } else { - throw new IllegalArgumentException("Unsupported shape: " + xShape); - } - return _shapes.remove(xShape); - } - - /** - * @param shapeId 1-based shapeId - */ - static CTGroupShape prototype(int shapeId) { - CTGroupShape ct = CTGroupShape.Factory.newInstance(); - CTGroupShapeNonVisual nvSpPr = ct.addNewNvGrpSpPr(); - CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); - cnv.setName("Group " + shapeId); - cnv.setId(shapeId + 1); - - nvSpPr.addNewCNvGrpSpPr(); - nvSpPr.addNewNvPr(); - ct.addNewGrpSpPr(); - return ct; - } - - // shape factory methods - private XSLFDrawing getDrawing(){ - if(_drawing == null) { - _drawing = new XSLFDrawing(getSheet(), (CTGroupShape)getXmlObject()); - } - return _drawing; - } - - public XSLFAutoShape createAutoShape(){ - XSLFAutoShape sh = getDrawing().createAutoShape(); - _shapes.add(sh); - sh.setParent(this); - return sh; - } - - public XSLFFreeformShape createFreeform(){ - XSLFFreeformShape sh = getDrawing().createFreeform(); - _shapes.add(sh); - sh.setParent(this); - return sh; - } - - public XSLFTextBox createTextBox(){ - XSLFTextBox sh = getDrawing().createTextBox(); - _shapes.add(sh); - sh.setParent(this); - return sh; - } - - public XSLFConnectorShape createConnector(){ - XSLFConnectorShape sh = getDrawing().createConnector(); - _shapes.add(sh); - sh.setParent(this); - return sh; - } - - public XSLFGroupShape createGroup(){ - XSLFGroupShape sh = getDrawing().createGroup(); - _shapes.add(sh); - sh.setParent(this); - return sh; - } - - public XSLFPictureShape createPicture(PictureData pictureData){ - if (!(pictureData instanceof XSLFPictureData)) { - throw new IllegalArgumentException("pictureData needs to be of type XSLFPictureData"); - } - XSLFPictureData xPictureData = (XSLFPictureData)pictureData; - PackagePart pic = xPictureData.getPackagePart(); - - PackageRelationship rel = getSheet().getPackagePart().addRelationship( - pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation()); - - XSLFPictureShape sh = getDrawing().createPicture(rel.getId()); - new DrawPictureShape(sh).resize(); - _shapes.add(sh); - sh.setParent(this); - return sh; - } - - public XSLFTable createTable(){ - XSLFTable sh = getDrawing().createTable(); - _shapes.add(sh); - sh.setParent(this); - return sh; - } - - @Override - public XSLFTable createTable(int numRows, int numCols){ - if (numRows < 1 || numCols < 1) { - throw new IllegalArgumentException("numRows and numCols must be greater than 0"); - } - XSLFTable sh = getDrawing().createTable(); - _shapes.add(sh); - sh.setParent(this); - for (int r=0; r shapes = new ArrayList(getShapes()); - for(XSLFShape shape : shapes){ - removeShape(shape); - } - } - - public void addShape(XSLFShape shape) { - throw new UnsupportedOperationException( - "Adding a shape from a different container is not supported -" - + " create it from scratch with XSLFGroupShape.create* methods"); - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.sl.draw.DrawPictureShape; +import org.apache.poi.sl.usermodel.GroupShape; +import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.util.Beta; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; + +/** + * Represents a group shape that consists of many shapes grouped together. + * + * @author Yegor Kozlov + */ +@Beta +public class XSLFGroupShape extends XSLFShape +implements XSLFShapeContainer, GroupShape { + private final static POILogger _logger = POILogFactory.getLogger(XSLFGroupShape.class); + + private final List _shapes; + private final CTGroupShapeProperties _grpSpPr; + private XSLFDrawing _drawing; + + protected XSLFGroupShape(CTGroupShape shape, XSLFSheet sheet){ + super(shape,sheet); + _shapes = XSLFSheet.buildShapes(shape, sheet); + _grpSpPr = shape.getGrpSpPr(); + } + + protected CTGroupShapeProperties getGrpSpPr() { + return _grpSpPr; + } + + protected CTGroupTransform2D getSafeXfrm() { + CTGroupTransform2D xfrm = getXfrm(); + return (xfrm == null ? getGrpSpPr().addNewXfrm() : xfrm); + } + + protected CTGroupTransform2D getXfrm() { + return getGrpSpPr().getXfrm(); + } + + @Override + public Rectangle2D getAnchor(){ + CTGroupTransform2D xfrm = getXfrm(); + CTPoint2D off = xfrm.getOff(); + double x = Units.toPoints(off.getX()); + double y = Units.toPoints(off.getY()); + CTPositiveSize2D ext = xfrm.getExt(); + double cx = Units.toPoints(ext.getCx()); + double cy = Units.toPoints(ext.getCy()); + return new Rectangle2D.Double(x,y,cx,cy); + } + + @Override + public void setAnchor(Rectangle2D anchor){ + CTGroupTransform2D xfrm = getSafeXfrm(); + CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); + long x = Units.toEMU(anchor.getX()); + long y = Units.toEMU(anchor.getY()); + off.setX(x); + off.setY(y); + CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt(); + long cx = Units.toEMU(anchor.getWidth()); + long cy = Units.toEMU(anchor.getHeight()); + ext.setCx(cx); + ext.setCy(cy); + } + + /** + * + * @return the coordinates of the child extents rectangle + * used for calculations of grouping, scaling, and rotation + * behavior of shapes placed within a group. + */ + @Override + public Rectangle2D getInteriorAnchor(){ + CTGroupTransform2D xfrm = getXfrm(); + CTPoint2D off = xfrm.getChOff(); + double x = Units.toPoints(off.getX()); + double y = Units.toPoints(off.getY()); + CTPositiveSize2D ext = xfrm.getChExt(); + double cx = Units.toPoints(ext.getCx()); + double cy = Units.toPoints(ext.getCy()); + return new Rectangle2D.Double(x, y, cx, cy); + } + + /** + * + * @param anchor the coordinates of the child extents rectangle + * used for calculations of grouping, scaling, and rotation + * behavior of shapes placed within a group. + */ + @Override + public void setInteriorAnchor(Rectangle2D anchor) { + CTGroupTransform2D xfrm = getSafeXfrm(); + CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); + long x = Units.toEMU(anchor.getX()); + long y = Units.toEMU(anchor.getY()); + off.setX(x); + off.setY(y); + CTPositiveSize2D ext = xfrm.isSetChExt() ? xfrm.getChExt() : xfrm.addNewChExt(); + long cx = Units.toEMU(anchor.getWidth()); + long cy = Units.toEMU(anchor.getHeight()); + ext.setCx(cx); + ext.setCy(cy); + } + + /** + * @return child shapes contained within this group + */ + @Override + public List getShapes(){ + return _shapes; + } + + /** + * Returns an iterator over the shapes in this sheet + * + * @return an iterator over the shapes in this sheet + */ + public Iterator iterator(){ + return _shapes.iterator(); + } + + /** + * Remove the specified shape from this group + */ + public boolean removeShape(XSLFShape xShape) { + XmlObject obj = xShape.getXmlObject(); + CTGroupShape grpSp = (CTGroupShape)getXmlObject(); + if(obj instanceof CTShape){ + grpSp.getSpList().remove(obj); + } else if (obj instanceof CTGroupShape){ + grpSp.getGrpSpList().remove(obj); + } else if (obj instanceof CTConnector){ + grpSp.getCxnSpList().remove(obj); + } else if (obj instanceof CTGraphicalObjectFrame) { + grpSp.getGraphicFrameList().remove(obj); + } else if (obj instanceof CTPicture) { + XSLFPictureShape ps = (XSLFPictureShape)xShape; + XSLFSheet sh = getSheet(); + if (sh != null) { + sh.removePictureRelation(ps); + } + grpSp.getPicList().remove(obj); + } else { + throw new IllegalArgumentException("Unsupported shape: " + xShape); + } + return _shapes.remove(xShape); + } + + /** + * @param shapeId 1-based shapeId + */ + static CTGroupShape prototype(int shapeId) { + CTGroupShape ct = CTGroupShape.Factory.newInstance(); + CTGroupShapeNonVisual nvSpPr = ct.addNewNvGrpSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Group " + shapeId); + cnv.setId(shapeId + 1); + + nvSpPr.addNewCNvGrpSpPr(); + nvSpPr.addNewNvPr(); + ct.addNewGrpSpPr(); + return ct; + } + + // shape factory methods + private XSLFDrawing getDrawing(){ + if(_drawing == null) { + _drawing = new XSLFDrawing(getSheet(), (CTGroupShape)getXmlObject()); + } + return _drawing; + } + + public XSLFAutoShape createAutoShape(){ + XSLFAutoShape sh = getDrawing().createAutoShape(); + _shapes.add(sh); + sh.setParent(this); + return sh; + } + + public XSLFFreeformShape createFreeform(){ + XSLFFreeformShape sh = getDrawing().createFreeform(); + _shapes.add(sh); + sh.setParent(this); + return sh; + } + + public XSLFTextBox createTextBox(){ + XSLFTextBox sh = getDrawing().createTextBox(); + _shapes.add(sh); + sh.setParent(this); + return sh; + } + + public XSLFConnectorShape createConnector(){ + XSLFConnectorShape sh = getDrawing().createConnector(); + _shapes.add(sh); + sh.setParent(this); + return sh; + } + + public XSLFGroupShape createGroup(){ + XSLFGroupShape sh = getDrawing().createGroup(); + _shapes.add(sh); + sh.setParent(this); + return sh; + } + + public XSLFPictureShape createPicture(PictureData pictureData){ + if (!(pictureData instanceof XSLFPictureData)) { + throw new IllegalArgumentException("pictureData needs to be of type XSLFPictureData"); + } + XSLFPictureData xPictureData = (XSLFPictureData)pictureData; + PackagePart pic = xPictureData.getPackagePart(); + + PackageRelationship rel = getSheet().getPackagePart().addRelationship( + pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation()); + + XSLFPictureShape sh = getDrawing().createPicture(rel.getId()); + new DrawPictureShape(sh).resize(); + _shapes.add(sh); + sh.setParent(this); + return sh; + } + + public XSLFTable createTable(){ + XSLFTable sh = getDrawing().createTable(); + _shapes.add(sh); + sh.setParent(this); + return sh; + } + + @Override + public XSLFTable createTable(int numRows, int numCols){ + if (numRows < 1 || numCols < 1) { + throw new IllegalArgumentException("numRows and numCols must be greater than 0"); + } + XSLFTable sh = getDrawing().createTable(); + _shapes.add(sh); + sh.setParent(this); + for (int r=0; r shapes = new ArrayList(getShapes()); + for(XSLFShape shape : shapes){ + removeShape(shape); + } + } + + public void addShape(XSLFShape shape) { + throw new UnsupportedOperationException( + "Adding a shape from a different container is not supported -" + + " create it from scratch with XSLFGroupShape.create* methods"); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java index 2f300623fb..c0e029fed7 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFHyperlink.java @@ -1,167 +1,167 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import java.net.URI; - -import org.apache.poi.common.usermodel.HyperlinkType; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.sl.usermodel.Hyperlink; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; - -public class XSLFHyperlink implements Hyperlink { - final XSLFSheet _sheet; - final CTHyperlink _link; - - XSLFHyperlink(CTHyperlink link, XSLFSheet sheet){ - _sheet = sheet; - _link = link; - } - - @Internal - public CTHyperlink getXmlObject(){ - return _link; - } - - @Override - public void setAddress(String address) { - linkToUrl(address); - } - - @Override - public String getAddress() { - String id = _link.getId(); - if (id == null || "".equals(id)) { - return _link.getAction(); - } - - URI targetURI = _sheet.getPackagePart().getRelationship(id).getTargetURI(); - - return targetURI.toASCIIString(); - } - - @Override - public String getLabel() { - return _link.getTooltip(); - } - - @Override - public void setLabel(String label) { - _link.setTooltip(label); - } - - /* (non-Javadoc) - * @deprecated POI 3.15. Use {@link #getTypeEnum()} instead. - * Will return a HyperlinkType enum in the future - */ - @Override - public int getType() { - return getTypeEnum().getCode(); - } - - @Override - public HyperlinkType getTypeEnum() { - String action = _link.getAction(); - if (action == null) { - action = ""; - } - if (action.equals("ppaction://hlinksldjump") || action.startsWith("ppaction://hlinkshowjump")) { - return HyperlinkType.DOCUMENT; - } - - String address = getAddress(); - if (address == null) { - address = ""; - } - if (address.startsWith("mailto:")) { - return HyperlinkType.EMAIL; - } else { - return HyperlinkType.URL; - } - } - - @Override - public void linkToEmail(String emailAddress) { - linkToExternal("mailto:"+emailAddress); - setLabel(emailAddress); - } - - @Override - public void linkToUrl(String url) { - linkToExternal(url); - setLabel(url); - } - - private void linkToExternal(String url) { - PackagePart thisPP = _sheet.getPackagePart(); - if (_link.isSetId() && !_link.getId().isEmpty()) { - thisPP.removeRelationship(_link.getId()); - } - PackageRelationship rel = thisPP.addExternalRelationship(url, XSLFRelation.HYPERLINK.getRelation()); - _link.setId(rel.getId()); - if (_link.isSetAction()) { - _link.unsetAction(); - } - } - - @Override - public void linkToSlide(Slide slide) { - PackagePart thisPP = _sheet.getPackagePart(); - PackagePartName otherPPN = ((XSLFSheet)slide).getPackagePart().getPartName(); - if (_link.isSetId() && !_link.getId().isEmpty()) { - thisPP.removeRelationship(_link.getId()); - } - PackageRelationship rel = - thisPP.addRelationship(otherPPN, TargetMode.INTERNAL, XSLFRelation.SLIDE.getRelation()); - _link.setId(rel.getId()); - _link.setAction("ppaction://hlinksldjump"); - } - - @Override - public void linkToNextSlide() { - linkToRelativeSlide("nextslide"); - } - - @Override - public void linkToPreviousSlide() { - linkToRelativeSlide("previousslide"); - } - - @Override - public void linkToFirstSlide() { - linkToRelativeSlide("firstslide"); - } - - @Override - public void linkToLastSlide() { - linkToRelativeSlide("lastslide"); - } - - private void linkToRelativeSlide(String jump) { - PackagePart thisPP = _sheet.getPackagePart(); - if (_link.isSetId() && !_link.getId().isEmpty()) { - thisPP.removeRelationship(_link.getId()); - } - _link.setId(""); - _link.setAction("ppaction://hlinkshowjump?jump="+jump); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import java.net.URI; + +import org.apache.poi.common.usermodel.HyperlinkType; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.sl.usermodel.Hyperlink; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.util.Internal; +import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; + +public class XSLFHyperlink implements Hyperlink { + final XSLFSheet _sheet; + final CTHyperlink _link; + + XSLFHyperlink(CTHyperlink link, XSLFSheet sheet){ + _sheet = sheet; + _link = link; + } + + @Internal + public CTHyperlink getXmlObject(){ + return _link; + } + + @Override + public void setAddress(String address) { + linkToUrl(address); + } + + @Override + public String getAddress() { + String id = _link.getId(); + if (id == null || "".equals(id)) { + return _link.getAction(); + } + + URI targetURI = _sheet.getPackagePart().getRelationship(id).getTargetURI(); + + return targetURI.toASCIIString(); + } + + @Override + public String getLabel() { + return _link.getTooltip(); + } + + @Override + public void setLabel(String label) { + _link.setTooltip(label); + } + + /* (non-Javadoc) + * @deprecated POI 3.15. Use {@link #getTypeEnum()} instead. + * Will return a HyperlinkType enum in the future + */ + @Override + public int getType() { + return getTypeEnum().getCode(); + } + + @Override + public HyperlinkType getTypeEnum() { + String action = _link.getAction(); + if (action == null) { + action = ""; + } + if (action.equals("ppaction://hlinksldjump") || action.startsWith("ppaction://hlinkshowjump")) { + return HyperlinkType.DOCUMENT; + } + + String address = getAddress(); + if (address == null) { + address = ""; + } + if (address.startsWith("mailto:")) { + return HyperlinkType.EMAIL; + } else { + return HyperlinkType.URL; + } + } + + @Override + public void linkToEmail(String emailAddress) { + linkToExternal("mailto:"+emailAddress); + setLabel(emailAddress); + } + + @Override + public void linkToUrl(String url) { + linkToExternal(url); + setLabel(url); + } + + private void linkToExternal(String url) { + PackagePart thisPP = _sheet.getPackagePart(); + if (_link.isSetId() && !_link.getId().isEmpty()) { + thisPP.removeRelationship(_link.getId()); + } + PackageRelationship rel = thisPP.addExternalRelationship(url, XSLFRelation.HYPERLINK.getRelation()); + _link.setId(rel.getId()); + if (_link.isSetAction()) { + _link.unsetAction(); + } + } + + @Override + public void linkToSlide(Slide slide) { + PackagePart thisPP = _sheet.getPackagePart(); + PackagePartName otherPPN = ((XSLFSheet)slide).getPackagePart().getPartName(); + if (_link.isSetId() && !_link.getId().isEmpty()) { + thisPP.removeRelationship(_link.getId()); + } + PackageRelationship rel = + thisPP.addRelationship(otherPPN, TargetMode.INTERNAL, XSLFRelation.SLIDE.getRelation()); + _link.setId(rel.getId()); + _link.setAction("ppaction://hlinksldjump"); + } + + @Override + public void linkToNextSlide() { + linkToRelativeSlide("nextslide"); + } + + @Override + public void linkToPreviousSlide() { + linkToRelativeSlide("previousslide"); + } + + @Override + public void linkToFirstSlide() { + linkToRelativeSlide("firstslide"); + } + + @Override + public void linkToLastSlide() { + linkToRelativeSlide("lastslide"); + } + + private void linkToRelativeSlide(String jump) { + PackagePart thisPP = _sheet.getPackagePart(); + if (_link.isSetId() && !_link.getId().isEmpty()) { + thisPP.removeRelationship(_link.getId()); + } + _link.setId(""); + _link.setAction("ppaction://hlinkshowjump?jump="+jump); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFLineBreak.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFLineBreak.java index 934c0e3eec..9c279b6aa7 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFLineBreak.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFLineBreak.java @@ -1,33 +1,33 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak; - -class XSLFLineBreak extends XSLFTextRun { - protected XSLFLineBreak(CTTextLineBreak r, XSLFTextParagraph p) { - super(r, p); - } - - public void setText(String text){ - throw new IllegalStateException("You cannot change text of a line break, it is always '\\n'"); - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak; + +class XSLFLineBreak extends XSLFTextRun { + protected XSLFLineBreak(CTTextLineBreak r, XSLFTextParagraph p) { + super(r, p); + } + + public void setText(String text){ + throw new IllegalStateException("You cannot change text of a line break, it is always '\\n'"); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java index 652cedcb50..fdcdbabe7e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFMetroShape.java @@ -1,62 +1,62 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - - -package org.apache.poi.xslf.usermodel; - -import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.util.Internal; -import org.apache.xmlbeans.XmlException; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; - -/** - * Experimental class for metro blobs, i.e. an alternative escher property - * containing an ooxml representation of the shape. - * This is the helper class for HSLFMetroShape to dive into OOXML classes - */ -@Internal -public class XSLFMetroShape { - /* - * parses the metro bytes to a XSLF shape - */ - public static Shape parseShape(byte metroBytes[]) - throws InvalidFormatException, IOException, XmlException { - PackagePartName shapePN = PackagingURIHelper.createPartName("/drs/shapexml.xml"); - OPCPackage pkg = null; - try { - pkg = OPCPackage.open(new ByteArrayInputStream(metroBytes)); - PackagePart shapePart = pkg.getPart(shapePN); - CTGroupShape gs = CTGroupShape.Factory.parse(shapePart.getInputStream(), DEFAULT_XML_OPTIONS); - XSLFGroupShape xgs = new XSLFGroupShape(gs, null); - return xgs.getShapes().get(0); - } finally { - if (pkg != null) { - pkg.close(); - } - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.xslf.usermodel; + +import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.util.Internal; +import org.apache.xmlbeans.XmlException; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; + +/** + * Experimental class for metro blobs, i.e. an alternative escher property + * containing an ooxml representation of the shape. + * This is the helper class for HSLFMetroShape to dive into OOXML classes + */ +@Internal +public class XSLFMetroShape { + /* + * parses the metro bytes to a XSLF shape + */ + public static Shape parseShape(byte metroBytes[]) + throws InvalidFormatException, IOException, XmlException { + PackagePartName shapePN = PackagingURIHelper.createPartName("/drs/shapexml.xml"); + OPCPackage pkg = null; + try { + pkg = OPCPackage.open(new ByteArrayInputStream(metroBytes)); + PackagePart shapePart = pkg.getPart(shapePN); + CTGroupShape gs = CTGroupShape.Factory.parse(shapePart.getInputStream(), DEFAULT_XML_OPTIONS); + XSLFGroupShape xgs = new XSLFGroupShape(gs, null); + return xgs.getShapes().get(0); + } finally { + if (pkg != null) { + pkg.close(); + } + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index c2428bc2ed..da3cf45c8b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -1,232 +1,232 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Insets; -import java.net.URI; - -import javax.xml.namespace.QName; - -import org.apache.poi.POIXMLException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.sl.usermodel.PictureShape; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.util.Beta; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtension; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtensionList; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTRelativeRect; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual; - -/** - * Represents a picture shape - */ -@Beta -public class XSLFPictureShape extends XSLFSimpleShape - implements PictureShape { - private XSLFPictureData _data; - - /*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) { - super(shape, sheet); - } - - - /** - * @param shapeId 1-based shapeId - * @param rel relationship to the picture data in the ooxml package - */ - static CTPicture prototype(int shapeId, String rel) { - CTPicture ct = CTPicture.Factory.newInstance(); - CTPictureNonVisual nvSpPr = ct.addNewNvPicPr(); - CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); - cnv.setName("Picture " + shapeId); - cnv.setId(shapeId + 1); - nvSpPr.addNewCNvPicPr().addNewPicLocks().setNoChangeAspect(true); - nvSpPr.addNewNvPr(); - - CTBlipFillProperties blipFill = ct.addNewBlipFill(); - CTBlip blip = blipFill.addNewBlip(); - blip.setEmbed(rel); - blipFill.addNewStretch().addNewFillRect(); - - CTShapeProperties spPr = ct.addNewSpPr(); - CTPresetGeometry2D prst = spPr.addNewPrstGeom(); - prst.setPrst(STShapeType.RECT); - prst.addNewAvLst(); - return ct; - } - - - /** - * Is this an internal picture (image data included within - * the PowerPoint file), or an external linked picture - * (image lives outside)? - */ - public boolean isExternalLinkedPicture() { - if (getBlipId() == null && getBlipLink() != null) { - return true; - } - return false; - } - - /** - * Return the data on the (internal) picture. - * For an external linked picture, will return null - */ - public XSLFPictureData getPictureData() { - if(_data == null){ - String blipId = getBlipId(); - if (blipId == null) return null; - - PackagePart p = getSheet().getPackagePart(); - PackageRelationship rel = p.getRelationship(blipId); - if (rel != null) { - try { - PackagePart imgPart = p.getRelatedPart(rel); - _data = new XSLFPictureData(imgPart); - } - catch (Exception e) { - throw new POIXMLException(e); - } - } - } - return _data; - } - - @Override - public void setPlaceholder(Placeholder placeholder) { - super.setPlaceholder(placeholder); - } - - - /** - * For an external linked picture, return the last-seen - * path to the picture. - * For an internal picture, returns null. - */ - public URI getPictureLink() { - if (getBlipId() != null) { - // Internal picture, nothing to return - return null; - } - - String rId = getBlipLink(); - if (rId == null) { - // No link recorded, nothing we can do - return null; - } - - PackagePart p = getSheet().getPackagePart(); - PackageRelationship rel = p.getRelationship(rId); - if (rel != null) { - return rel.getTargetURI(); - } - return null; - } - - protected CTBlipFillProperties getBlipFill() { - CTPicture ct = (CTPicture)getXmlObject(); - CTBlipFillProperties bfp = ct.getBlipFill(); - if (bfp != null) { - return bfp; - } - - String xquery = - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main'; " - + "declare namespace mc='http://schemas.openxmlformats.org/markup-compatibility/2006' " - + ".//mc:Fallback/p:blipFill" - ; - XmlObject xo = selectProperty(XmlObject.class, xquery); - try { - xo = CTPicture.Factory.parse(xo.getDomNode()); - } catch (XmlException xe) { - return null; - } - return ((CTPicture)xo).getBlipFill(); - } - - protected CTBlip getBlip(){ - return getBlipFill().getBlip(); - } - - protected String getBlipLink(){ - String link = getBlip().getLink(); - if (link.isEmpty()) return null; - return link; - } - - protected String getBlipId(){ - String id = getBlip().getEmbed(); - if (id.isEmpty()) return null; - return id; - } - - @Override - public Insets getClipping(){ - CTRelativeRect r = getBlipFill().getSrcRect(); - return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR()); - } - - @Override - void copy(XSLFShape sh){ - super.copy(sh); - - XSLFPictureShape p = (XSLFPictureShape)sh; - String blipId = p.getBlipId(); - String relId = getSheet().importBlip(blipId, p.getSheet().getPackagePart()); - - CTPicture ct = (CTPicture)getXmlObject(); - CTBlip blip = getBlipFill().getBlip(); - blip.setEmbed(relId); - - CTApplicationNonVisualDrawingProps nvPr = ct.getNvPicPr().getNvPr(); - if(nvPr.isSetCustDataLst()) { - // discard any custom tags associated with the picture being copied - nvPr.unsetCustDataLst(); - } - if(blip.isSetExtLst()) { - - CTOfficeArtExtensionList extLst = blip.getExtLst(); - for(CTOfficeArtExtension ext : extLst.getExtArray()){ - String xpath = "declare namespace a14='http://schemas.microsoft.com/office/drawing/2010/main' $this//a14:imgProps/a14:imgLayer"; - XmlObject[] obj = ext.selectPath(xpath); - if(obj != null && obj.length == 1){ - XmlCursor c = obj[0].newCursor(); - String id = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "embed"));//selectPath("declare namespace r='http://schemas.openxmlformats.org/officeDocument/2006/relationships' $this//[@embed]"); - String newId = getSheet().importBlip(id, p.getSheet().getPackagePart()); - c.setAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "embed"), newId); - c.dispose(); - } - } - } - - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Insets; +import java.net.URI; + +import javax.xml.namespace.QName; + +import org.apache.poi.POIXMLException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.sl.usermodel.PictureShape; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.util.Beta; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtension; +import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtensionList; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTRelativeRect; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual; + +/** + * Represents a picture shape + */ +@Beta +public class XSLFPictureShape extends XSLFSimpleShape + implements PictureShape { + private XSLFPictureData _data; + + /*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) { + super(shape, sheet); + } + + + /** + * @param shapeId 1-based shapeId + * @param rel relationship to the picture data in the ooxml package + */ + static CTPicture prototype(int shapeId, String rel) { + CTPicture ct = CTPicture.Factory.newInstance(); + CTPictureNonVisual nvSpPr = ct.addNewNvPicPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("Picture " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvPicPr().addNewPicLocks().setNoChangeAspect(true); + nvSpPr.addNewNvPr(); + + CTBlipFillProperties blipFill = ct.addNewBlipFill(); + CTBlip blip = blipFill.addNewBlip(); + blip.setEmbed(rel); + blipFill.addNewStretch().addNewFillRect(); + + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.RECT); + prst.addNewAvLst(); + return ct; + } + + + /** + * Is this an internal picture (image data included within + * the PowerPoint file), or an external linked picture + * (image lives outside)? + */ + public boolean isExternalLinkedPicture() { + if (getBlipId() == null && getBlipLink() != null) { + return true; + } + return false; + } + + /** + * Return the data on the (internal) picture. + * For an external linked picture, will return null + */ + public XSLFPictureData getPictureData() { + if(_data == null){ + String blipId = getBlipId(); + if (blipId == null) return null; + + PackagePart p = getSheet().getPackagePart(); + PackageRelationship rel = p.getRelationship(blipId); + if (rel != null) { + try { + PackagePart imgPart = p.getRelatedPart(rel); + _data = new XSLFPictureData(imgPart); + } + catch (Exception e) { + throw new POIXMLException(e); + } + } + } + return _data; + } + + @Override + public void setPlaceholder(Placeholder placeholder) { + super.setPlaceholder(placeholder); + } + + + /** + * For an external linked picture, return the last-seen + * path to the picture. + * For an internal picture, returns null. + */ + public URI getPictureLink() { + if (getBlipId() != null) { + // Internal picture, nothing to return + return null; + } + + String rId = getBlipLink(); + if (rId == null) { + // No link recorded, nothing we can do + return null; + } + + PackagePart p = getSheet().getPackagePart(); + PackageRelationship rel = p.getRelationship(rId); + if (rel != null) { + return rel.getTargetURI(); + } + return null; + } + + protected CTBlipFillProperties getBlipFill() { + CTPicture ct = (CTPicture)getXmlObject(); + CTBlipFillProperties bfp = ct.getBlipFill(); + if (bfp != null) { + return bfp; + } + + String xquery = + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main'; " + + "declare namespace mc='http://schemas.openxmlformats.org/markup-compatibility/2006' " + + ".//mc:Fallback/p:blipFill" + ; + XmlObject xo = selectProperty(XmlObject.class, xquery); + try { + xo = CTPicture.Factory.parse(xo.getDomNode()); + } catch (XmlException xe) { + return null; + } + return ((CTPicture)xo).getBlipFill(); + } + + protected CTBlip getBlip(){ + return getBlipFill().getBlip(); + } + + protected String getBlipLink(){ + String link = getBlip().getLink(); + if (link.isEmpty()) return null; + return link; + } + + protected String getBlipId(){ + String id = getBlip().getEmbed(); + if (id.isEmpty()) return null; + return id; + } + + @Override + public Insets getClipping(){ + CTRelativeRect r = getBlipFill().getSrcRect(); + return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR()); + } + + @Override + void copy(XSLFShape sh){ + super.copy(sh); + + XSLFPictureShape p = (XSLFPictureShape)sh; + String blipId = p.getBlipId(); + String relId = getSheet().importBlip(blipId, p.getSheet().getPackagePart()); + + CTPicture ct = (CTPicture)getXmlObject(); + CTBlip blip = getBlipFill().getBlip(); + blip.setEmbed(relId); + + CTApplicationNonVisualDrawingProps nvPr = ct.getNvPicPr().getNvPr(); + if(nvPr.isSetCustDataLst()) { + // discard any custom tags associated with the picture being copied + nvPr.unsetCustDataLst(); + } + if(blip.isSetExtLst()) { + + CTOfficeArtExtensionList extLst = blip.getExtLst(); + for(CTOfficeArtExtension ext : extLst.getExtArray()){ + String xpath = "declare namespace a14='http://schemas.microsoft.com/office/drawing/2010/main' $this//a14:imgProps/a14:imgLayer"; + XmlObject[] obj = ext.selectPath(xpath); + if(obj != null && obj.length == 1){ + XmlCursor c = obj[0].newCursor(); + String id = c.getAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "embed"));//selectPath("declare namespace r='http://schemas.openxmlformats.org/officeDocument/2006/relationships' $this//[@embed]"); + String newId = getSheet().importBlip(id, p.getSheet().getPackagePart()); + c.setAttributeText(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "embed"), newId); + c.dispose(); + } + } + } + + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java index 4adeba302b..6ab7711a84 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java @@ -1,107 +1,107 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; -import java.awt.geom.Rectangle2D; - -import org.apache.poi.sl.draw.DrawPaint; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.apache.poi.sl.usermodel.Shadow; -import org.apache.poi.util.Units; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; - -/** - * Represents a shadow of a shape. For now supports only outer shadows. - * - * @author Yegor Kozlov - */ -public class XSLFShadow extends XSLFShape implements Shadow { - - private XSLFSimpleShape _parent; - - /* package */XSLFShadow(CTOuterShadowEffect shape, XSLFSimpleShape parentShape) { - super(shape, parentShape.getSheet()); - - _parent = parentShape; - } - - @Override - public XSLFSimpleShape getShadowParent() { - return _parent; - } - - @Override - public Rectangle2D getAnchor(){ - return _parent.getAnchor(); - } - - public void setAnchor(Rectangle2D anchor){ - throw new IllegalStateException("You can't set anchor of a shadow"); - } - - /** - * @return the offset of this shadow in points - */ - public double getDistance(){ - CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); - return ct.isSetDist() ? Units.toPoints(ct.getDist()) : 0; - } - - /** - * - * @return the direction to offset the shadow in angles - */ - public double getAngle(){ - CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); - return ct.isSetDir() ? (double)ct.getDir() / 60000 : 0; - } - - /** - * - * @return the blur radius of the shadow - * TODO: figure out how to make sense of this property when rendering shadows - */ - public double getBlur(){ - CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); - return ct.isSetBlurRad() ? Units.toPoints(ct.getBlurRad()) : 0; - } - - /** - * @return the color of this shadow. - * Depending whether the parent shape is filled or stroked, this color is used to fill or stroke this shadow - */ - public Color getFillColor() { - SolidPaint ps = getFillStyle(); - if (ps == null) return null; - Color col = DrawPaint.applyColorTransform(ps.getSolidColor()); - return col; - } - - @Override - public SolidPaint getFillStyle() { - XSLFTheme theme = getSheet().getTheme(); - CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); - if(ct == null) return null; - - CTSchemeColor phClr = ct.getSchemeClr(); - final XSLFColor xc = new XSLFColor(ct, theme, phClr); - return DrawPaint.createSolidPaint(xc.getColorStyle()); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.Shadow; +import org.apache.poi.util.Units; +import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; + +/** + * Represents a shadow of a shape. For now supports only outer shadows. + * + * @author Yegor Kozlov + */ +public class XSLFShadow extends XSLFShape implements Shadow { + + private XSLFSimpleShape _parent; + + /* package */XSLFShadow(CTOuterShadowEffect shape, XSLFSimpleShape parentShape) { + super(shape, parentShape.getSheet()); + + _parent = parentShape; + } + + @Override + public XSLFSimpleShape getShadowParent() { + return _parent; + } + + @Override + public Rectangle2D getAnchor(){ + return _parent.getAnchor(); + } + + public void setAnchor(Rectangle2D anchor){ + throw new IllegalStateException("You can't set anchor of a shadow"); + } + + /** + * @return the offset of this shadow in points + */ + public double getDistance(){ + CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); + return ct.isSetDist() ? Units.toPoints(ct.getDist()) : 0; + } + + /** + * + * @return the direction to offset the shadow in angles + */ + public double getAngle(){ + CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); + return ct.isSetDir() ? (double)ct.getDir() / 60000 : 0; + } + + /** + * + * @return the blur radius of the shadow + * TODO: figure out how to make sense of this property when rendering shadows + */ + public double getBlur(){ + CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); + return ct.isSetBlurRad() ? Units.toPoints(ct.getBlurRad()) : 0; + } + + /** + * @return the color of this shadow. + * Depending whether the parent shape is filled or stroked, this color is used to fill or stroke this shadow + */ + public Color getFillColor() { + SolidPaint ps = getFillStyle(); + if (ps == null) return null; + Color col = DrawPaint.applyColorTransform(ps.getSolidColor()); + return col; + } + + @Override + public SolidPaint getFillStyle() { + XSLFTheme theme = getSheet().getTheme(); + CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); + if(ct == null) return null; + + CTSchemeColor phClr = ct.getSchemeClr(); + final XSLFColor xc = new XSLFColor(ct, theme, phClr); + return DrawPaint.createSolidPaint(xc.getColorStyle()); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index d73dcc8c0a..d3011604ce 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -1,562 +1,562 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Comparator; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.sl.draw.DrawFactory; -import org.apache.poi.sl.draw.DrawPaint; -import org.apache.poi.sl.usermodel.ColorStyle; -import org.apache.poi.sl.usermodel.MasterSheet; -import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; -import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; -import org.apache.poi.sl.usermodel.PlaceableShape; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.util.Beta; -import org.apache.poi.util.Internal; -import org.apache.poi.xslf.model.PropertyFetcher; -import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStop; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; -import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; -import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType; -import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; -import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; -import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; -import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; - -/** - * Base super-class class for all shapes in PresentationML - */ -@Beta -public abstract class XSLFShape implements Shape { - protected static final String PML_NS = "http://schemas.openxmlformats.org/presentationml/2006/main"; - - private final XmlObject _shape; - private final XSLFSheet _sheet; - private XSLFShapeContainer _parent; - - private CTShapeStyle _spStyle; - private CTNonVisualDrawingProps _nvPr; - private CTPlaceholder _ph; - - protected XSLFShape(XmlObject shape, XSLFSheet sheet) { - _shape = shape; - _sheet = sheet; - } - - /** - * @return the xml bean holding this shape's data - */ - public final XmlObject getXmlObject() { - // it's final because the xslf inheritance hierarchy is not necessary the same as - // the (not existing) xmlbeans hierarchy and subclasses shouldn't narrow it's return value - return _shape; - } - - public XSLFSheet getSheet() { - return _sheet; - } - - /** - * @return human-readable name of this shape, e.g. "Rectange 3" - */ - public String getShapeName(){ - return getCNvPr().getName(); - } - - /** - * Returns a unique identifier for this shape within the current document. - * This ID may be used to assist in uniquely identifying this object so that it can - * be referred to by other parts of the document. - *

- * If multiple objects within the same document share the same id attribute value, - * then the document shall be considered non-conformant. - *

- * - * @return unique id of this shape - */ - public int getShapeId() { - return (int)getCNvPr().getId(); - } - - /** - * Set the contents of this shape to be a copy of the source shape. - * This method is called recursively for each shape when merging slides - * - * @param sh the source shape - * @see org.apache.poi.xslf.usermodel.XSLFSlide#importContent(XSLFSheet) - */ - @Internal - void copy(XSLFShape sh) { - if (!getClass().isInstance(sh)) { - throw new IllegalArgumentException( - "Can't copy " + sh.getClass().getSimpleName() + " into " + getClass().getSimpleName()); - } - - if (this instanceof PlaceableShape) { - PlaceableShape ps = (PlaceableShape)this; - ps.setAnchor(sh.getAnchor()); - } - - - } - - public void setParent(XSLFShapeContainer parent) { - this._parent = parent; - } - - public XSLFShapeContainer getParent() { - return this._parent; - } - - protected PaintStyle getFillPaint() { - final XSLFTheme theme = getSheet().getTheme(); - final boolean hasPlaceholder = getPlaceholder() != null; - PropertyFetcher fetcher = new PropertyFetcher() { - public boolean fetch(XSLFShape shape) { - XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(shape.getShapeProperties()); - if (fp == null) { - return false; - } - - if (fp.isSetNoFill()) { - setValue(null); - return true; - } - - PackagePart pp = shape.getSheet().getPackagePart(); - PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder); - if (paint != null) { - setValue(paint); - return true; - } - - CTShapeStyle style = shape.getSpStyle(); - if (style != null) { - fp = XSLFPropertiesDelegate.getFillDelegate(style.getFillRef()); - paint = selectPaint(fp, null, pp, theme, hasPlaceholder); - } - if (paint != null) { - setValue(paint); - return true; - } - - - return false; - } - }; - fetchShapeProperty(fetcher); - - return fetcher.getValue(); - } - - protected CTBackgroundProperties getBgPr() { - return getChild(CTBackgroundProperties.class, PML_NS, "bgPr"); - } - - protected CTStyleMatrixReference getBgRef() { - return getChild(CTStyleMatrixReference.class, PML_NS, "bgRef"); - } - - protected CTGroupShapeProperties getGrpSpPr() { - return getChild(CTGroupShapeProperties.class, PML_NS, "grpSpPr"); - } - - protected CTNonVisualDrawingProps getCNvPr() { - if (_nvPr == null) { - String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"; - _nvPr = selectProperty(CTNonVisualDrawingProps.class, xquery); - } - return _nvPr; - } - - protected CTShapeStyle getSpStyle() { - if (_spStyle == null) { - _spStyle = getChild(CTShapeStyle.class, PML_NS, "style"); - } - return _spStyle; - } - - /** - * Return direct child objects of this shape - * - * @param childClass the class to cast the properties to - * @param namespace the namespace - usually it is {@code "http://schemas.openxmlformats.org/presentationml/2006/main"} - * @param nodename the node name, without prefix - * @return the properties object or null if it can't be found - */ - @SuppressWarnings("unchecked") - protected T getChild(Class childClass, String namespace, String nodename) { - XmlCursor cur = getXmlObject().newCursor(); - T child = null; - if (cur.toChild(namespace, nodename)) { - child = (T)cur.getObject(); - } - if (cur.toChild("http://schemas.openxmlformats.org/drawingml/2006/main", nodename)) { - child = (T)cur.getObject(); - } - cur.dispose(); - return child; - } - - protected CTPlaceholder getCTPlaceholder() { - if (_ph == null) { - String xquery = "declare namespace p='"+PML_NS+"' .//*/p:nvPr/p:ph"; - _ph = selectProperty(CTPlaceholder.class, xquery); - } - return _ph; - } - - public Placeholder getPlaceholder() { - CTPlaceholder ph = getCTPlaceholder(); - if (ph == null || !(ph.isSetType() || ph.isSetIdx())) { - return null; - } - return Placeholder.lookupOoxml(ph.getType().intValue()); - } - - /** - * Specifies that the corresponding shape should be represented by the generating application - * as a placeholder. When a shape is considered a placeholder by the generating application - * it can have special properties to alert the user that they may enter content into the shape. - * Different types of placeholders are allowed and can be specified by using the placeholder - * type attribute for this element - * - * @param placeholder The shape to use as placeholder or null if no placeholder should be set. - */ - protected void setPlaceholder(Placeholder placeholder) { - String xquery = "declare namespace p='"+PML_NS+"' .//*/p:nvPr"; - CTApplicationNonVisualDrawingProps nv = selectProperty(CTApplicationNonVisualDrawingProps.class, xquery); - if (nv == null) return; - if(placeholder == null) { - if (nv.isSetPh()) nv.unsetPh(); - _ph = null; - } else { - nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ooxmlId)); - } - } - - - /** - * As there's no xmlbeans hierarchy, but XSLF works with subclassing, not all - * child classes work with a {@link CTShape} object, but often contain the same - * properties. This method is the generalized form of selecting and casting those - * properties. - * - * @param resultClass the requested result class - * @param xquery the simple (xmlbean) xpath expression to the property - * @return the xml object at the xpath location, or null if not found - */ - @SuppressWarnings("unchecked") - protected T selectProperty(Class resultClass, String xquery) { - XmlObject[] rs = getXmlObject().selectPath(xquery); - if (rs.length == 0) return null; - return (resultClass.isInstance(rs[0])) ? (T)rs[0] : null; - } - - /** - * Walk up the inheritance tree and fetch shape properties.

- * - * The following order of inheritance is assumed:

- *

    - *
  1. slide - *
  2. slideLayout - *
  3. slideMaster - *
- * - * Currently themes and their defaults aren't correctly handled - * - * @param visitor the object that collects the desired property - * @return true if the property was fetched - */ - protected boolean fetchShapeProperty(PropertyFetcher visitor) { - // try shape properties in slide - if (visitor.fetch(this)) { - return true; - } - - CTPlaceholder ph = getCTPlaceholder(); - if (ph == null) { - return false; - } - MasterSheet sm = getSheet().getMasterSheet(); - - // try slide layout - if (sm instanceof XSLFSlideLayout) { - XSLFSlideLayout slideLayout = (XSLFSlideLayout)sm; - XSLFSimpleShape placeholderShape = slideLayout.getPlaceholder(ph); - if (placeholderShape != null && visitor.fetch(placeholderShape)) { - return true; - } - sm = slideLayout.getMasterSheet(); - } - - // try slide master - if (sm instanceof XSLFSlideMaster) { - XSLFSlideMaster master = (XSLFSlideMaster)sm; - int textType = getPlaceholderType(ph); - XSLFSimpleShape masterShape = master.getPlaceholderByType(textType); - if (masterShape != null && visitor.fetch(masterShape)) { - return true; - } - } - - return false; - } - - private static int getPlaceholderType(CTPlaceholder ph) { - if ( !ph.isSetType()) { - return STPlaceholderType.INT_BODY; - } - - switch (ph.getType().intValue()) { - case STPlaceholderType.INT_TITLE: - case STPlaceholderType.INT_CTR_TITLE: - return STPlaceholderType.INT_TITLE; - case STPlaceholderType.INT_FTR: - case STPlaceholderType.INT_SLD_NUM: - case STPlaceholderType.INT_DT: - return ph.getType().intValue(); - default: - return STPlaceholderType.INT_BODY; - } - } - - /** - * Convert shape fill into java.awt.Paint. The result is either Color or - * TexturePaint or GradientPaint or null - * - * @param fp a properties handler specific to the underlying shape properties - * @param phClr context color - * @param parentPart the parent package part. Any external references (images, etc.) are resolved relative to it. - * @param theme the theme for the shape/sheet - * - * @return the applied Paint or null if none was applied - */ - protected static PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme, boolean hasPlaceholder) { - if (fp == null || fp.isSetNoFill()) { - return null; - } else if (fp.isSetSolidFill()) { - return selectPaint(fp.getSolidFill(), phClr, theme); - } else if (fp.isSetBlipFill()) { - return selectPaint(fp.getBlipFill(), parentPart); - } else if (fp.isSetGradFill()) { - return selectPaint(fp.getGradFill(), phClr, theme); - } else if (fp.isSetMatrixStyle()) { - return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle(), hasPlaceholder); - } else { - return null; - } - } - - protected static PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) { - if (solidFill.isSetSchemeClr()) { - // if there's a reference to the placeholder color, - // stop evaluating further and let the caller select - // the next style inheritance level - if (STSchemeColorVal.PH_CLR.equals(solidFill.getSchemeClr().getVal())) { - return null; - } - if (phClr == null) { - phClr = solidFill.getSchemeClr(); - } - } - final XSLFColor c = new XSLFColor(solidFill, theme, phClr); - return DrawPaint.createSolidPaint(c.getColorStyle()); - } - - protected static PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) { - final CTBlip blip = blipFill.getBlip(); - return new TexturePaint() { - private PackagePart getPart() { - try { - String blipId = blip.getEmbed(); - PackageRelationship rel = parentPart.getRelationship(blipId); - return parentPart.getRelatedPart(rel); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } - } - - public InputStream getImageData() { - try { - return getPart().getInputStream(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public String getContentType() { - /* TOOD: map content-type */ - return getPart().getContentType(); - } - - public int getAlpha() { - return (blip.sizeOfAlphaModFixArray() > 0) - ? blip.getAlphaModFixArray(0).getAmt() - : 100000; - } - }; - } - - protected static PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) { - - final CTGradientStop[] gs = gradFill.getGsLst().getGsArray(); - - Arrays.sort(gs, new Comparator() { - public int compare(CTGradientStop o1, CTGradientStop o2) { - Integer pos1 = o1.getPos(); - Integer pos2 = o2.getPos(); - return pos1.compareTo(pos2); - } - }); - - final ColorStyle cs[] = new ColorStyle[gs.length]; - final float fractions[] = new float[gs.length]; - - int i=0; - for (CTGradientStop cgs : gs) { - CTSchemeColor phClrCgs = phClr; - if (phClrCgs == null && cgs.isSetSchemeClr()) { - phClrCgs = cgs.getSchemeClr(); - } - cs[i] = new XSLFColor(cgs, theme, phClrCgs).getColorStyle(); - fractions[i] = cgs.getPos() / 100000.f; - i++; - } - - return new GradientPaint() { - - public double getGradientAngle() { - return (gradFill.isSetLin()) - ? gradFill.getLin().getAng() / 60000.d - : 0; - } - - public ColorStyle[] getGradientColors() { - return cs; - } - - public float[] getGradientFractions() { - return fractions; - } - - public boolean isRotatedWithShape() { - // TODO: is this correct??? - return (gradFill.isSetRotWithShape() || !gradFill.getRotWithShape()); - } - - public GradientType getGradientType() { - if (gradFill.isSetLin()) { - return GradientType.linear; - } - - if (gradFill.isSetPath()) { - /* TODO: handle rect path */ - STPathShadeType.Enum ps = gradFill.getPath().getPath(); - if (ps == STPathShadeType.CIRCLE) { - return GradientType.circular; - } else if (ps == STPathShadeType.SHAPE) { - return GradientType.shape; - } - } - - return GradientType.linear; - } - }; - } - - protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) { - if (fillRef == null) return null; - - // The idx attribute refers to the index of a fill style or - // background fill style within the presentation's style matrix, defined by the fmtScheme element. - // value of 0 or 1000 indicates no background, - // values 1-999 refer to the index of a fill style within the fillStyleLst element - // values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element. - int idx = (int)fillRef.getIdx(); - CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme(); - final XmlObject styleLst; - int childIdx; - if (idx >= 1 && idx <= 999) { - childIdx = idx-1; - styleLst = (isLineStyle) ? matrix.getLnStyleLst() : matrix.getFillStyleLst(); - } else if (idx >= 1001 ){ - childIdx = idx - 1001; - styleLst = matrix.getBgFillStyleLst(); - } else { - return null; - } - XmlCursor cur = styleLst.newCursor(); - XSLFFillProperties fp = null; - if (cur.toChild(childIdx)) { - fp = XSLFPropertiesDelegate.getFillDelegate(cur.getObject()); - } - cur.dispose(); - - CTSchemeColor phClr = fillRef.getSchemeClr(); - PaintStyle res = selectPaint(fp, phClr, theme.getPackagePart(), theme, hasPlaceholder); - // check for empty placeholder value - // see http://officeopenxml.com/prSlide-color.php - "Color Placeholders within Themes" - if (res != null || hasPlaceholder) { - return res; - } - XSLFColor col = new XSLFColor(fillRef, theme, phClr); - return DrawPaint.createSolidPaint(col.getColorStyle()); - } - - @Override - public void draw(Graphics2D graphics, Rectangle2D bounds) { - DrawFactory.getInstance(graphics).drawShape(graphics, this, bounds); - } - - /** - * Return the shape specific (visual) properties - * - * @return the shape specific properties - */ - protected XmlObject getShapeProperties() { - return getChild(CTShapeProperties.class, PML_NS, "spPr"); - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Comparator; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.sl.draw.DrawFactory; +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.ColorStyle; +import org.apache.poi.sl.usermodel.MasterSheet; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; +import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; +import org.apache.poi.sl.usermodel.PlaceableShape; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.util.Beta; +import org.apache.poi.util.Internal; +import org.apache.poi.xslf.model.PropertyFetcher; +import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStop; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; +import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; +import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType; +import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; +import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; +import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; + +/** + * Base super-class class for all shapes in PresentationML + */ +@Beta +public abstract class XSLFShape implements Shape { + protected static final String PML_NS = "http://schemas.openxmlformats.org/presentationml/2006/main"; + + private final XmlObject _shape; + private final XSLFSheet _sheet; + private XSLFShapeContainer _parent; + + private CTShapeStyle _spStyle; + private CTNonVisualDrawingProps _nvPr; + private CTPlaceholder _ph; + + protected XSLFShape(XmlObject shape, XSLFSheet sheet) { + _shape = shape; + _sheet = sheet; + } + + /** + * @return the xml bean holding this shape's data + */ + public final XmlObject getXmlObject() { + // it's final because the xslf inheritance hierarchy is not necessary the same as + // the (not existing) xmlbeans hierarchy and subclasses shouldn't narrow it's return value + return _shape; + } + + public XSLFSheet getSheet() { + return _sheet; + } + + /** + * @return human-readable name of this shape, e.g. "Rectange 3" + */ + public String getShapeName(){ + return getCNvPr().getName(); + } + + /** + * Returns a unique identifier for this shape within the current document. + * This ID may be used to assist in uniquely identifying this object so that it can + * be referred to by other parts of the document. + *

+ * If multiple objects within the same document share the same id attribute value, + * then the document shall be considered non-conformant. + *

+ * + * @return unique id of this shape + */ + public int getShapeId() { + return (int)getCNvPr().getId(); + } + + /** + * Set the contents of this shape to be a copy of the source shape. + * This method is called recursively for each shape when merging slides + * + * @param sh the source shape + * @see org.apache.poi.xslf.usermodel.XSLFSlide#importContent(XSLFSheet) + */ + @Internal + void copy(XSLFShape sh) { + if (!getClass().isInstance(sh)) { + throw new IllegalArgumentException( + "Can't copy " + sh.getClass().getSimpleName() + " into " + getClass().getSimpleName()); + } + + if (this instanceof PlaceableShape) { + PlaceableShape ps = (PlaceableShape)this; + ps.setAnchor(sh.getAnchor()); + } + + + } + + public void setParent(XSLFShapeContainer parent) { + this._parent = parent; + } + + public XSLFShapeContainer getParent() { + return this._parent; + } + + protected PaintStyle getFillPaint() { + final XSLFTheme theme = getSheet().getTheme(); + final boolean hasPlaceholder = getPlaceholder() != null; + PropertyFetcher fetcher = new PropertyFetcher() { + public boolean fetch(XSLFShape shape) { + XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(shape.getShapeProperties()); + if (fp == null) { + return false; + } + + if (fp.isSetNoFill()) { + setValue(null); + return true; + } + + PackagePart pp = shape.getSheet().getPackagePart(); + PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder); + if (paint != null) { + setValue(paint); + return true; + } + + CTShapeStyle style = shape.getSpStyle(); + if (style != null) { + fp = XSLFPropertiesDelegate.getFillDelegate(style.getFillRef()); + paint = selectPaint(fp, null, pp, theme, hasPlaceholder); + } + if (paint != null) { + setValue(paint); + return true; + } + + + return false; + } + }; + fetchShapeProperty(fetcher); + + return fetcher.getValue(); + } + + protected CTBackgroundProperties getBgPr() { + return getChild(CTBackgroundProperties.class, PML_NS, "bgPr"); + } + + protected CTStyleMatrixReference getBgRef() { + return getChild(CTStyleMatrixReference.class, PML_NS, "bgRef"); + } + + protected CTGroupShapeProperties getGrpSpPr() { + return getChild(CTGroupShapeProperties.class, PML_NS, "grpSpPr"); + } + + protected CTNonVisualDrawingProps getCNvPr() { + if (_nvPr == null) { + String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"; + _nvPr = selectProperty(CTNonVisualDrawingProps.class, xquery); + } + return _nvPr; + } + + protected CTShapeStyle getSpStyle() { + if (_spStyle == null) { + _spStyle = getChild(CTShapeStyle.class, PML_NS, "style"); + } + return _spStyle; + } + + /** + * Return direct child objects of this shape + * + * @param childClass the class to cast the properties to + * @param namespace the namespace - usually it is {@code "http://schemas.openxmlformats.org/presentationml/2006/main"} + * @param nodename the node name, without prefix + * @return the properties object or null if it can't be found + */ + @SuppressWarnings("unchecked") + protected T getChild(Class childClass, String namespace, String nodename) { + XmlCursor cur = getXmlObject().newCursor(); + T child = null; + if (cur.toChild(namespace, nodename)) { + child = (T)cur.getObject(); + } + if (cur.toChild("http://schemas.openxmlformats.org/drawingml/2006/main", nodename)) { + child = (T)cur.getObject(); + } + cur.dispose(); + return child; + } + + protected CTPlaceholder getCTPlaceholder() { + if (_ph == null) { + String xquery = "declare namespace p='"+PML_NS+"' .//*/p:nvPr/p:ph"; + _ph = selectProperty(CTPlaceholder.class, xquery); + } + return _ph; + } + + public Placeholder getPlaceholder() { + CTPlaceholder ph = getCTPlaceholder(); + if (ph == null || !(ph.isSetType() || ph.isSetIdx())) { + return null; + } + return Placeholder.lookupOoxml(ph.getType().intValue()); + } + + /** + * Specifies that the corresponding shape should be represented by the generating application + * as a placeholder. When a shape is considered a placeholder by the generating application + * it can have special properties to alert the user that they may enter content into the shape. + * Different types of placeholders are allowed and can be specified by using the placeholder + * type attribute for this element + * + * @param placeholder The shape to use as placeholder or null if no placeholder should be set. + */ + protected void setPlaceholder(Placeholder placeholder) { + String xquery = "declare namespace p='"+PML_NS+"' .//*/p:nvPr"; + CTApplicationNonVisualDrawingProps nv = selectProperty(CTApplicationNonVisualDrawingProps.class, xquery); + if (nv == null) return; + if(placeholder == null) { + if (nv.isSetPh()) nv.unsetPh(); + _ph = null; + } else { + nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ooxmlId)); + } + } + + + /** + * As there's no xmlbeans hierarchy, but XSLF works with subclassing, not all + * child classes work with a {@link CTShape} object, but often contain the same + * properties. This method is the generalized form of selecting and casting those + * properties. + * + * @param resultClass the requested result class + * @param xquery the simple (xmlbean) xpath expression to the property + * @return the xml object at the xpath location, or null if not found + */ + @SuppressWarnings("unchecked") + protected T selectProperty(Class resultClass, String xquery) { + XmlObject[] rs = getXmlObject().selectPath(xquery); + if (rs.length == 0) return null; + return (resultClass.isInstance(rs[0])) ? (T)rs[0] : null; + } + + /** + * Walk up the inheritance tree and fetch shape properties.

+ * + * The following order of inheritance is assumed:

+ *

    + *
  1. slide + *
  2. slideLayout + *
  3. slideMaster + *
+ * + * Currently themes and their defaults aren't correctly handled + * + * @param visitor the object that collects the desired property + * @return true if the property was fetched + */ + protected boolean fetchShapeProperty(PropertyFetcher visitor) { + // try shape properties in slide + if (visitor.fetch(this)) { + return true; + } + + CTPlaceholder ph = getCTPlaceholder(); + if (ph == null) { + return false; + } + MasterSheet sm = getSheet().getMasterSheet(); + + // try slide layout + if (sm instanceof XSLFSlideLayout) { + XSLFSlideLayout slideLayout = (XSLFSlideLayout)sm; + XSLFSimpleShape placeholderShape = slideLayout.getPlaceholder(ph); + if (placeholderShape != null && visitor.fetch(placeholderShape)) { + return true; + } + sm = slideLayout.getMasterSheet(); + } + + // try slide master + if (sm instanceof XSLFSlideMaster) { + XSLFSlideMaster master = (XSLFSlideMaster)sm; + int textType = getPlaceholderType(ph); + XSLFSimpleShape masterShape = master.getPlaceholderByType(textType); + if (masterShape != null && visitor.fetch(masterShape)) { + return true; + } + } + + return false; + } + + private static int getPlaceholderType(CTPlaceholder ph) { + if ( !ph.isSetType()) { + return STPlaceholderType.INT_BODY; + } + + switch (ph.getType().intValue()) { + case STPlaceholderType.INT_TITLE: + case STPlaceholderType.INT_CTR_TITLE: + return STPlaceholderType.INT_TITLE; + case STPlaceholderType.INT_FTR: + case STPlaceholderType.INT_SLD_NUM: + case STPlaceholderType.INT_DT: + return ph.getType().intValue(); + default: + return STPlaceholderType.INT_BODY; + } + } + + /** + * Convert shape fill into java.awt.Paint. The result is either Color or + * TexturePaint or GradientPaint or null + * + * @param fp a properties handler specific to the underlying shape properties + * @param phClr context color + * @param parentPart the parent package part. Any external references (images, etc.) are resolved relative to it. + * @param theme the theme for the shape/sheet + * + * @return the applied Paint or null if none was applied + */ + protected static PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme, boolean hasPlaceholder) { + if (fp == null || fp.isSetNoFill()) { + return null; + } else if (fp.isSetSolidFill()) { + return selectPaint(fp.getSolidFill(), phClr, theme); + } else if (fp.isSetBlipFill()) { + return selectPaint(fp.getBlipFill(), parentPart); + } else if (fp.isSetGradFill()) { + return selectPaint(fp.getGradFill(), phClr, theme); + } else if (fp.isSetMatrixStyle()) { + return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle(), hasPlaceholder); + } else { + return null; + } + } + + protected static PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) { + if (solidFill.isSetSchemeClr()) { + // if there's a reference to the placeholder color, + // stop evaluating further and let the caller select + // the next style inheritance level + if (STSchemeColorVal.PH_CLR.equals(solidFill.getSchemeClr().getVal())) { + return null; + } + if (phClr == null) { + phClr = solidFill.getSchemeClr(); + } + } + final XSLFColor c = new XSLFColor(solidFill, theme, phClr); + return DrawPaint.createSolidPaint(c.getColorStyle()); + } + + protected static PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) { + final CTBlip blip = blipFill.getBlip(); + return new TexturePaint() { + private PackagePart getPart() { + try { + String blipId = blip.getEmbed(); + PackageRelationship rel = parentPart.getRelationship(blipId); + return parentPart.getRelatedPart(rel); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } + } + + public InputStream getImageData() { + try { + return getPart().getInputStream(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public String getContentType() { + /* TOOD: map content-type */ + return getPart().getContentType(); + } + + public int getAlpha() { + return (blip.sizeOfAlphaModFixArray() > 0) + ? blip.getAlphaModFixArray(0).getAmt() + : 100000; + } + }; + } + + protected static PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) { + + final CTGradientStop[] gs = gradFill.getGsLst().getGsArray(); + + Arrays.sort(gs, new Comparator() { + public int compare(CTGradientStop o1, CTGradientStop o2) { + Integer pos1 = o1.getPos(); + Integer pos2 = o2.getPos(); + return pos1.compareTo(pos2); + } + }); + + final ColorStyle cs[] = new ColorStyle[gs.length]; + final float fractions[] = new float[gs.length]; + + int i=0; + for (CTGradientStop cgs : gs) { + CTSchemeColor phClrCgs = phClr; + if (phClrCgs == null && cgs.isSetSchemeClr()) { + phClrCgs = cgs.getSchemeClr(); + } + cs[i] = new XSLFColor(cgs, theme, phClrCgs).getColorStyle(); + fractions[i] = cgs.getPos() / 100000.f; + i++; + } + + return new GradientPaint() { + + public double getGradientAngle() { + return (gradFill.isSetLin()) + ? gradFill.getLin().getAng() / 60000.d + : 0; + } + + public ColorStyle[] getGradientColors() { + return cs; + } + + public float[] getGradientFractions() { + return fractions; + } + + public boolean isRotatedWithShape() { + // TODO: is this correct??? + return (gradFill.isSetRotWithShape() || !gradFill.getRotWithShape()); + } + + public GradientType getGradientType() { + if (gradFill.isSetLin()) { + return GradientType.linear; + } + + if (gradFill.isSetPath()) { + /* TODO: handle rect path */ + STPathShadeType.Enum ps = gradFill.getPath().getPath(); + if (ps == STPathShadeType.CIRCLE) { + return GradientType.circular; + } else if (ps == STPathShadeType.SHAPE) { + return GradientType.shape; + } + } + + return GradientType.linear; + } + }; + } + + protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) { + if (fillRef == null) return null; + + // The idx attribute refers to the index of a fill style or + // background fill style within the presentation's style matrix, defined by the fmtScheme element. + // value of 0 or 1000 indicates no background, + // values 1-999 refer to the index of a fill style within the fillStyleLst element + // values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element. + int idx = (int)fillRef.getIdx(); + CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme(); + final XmlObject styleLst; + int childIdx; + if (idx >= 1 && idx <= 999) { + childIdx = idx-1; + styleLst = (isLineStyle) ? matrix.getLnStyleLst() : matrix.getFillStyleLst(); + } else if (idx >= 1001 ){ + childIdx = idx - 1001; + styleLst = matrix.getBgFillStyleLst(); + } else { + return null; + } + XmlCursor cur = styleLst.newCursor(); + XSLFFillProperties fp = null; + if (cur.toChild(childIdx)) { + fp = XSLFPropertiesDelegate.getFillDelegate(cur.getObject()); + } + cur.dispose(); + + CTSchemeColor phClr = fillRef.getSchemeClr(); + PaintStyle res = selectPaint(fp, phClr, theme.getPackagePart(), theme, hasPlaceholder); + // check for empty placeholder value + // see http://officeopenxml.com/prSlide-color.php - "Color Placeholders within Themes" + if (res != null || hasPlaceholder) { + return res; + } + XSLFColor col = new XSLFColor(fillRef, theme, phClr); + return DrawPaint.createSolidPaint(col.getColorStyle()); + } + + @Override + public void draw(Graphics2D graphics, Rectangle2D bounds) { + DrawFactory.getInstance(graphics).drawShape(graphics, this, bounds); + } + + /** + * Return the shape specific (visual) properties + * + * @return the shape specific properties + */ + protected XmlObject getShapeProperties() { + return getChild(CTShapeProperties.class, PML_NS, "spPr"); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java index 346d81b73e..71378e70ec 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java @@ -1,100 +1,100 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xslf.usermodel; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackageAccess; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.SlideShowFactory; -import org.apache.poi.util.Internal; - -@Internal -public class XSLFSlideShowFactory extends SlideShowFactory { - - /** - * Creates a XMLSlideShow from the given OOXML Package - * - *

Note that in order to properly release resources the - * SlideShow should be closed after use.

- * - * @param pkg The {@link OPCPackage} opened for reading data. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws InvalidFormatException - */ - public static SlideShow createSlideShow(OPCPackage pkg) throws IOException { - try { - return new XMLSlideShow(pkg); - } catch (IllegalArgumentException ioe) { - // ensure that file handles are closed (use revert() to not re-write the file) - pkg.revert(); - //pkg.close(); - - // rethrow exception - throw ioe; - } - } - - /** - * Creates the XMLSlideShow from the given File, which must exist and be readable. - *

Note that in order to properly release resources theSlideShow should be closed after use. - * - * @param file The file to read data from. - * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back - * changes when the document is closed. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws EncryptedDocumentException If the wrong password is given for a protected file - */ - @SuppressWarnings("resource") - public static SlideShow createSlideShow(File file, boolean readOnly) - throws IOException, InvalidFormatException { - OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE); - return createSlideShow(pkg); - } - - /** - * Creates a XMLSlideShow from the given InputStream - * - *

Note that in order to properly release resources the - * SlideShow should be closed after use.

- * - * @param stream The {@link InputStream} to read data from. - * - * @return The created SlideShow - * - * @throws IOException if an error occurs while reading the data - * @throws InvalidFormatException - */ - @SuppressWarnings("resource") - public static SlideShow createSlideShow(InputStream stream) throws IOException, InvalidFormatException { - OPCPackage pkg = OPCPackage.open(stream); - return createSlideShow(pkg); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xslf.usermodel; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.util.Internal; + +@Internal +public class XSLFSlideShowFactory extends SlideShowFactory { + + /** + * Creates a XMLSlideShow from the given OOXML Package + * + *

Note that in order to properly release resources the + * SlideShow should be closed after use.

+ * + * @param pkg The {@link OPCPackage} opened for reading data. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException + */ + public static SlideShow createSlideShow(OPCPackage pkg) throws IOException { + try { + return new XMLSlideShow(pkg); + } catch (IllegalArgumentException ioe) { + // ensure that file handles are closed (use revert() to not re-write the file) + pkg.revert(); + //pkg.close(); + + // rethrow exception + throw ioe; + } + } + + /** + * Creates the XMLSlideShow from the given File, which must exist and be readable. + *

Note that in order to properly release resources theSlideShow should be closed after use. + * + * @param file The file to read data from. + * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back + * changes when the document is closed. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the wrong password is given for a protected file + */ + @SuppressWarnings("resource") + public static SlideShow createSlideShow(File file, boolean readOnly) + throws IOException, InvalidFormatException { + OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE); + return createSlideShow(pkg); + } + + /** + * Creates a XMLSlideShow from the given InputStream + * + *

Note that in order to properly release resources the + * SlideShow should be closed after use.

+ * + * @param stream The {@link InputStream} to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException + */ + @SuppressWarnings("resource") + public static SlideShow createSlideShow(InputStream stream) throws IOException, InvalidFormatException { + OPCPackage pkg = OPCPackage.open(stream); + return createSlideShow(pkg); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java index 2637381d3e..484fa5f66f 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java @@ -1,350 +1,350 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import javax.xml.namespace.QName; - -import org.apache.poi.sl.draw.DrawFactory; -import org.apache.poi.sl.draw.DrawTableShape; -import org.apache.poi.sl.draw.DrawTextShape; -import org.apache.poi.sl.usermodel.TableShape; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Units; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTable; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual; - -/** - * Represents a table in a .pptx presentation - */ -public class XSLFTable extends XSLFGraphicFrame implements Iterable, - TableShape { - /* package */ static final String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table"; - /* package */ static final String DRAWINGML_URI = "http://schemas.openxmlformats.org/drawingml/2006/main"; - - private CTTable _table; - private List _rows; - - /*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){ - super(shape, sheet); - - CTGraphicalObjectData god = shape.getGraphic().getGraphicData(); - XmlCursor xc = god.newCursor(); - if (!xc.toChild(DRAWINGML_URI, "tbl")) { - throw new IllegalStateException("a:tbl element was not found in\n " + god); - } - - XmlObject xo = xc.getObject(); - // Pesky XmlBeans bug - see Bugzilla #49934 - // it never happens when using the full ooxml-schemas jar but may happen with the abridged poi-ooxml-schemas - if (xo instanceof XmlAnyTypeImpl){ - String errStr = - "Schemas (*.xsb) for CTTable can't be loaded - usually this happens when OSGI " + - "loading is used and the thread context classloader has no reference to " + - "the xmlbeans classes - use POIXMLTypeLoader.setClassLoader() to set the loader, " + - "e.g. with CTTable.class.getClassLoader()" - ; - throw new IllegalStateException(errStr); - } - _table = (CTTable)xo; - xc.dispose(); - - _rows = new ArrayList(_table.sizeOfTrArray()); - for(CTTableRow row : _table.getTrArray()) { - _rows.add(new XSLFTableRow(row, this)); - } - updateRowColIndexes(); - } - - @Override - public XSLFTableCell getCell(int row, int col) { - List rows = getRows(); - if (row < 0 || rows.size() <= row) { - return null; - } - XSLFTableRow r = rows.get(row); - if (r == null) { - // empty row - return null; - } - List cells = r.getCells(); - if (col < 0 || cells.size() <= col) { - return null; - } - // cell can be potentially empty ... - return cells.get(col); - } - - @Internal - public CTTable getCTTable(){ - return _table; - } - - @Override - public int getNumberOfColumns() { - return _table.getTblGrid().sizeOfGridColArray(); - } - - @Override - public int getNumberOfRows() { - return _table.sizeOfTrArray(); - } - - @Override - public double getColumnWidth(int idx){ - return Units.toPoints( - _table.getTblGrid().getGridColArray(idx).getW()); - } - - @Override - public void setColumnWidth(int idx, double width) { - _table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width)); - } - - @Override - public double getRowHeight(int row) { - return Units.toPoints(_table.getTrArray(row).getH()); - } - - @Override - public void setRowHeight(int row, double height) { - _table.getTrArray(row).setH(Units.toEMU(height)); - } - - public Iterator iterator(){ - return _rows.iterator(); - } - - public List getRows(){ - return Collections.unmodifiableList(_rows); - } - - public XSLFTableRow addRow(){ - CTTableRow tr = _table.addNewTr(); - XSLFTableRow row = new XSLFTableRow(tr, this); - // default height is 20 points - row.setHeight(20.0); - _rows.add(row); - updateRowColIndexes(); - return row; - } - - static CTGraphicalObjectFrame prototype(int shapeId){ - CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance(); - CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr(); - - CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr(); - cnv.setName("Table " + shapeId); - cnv.setId(shapeId + 1); - nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true); - nvGr.addNewNvPr(); - - frame.addNewXfrm(); - CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData(); - XmlCursor grCur = gr.newCursor(); - grCur.toNextToken(); - grCur.beginElement(new QName(DRAWINGML_URI, "tbl")); - - CTTable tbl = CTTable.Factory.newInstance(); - tbl.addNewTblPr(); - tbl.addNewTblGrid(); - XmlCursor tblCur = tbl.newCursor(); - - tblCur.moveXmlContents(grCur); - tblCur.dispose(); - grCur.dispose(); - gr.setUri(TABLE_URI); - return frame; - } - - /** - * Merge cells of a table - */ - public void mergeCells(int firstRow, int lastRow, int firstCol, int lastCol) { - - if(firstRow > lastRow) { - throw new IllegalArgumentException( - "Cannot merge, first row > last row : " - + firstRow + " > " + lastRow - ); - } - - if(firstCol > lastCol) { - throw new IllegalArgumentException( - "Cannot merge, first column > last column : " - + firstCol + " > " + lastCol - ); - } - - int rowSpan = (lastRow - firstRow) + 1; - boolean mergeRowRequired = rowSpan > 1; - - int colSpan = (lastCol - firstCol) + 1; - boolean mergeColumnRequired = colSpan > 1; - - for(int i = firstRow; i <= lastRow; i++) { - - XSLFTableRow row = _rows.get(i); - - for(int colPos = firstCol; colPos <= lastCol; colPos++) { - - XSLFTableCell cell = row.getCells().get(colPos); - - if(mergeRowRequired) { - if(i == firstRow) { - cell.setRowSpan(rowSpan); - } else { - cell.setVMerge(true); - } - } - if(mergeColumnRequired) { - if(colPos == firstCol) { - cell.setGridSpan(colSpan); - } else { - cell.setHMerge(true); - } - } - } - } - } - - /** - * Get assigned TableStyle - * - * @return the assigned TableStyle - * - * @since POI 3.15-beta2 - */ - protected XSLFTableStyle getTableStyle() { - CTTable tab = getCTTable(); - // TODO: support inline table style - if (!tab.isSetTblPr() || !tab.getTblPr().isSetTableStyleId()) { - return null; - } - - String styleId = tab.getTblPr().getTableStyleId(); - XSLFTableStyles styles = getSheet().getSlideShow().getTableStyles(); - for (XSLFTableStyle style : styles.getStyles()) { - if (style.getStyleId().equals(styleId)) { - return style; - } - } - return null; - } - - /* package */ void updateRowColIndexes() { - int rowIdx = 0; - for (XSLFTableRow xr : this) { - int colIdx = 0; - for (XSLFTableCell tc : xr) { - tc.setRowColIndex(rowIdx, colIdx); - colIdx++; - } - rowIdx++; - } - } - - /* package */ void updateCellAnchor() { - int rows = getNumberOfRows(); - int cols = getNumberOfColumns(); - - double colWidths[] = new double[cols]; - double rowHeights[] = new double[rows]; - - for (int row=0; row, + TableShape { + /* package */ static final String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table"; + /* package */ static final String DRAWINGML_URI = "http://schemas.openxmlformats.org/drawingml/2006/main"; + + private CTTable _table; + private List _rows; + + /*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){ + super(shape, sheet); + + CTGraphicalObjectData god = shape.getGraphic().getGraphicData(); + XmlCursor xc = god.newCursor(); + if (!xc.toChild(DRAWINGML_URI, "tbl")) { + throw new IllegalStateException("a:tbl element was not found in\n " + god); + } + + XmlObject xo = xc.getObject(); + // Pesky XmlBeans bug - see Bugzilla #49934 + // it never happens when using the full ooxml-schemas jar but may happen with the abridged poi-ooxml-schemas + if (xo instanceof XmlAnyTypeImpl){ + String errStr = + "Schemas (*.xsb) for CTTable can't be loaded - usually this happens when OSGI " + + "loading is used and the thread context classloader has no reference to " + + "the xmlbeans classes - use POIXMLTypeLoader.setClassLoader() to set the loader, " + + "e.g. with CTTable.class.getClassLoader()" + ; + throw new IllegalStateException(errStr); + } + _table = (CTTable)xo; + xc.dispose(); + + _rows = new ArrayList(_table.sizeOfTrArray()); + for(CTTableRow row : _table.getTrArray()) { + _rows.add(new XSLFTableRow(row, this)); + } + updateRowColIndexes(); + } + + @Override + public XSLFTableCell getCell(int row, int col) { + List rows = getRows(); + if (row < 0 || rows.size() <= row) { + return null; + } + XSLFTableRow r = rows.get(row); + if (r == null) { + // empty row + return null; + } + List cells = r.getCells(); + if (col < 0 || cells.size() <= col) { + return null; + } + // cell can be potentially empty ... + return cells.get(col); + } + + @Internal + public CTTable getCTTable(){ + return _table; + } + + @Override + public int getNumberOfColumns() { + return _table.getTblGrid().sizeOfGridColArray(); + } + + @Override + public int getNumberOfRows() { + return _table.sizeOfTrArray(); + } + + @Override + public double getColumnWidth(int idx){ + return Units.toPoints( + _table.getTblGrid().getGridColArray(idx).getW()); + } + + @Override + public void setColumnWidth(int idx, double width) { + _table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width)); + } + + @Override + public double getRowHeight(int row) { + return Units.toPoints(_table.getTrArray(row).getH()); + } + + @Override + public void setRowHeight(int row, double height) { + _table.getTrArray(row).setH(Units.toEMU(height)); + } + + public Iterator iterator(){ + return _rows.iterator(); + } + + public List getRows(){ + return Collections.unmodifiableList(_rows); + } + + public XSLFTableRow addRow(){ + CTTableRow tr = _table.addNewTr(); + XSLFTableRow row = new XSLFTableRow(tr, this); + // default height is 20 points + row.setHeight(20.0); + _rows.add(row); + updateRowColIndexes(); + return row; + } + + static CTGraphicalObjectFrame prototype(int shapeId){ + CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance(); + CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr(); + + CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr(); + cnv.setName("Table " + shapeId); + cnv.setId(shapeId + 1); + nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true); + nvGr.addNewNvPr(); + + frame.addNewXfrm(); + CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData(); + XmlCursor grCur = gr.newCursor(); + grCur.toNextToken(); + grCur.beginElement(new QName(DRAWINGML_URI, "tbl")); + + CTTable tbl = CTTable.Factory.newInstance(); + tbl.addNewTblPr(); + tbl.addNewTblGrid(); + XmlCursor tblCur = tbl.newCursor(); + + tblCur.moveXmlContents(grCur); + tblCur.dispose(); + grCur.dispose(); + gr.setUri(TABLE_URI); + return frame; + } + + /** + * Merge cells of a table + */ + public void mergeCells(int firstRow, int lastRow, int firstCol, int lastCol) { + + if(firstRow > lastRow) { + throw new IllegalArgumentException( + "Cannot merge, first row > last row : " + + firstRow + " > " + lastRow + ); + } + + if(firstCol > lastCol) { + throw new IllegalArgumentException( + "Cannot merge, first column > last column : " + + firstCol + " > " + lastCol + ); + } + + int rowSpan = (lastRow - firstRow) + 1; + boolean mergeRowRequired = rowSpan > 1; + + int colSpan = (lastCol - firstCol) + 1; + boolean mergeColumnRequired = colSpan > 1; + + for(int i = firstRow; i <= lastRow; i++) { + + XSLFTableRow row = _rows.get(i); + + for(int colPos = firstCol; colPos <= lastCol; colPos++) { + + XSLFTableCell cell = row.getCells().get(colPos); + + if(mergeRowRequired) { + if(i == firstRow) { + cell.setRowSpan(rowSpan); + } else { + cell.setVMerge(true); + } + } + if(mergeColumnRequired) { + if(colPos == firstCol) { + cell.setGridSpan(colSpan); + } else { + cell.setHMerge(true); + } + } + } + } + } + + /** + * Get assigned TableStyle + * + * @return the assigned TableStyle + * + * @since POI 3.15-beta2 + */ + protected XSLFTableStyle getTableStyle() { + CTTable tab = getCTTable(); + // TODO: support inline table style + if (!tab.isSetTblPr() || !tab.getTblPr().isSetTableStyleId()) { + return null; + } + + String styleId = tab.getTblPr().getTableStyleId(); + XSLFTableStyles styles = getSheet().getSlideShow().getTableStyles(); + for (XSLFTableStyle style : styles.getStyles()) { + if (style.getStyleId().equals(styleId)) { + return style; + } + } + return null; + } + + /* package */ void updateRowColIndexes() { + int rowIdx = 0; + for (XSLFTableRow xr : this) { + int colIdx = 0; + for (XSLFTableCell tc : xr) { + tc.setRowColIndex(rowIdx, colIdx); + colIdx++; + } + rowIdx++; + } + } + + /* package */ void updateCellAnchor() { + int rows = getNumberOfRows(); + int cols = getNumberOfColumns(); + + double colWidths[] = new double[cols]; + double rowHeights[] = new double[rows]; + + for (int row=0; row { - private CTTableCellProperties _tcPr = null; - private final XSLFTable table; - private int row = 0, col = 0; - - /** - * Volatile/temporary anchor - e.g. for rendering - */ - private Rectangle2D anchor = null; - - /*package*/ XSLFTableCell(CTTableCell cell, XSLFTable table){ - super(cell, table.getSheet()); - this.table = table; - } - - @Override - protected CTTextBody getTextBody(boolean create){ - CTTableCell cell = getCell(); - CTTextBody txBody = cell.getTxBody(); - if (txBody == null && create) { - txBody = cell.addNewTxBody(); - XSLFAutoShape.initTextBody(txBody); - } - return txBody; - } - - static CTTableCell prototype() { - CTTableCell cell = CTTableCell.Factory.newInstance(); - CTTableCellProperties pr = cell.addNewTcPr(); - pr.addNewLnL().addNewNoFill(); - pr.addNewLnR().addNewNoFill(); - pr.addNewLnT().addNewNoFill(); - pr.addNewLnB().addNewNoFill(); - return cell; - } - - protected CTTableCellProperties getCellProperties(boolean create) { - if (_tcPr == null) { - CTTableCell cell = getCell(); - _tcPr = cell.getTcPr(); - if (_tcPr == null && create) { - _tcPr = cell.addNewTcPr(); - } - } - return _tcPr; - } - - @Override - public void setLeftInset(double margin){ - CTTableCellProperties pr = getCellProperties(true); - pr.setMarL(Units.toEMU(margin)); - } - - @Override - public void setRightInset(double margin){ - CTTableCellProperties pr = getCellProperties(true); - pr.setMarR(Units.toEMU(margin)); - } - - @Override - public void setTopInset(double margin){ - CTTableCellProperties pr = getCellProperties(true); - pr.setMarT(Units.toEMU(margin)); - } - - @Override - public void setBottomInset(double margin){ - CTTableCellProperties pr = getCellProperties(true); - pr.setMarB(Units.toEMU(margin)); - } - - private CTLineProperties getCTLine(BorderEdge edge, boolean create) { - if (edge == null) { - throw new IllegalArgumentException("BorderEdge needs to be specified."); - } - - CTTableCellProperties pr = getCellProperties(create); - if (pr == null) { - return null; - } - - switch (edge) { - case bottom: - return (pr.isSetLnB()) ? pr.getLnB() : (create ? pr.addNewLnB() : null); - case left: - return (pr.isSetLnL()) ? pr.getLnL() : (create ? pr.addNewLnL() : null); - case top: - return (pr.isSetLnT()) ? pr.getLnT() : (create ? pr.addNewLnT() : null); - case right: - return (pr.isSetLnR()) ? pr.getLnR() : (create ? pr.addNewLnR() : null); - default: - return null; - } - } - - @Override - public void removeBorder(BorderEdge edge) { - CTTableCellProperties pr = getCellProperties(false); - if (pr == null) { - return; - } - switch (edge) { - case bottom: - if (pr.isSetLnB()) { - pr.unsetLnB(); - } - break; - case left: - if (pr.isSetLnL()) { - pr.unsetLnL(); - } - break; - case top: - if (pr.isSetLnT()) { - pr.unsetLnT(); - } - break; - case right: - if (pr.isSetLnR()) { - pr.unsetLnB(); - } - break; - default: - throw new IllegalArgumentException(); - } - } - - @Override - public StrokeStyle getBorderStyle(final BorderEdge edge) { - final Double width = getBorderWidth(edge); - return (width == null) ? null : new StrokeStyle() { - @Override - public PaintStyle getPaint() { - return DrawPaint.createSolidPaint(getBorderColor(edge)); - } - - @Override - public LineCap getLineCap() { - return getBorderCap(edge); - } - - @Override - public LineDash getLineDash() { - return getBorderDash(edge); - } - - @Override - public LineCompound getLineCompound() { - return getBorderCompound(edge); - } - - @Override - public double getLineWidth() { - return width; - } - }; - } - - @Override - public void setBorderStyle(BorderEdge edge, StrokeStyle style) { - if (style == null) { - throw new IllegalArgumentException("StrokeStyle needs to be specified."); - } - - LineCap cap = style.getLineCap(); - if (cap != null) { - setBorderCap(edge, cap); - } - - LineCompound compound = style.getLineCompound(); - if (compound != null) { - setBorderCompound(edge, compound); - } - - LineDash dash = style.getLineDash(); - if (dash != null) { - setBorderDash(edge, dash); - } - - double width = style.getLineWidth(); - setBorderWidth(edge, width); - } - - public Double getBorderWidth(BorderEdge edge) { - CTLineProperties ln = getCTLine(edge, false); - return (ln == null || !ln.isSetW()) ? null : Units.toPoints(ln.getW()); - } - - @Override - public void setBorderWidth(BorderEdge edge, double width) { - CTLineProperties ln = getCTLine(edge, true); - ln.setW(Units.toEMU(width)); - } - - private CTLineProperties setBorderDefaults(BorderEdge edge) { - CTLineProperties ln = getCTLine(edge, true); - if (ln.isSetNoFill()) { - ln.unsetNoFill(); - } - - if(!ln.isSetPrstDash()) { - ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID); - } - if (!ln.isSetCmpd()) { - ln.setCmpd(STCompoundLine.SNG); - } - if (!ln.isSetAlgn()) { - ln.setAlgn(STPenAlignment.CTR); - } - if (!ln.isSetCap()) { - ln.setCap(STLineCap.FLAT); - } - if (!ln.isSetRound()) { - ln.addNewRound(); - } - - if (!ln.isSetHeadEnd()) { - CTLineEndProperties hd = ln.addNewHeadEnd(); - hd.setType(STLineEndType.NONE); - hd.setW(STLineEndWidth.MED); - hd.setLen(STLineEndLength.MED); - } - - if (!ln.isSetTailEnd()) { - CTLineEndProperties tl = ln.addNewTailEnd(); - tl.setType(STLineEndType.NONE); - tl.setW(STLineEndWidth.MED); - tl.setLen(STLineEndLength.MED); - } - - return ln; - } - - @Override - public void setBorderColor(BorderEdge edge, Color color) { - if (color == null) { - throw new IllegalArgumentException("Colors need to be specified."); - } - - CTLineProperties ln = setBorderDefaults(edge); - CTSolidColorFillProperties fill = ln.addNewSolidFill(); - XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); - c.setColor(color); - } - - public Color getBorderColor(BorderEdge edge) { - CTLineProperties ln = getCTLine(edge, false); - if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) { - return null; - } - - CTSolidColorFillProperties fill = ln.getSolidFill(); - XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); - return c.getColor(); - } - - public LineCompound getBorderCompound(BorderEdge edge) { - CTLineProperties ln = getCTLine(edge, false); - if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCmpd()) { - return null; - } - - return LineCompound.fromOoxmlId(ln.getCmpd().intValue()); - } - - @Override - public void setBorderCompound(BorderEdge edge, LineCompound compound) { - if (compound == null) { - throw new IllegalArgumentException("LineCompound need to be specified."); - } - - CTLineProperties ln = setBorderDefaults(edge); - ln.setCmpd(STCompoundLine.Enum.forInt(compound.ooxmlId)); - } - - public LineDash getBorderDash(BorderEdge edge) { - CTLineProperties ln = getCTLine(edge, false); - if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetPrstDash()) { - return null; - } - - return LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue()); - } - - @Override - public void setBorderDash(BorderEdge edge, LineDash dash) { - if (dash == null) { - throw new IllegalArgumentException("LineDash need to be specified."); - } - - CTLineProperties ln = setBorderDefaults(edge); - ln.getPrstDash().setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId)); - } - - public LineCap getBorderCap(BorderEdge edge) { - CTLineProperties ln = getCTLine(edge, false); - if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCap()) { - return null; - } - - return LineCap.fromOoxmlId(ln.getCap().intValue()); - } - - public void setBorderCap(BorderEdge edge, LineCap cap) { - if (cap == null) { - throw new IllegalArgumentException("LineCap need to be specified."); - } - - CTLineProperties ln = setBorderDefaults(edge); - ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId)); - } - - - - /** - * Specifies a solid color fill. The shape is filled entirely with the specified color. - * - * @param color the solid color fill. - * The value of null unsets the solidFIll attribute from the underlying xml - */ - @Override - public void setFillColor(Color color) { - CTTableCellProperties spPr = getCellProperties(true); - if (color == null) { - if(spPr.isSetSolidFill()) { - spPr.unsetSolidFill(); - } - } else { - CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill(); - XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); - c.setColor(color); - } - } - - /** - * - * @return solid fill color of null if not set - */ - @Override - public Color getFillColor(){ - PaintStyle ps = getFillPaint(); - if (ps instanceof SolidPaint) { - ColorStyle cs = ((SolidPaint)ps).getSolidColor(); - return DrawPaint.applyColorTransform(cs); - } - - return null; - } - - @SuppressWarnings("resource") - @Override - public PaintStyle getFillPaint() { - XSLFSheet sheet = getSheet(); - XSLFTheme theme = sheet.getTheme(); - final boolean hasPlaceholder = getPlaceholder() != null; - XmlObject props = getCellProperties(false); - XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props); - if (fp != null) { - PaintStyle paint = selectPaint(fp, null, sheet.getPackagePart(), theme, hasPlaceholder); - if (paint != null) { - return paint; - } - } - - CTTablePartStyle tps = getTablePartStyle(null); - if (tps == null || !tps.isSetTcStyle()) { - tps = getTablePartStyle(TablePartStyle.wholeTbl); - if (tps == null || !tps.isSetTcStyle()) { - return null; - } - } - - XMLSlideShow slideShow = sheet.getSlideShow(); - CTTableStyleCellStyle tcStyle = tps.getTcStyle(); - if (tcStyle.isSetFill()) { - props = tcStyle.getFill(); - } else if (tcStyle.isSetFillRef()) { - props = tcStyle.getFillRef(); - } else { - return null; - } - - fp = XSLFPropertiesDelegate.getFillDelegate(props); - if (fp != null) { - PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder); - if (paint != null) { - return paint; - } - } - - return null; - } - - /** - * Retrieves the part style depending on the location of this cell - * - * @param tablePartStyle the part to be returned, usually this is null - * and only set when used as a helper method - * @return the table part style - */ - private CTTablePartStyle getTablePartStyle(TablePartStyle tablePartStyle) { - CTTable ct = table.getCTTable(); - if (!ct.isSetTblPr()) { - return null; - } - - CTTableProperties pr = ct.getTblPr(); - boolean bandRow = (pr.isSetBandRow() && pr.getBandRow()); - boolean firstRow = (pr.isSetFirstRow() && pr.getFirstRow()); - boolean lastRow = (pr.isSetLastRow() && pr.getLastRow()); - boolean bandCol = (pr.isSetBandCol() && pr.getBandCol()); - boolean firstCol = (pr.isSetFirstCol() && pr.getFirstCol()); - boolean lastCol = (pr.isSetLastCol() && pr.getLastCol()); - - TablePartStyle tps; - if (tablePartStyle != null) { - tps = tablePartStyle; - } else if (row == 0 && firstRow) { - tps = TablePartStyle.firstRow; - } else if (row == table.getNumberOfRows()-1 && lastRow) { - tps = TablePartStyle.lastRow; - } else if (col == 0 && firstCol) { - tps = TablePartStyle.firstCol; - } else if (col == table.getNumberOfColumns()-1 && lastCol) { - tps = TablePartStyle.lastCol; - } else { - tps = TablePartStyle.wholeTbl; - - int br = row + (firstRow ? 1 : 0); - int bc = col + (firstCol ? 1 : 0); - if (bandRow && (br & 1) == 0) { - tps = TablePartStyle.band1H; - } else if (bandCol && (bc & 1) == 0) { - tps = TablePartStyle.band1V; - } - } - - XSLFTableStyle tabStyle = table.getTableStyle(); - if (tabStyle == null) { - return null; - } - - CTTablePartStyle part = tabStyle.getTablePartStyle(tps); - return (part == null) ? tabStyle.getTablePartStyle(TablePartStyle.wholeTbl) : part; - } - - void setGridSpan(int gridSpan_) { - getCell().setGridSpan(gridSpan_); - } - - @Override - public int getGridSpan() { - CTTableCell c = getCell(); - return (c.isSetGridSpan()) ? c.getGridSpan() : 1; - } - - void setRowSpan(int rowSpan_) { - getCell().setRowSpan(rowSpan_); - } - - @Override - public int getRowSpan() { - CTTableCell c = getCell(); - return (c.isSetRowSpan()) ? c.getRowSpan() : 1; - } - - void setHMerge(boolean merge_) { - getCell().setHMerge(merge_); - } - - void setVMerge(boolean merge_) { - getCell().setVMerge(merge_); - } - - @Override - public void setVerticalAlignment(VerticalAlignment anchor){ - CTTableCellProperties cellProps = getCellProperties(true); - if(anchor == null) { - if(cellProps.isSetAnchor()) { - cellProps.unsetAnchor(); - } - } else { - cellProps.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); - } - } - - @Override - public VerticalAlignment getVerticalAlignment(){ - CTTableCellProperties cellProps = getCellProperties(false); - - VerticalAlignment align = VerticalAlignment.TOP; - if(cellProps != null && cellProps.isSetAnchor()) { - int ival = cellProps.getAnchor().intValue(); - align = VerticalAlignment.values()[ival - 1]; - } - return align; - } - - /** - * @since POI 3.15-beta2 - */ - @Override - public void setTextDirection(TextDirection orientation) { - CTTableCellProperties cellProps = getCellProperties(true); - if(orientation == null) { - if (cellProps.isSetVert()) { - cellProps.unsetVert(); - } - } else { - STTextVerticalType.Enum vt; - switch (orientation) { - default: - case HORIZONTAL: - vt = STTextVerticalType.HORZ; - break; - case VERTICAL: - vt = STTextVerticalType.VERT; - break; - case VERTICAL_270: - vt = STTextVerticalType.VERT_270; - break; - case STACKED: - vt = STTextVerticalType.WORD_ART_VERT; - break; - } - - cellProps.setVert(vt); - } - } - - /** - * @since POI 3.15-beta2 - */ - @Override - public TextDirection getTextDirection() { - CTTableCellProperties cellProps = getCellProperties(false); - - STTextVerticalType.Enum orientation; - if (cellProps != null && cellProps.isSetVert()) { - orientation = cellProps.getVert(); - } else { - orientation = STTextVerticalType.HORZ; - } - - switch (orientation.intValue()) { - default: - case STTextVerticalType.INT_HORZ: - return TextDirection.HORIZONTAL; - case STTextVerticalType.INT_VERT: - case STTextVerticalType.INT_EA_VERT: - case STTextVerticalType.INT_MONGOLIAN_VERT: - return TextDirection.VERTICAL; - case STTextVerticalType.INT_VERT_270: - return TextDirection.VERTICAL_270; - case STTextVerticalType.INT_WORD_ART_VERT: - case STTextVerticalType.INT_WORD_ART_VERT_RTL: - return TextDirection.STACKED; - } - } - - private CTTableCell getCell() { - return (CTTableCell)getXmlObject(); - } - - /* package */ void setRowColIndex(int row, int col) { - this.row = row; - this.col = col; - } - - /** - * Return a fake-xfrm which is used for calculating the text height - */ - protected CTTransform2D getXfrm() { - Rectangle2D anc = getAnchor(); - CTTransform2D xfrm = CTTransform2D.Factory.newInstance(); - CTPoint2D off = xfrm.addNewOff(); - off.setX(Units.toEMU(anc.getX())); - off.setY(Units.toEMU(anc.getY())); - CTPositiveSize2D size = xfrm.addNewExt(); - size.setCx(Units.toEMU(anc.getWidth())); - size.setCy(Units.toEMU(anc.getHeight())); - return xfrm; - } - - /** - * There's no real anchor for table cells - this method is used to temporarily store the location - * of the cell for a later retrieval, e.g. for rendering - * - * @since POI 3.15-beta2 - */ - @Override - public void setAnchor(Rectangle2D anchor) { - if (this.anchor == null) { - this.anchor = (Rectangle2D)anchor.clone(); - } else { - this.anchor.setRect(anchor); - } - } - - /** - * @since POI 3.15-beta2 - */ - @Override - public Rectangle2D getAnchor() { - if (anchor == null) { - table.updateCellAnchor(); - } - // anchor should be set, after updateCellAnchor is through - assert(anchor != null); - return anchor; - } - - /** - * @since POI 3.15-beta2 - */ - @Override - public boolean isMerged() { - CTTableCell c = getCell(); - return (c.isSetHMerge() && c.getHMerge()) || (c.isSetVMerge() && c.getVMerge()); - } - - /** - * @since POI 3.15-beta2 - */ - @Override - protected XSLFCellTextParagraph newTextParagraph(CTTextParagraph p) { - return new XSLFCellTextParagraph(p, this); - } - - @Override - protected XmlObject getShapeProperties() { - return getCellProperties(false); - } - - /** - * @since POI 3.15-beta2 - */ - private class XSLFCellTextParagraph extends XSLFTextParagraph { - protected XSLFCellTextParagraph(CTTextParagraph p, XSLFTextShape shape) { - super(p, shape); - } - - @Override - protected XSLFCellTextRun newTextRun(CTRegularTextRun r) { - return new XSLFCellTextRun(r, this); - } - } - - /** - * @since POI 3.15-beta2 - */ - private class XSLFCellTextRun extends XSLFTextRun { - protected XSLFCellTextRun(CTRegularTextRun r, XSLFTextParagraph p) { - super(r, p); - } - - @Override - public PaintStyle getFontColor(){ - CTTableStyleTextStyle txStyle = getTextStyle(); - if (txStyle == null) { - return super.getFontColor(); - } - - CTSchemeColor phClr = null; - CTFontReference fontRef = txStyle.getFontRef(); - if (fontRef != null) { - phClr = fontRef.getSchemeClr(); - } - - XSLFTheme theme = getSheet().getTheme(); - final XSLFColor c = new XSLFColor(txStyle, theme, phClr); - return DrawPaint.createSolidPaint(c.getColorStyle()); - } - - @Override - public boolean isBold() { - CTTableStyleTextStyle txStyle = getTextStyle(); - if (txStyle == null) { - return super.isBold(); - } else { - return txStyle.isSetB() && txStyle.getB().intValue() == STOnOffStyleType.INT_ON; - } - } - - @Override - public boolean isItalic() { - CTTableStyleTextStyle txStyle = getTextStyle(); - if (txStyle == null) { - return super.isItalic(); - } else { - return txStyle.isSetI() && txStyle.getI().intValue() == STOnOffStyleType.INT_ON; - } - } - - private CTTableStyleTextStyle getTextStyle() { - CTTablePartStyle tps = getTablePartStyle(null); - if (tps == null || !tps.isSetTcTxStyle()) { - tps = getTablePartStyle(TablePartStyle.wholeTbl); - } - return (tps == null) ? null : tps.getTcTxStyle(); - } - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; +import java.awt.geom.Rectangle2D; + +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.ColorStyle; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.StrokeStyle; +import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; +import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; +import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; +import org.apache.poi.sl.usermodel.TableCell; +import org.apache.poi.sl.usermodel.VerticalAlignment; +import org.apache.poi.util.Units; +import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties; +import org.apache.poi.xslf.usermodel.XSLFTableStyle.TablePartStyle; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTable; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleCellStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleTextStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; +import org.openxmlformats.schemas.drawingml.x2006.main.STOnOffStyleType; +import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType; + +/** + * Represents a cell of a table in a .pptx presentation + */ +public class XSLFTableCell extends XSLFTextShape implements TableCell { + private CTTableCellProperties _tcPr = null; + private final XSLFTable table; + private int row = 0, col = 0; + + /** + * Volatile/temporary anchor - e.g. for rendering + */ + private Rectangle2D anchor = null; + + /*package*/ XSLFTableCell(CTTableCell cell, XSLFTable table){ + super(cell, table.getSheet()); + this.table = table; + } + + @Override + protected CTTextBody getTextBody(boolean create){ + CTTableCell cell = getCell(); + CTTextBody txBody = cell.getTxBody(); + if (txBody == null && create) { + txBody = cell.addNewTxBody(); + XSLFAutoShape.initTextBody(txBody); + } + return txBody; + } + + static CTTableCell prototype() { + CTTableCell cell = CTTableCell.Factory.newInstance(); + CTTableCellProperties pr = cell.addNewTcPr(); + pr.addNewLnL().addNewNoFill(); + pr.addNewLnR().addNewNoFill(); + pr.addNewLnT().addNewNoFill(); + pr.addNewLnB().addNewNoFill(); + return cell; + } + + protected CTTableCellProperties getCellProperties(boolean create) { + if (_tcPr == null) { + CTTableCell cell = getCell(); + _tcPr = cell.getTcPr(); + if (_tcPr == null && create) { + _tcPr = cell.addNewTcPr(); + } + } + return _tcPr; + } + + @Override + public void setLeftInset(double margin){ + CTTableCellProperties pr = getCellProperties(true); + pr.setMarL(Units.toEMU(margin)); + } + + @Override + public void setRightInset(double margin){ + CTTableCellProperties pr = getCellProperties(true); + pr.setMarR(Units.toEMU(margin)); + } + + @Override + public void setTopInset(double margin){ + CTTableCellProperties pr = getCellProperties(true); + pr.setMarT(Units.toEMU(margin)); + } + + @Override + public void setBottomInset(double margin){ + CTTableCellProperties pr = getCellProperties(true); + pr.setMarB(Units.toEMU(margin)); + } + + private CTLineProperties getCTLine(BorderEdge edge, boolean create) { + if (edge == null) { + throw new IllegalArgumentException("BorderEdge needs to be specified."); + } + + CTTableCellProperties pr = getCellProperties(create); + if (pr == null) { + return null; + } + + switch (edge) { + case bottom: + return (pr.isSetLnB()) ? pr.getLnB() : (create ? pr.addNewLnB() : null); + case left: + return (pr.isSetLnL()) ? pr.getLnL() : (create ? pr.addNewLnL() : null); + case top: + return (pr.isSetLnT()) ? pr.getLnT() : (create ? pr.addNewLnT() : null); + case right: + return (pr.isSetLnR()) ? pr.getLnR() : (create ? pr.addNewLnR() : null); + default: + return null; + } + } + + @Override + public void removeBorder(BorderEdge edge) { + CTTableCellProperties pr = getCellProperties(false); + if (pr == null) { + return; + } + switch (edge) { + case bottom: + if (pr.isSetLnB()) { + pr.unsetLnB(); + } + break; + case left: + if (pr.isSetLnL()) { + pr.unsetLnL(); + } + break; + case top: + if (pr.isSetLnT()) { + pr.unsetLnT(); + } + break; + case right: + if (pr.isSetLnR()) { + pr.unsetLnB(); + } + break; + default: + throw new IllegalArgumentException(); + } + } + + @Override + public StrokeStyle getBorderStyle(final BorderEdge edge) { + final Double width = getBorderWidth(edge); + return (width == null) ? null : new StrokeStyle() { + @Override + public PaintStyle getPaint() { + return DrawPaint.createSolidPaint(getBorderColor(edge)); + } + + @Override + public LineCap getLineCap() { + return getBorderCap(edge); + } + + @Override + public LineDash getLineDash() { + return getBorderDash(edge); + } + + @Override + public LineCompound getLineCompound() { + return getBorderCompound(edge); + } + + @Override + public double getLineWidth() { + return width; + } + }; + } + + @Override + public void setBorderStyle(BorderEdge edge, StrokeStyle style) { + if (style == null) { + throw new IllegalArgumentException("StrokeStyle needs to be specified."); + } + + LineCap cap = style.getLineCap(); + if (cap != null) { + setBorderCap(edge, cap); + } + + LineCompound compound = style.getLineCompound(); + if (compound != null) { + setBorderCompound(edge, compound); + } + + LineDash dash = style.getLineDash(); + if (dash != null) { + setBorderDash(edge, dash); + } + + double width = style.getLineWidth(); + setBorderWidth(edge, width); + } + + public Double getBorderWidth(BorderEdge edge) { + CTLineProperties ln = getCTLine(edge, false); + return (ln == null || !ln.isSetW()) ? null : Units.toPoints(ln.getW()); + } + + @Override + public void setBorderWidth(BorderEdge edge, double width) { + CTLineProperties ln = getCTLine(edge, true); + ln.setW(Units.toEMU(width)); + } + + private CTLineProperties setBorderDefaults(BorderEdge edge) { + CTLineProperties ln = getCTLine(edge, true); + if (ln.isSetNoFill()) { + ln.unsetNoFill(); + } + + if(!ln.isSetPrstDash()) { + ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID); + } + if (!ln.isSetCmpd()) { + ln.setCmpd(STCompoundLine.SNG); + } + if (!ln.isSetAlgn()) { + ln.setAlgn(STPenAlignment.CTR); + } + if (!ln.isSetCap()) { + ln.setCap(STLineCap.FLAT); + } + if (!ln.isSetRound()) { + ln.addNewRound(); + } + + if (!ln.isSetHeadEnd()) { + CTLineEndProperties hd = ln.addNewHeadEnd(); + hd.setType(STLineEndType.NONE); + hd.setW(STLineEndWidth.MED); + hd.setLen(STLineEndLength.MED); + } + + if (!ln.isSetTailEnd()) { + CTLineEndProperties tl = ln.addNewTailEnd(); + tl.setType(STLineEndType.NONE); + tl.setW(STLineEndWidth.MED); + tl.setLen(STLineEndLength.MED); + } + + return ln; + } + + @Override + public void setBorderColor(BorderEdge edge, Color color) { + if (color == null) { + throw new IllegalArgumentException("Colors need to be specified."); + } + + CTLineProperties ln = setBorderDefaults(edge); + CTSolidColorFillProperties fill = ln.addNewSolidFill(); + XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); + c.setColor(color); + } + + public Color getBorderColor(BorderEdge edge) { + CTLineProperties ln = getCTLine(edge, false); + if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) { + return null; + } + + CTSolidColorFillProperties fill = ln.getSolidFill(); + XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); + return c.getColor(); + } + + public LineCompound getBorderCompound(BorderEdge edge) { + CTLineProperties ln = getCTLine(edge, false); + if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCmpd()) { + return null; + } + + return LineCompound.fromOoxmlId(ln.getCmpd().intValue()); + } + + @Override + public void setBorderCompound(BorderEdge edge, LineCompound compound) { + if (compound == null) { + throw new IllegalArgumentException("LineCompound need to be specified."); + } + + CTLineProperties ln = setBorderDefaults(edge); + ln.setCmpd(STCompoundLine.Enum.forInt(compound.ooxmlId)); + } + + public LineDash getBorderDash(BorderEdge edge) { + CTLineProperties ln = getCTLine(edge, false); + if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetPrstDash()) { + return null; + } + + return LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue()); + } + + @Override + public void setBorderDash(BorderEdge edge, LineDash dash) { + if (dash == null) { + throw new IllegalArgumentException("LineDash need to be specified."); + } + + CTLineProperties ln = setBorderDefaults(edge); + ln.getPrstDash().setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId)); + } + + public LineCap getBorderCap(BorderEdge edge) { + CTLineProperties ln = getCTLine(edge, false); + if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCap()) { + return null; + } + + return LineCap.fromOoxmlId(ln.getCap().intValue()); + } + + public void setBorderCap(BorderEdge edge, LineCap cap) { + if (cap == null) { + throw new IllegalArgumentException("LineCap need to be specified."); + } + + CTLineProperties ln = setBorderDefaults(edge); + ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId)); + } + + + + /** + * Specifies a solid color fill. The shape is filled entirely with the specified color. + * + * @param color the solid color fill. + * The value of null unsets the solidFIll attribute from the underlying xml + */ + @Override + public void setFillColor(Color color) { + CTTableCellProperties spPr = getCellProperties(true); + if (color == null) { + if(spPr.isSetSolidFill()) { + spPr.unsetSolidFill(); + } + } else { + CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill(); + XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); + c.setColor(color); + } + } + + /** + * + * @return solid fill color of null if not set + */ + @Override + public Color getFillColor(){ + PaintStyle ps = getFillPaint(); + if (ps instanceof SolidPaint) { + ColorStyle cs = ((SolidPaint)ps).getSolidColor(); + return DrawPaint.applyColorTransform(cs); + } + + return null; + } + + @SuppressWarnings("resource") + @Override + public PaintStyle getFillPaint() { + XSLFSheet sheet = getSheet(); + XSLFTheme theme = sheet.getTheme(); + final boolean hasPlaceholder = getPlaceholder() != null; + XmlObject props = getCellProperties(false); + XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props); + if (fp != null) { + PaintStyle paint = selectPaint(fp, null, sheet.getPackagePart(), theme, hasPlaceholder); + if (paint != null) { + return paint; + } + } + + CTTablePartStyle tps = getTablePartStyle(null); + if (tps == null || !tps.isSetTcStyle()) { + tps = getTablePartStyle(TablePartStyle.wholeTbl); + if (tps == null || !tps.isSetTcStyle()) { + return null; + } + } + + XMLSlideShow slideShow = sheet.getSlideShow(); + CTTableStyleCellStyle tcStyle = tps.getTcStyle(); + if (tcStyle.isSetFill()) { + props = tcStyle.getFill(); + } else if (tcStyle.isSetFillRef()) { + props = tcStyle.getFillRef(); + } else { + return null; + } + + fp = XSLFPropertiesDelegate.getFillDelegate(props); + if (fp != null) { + PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder); + if (paint != null) { + return paint; + } + } + + return null; + } + + /** + * Retrieves the part style depending on the location of this cell + * + * @param tablePartStyle the part to be returned, usually this is null + * and only set when used as a helper method + * @return the table part style + */ + private CTTablePartStyle getTablePartStyle(TablePartStyle tablePartStyle) { + CTTable ct = table.getCTTable(); + if (!ct.isSetTblPr()) { + return null; + } + + CTTableProperties pr = ct.getTblPr(); + boolean bandRow = (pr.isSetBandRow() && pr.getBandRow()); + boolean firstRow = (pr.isSetFirstRow() && pr.getFirstRow()); + boolean lastRow = (pr.isSetLastRow() && pr.getLastRow()); + boolean bandCol = (pr.isSetBandCol() && pr.getBandCol()); + boolean firstCol = (pr.isSetFirstCol() && pr.getFirstCol()); + boolean lastCol = (pr.isSetLastCol() && pr.getLastCol()); + + TablePartStyle tps; + if (tablePartStyle != null) { + tps = tablePartStyle; + } else if (row == 0 && firstRow) { + tps = TablePartStyle.firstRow; + } else if (row == table.getNumberOfRows()-1 && lastRow) { + tps = TablePartStyle.lastRow; + } else if (col == 0 && firstCol) { + tps = TablePartStyle.firstCol; + } else if (col == table.getNumberOfColumns()-1 && lastCol) { + tps = TablePartStyle.lastCol; + } else { + tps = TablePartStyle.wholeTbl; + + int br = row + (firstRow ? 1 : 0); + int bc = col + (firstCol ? 1 : 0); + if (bandRow && (br & 1) == 0) { + tps = TablePartStyle.band1H; + } else if (bandCol && (bc & 1) == 0) { + tps = TablePartStyle.band1V; + } + } + + XSLFTableStyle tabStyle = table.getTableStyle(); + if (tabStyle == null) { + return null; + } + + CTTablePartStyle part = tabStyle.getTablePartStyle(tps); + return (part == null) ? tabStyle.getTablePartStyle(TablePartStyle.wholeTbl) : part; + } + + void setGridSpan(int gridSpan_) { + getCell().setGridSpan(gridSpan_); + } + + @Override + public int getGridSpan() { + CTTableCell c = getCell(); + return (c.isSetGridSpan()) ? c.getGridSpan() : 1; + } + + void setRowSpan(int rowSpan_) { + getCell().setRowSpan(rowSpan_); + } + + @Override + public int getRowSpan() { + CTTableCell c = getCell(); + return (c.isSetRowSpan()) ? c.getRowSpan() : 1; + } + + void setHMerge(boolean merge_) { + getCell().setHMerge(merge_); + } + + void setVMerge(boolean merge_) { + getCell().setVMerge(merge_); + } + + @Override + public void setVerticalAlignment(VerticalAlignment anchor){ + CTTableCellProperties cellProps = getCellProperties(true); + if(anchor == null) { + if(cellProps.isSetAnchor()) { + cellProps.unsetAnchor(); + } + } else { + cellProps.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); + } + } + + @Override + public VerticalAlignment getVerticalAlignment(){ + CTTableCellProperties cellProps = getCellProperties(false); + + VerticalAlignment align = VerticalAlignment.TOP; + if(cellProps != null && cellProps.isSetAnchor()) { + int ival = cellProps.getAnchor().intValue(); + align = VerticalAlignment.values()[ival - 1]; + } + return align; + } + + /** + * @since POI 3.15-beta2 + */ + @Override + public void setTextDirection(TextDirection orientation) { + CTTableCellProperties cellProps = getCellProperties(true); + if(orientation == null) { + if (cellProps.isSetVert()) { + cellProps.unsetVert(); + } + } else { + STTextVerticalType.Enum vt; + switch (orientation) { + default: + case HORIZONTAL: + vt = STTextVerticalType.HORZ; + break; + case VERTICAL: + vt = STTextVerticalType.VERT; + break; + case VERTICAL_270: + vt = STTextVerticalType.VERT_270; + break; + case STACKED: + vt = STTextVerticalType.WORD_ART_VERT; + break; + } + + cellProps.setVert(vt); + } + } + + /** + * @since POI 3.15-beta2 + */ + @Override + public TextDirection getTextDirection() { + CTTableCellProperties cellProps = getCellProperties(false); + + STTextVerticalType.Enum orientation; + if (cellProps != null && cellProps.isSetVert()) { + orientation = cellProps.getVert(); + } else { + orientation = STTextVerticalType.HORZ; + } + + switch (orientation.intValue()) { + default: + case STTextVerticalType.INT_HORZ: + return TextDirection.HORIZONTAL; + case STTextVerticalType.INT_VERT: + case STTextVerticalType.INT_EA_VERT: + case STTextVerticalType.INT_MONGOLIAN_VERT: + return TextDirection.VERTICAL; + case STTextVerticalType.INT_VERT_270: + return TextDirection.VERTICAL_270; + case STTextVerticalType.INT_WORD_ART_VERT: + case STTextVerticalType.INT_WORD_ART_VERT_RTL: + return TextDirection.STACKED; + } + } + + private CTTableCell getCell() { + return (CTTableCell)getXmlObject(); + } + + /* package */ void setRowColIndex(int row, int col) { + this.row = row; + this.col = col; + } + + /** + * Return a fake-xfrm which is used for calculating the text height + */ + protected CTTransform2D getXfrm() { + Rectangle2D anc = getAnchor(); + CTTransform2D xfrm = CTTransform2D.Factory.newInstance(); + CTPoint2D off = xfrm.addNewOff(); + off.setX(Units.toEMU(anc.getX())); + off.setY(Units.toEMU(anc.getY())); + CTPositiveSize2D size = xfrm.addNewExt(); + size.setCx(Units.toEMU(anc.getWidth())); + size.setCy(Units.toEMU(anc.getHeight())); + return xfrm; + } + + /** + * There's no real anchor for table cells - this method is used to temporarily store the location + * of the cell for a later retrieval, e.g. for rendering + * + * @since POI 3.15-beta2 + */ + @Override + public void setAnchor(Rectangle2D anchor) { + if (this.anchor == null) { + this.anchor = (Rectangle2D)anchor.clone(); + } else { + this.anchor.setRect(anchor); + } + } + + /** + * @since POI 3.15-beta2 + */ + @Override + public Rectangle2D getAnchor() { + if (anchor == null) { + table.updateCellAnchor(); + } + // anchor should be set, after updateCellAnchor is through + assert(anchor != null); + return anchor; + } + + /** + * @since POI 3.15-beta2 + */ + @Override + public boolean isMerged() { + CTTableCell c = getCell(); + return (c.isSetHMerge() && c.getHMerge()) || (c.isSetVMerge() && c.getVMerge()); + } + + /** + * @since POI 3.15-beta2 + */ + @Override + protected XSLFCellTextParagraph newTextParagraph(CTTextParagraph p) { + return new XSLFCellTextParagraph(p, this); + } + + @Override + protected XmlObject getShapeProperties() { + return getCellProperties(false); + } + + /** + * @since POI 3.15-beta2 + */ + private class XSLFCellTextParagraph extends XSLFTextParagraph { + protected XSLFCellTextParagraph(CTTextParagraph p, XSLFTextShape shape) { + super(p, shape); + } + + @Override + protected XSLFCellTextRun newTextRun(CTRegularTextRun r) { + return new XSLFCellTextRun(r, this); + } + } + + /** + * @since POI 3.15-beta2 + */ + private class XSLFCellTextRun extends XSLFTextRun { + protected XSLFCellTextRun(CTRegularTextRun r, XSLFTextParagraph p) { + super(r, p); + } + + @Override + public PaintStyle getFontColor(){ + CTTableStyleTextStyle txStyle = getTextStyle(); + if (txStyle == null) { + return super.getFontColor(); + } + + CTSchemeColor phClr = null; + CTFontReference fontRef = txStyle.getFontRef(); + if (fontRef != null) { + phClr = fontRef.getSchemeClr(); + } + + XSLFTheme theme = getSheet().getTheme(); + final XSLFColor c = new XSLFColor(txStyle, theme, phClr); + return DrawPaint.createSolidPaint(c.getColorStyle()); + } + + @Override + public boolean isBold() { + CTTableStyleTextStyle txStyle = getTextStyle(); + if (txStyle == null) { + return super.isBold(); + } else { + return txStyle.isSetB() && txStyle.getB().intValue() == STOnOffStyleType.INT_ON; + } + } + + @Override + public boolean isItalic() { + CTTableStyleTextStyle txStyle = getTextStyle(); + if (txStyle == null) { + return super.isItalic(); + } else { + return txStyle.isSetI() && txStyle.getI().intValue() == STOnOffStyleType.INT_ON; + } + } + + private CTTableStyleTextStyle getTextStyle() { + CTTablePartStyle tps = getTablePartStyle(null); + if (tps == null || !tps.isSetTcTxStyle()) { + tps = getTablePartStyle(TablePartStyle.wholeTbl); + } + return (tps == null) ? null : tps.getTcTxStyle(); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java index c4529c4aa7..a49d5a9242 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableRow.java @@ -1,106 +1,106 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.util.Units; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow; - -/** - * Represents a table in a .pptx presentation - */ -public class XSLFTableRow implements Iterable { - private final CTTableRow _row; - private final List _cells; - private final XSLFTable _table; - - /*package*/ XSLFTableRow(CTTableRow row, XSLFTable table){ - _row = row; - _table = table; - CTTableCell[] tcArray = _row.getTcArray(); - _cells = new ArrayList(tcArray.length); - for(CTTableCell cell : tcArray) { - _cells.add(new XSLFTableCell(cell, table)); - } - } - - public CTTableRow getXmlObject(){ - return _row; - } - - public Iterator iterator(){ - return _cells.iterator(); - } - - public List getCells(){ - return Collections.unmodifiableList(_cells); - } - - public double getHeight(){ - return Units.toPoints(_row.getH()); - } - - public void setHeight(double height){ - _row.setH(Units.toEMU(height)); - } - - public XSLFTableCell addCell(){ - CTTableCell c = _row.addNewTc(); - c.set(XSLFTableCell.prototype()); - XSLFTableCell cell = new XSLFTableCell(c, _table); - _cells.add(cell); - - if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) { - _table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0)); - } - _table.updateRowColIndexes(); - return cell; - } - - /** - * Merge cells of a table row, inclusive. - * Indices are 0-based. - * - * @param firstCol 0-based index of first column to merge, inclusive - * @param lastCol 0-based index of last column to merge, inclusive - */ - public void mergeCells(int firstCol, int lastCol) - { - if (firstCol >= lastCol) { - throw new IllegalArgumentException( - "Cannot merge, first column >= last column : " - + firstCol + " >= " + lastCol - ); - } - - final int colSpan = (lastCol - firstCol) + 1; - - _cells.get(firstCol).setGridSpan(colSpan); - for (final XSLFTableCell cell : _cells.subList(firstCol+1, lastCol+1)) { - cell.setHMerge(true); - } - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.util.Units; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow; + +/** + * Represents a table in a .pptx presentation + */ +public class XSLFTableRow implements Iterable { + private final CTTableRow _row; + private final List _cells; + private final XSLFTable _table; + + /*package*/ XSLFTableRow(CTTableRow row, XSLFTable table){ + _row = row; + _table = table; + CTTableCell[] tcArray = _row.getTcArray(); + _cells = new ArrayList(tcArray.length); + for(CTTableCell cell : tcArray) { + _cells.add(new XSLFTableCell(cell, table)); + } + } + + public CTTableRow getXmlObject(){ + return _row; + } + + public Iterator iterator(){ + return _cells.iterator(); + } + + public List getCells(){ + return Collections.unmodifiableList(_cells); + } + + public double getHeight(){ + return Units.toPoints(_row.getH()); + } + + public void setHeight(double height){ + _row.setH(Units.toEMU(height)); + } + + public XSLFTableCell addCell(){ + CTTableCell c = _row.addNewTc(); + c.set(XSLFTableCell.prototype()); + XSLFTableCell cell = new XSLFTableCell(c, _table); + _cells.add(cell); + + if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) { + _table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0)); + } + _table.updateRowColIndexes(); + return cell; + } + + /** + * Merge cells of a table row, inclusive. + * Indices are 0-based. + * + * @param firstCol 0-based index of first column to merge, inclusive + * @param lastCol 0-based index of last column to merge, inclusive + */ + public void mergeCells(int firstCol, int lastCol) + { + if (firstCol >= lastCol) { + throw new IllegalArgumentException( + "Cannot merge, first column >= last column : " + + firstCol + " >= " + lastCol + ); + } + + final int colSpan = (lastCol - firstCol) + 1; + + _cells.get(firstCol).setGridSpan(colSpan); + for (final XSLFTableCell cell : _cells.subList(firstCol+1, lastCol+1)) { + cell.setHMerge(true); + } + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyle.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyle.java index b3bcdfabd9..b821910eaf 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyle.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableStyle.java @@ -1,85 +1,85 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle; - -/** - * Represents a table style in a .pptx presentation - */ -public class XSLFTableStyle { - private CTTableStyle _tblStyle; - - public enum TablePartStyle { - wholeTbl, band1H, band2H, band1V, band2V, firstCol, lastCol, firstRow, lastRow, seCell, swCell, neCell, nwCell; - } - - /*package*/ XSLFTableStyle(CTTableStyle style){ - _tblStyle = style; - } - - public CTTableStyle getXmlObject(){ - return _tblStyle; - } - - public String getStyleName(){ - return _tblStyle.getStyleName(); - } - - public String getStyleId(){ - return _tblStyle.getStyleId(); - } - - /** - * @since POI 3.15-beta2 - */ - protected CTTablePartStyle getTablePartStyle(TablePartStyle tps) { - switch (tps) { - default: - case wholeTbl: - return _tblStyle.getWholeTbl(); - case band1H: - return _tblStyle.getBand1H(); - case band2H: - return _tblStyle.getBand2H(); - case band1V: - return _tblStyle.getBand1V(); - case band2V: - return _tblStyle.getBand2V(); - case firstCol: - return _tblStyle.getFirstCol(); - case lastCol: - return _tblStyle.getLastCol(); - case firstRow: - return _tblStyle.getFirstRow(); - case lastRow: - return _tblStyle.getLastRow(); - case seCell: - return _tblStyle.getSeCell(); - case swCell: - return _tblStyle.getSwCell(); - case neCell: - return _tblStyle.getNeCell(); - case nwCell: - return _tblStyle.getNwCell(); - } - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle; + +/** + * Represents a table style in a .pptx presentation + */ +public class XSLFTableStyle { + private CTTableStyle _tblStyle; + + public enum TablePartStyle { + wholeTbl, band1H, band2H, band1V, band2V, firstCol, lastCol, firstRow, lastRow, seCell, swCell, neCell, nwCell; + } + + /*package*/ XSLFTableStyle(CTTableStyle style){ + _tblStyle = style; + } + + public CTTableStyle getXmlObject(){ + return _tblStyle; + } + + public String getStyleName(){ + return _tblStyle.getStyleName(); + } + + public String getStyleId(){ + return _tblStyle.getStyleId(); + } + + /** + * @since POI 3.15-beta2 + */ + protected CTTablePartStyle getTablePartStyle(TablePartStyle tps) { + switch (tps) { + default: + case wholeTbl: + return _tblStyle.getWholeTbl(); + case band1H: + return _tblStyle.getBand1H(); + case band2H: + return _tblStyle.getBand2H(); + case band1V: + return _tblStyle.getBand1V(); + case band2V: + return _tblStyle.getBand2V(); + case firstCol: + return _tblStyle.getFirstCol(); + case lastCol: + return _tblStyle.getLastCol(); + case firstRow: + return _tblStyle.getFirstRow(); + case lastRow: + return _tblStyle.getLastRow(); + case seCell: + return _tblStyle.getSeCell(); + case swCell: + return _tblStyle.getSwCell(); + case neCell: + return _tblStyle.getNeCell(); + case nwCell: + return _tblStyle.getNwCell(); + } + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java index bb5bd42ae5..2f172d2fdc 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextBox.java @@ -1,61 +1,61 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import org.apache.poi.sl.usermodel.TextBox; -import org.apache.poi.util.Beta; -import org.openxmlformats.schemas.drawingml.x2006.main.*; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; - - -/** - * @author Yegor Kozlov - */ -@Beta -public class XSLFTextBox extends XSLFAutoShape - implements TextBox { - - /*package*/ XSLFTextBox(CTShape shape, XSLFSheet sheet){ - super(shape, sheet); - } - - /** - * - * @param shapeId 1-based shapeId - */ - static CTShape prototype(int shapeId){ - CTShape ct = CTShape.Factory.newInstance(); - CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); - CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); - cnv.setName("TextBox " + shapeId); - cnv.setId(shapeId + 1); - nvSpPr.addNewCNvSpPr().setTxBox(true); - nvSpPr.addNewNvPr(); - CTShapeProperties spPr = ct.addNewSpPr(); - CTPresetGeometry2D prst = spPr.addNewPrstGeom(); - prst.setPrst(STShapeType.RECT); - prst.addNewAvLst(); - CTTextBody txBody = ct.addNewTxBody(); - XSLFAutoShape.initTextBody(txBody); - - return ct; - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import org.apache.poi.sl.usermodel.TextBox; +import org.apache.poi.util.Beta; +import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; + + +/** + * @author Yegor Kozlov + */ +@Beta +public class XSLFTextBox extends XSLFAutoShape + implements TextBox { + + /*package*/ XSLFTextBox(CTShape shape, XSLFSheet sheet){ + super(shape, sheet); + } + + /** + * + * @param shapeId 1-based shapeId + */ + static CTShape prototype(int shapeId){ + CTShape ct = CTShape.Factory.newInstance(); + CTShapeNonVisual nvSpPr = ct.addNewNvSpPr(); + CTNonVisualDrawingProps cnv = nvSpPr.addNewCNvPr(); + cnv.setName("TextBox " + shapeId); + cnv.setId(shapeId + 1); + nvSpPr.addNewCNvSpPr().setTxBox(true); + nvSpPr.addNewNvPr(); + CTShapeProperties spPr = ct.addNewSpPr(); + CTPresetGeometry2D prst = spPr.addNewPrstGeom(); + prst.setPrst(STShapeType.RECT); + prst.addNewAvLst(); + CTTextBody txBody = ct.addNewTxBody(); + XSLFAutoShape.initTextBody(txBody); + + return ct; + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java index 7bf2a6c6ef..8048e59b55 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java @@ -1,629 +1,629 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import java.awt.Color; - -import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.sl.draw.DrawPaint; -import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.apache.poi.sl.usermodel.TextRun; -import org.apache.poi.util.Beta; -import org.apache.poi.xslf.model.CharacterPropertyFetcher; -import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; -import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; - -/** - * Represents a run of text within the containing text body. The run element is the - * lowest level text separation mechanism within a text body. - */ -@Beta -public class XSLFTextRun implements TextRun { - private final XmlObject _r; - private final XSLFTextParagraph _p; - - protected XSLFTextRun(XmlObject r, XSLFTextParagraph p){ - _r = r; - _p = p; - if (!(r instanceof CTRegularTextRun || r instanceof CTTextLineBreak || r instanceof CTTextField)) { - throw new OpenXML4JRuntimeException("unsupported text run of type "+r.getClass()); - } - } - - XSLFTextParagraph getParentParagraph(){ - return _p; - } - - public String getRawText(){ - if (_r instanceof CTTextField) { - return ((CTTextField)_r).getT(); - } else if (_r instanceof CTTextLineBreak) { - return "\n"; - } - return ((CTRegularTextRun)_r).getT(); - } - - String getRenderableText(){ - if (_r instanceof CTTextField) { - CTTextField tf = (CTTextField)_r; - XSLFSheet sheet = _p.getParentShape().getSheet(); - if ("slidenum".equals(tf.getType()) && sheet instanceof XSLFSlide) { - return Integer.toString(((XSLFSlide)sheet).getSlideNumber()); - } - return tf.getT(); - } else if (_r instanceof CTTextLineBreak) { - return "\n"; - } - - - String txt = ((CTRegularTextRun)_r).getT(); - TextCap cap = getTextCap(); - StringBuffer buf = new StringBuffer(); - for(int i = 0; i < txt.length(); i++) { - char c = txt.charAt(i); - if(c == '\t') { - // TODO: finish support for tabs - buf.append(" "); - } else { - switch (cap){ - case ALL: - buf.append(Character.toUpperCase(c)); - break; - case SMALL: - buf.append(Character.toLowerCase(c)); - break; - default: - buf.append(c); - } - } - } - - return buf.toString(); - } - - public void setText(String text){ - if (_r instanceof CTTextField) { - ((CTTextField)_r).setT(text); - } else if (_r instanceof CTTextLineBreak) { - // ignored - return; - } else { - ((CTRegularTextRun)_r).setT(text); - } - } - - /** - * Return the text run xmlbeans object. - * Depending on the type of text run, this can be {@link CTTextField}, - * {@link CTTextLineBreak} or usually a {@link CTRegularTextRun} - * - * @return the xmlbeans object - */ - public XmlObject getXmlObject(){ - return _r; - } - - @Override - public void setFontColor(Color color) { - setFontColor(DrawPaint.createSolidPaint(color)); - } - - @Override - public void setFontColor(PaintStyle color) { - if (!(color instanceof SolidPaint)) { - throw new IllegalArgumentException("Currently only SolidPaint is supported!"); - } - SolidPaint sp = (SolidPaint)color; - Color c = DrawPaint.applyColorTransform(sp.getSolidColor()); - - CTTextCharacterProperties rPr = getRPr(true); - CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill(); - - XSLFColor col = new XSLFColor(fill, getParentParagraph().getParentShape().getSheet().getTheme(), fill.getSchemeClr()); - col.setColor(c); - } - - @Override - public PaintStyle getFontColor(){ - final boolean hasPlaceholder = getParentParagraph().getParentShape().getPlaceholder() != null; - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props == null) { - return false; - } - - XSLFShape shape = _p.getParentShape(); - CTShapeStyle style = shape.getSpStyle(); - CTSchemeColor phClr = null; - if (style != null && style.getFontRef() != null) { - phClr = style.getFontRef().getSchemeClr(); - } - - XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props); - XSLFSheet sheet = shape.getSheet(); - PackagePart pp = sheet.getPackagePart(); - XSLFTheme theme = sheet.getTheme(); - PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme, hasPlaceholder); - - if (ps != null) { - setValue(ps); - return true; - } - - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue(); - } - - @Override - public void setFontSize(Double fontSize){ - CTTextCharacterProperties rPr = getRPr(true); - if(fontSize == null) { - if (rPr.isSetSz()) rPr.unsetSz(); - } else { - if (fontSize < 1.0) { - throw new IllegalArgumentException("Minimum font size is 1pt but was " + fontSize); - } - - rPr.setSz((int)(100*fontSize)); - } - } - - @Override - public Double getFontSize(){ - double scale = 1; - CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit(); - if(afit != null) scale = (double)afit.getFontScale() / 100000; - - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetSz()) { - setValue(props.getSz()*0.01); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? null : fetcher.getValue()*scale; - } - - /** - * - * @return the spacing between characters within a text run, - * If this attribute is omitted than a value of 0 or no adjustment is assumed. - */ - public double getCharacterSpacing(){ - - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetSpc()) { - setValue(props.getSpc()*0.01); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - /** - * Set the spacing between characters within a text run. - *

- * The spacing is specified in points. Positive values will cause the text to expand, - * negative values to condense. - *

- * - * @param spc character spacing in points. - */ - public void setCharacterSpacing(double spc){ - CTTextCharacterProperties rPr = getRPr(true); - if(spc == 0.0) { - if(rPr.isSetSpc()) rPr.unsetSpc(); - } else { - rPr.setSpc((int)(100*spc)); - } - } - - @Override - public void setFontFamily(String typeface){ - setFontFamily(typeface, (byte)-1, (byte)-1, false); - } - - public void setFontFamily(String typeface, byte charset, byte pictAndFamily, boolean isSymbol){ - CTTextCharacterProperties rPr = getRPr(true); - - if(typeface == null){ - if(rPr.isSetLatin()) rPr.unsetLatin(); - if(rPr.isSetCs()) rPr.unsetCs(); - if(rPr.isSetSym()) rPr.unsetSym(); - } else { - if(isSymbol){ - CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym(); - font.setTypeface(typeface); - } else { - CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); - latin.setTypeface(typeface); - if(charset != -1) latin.setCharset(charset); - if(pictAndFamily != -1) latin.setPitchFamily(pictAndFamily); - } - } - } - - @Override - public String getFontFamily(){ - final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); - - CharacterPropertyFetcher visitor = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null) { - CTTextFont font = props.getLatin(); - if (font != null) { - String typeface = font.getTypeface(); - if("+mj-lt".equals(typeface)) { - typeface = theme.getMajorFont(); - } else if ("+mn-lt".equals(typeface)){ - typeface = theme.getMinorFont(); - } - setValue(typeface); - return true; - } - } - return false; - } - }; - fetchCharacterProperty(visitor); - - return visitor.getValue(); - } - - public byte getPitchAndFamily(){ - // final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); - - CharacterPropertyFetcher visitor = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null) { - CTTextFont font = props.getLatin(); - if (font != null) { - setValue(font.getPitchFamily()); - return true; - } - } - return false; - } - }; - fetchCharacterProperty(visitor); - - return visitor.getValue() == null ? 0 : visitor.getValue(); - } - - @Override - public void setStrikethrough(boolean strike) { - getRPr(true).setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE); - } - - @Override - public boolean isStrikethrough() { - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if(props != null && props.isSetStrike()) { - setValue(props.getStrike() != STTextStrikeType.NO_STRIKE); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - @Override - public boolean isSuperscript() { - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetBaseline()) { - setValue(props.getBaseline() > 0); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - /** - * Set the baseline for both the superscript and subscript fonts. - *

- * The size is specified using a percentage. - * Positive values indicate superscript, negative values indicate subscript. - *

- * - * @param baselineOffset - */ - public void setBaselineOffset(double baselineOffset){ - getRPr(true).setBaseline((int) baselineOffset * 1000); - } - - /** - * Set whether the text in this run is formatted as superscript. - * Default base line offset is 30% - * - * @see #setBaselineOffset(double) - */ - public void setSuperscript(boolean flag){ - setBaselineOffset(flag ? 30. : 0.); - } - - /** - * Set whether the text in this run is formatted as subscript. - * Default base line offset is -25%. - * - * @see #setBaselineOffset(double) - */ - public void setSubscript(boolean flag){ - setBaselineOffset(flag ? -25.0 : 0.); - } - - @Override - public boolean isSubscript() { - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetBaseline()) { - setValue(props.getBaseline() < 0); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - /** - * @return whether a run of text will be formatted as a superscript text. Default is false. - */ - public TextCap getTextCap() { - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetCap()) { - int idx = props.getCap().intValue() - 1; - setValue(TextCap.values()[idx]); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? TextCap.NONE : fetcher.getValue(); - } - - @Override - public void setBold(boolean bold){ - getRPr(true).setB(bold); - } - - @Override - public boolean isBold(){ - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetB()) { - setValue(props.getB()); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - @Override - public void setItalic(boolean italic){ - getRPr(true).setI(italic); - } - - @Override - public boolean isItalic(){ - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetI()) { - setValue(props.getI()); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - @Override - public void setUnderlined(boolean underline) { - getRPr(true).setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE); - } - - @Override - public boolean isUnderlined(){ - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetU()) { - setValue(props.getU() != STTextUnderlineType.NONE); - return true; - } - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - /** - * Return the character properties - * - * @param create if true, create an empty character properties object if it doesn't exist - * @return the character properties or null if create was false and the properties haven't exist - */ - protected CTTextCharacterProperties getRPr(boolean create) { - if (_r instanceof CTTextField) { - CTTextField tf = (CTTextField)_r; - if (tf.isSetRPr()) { - return tf.getRPr(); - } else if (create) { - return tf.addNewRPr(); - } - } else if (_r instanceof CTTextLineBreak) { - CTTextLineBreak tlb = (CTTextLineBreak)_r; - if (tlb.isSetRPr()) { - return tlb.getRPr(); - } else if (create) { - return tlb.addNewRPr(); - } - } else { - CTRegularTextRun tr = (CTRegularTextRun)_r; - if (tr.isSetRPr()) { - return tr.getRPr(); - } else if (create) { - return tr.addNewRPr(); - } - } - return null; - } - - @Override - public String toString(){ - return "[" + getClass() + "]" + getRawText(); - } - - @Override - public XSLFHyperlink createHyperlink(){ - XSLFHyperlink hl = getHyperlink(); - if (hl != null) { - return hl; - } - - CTTextCharacterProperties rPr = getRPr(true); - return new XSLFHyperlink(rPr.addNewHlinkClick(), _p.getParentShape().getSheet()); - } - - @Override - public XSLFHyperlink getHyperlink(){ - CTTextCharacterProperties rPr = getRPr(false); - if (rPr == null) { - return null; - } - CTHyperlink hl = rPr.getHlinkClick(); - if (hl == null) { - return null; - } - return new XSLFHyperlink(hl, _p.getParentShape().getSheet()); - } - - private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){ - XSLFTextShape shape = _p.getParentShape(); - XSLFSheet sheet = shape.getSheet(); - - CTTextCharacterProperties rPr = getRPr(false); - if (rPr != null && fetcher.fetch(rPr)) { - return true; - } - - if (shape.fetchShapeProperty(fetcher)) { - return true; - } - - CTPlaceholder ph = shape.getCTPlaceholder(); - if (ph == null){ - // if it is a plain text box then take defaults from presentation.xml - @SuppressWarnings("resource") - XMLSlideShow ppt = sheet.getSlideShow(); - // TODO: determine master shape - CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel()); - if (themeProps != null && fetcher.fetch(themeProps)) { - return true; - } - } - - // TODO: determine master shape - CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle(); - if(defaultProps != null && fetcher.fetch(defaultProps)) { - return true; - } - - return false; - } - - void copy(XSLFTextRun r){ - String srcFontFamily = r.getFontFamily(); - if(srcFontFamily != null && !srcFontFamily.equals(getFontFamily())){ - setFontFamily(srcFontFamily); - } - - PaintStyle srcFontColor = r.getFontColor(); - if(srcFontColor != null && !srcFontColor.equals(getFontColor())){ - setFontColor(srcFontColor); - } - - double srcFontSize = r.getFontSize(); - if(srcFontSize != getFontSize()){ - setFontSize(srcFontSize); - } - - boolean bold = r.isBold(); - if(bold != isBold()) setBold(bold); - - boolean italic = r.isItalic(); - if(italic != isItalic()) setItalic(italic); - - boolean underline = r.isUnderlined(); - if(underline != isUnderlined()) setUnderlined(underline); - - boolean strike = r.isStrikethrough(); - if(strike != isStrikethrough()) setStrikethrough(strike); - } - - - @Override - public FieldType getFieldType() { - if (_r instanceof CTTextField) { - CTTextField tf = (CTTextField)_r; - if ("slidenum".equals(tf.getType())) { - return FieldType.SLIDE_NUMBER; - } - } - return null; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import java.awt.Color; + +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.TextRun; +import org.apache.poi.util.Beta; +import org.apache.poi.xslf.model.CharacterPropertyFetcher; +import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; +import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; + +/** + * Represents a run of text within the containing text body. The run element is the + * lowest level text separation mechanism within a text body. + */ +@Beta +public class XSLFTextRun implements TextRun { + private final XmlObject _r; + private final XSLFTextParagraph _p; + + protected XSLFTextRun(XmlObject r, XSLFTextParagraph p){ + _r = r; + _p = p; + if (!(r instanceof CTRegularTextRun || r instanceof CTTextLineBreak || r instanceof CTTextField)) { + throw new OpenXML4JRuntimeException("unsupported text run of type "+r.getClass()); + } + } + + XSLFTextParagraph getParentParagraph(){ + return _p; + } + + public String getRawText(){ + if (_r instanceof CTTextField) { + return ((CTTextField)_r).getT(); + } else if (_r instanceof CTTextLineBreak) { + return "\n"; + } + return ((CTRegularTextRun)_r).getT(); + } + + String getRenderableText(){ + if (_r instanceof CTTextField) { + CTTextField tf = (CTTextField)_r; + XSLFSheet sheet = _p.getParentShape().getSheet(); + if ("slidenum".equals(tf.getType()) && sheet instanceof XSLFSlide) { + return Integer.toString(((XSLFSlide)sheet).getSlideNumber()); + } + return tf.getT(); + } else if (_r instanceof CTTextLineBreak) { + return "\n"; + } + + + String txt = ((CTRegularTextRun)_r).getT(); + TextCap cap = getTextCap(); + StringBuffer buf = new StringBuffer(); + for(int i = 0; i < txt.length(); i++) { + char c = txt.charAt(i); + if(c == '\t') { + // TODO: finish support for tabs + buf.append(" "); + } else { + switch (cap){ + case ALL: + buf.append(Character.toUpperCase(c)); + break; + case SMALL: + buf.append(Character.toLowerCase(c)); + break; + default: + buf.append(c); + } + } + } + + return buf.toString(); + } + + public void setText(String text){ + if (_r instanceof CTTextField) { + ((CTTextField)_r).setT(text); + } else if (_r instanceof CTTextLineBreak) { + // ignored + return; + } else { + ((CTRegularTextRun)_r).setT(text); + } + } + + /** + * Return the text run xmlbeans object. + * Depending on the type of text run, this can be {@link CTTextField}, + * {@link CTTextLineBreak} or usually a {@link CTRegularTextRun} + * + * @return the xmlbeans object + */ + public XmlObject getXmlObject(){ + return _r; + } + + @Override + public void setFontColor(Color color) { + setFontColor(DrawPaint.createSolidPaint(color)); + } + + @Override + public void setFontColor(PaintStyle color) { + if (!(color instanceof SolidPaint)) { + throw new IllegalArgumentException("Currently only SolidPaint is supported!"); + } + SolidPaint sp = (SolidPaint)color; + Color c = DrawPaint.applyColorTransform(sp.getSolidColor()); + + CTTextCharacterProperties rPr = getRPr(true); + CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill(); + + XSLFColor col = new XSLFColor(fill, getParentParagraph().getParentShape().getSheet().getTheme(), fill.getSchemeClr()); + col.setColor(c); + } + + @Override + public PaintStyle getFontColor(){ + final boolean hasPlaceholder = getParentParagraph().getParentShape().getPlaceholder() != null; + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props == null) { + return false; + } + + XSLFShape shape = _p.getParentShape(); + CTShapeStyle style = shape.getSpStyle(); + CTSchemeColor phClr = null; + if (style != null && style.getFontRef() != null) { + phClr = style.getFontRef().getSchemeClr(); + } + + XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props); + XSLFSheet sheet = shape.getSheet(); + PackagePart pp = sheet.getPackagePart(); + XSLFTheme theme = sheet.getTheme(); + PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme, hasPlaceholder); + + if (ps != null) { + setValue(ps); + return true; + } + + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue(); + } + + @Override + public void setFontSize(Double fontSize){ + CTTextCharacterProperties rPr = getRPr(true); + if(fontSize == null) { + if (rPr.isSetSz()) rPr.unsetSz(); + } else { + if (fontSize < 1.0) { + throw new IllegalArgumentException("Minimum font size is 1pt but was " + fontSize); + } + + rPr.setSz((int)(100*fontSize)); + } + } + + @Override + public Double getFontSize(){ + double scale = 1; + CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit(); + if(afit != null) scale = (double)afit.getFontScale() / 100000; + + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetSz()) { + setValue(props.getSz()*0.01); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? null : fetcher.getValue()*scale; + } + + /** + * + * @return the spacing between characters within a text run, + * If this attribute is omitted than a value of 0 or no adjustment is assumed. + */ + public double getCharacterSpacing(){ + + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetSpc()) { + setValue(props.getSpc()*0.01); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? 0 : fetcher.getValue(); + } + + /** + * Set the spacing between characters within a text run. + *

+ * The spacing is specified in points. Positive values will cause the text to expand, + * negative values to condense. + *

+ * + * @param spc character spacing in points. + */ + public void setCharacterSpacing(double spc){ + CTTextCharacterProperties rPr = getRPr(true); + if(spc == 0.0) { + if(rPr.isSetSpc()) rPr.unsetSpc(); + } else { + rPr.setSpc((int)(100*spc)); + } + } + + @Override + public void setFontFamily(String typeface){ + setFontFamily(typeface, (byte)-1, (byte)-1, false); + } + + public void setFontFamily(String typeface, byte charset, byte pictAndFamily, boolean isSymbol){ + CTTextCharacterProperties rPr = getRPr(true); + + if(typeface == null){ + if(rPr.isSetLatin()) rPr.unsetLatin(); + if(rPr.isSetCs()) rPr.unsetCs(); + if(rPr.isSetSym()) rPr.unsetSym(); + } else { + if(isSymbol){ + CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym(); + font.setTypeface(typeface); + } else { + CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); + latin.setTypeface(typeface); + if(charset != -1) latin.setCharset(charset); + if(pictAndFamily != -1) latin.setPitchFamily(pictAndFamily); + } + } + } + + @Override + public String getFontFamily(){ + final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); + + CharacterPropertyFetcher visitor = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null) { + CTTextFont font = props.getLatin(); + if (font != null) { + String typeface = font.getTypeface(); + if("+mj-lt".equals(typeface)) { + typeface = theme.getMajorFont(); + } else if ("+mn-lt".equals(typeface)){ + typeface = theme.getMinorFont(); + } + setValue(typeface); + return true; + } + } + return false; + } + }; + fetchCharacterProperty(visitor); + + return visitor.getValue(); + } + + public byte getPitchAndFamily(){ + // final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); + + CharacterPropertyFetcher visitor = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null) { + CTTextFont font = props.getLatin(); + if (font != null) { + setValue(font.getPitchFamily()); + return true; + } + } + return false; + } + }; + fetchCharacterProperty(visitor); + + return visitor.getValue() == null ? 0 : visitor.getValue(); + } + + @Override + public void setStrikethrough(boolean strike) { + getRPr(true).setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE); + } + + @Override + public boolean isStrikethrough() { + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if(props != null && props.isSetStrike()) { + setValue(props.getStrike() != STTextStrikeType.NO_STRIKE); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? false : fetcher.getValue(); + } + + @Override + public boolean isSuperscript() { + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetBaseline()) { + setValue(props.getBaseline() > 0); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? false : fetcher.getValue(); + } + + /** + * Set the baseline for both the superscript and subscript fonts. + *

+ * The size is specified using a percentage. + * Positive values indicate superscript, negative values indicate subscript. + *

+ * + * @param baselineOffset + */ + public void setBaselineOffset(double baselineOffset){ + getRPr(true).setBaseline((int) baselineOffset * 1000); + } + + /** + * Set whether the text in this run is formatted as superscript. + * Default base line offset is 30% + * + * @see #setBaselineOffset(double) + */ + public void setSuperscript(boolean flag){ + setBaselineOffset(flag ? 30. : 0.); + } + + /** + * Set whether the text in this run is formatted as subscript. + * Default base line offset is -25%. + * + * @see #setBaselineOffset(double) + */ + public void setSubscript(boolean flag){ + setBaselineOffset(flag ? -25.0 : 0.); + } + + @Override + public boolean isSubscript() { + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetBaseline()) { + setValue(props.getBaseline() < 0); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? false : fetcher.getValue(); + } + + /** + * @return whether a run of text will be formatted as a superscript text. Default is false. + */ + public TextCap getTextCap() { + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetCap()) { + int idx = props.getCap().intValue() - 1; + setValue(TextCap.values()[idx]); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? TextCap.NONE : fetcher.getValue(); + } + + @Override + public void setBold(boolean bold){ + getRPr(true).setB(bold); + } + + @Override + public boolean isBold(){ + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetB()) { + setValue(props.getB()); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? false : fetcher.getValue(); + } + + @Override + public void setItalic(boolean italic){ + getRPr(true).setI(italic); + } + + @Override + public boolean isItalic(){ + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetI()) { + setValue(props.getI()); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? false : fetcher.getValue(); + } + + @Override + public void setUnderlined(boolean underline) { + getRPr(true).setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE); + } + + @Override + public boolean isUnderlined(){ + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public boolean fetch(CTTextCharacterProperties props){ + if (props != null && props.isSetU()) { + setValue(props.getU() != STTextUnderlineType.NONE); + return true; + } + return false; + } + }; + fetchCharacterProperty(fetcher); + return fetcher.getValue() == null ? false : fetcher.getValue(); + } + + /** + * Return the character properties + * + * @param create if true, create an empty character properties object if it doesn't exist + * @return the character properties or null if create was false and the properties haven't exist + */ + protected CTTextCharacterProperties getRPr(boolean create) { + if (_r instanceof CTTextField) { + CTTextField tf = (CTTextField)_r; + if (tf.isSetRPr()) { + return tf.getRPr(); + } else if (create) { + return tf.addNewRPr(); + } + } else if (_r instanceof CTTextLineBreak) { + CTTextLineBreak tlb = (CTTextLineBreak)_r; + if (tlb.isSetRPr()) { + return tlb.getRPr(); + } else if (create) { + return tlb.addNewRPr(); + } + } else { + CTRegularTextRun tr = (CTRegularTextRun)_r; + if (tr.isSetRPr()) { + return tr.getRPr(); + } else if (create) { + return tr.addNewRPr(); + } + } + return null; + } + + @Override + public String toString(){ + return "[" + getClass() + "]" + getRawText(); + } + + @Override + public XSLFHyperlink createHyperlink(){ + XSLFHyperlink hl = getHyperlink(); + if (hl != null) { + return hl; + } + + CTTextCharacterProperties rPr = getRPr(true); + return new XSLFHyperlink(rPr.addNewHlinkClick(), _p.getParentShape().getSheet()); + } + + @Override + public XSLFHyperlink getHyperlink(){ + CTTextCharacterProperties rPr = getRPr(false); + if (rPr == null) { + return null; + } + CTHyperlink hl = rPr.getHlinkClick(); + if (hl == null) { + return null; + } + return new XSLFHyperlink(hl, _p.getParentShape().getSheet()); + } + + private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){ + XSLFTextShape shape = _p.getParentShape(); + XSLFSheet sheet = shape.getSheet(); + + CTTextCharacterProperties rPr = getRPr(false); + if (rPr != null && fetcher.fetch(rPr)) { + return true; + } + + if (shape.fetchShapeProperty(fetcher)) { + return true; + } + + CTPlaceholder ph = shape.getCTPlaceholder(); + if (ph == null){ + // if it is a plain text box then take defaults from presentation.xml + @SuppressWarnings("resource") + XMLSlideShow ppt = sheet.getSlideShow(); + // TODO: determine master shape + CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel()); + if (themeProps != null && fetcher.fetch(themeProps)) { + return true; + } + } + + // TODO: determine master shape + CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle(); + if(defaultProps != null && fetcher.fetch(defaultProps)) { + return true; + } + + return false; + } + + void copy(XSLFTextRun r){ + String srcFontFamily = r.getFontFamily(); + if(srcFontFamily != null && !srcFontFamily.equals(getFontFamily())){ + setFontFamily(srcFontFamily); + } + + PaintStyle srcFontColor = r.getFontColor(); + if(srcFontColor != null && !srcFontColor.equals(getFontColor())){ + setFontColor(srcFontColor); + } + + double srcFontSize = r.getFontSize(); + if(srcFontSize != getFontSize()){ + setFontSize(srcFontSize); + } + + boolean bold = r.isBold(); + if(bold != isBold()) setBold(bold); + + boolean italic = r.isItalic(); + if(italic != isItalic()) setItalic(italic); + + boolean underline = r.isUnderlined(); + if(underline != isUnderlined()) setUnderlined(underline); + + boolean strike = r.isStrikethrough(); + if(strike != isStrikethrough()) setStrikethrough(strike); + } + + + @Override + public FieldType getFieldType() { + if (_r instanceof CTTextField) { + CTTextField tf = (CTTextField)_r; + if ("slidenum".equals(tf.getType())) { + return FieldType.SLIDE_NUMBER; + } + } + return null; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java index 76d1b59006..31475410df 100644 --- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java +++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java @@ -1,214 +1,214 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.util; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.File; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.TreeSet; - -import javax.imageio.ImageIO; - -import org.apache.poi.sl.draw.DrawFactory; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.SlideShowFactory; - -/** - * An utility to convert slides of a .pptx slide show to a PNG image - * - * @author Yegor Kozlov - */ -public class PPTX2PNG { - - static void usage(String error){ - String msg = - "Usage: PPTX2PNG [options] \n" + - (error == null ? "" : ("Error: "+error+"\n")) + - "Options:\n" + - " -scale scale factor\n" + - " -slide 1-based index of a slide to render\n" + - " -format png,gif,jpg (,null for testing)" + - " -outdir output directory, defaults to origin of the ppt/pptx file" + - " -quiet do not write to console (for normal processing)"; - - System.out.println(msg); - // no System.exit here, as we also run in junit tests! - } - - public static void main(String[] args) throws Exception { - if (args.length == 0) { - usage(null); - return; - } - - String slidenumStr = "-1"; - float scale = 1; - File file = null; - String format = "png"; - File outdir = null; - boolean quiet = false; - - for (int i = 0; i < args.length; i++) { - if (args[i].startsWith("-")) { - if ("-scale".equals(args[i])) { - scale = Float.parseFloat(args[++i]); - } else if ("-slide".equals(args[i])) { - slidenumStr = args[++i]; - } else if ("-format".equals(args[i])) { - format = args[++i]; - } else if ("-outdir".equals(args[i])) { - outdir = new File(args[++i]); - } else if ("-quiet".equals(args[i])) { - quiet = true; - } - } else { - file = new File(args[i]); - } - } - - if (file == null || !file.exists()) { - usage("File not specified or it doesn't exist"); - return; - } - - if (format == null || !format.matches("^(png|gif|jpg|null)$")) { - usage("Invalid format given"); - return; - } - - if (outdir == null) { - outdir = file.getParentFile(); - } - - if (!"null".equals(format) && (outdir == null || !outdir.exists() || !outdir.isDirectory())) { - usage("Output directory doesn't exist"); - return; - } - - if (scale < 0) { - usage("Invalid scale given"); - return; - } - - if (!quiet) { - System.out.println("Processing " + file); - } - SlideShow ss = SlideShowFactory.create(file, null, true); - try { - List> slides = ss.getSlides(); - - Set slidenum = slideIndexes(slides.size(), slidenumStr); - - if (slidenum.isEmpty()) { - usage("slidenum must be either -1 (for all) or within range: [1.." + slides.size() + "] for " + file); - return; - } - - Dimension pgsize = ss.getPageSize(); - int width = (int) (pgsize.width * scale); - int height = (int) (pgsize.height * scale); - - for (Integer slideNo : slidenum) { - Slide slide = slides.get(slideNo); - String title = slide.getTitle(); - if (!quiet) { - System.out.println("Rendering slide " + slideNo + (title == null ? "" : ": " + title)); - } - - BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = img.createGraphics(); - DrawFactory.getInstance(graphics).fixFonts(graphics); - - // default rendering options - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - - graphics.scale(scale, scale); - - // draw stuff - slide.draw(graphics); - - // save the result - if (!"null".equals(format)) { - String outname = file.getName().replaceFirst(".pptx?", ""); - outname = String.format(Locale.ROOT, "%1$s-%2$04d.%3$s", outname, slideNo, format); - File outfile = new File(outdir, outname); - ImageIO.write(img, format, outfile); - } - - graphics.dispose(); - img.flush(); - } - } finally { - ss.close(); - } - - if (!quiet) { - System.out.println("Done"); - } - } - - private static Set slideIndexes(final int slideCount, String range) { - Set slideIdx = new TreeSet(); - if ("-1".equals(range)) { - for (int i=0; i\n" + + (error == null ? "" : ("Error: "+error+"\n")) + + "Options:\n" + + " -scale scale factor\n" + + " -slide 1-based index of a slide to render\n" + + " -format png,gif,jpg (,null for testing)" + + " -outdir output directory, defaults to origin of the ppt/pptx file" + + " -quiet do not write to console (for normal processing)"; + + System.out.println(msg); + // no System.exit here, as we also run in junit tests! + } + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + usage(null); + return; + } + + String slidenumStr = "-1"; + float scale = 1; + File file = null; + String format = "png"; + File outdir = null; + boolean quiet = false; + + for (int i = 0; i < args.length; i++) { + if (args[i].startsWith("-")) { + if ("-scale".equals(args[i])) { + scale = Float.parseFloat(args[++i]); + } else if ("-slide".equals(args[i])) { + slidenumStr = args[++i]; + } else if ("-format".equals(args[i])) { + format = args[++i]; + } else if ("-outdir".equals(args[i])) { + outdir = new File(args[++i]); + } else if ("-quiet".equals(args[i])) { + quiet = true; + } + } else { + file = new File(args[i]); + } + } + + if (file == null || !file.exists()) { + usage("File not specified or it doesn't exist"); + return; + } + + if (format == null || !format.matches("^(png|gif|jpg|null)$")) { + usage("Invalid format given"); + return; + } + + if (outdir == null) { + outdir = file.getParentFile(); + } + + if (!"null".equals(format) && (outdir == null || !outdir.exists() || !outdir.isDirectory())) { + usage("Output directory doesn't exist"); + return; + } + + if (scale < 0) { + usage("Invalid scale given"); + return; + } + + if (!quiet) { + System.out.println("Processing " + file); + } + SlideShow ss = SlideShowFactory.create(file, null, true); + try { + List> slides = ss.getSlides(); + + Set slidenum = slideIndexes(slides.size(), slidenumStr); + + if (slidenum.isEmpty()) { + usage("slidenum must be either -1 (for all) or within range: [1.." + slides.size() + "] for " + file); + return; + } + + Dimension pgsize = ss.getPageSize(); + int width = (int) (pgsize.width * scale); + int height = (int) (pgsize.height * scale); + + for (Integer slideNo : slidenum) { + Slide slide = slides.get(slideNo); + String title = slide.getTitle(); + if (!quiet) { + System.out.println("Rendering slide " + slideNo + (title == null ? "" : ": " + title)); + } + + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = img.createGraphics(); + DrawFactory.getInstance(graphics).fixFonts(graphics); + + // default rendering options + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + graphics.scale(scale, scale); + + // draw stuff + slide.draw(graphics); + + // save the result + if (!"null".equals(format)) { + String outname = file.getName().replaceFirst(".pptx?", ""); + outname = String.format(Locale.ROOT, "%1$s-%2$04d.%3$s", outname, slideNo, format); + File outfile = new File(outdir, outname); + ImageIO.write(img, format, outfile); + } + + graphics.dispose(); + img.flush(); + } + } finally { + ss.close(); + } + + if (!quiet) { + System.out.println("Done"); + } + } + + private static Set slideIndexes(final int slideCount, String range) { + Set slideIdx = new TreeSet(); + if ("-1".equals(range)) { + for (int i=0; i0 - private int _numberOfCellsOfLastFlushedRow; // meaningful only of _numberOfFlushedRows>0 - private int _numberLastFlushedRow = -1; // meaningful only of _numberOfFlushedRows>0 - - /** - * Table of strings shared across this workbook. - * If two cells contain the same string, then the cell value is the same index into SharedStringsTable - */ - private SharedStringsTable _sharedStringSource; - - public SheetDataWriter() throws IOException { - _fd = createTempFile(); - _out = createWriter(_fd); - } - - public SheetDataWriter(SharedStringsTable sharedStringsTable) throws IOException { - this(); - this._sharedStringSource = sharedStringsTable; - } - /** - * Create a temp file to write sheet data. - * By default, temp files are created in the default temporary-file directory - * with a prefix "poi-sxssf-sheet" and suffix ".xml". Subclasses can override - * it and specify a different temp directory or filename or suffix, e.g. .gz - * - * @return temp file to write sheet data - */ - public File createTempFile() throws IOException { - return TempFile.createTempFile("poi-sxssf-sheet", ".xml"); - } - - /** - * Create a writer for the sheet data. - * - * @param fd the file to write to - */ - public Writer createWriter(File fd) throws IOException { - FileOutputStream fos = new FileOutputStream(fd); - OutputStream decorated; - try { - decorated = decorateOutputStream(fos); - } catch (final IOException e) { - fos.close(); - throw e; - } - return new BufferedWriter( - new OutputStreamWriter(decorated, "UTF-8")); - } - - /** - * Override this to translate (such as encrypt or compress) the file output stream - * as it is being written to disk. - * The default behavior is to to pass the stream through unmodified. - * - * @param fos the stream to decorate - * @return a decorated stream - * @throws IOException - * @see #decorateInputStream(FileInputStream) - */ - protected OutputStream decorateOutputStream(FileOutputStream fos) throws IOException { - return fos; - } - - /** - * flush and close the temp data writer. - * This method must be invoked before calling {@link #getWorksheetXMLInputStream()} - */ - public void close() throws IOException{ - _out.flush(); - _out.close(); - } - - protected File getTempFile(){ - return _fd; - } - - /** - * @return a stream to read temp file with the sheet data - */ - public InputStream getWorksheetXMLInputStream() throws IOException { - File fd = getTempFile(); - FileInputStream fis = new FileInputStream(fd); - try { - return decorateInputStream(fis); - } catch (IOException e) { - fis.close(); - throw e; - } - } - - /** - * Override this to translate (such as decrypt or expand) the file input stream - * as it is being read from disk. - * The default behavior is to to pass the stream through unmodified. - * - * @param fis the stream to decorate - * @return a decorated stream - * @throws IOException - * @see #decorateOutputStream(FileOutputStream) - */ - protected InputStream decorateInputStream(FileInputStream fis) throws IOException { - return fis; - } - - public int getNumberOfFlushedRows() { - return _numberOfFlushedRows; - } - - public int getNumberOfCellsOfLastFlushedRow() { - return _numberOfCellsOfLastFlushedRow; - } - - public int getLowestIndexOfFlushedRows() { - return _lowestIndexOfFlushedRows; - } - - public int getLastFlushedRow() { - return _numberLastFlushedRow; - } - - @Override - protected void finalize() throws Throwable { - if (!_fd.delete()) { - logger.log(POILogger.ERROR, "Can't delete temporary encryption file: "+_fd); - } - - super.finalize(); - } - - /** - * Write a row to the file - * - * @param rownum 0-based row number - * @param row a row - */ - public void writeRow(int rownum, SXSSFRow row) throws IOException { - if (_numberOfFlushedRows == 0) - _lowestIndexOfFlushedRows = rownum; - _numberLastFlushedRow = Math.max(rownum, _numberLastFlushedRow); - _numberOfCellsOfLastFlushedRow = row.getLastCellNum(); - _numberOfFlushedRows++; - beginRow(rownum, row); - Iterator cells = row.allCellsIterator(); - int columnIndex = 0; - while (cells.hasNext()) { - writeCell(columnIndex++, cells.next()); - } - endRow(); - } - - void beginRow(int rownum, SXSSFRow row) throws IOException { - _out.write("\n"); - } - - public void writeCell(int columnIndex, Cell cell) throws IOException { - if (cell == null) { - return; - } - String ref = new CellReference(_rownum, columnIndex).formatAsString(); - _out.write(""); - break; - } - case FORMULA: { - _out.write(">"); - _out.write(""); - outputQuotedString(cell.getCellFormula()); - _out.write(""); - switch (cell.getCachedFormulaResultTypeEnum()) { - case NUMERIC: - double nval = cell.getNumericCellValue(); - if (!Double.isNaN(nval)) { - _out.write("" + nval + ""); - } - break; - default: - break; - } - break; - } - case STRING: { - if (_sharedStringSource != null) { - XSSFRichTextString rt = new XSSFRichTextString(cell.getStringCellValue()); - int sRef = _sharedStringSource.addEntry(rt.getCTRst()); - - _out.write(" t=\"" + STCellType.S.toString() + "\">"); - _out.write(""); - _out.write(String.valueOf(sRef)); - _out.write(""); - } else { - _out.write(" t=\"inlineStr\">"); - _out.write(""); - outputQuotedString(cell.getStringCellValue()); - _out.write(""); - } - break; - } - case NUMERIC: { - _out.write(" t=\"n\">"); - _out.write("" + cell.getNumericCellValue() + ""); - break; - } - case BOOLEAN: { - _out.write(" t=\"b\">"); - _out.write("" + (cell.getBooleanCellValue() ? "1" : "0") + ""); - break; - } - case ERROR: { - FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); - - _out.write(" t=\"e\">"); - _out.write("" + error.getString() + ""); - break; - } - default: { - throw new IllegalStateException("Invalid cell type: " + cellType); - } - } - _out.write(""); - } - - - /** - * @return whether the string has leading / trailing spaces that - * need to be preserved with the xml:space=\"preserve\" attribute - */ - boolean hasLeadingTrailingSpaces(String str) { - if (str != null && str.length() > 0) { - char firstChar = str.charAt(0); - char lastChar = str.charAt(str.length() - 1); - return Character.isWhitespace(firstChar) || Character.isWhitespace(lastChar) ; - } - return false; - } - - //Taken from jdk1.3/src/javax/swing/text/html/HTMLWriter.java - protected void outputQuotedString(String s) throws IOException { - if (s == null || s.length() == 0) { - return; - } - - char[] chars = s.toCharArray(); - int last = 0; - int length = s.length(); - for (int counter = 0; counter < length; counter++) { - char c = chars[counter]; - switch (c) { - case '<': - if (counter > last) { - _out.write(chars, last, counter - last); - } - last = counter + 1; - _out.write("<"); - break; - case '>': - if (counter > last) { - _out.write(chars, last, counter - last); - } - last = counter + 1; - _out.write(">"); - break; - case '&': - if (counter > last) { - _out.write(chars, last, counter - last); - } - last = counter + 1; - _out.write("&"); - break; - case '"': - if (counter > last) { - _out.write(chars, last, counter - last); - } - last = counter + 1; - _out.write("""); - break; - // Special characters - case '\n': - case '\r': - if (counter > last) { - _out.write(chars, last, counter - last); - } - _out.write(" "); - last = counter + 1; - break; - case '\t': - if (counter > last) { - _out.write(chars, last, counter - last); - } - _out.write(" "); - last = counter + 1; - break; - case 0xa0: - if (counter > last) { - _out.write(chars, last, counter - last); - } - _out.write(" "); - last = counter + 1; - break; - default: - // YK: XmlBeans silently replaces all ISO control characters ( < 32) with question marks. - // the same rule applies to unicode surrogates and "not a character" symbols. - if( c < ' ' || Character.isLowSurrogate(c) || Character.isHighSurrogate(c) || - ('\uFFFE' <= c && c <= '\uFFFF')) { - if (counter > last) { - _out.write(chars, last, counter - last); - } - _out.write('?'); - last = counter + 1; - } - else if (c > 127) { - if (counter > last) { - _out.write(chars, last, counter - last); - } - last = counter + 1; - // If the character is outside of ascii, write the - // numeric value. - _out.write("&#"); - _out.write(String.valueOf((int) c)); - _out.write(";"); - } - break; - } - } - if (last < length) { - _out.write(chars, last, length - last); - } - } - - /** - * Deletes the temporary file that backed this sheet on disk. - * @return true if the file was deleted, false if it wasn't. - */ - boolean dispose() throws IOException { - final boolean ret; - try { - _out.close(); - } finally { - ret = _fd.delete(); - } - return ret; - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xssf.streaming; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Iterator; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.FormulaError; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.TempFile; +import org.apache.poi.xssf.model.SharedStringsTable; +import org.apache.poi.xssf.usermodel.XSSFRichTextString; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; + +/** + * Initially copied from BigGridDemo "SpreadsheetWriter". + * Unlike the original code which wrote the entire document, + * this class only writes the "sheetData" document fragment + * so that it was renamed to "SheetDataWriter" + */ +public class SheetDataWriter { + private static final POILogger logger = POILogFactory.getLogger(SheetDataWriter.class); + + private final File _fd; + private final Writer _out; + private int _rownum; + private int _numberOfFlushedRows; + private int _lowestIndexOfFlushedRows; // meaningful only of _numberOfFlushedRows>0 + private int _numberOfCellsOfLastFlushedRow; // meaningful only of _numberOfFlushedRows>0 + private int _numberLastFlushedRow = -1; // meaningful only of _numberOfFlushedRows>0 + + /** + * Table of strings shared across this workbook. + * If two cells contain the same string, then the cell value is the same index into SharedStringsTable + */ + private SharedStringsTable _sharedStringSource; + + public SheetDataWriter() throws IOException { + _fd = createTempFile(); + _out = createWriter(_fd); + } + + public SheetDataWriter(SharedStringsTable sharedStringsTable) throws IOException { + this(); + this._sharedStringSource = sharedStringsTable; + } + /** + * Create a temp file to write sheet data. + * By default, temp files are created in the default temporary-file directory + * with a prefix "poi-sxssf-sheet" and suffix ".xml". Subclasses can override + * it and specify a different temp directory or filename or suffix, e.g. .gz + * + * @return temp file to write sheet data + */ + public File createTempFile() throws IOException { + return TempFile.createTempFile("poi-sxssf-sheet", ".xml"); + } + + /** + * Create a writer for the sheet data. + * + * @param fd the file to write to + */ + public Writer createWriter(File fd) throws IOException { + FileOutputStream fos = new FileOutputStream(fd); + OutputStream decorated; + try { + decorated = decorateOutputStream(fos); + } catch (final IOException e) { + fos.close(); + throw e; + } + return new BufferedWriter( + new OutputStreamWriter(decorated, "UTF-8")); + } + + /** + * Override this to translate (such as encrypt or compress) the file output stream + * as it is being written to disk. + * The default behavior is to to pass the stream through unmodified. + * + * @param fos the stream to decorate + * @return a decorated stream + * @throws IOException + * @see #decorateInputStream(FileInputStream) + */ + protected OutputStream decorateOutputStream(FileOutputStream fos) throws IOException { + return fos; + } + + /** + * flush and close the temp data writer. + * This method must be invoked before calling {@link #getWorksheetXMLInputStream()} + */ + public void close() throws IOException{ + _out.flush(); + _out.close(); + } + + protected File getTempFile(){ + return _fd; + } + + /** + * @return a stream to read temp file with the sheet data + */ + public InputStream getWorksheetXMLInputStream() throws IOException { + File fd = getTempFile(); + FileInputStream fis = new FileInputStream(fd); + try { + return decorateInputStream(fis); + } catch (IOException e) { + fis.close(); + throw e; + } + } + + /** + * Override this to translate (such as decrypt or expand) the file input stream + * as it is being read from disk. + * The default behavior is to to pass the stream through unmodified. + * + * @param fis the stream to decorate + * @return a decorated stream + * @throws IOException + * @see #decorateOutputStream(FileOutputStream) + */ + protected InputStream decorateInputStream(FileInputStream fis) throws IOException { + return fis; + } + + public int getNumberOfFlushedRows() { + return _numberOfFlushedRows; + } + + public int getNumberOfCellsOfLastFlushedRow() { + return _numberOfCellsOfLastFlushedRow; + } + + public int getLowestIndexOfFlushedRows() { + return _lowestIndexOfFlushedRows; + } + + public int getLastFlushedRow() { + return _numberLastFlushedRow; + } + + @Override + protected void finalize() throws Throwable { + if (!_fd.delete()) { + logger.log(POILogger.ERROR, "Can't delete temporary encryption file: "+_fd); + } + + super.finalize(); + } + + /** + * Write a row to the file + * + * @param rownum 0-based row number + * @param row a row + */ + public void writeRow(int rownum, SXSSFRow row) throws IOException { + if (_numberOfFlushedRows == 0) + _lowestIndexOfFlushedRows = rownum; + _numberLastFlushedRow = Math.max(rownum, _numberLastFlushedRow); + _numberOfCellsOfLastFlushedRow = row.getLastCellNum(); + _numberOfFlushedRows++; + beginRow(rownum, row); + Iterator cells = row.allCellsIterator(); + int columnIndex = 0; + while (cells.hasNext()) { + writeCell(columnIndex++, cells.next()); + } + endRow(); + } + + void beginRow(int rownum, SXSSFRow row) throws IOException { + _out.write("\n"); + } + + public void writeCell(int columnIndex, Cell cell) throws IOException { + if (cell == null) { + return; + } + String ref = new CellReference(_rownum, columnIndex).formatAsString(); + _out.write(""); + break; + } + case FORMULA: { + _out.write(">"); + _out.write(""); + outputQuotedString(cell.getCellFormula()); + _out.write(""); + switch (cell.getCachedFormulaResultTypeEnum()) { + case NUMERIC: + double nval = cell.getNumericCellValue(); + if (!Double.isNaN(nval)) { + _out.write("" + nval + ""); + } + break; + default: + break; + } + break; + } + case STRING: { + if (_sharedStringSource != null) { + XSSFRichTextString rt = new XSSFRichTextString(cell.getStringCellValue()); + int sRef = _sharedStringSource.addEntry(rt.getCTRst()); + + _out.write(" t=\"" + STCellType.S.toString() + "\">"); + _out.write(""); + _out.write(String.valueOf(sRef)); + _out.write(""); + } else { + _out.write(" t=\"inlineStr\">"); + _out.write(""); + outputQuotedString(cell.getStringCellValue()); + _out.write(""); + } + break; + } + case NUMERIC: { + _out.write(" t=\"n\">"); + _out.write("" + cell.getNumericCellValue() + ""); + break; + } + case BOOLEAN: { + _out.write(" t=\"b\">"); + _out.write("" + (cell.getBooleanCellValue() ? "1" : "0") + ""); + break; + } + case ERROR: { + FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); + + _out.write(" t=\"e\">"); + _out.write("" + error.getString() + ""); + break; + } + default: { + throw new IllegalStateException("Invalid cell type: " + cellType); + } + } + _out.write(""); + } + + + /** + * @return whether the string has leading / trailing spaces that + * need to be preserved with the xml:space=\"preserve\" attribute + */ + boolean hasLeadingTrailingSpaces(String str) { + if (str != null && str.length() > 0) { + char firstChar = str.charAt(0); + char lastChar = str.charAt(str.length() - 1); + return Character.isWhitespace(firstChar) || Character.isWhitespace(lastChar) ; + } + return false; + } + + //Taken from jdk1.3/src/javax/swing/text/html/HTMLWriter.java + protected void outputQuotedString(String s) throws IOException { + if (s == null || s.length() == 0) { + return; + } + + char[] chars = s.toCharArray(); + int last = 0; + int length = s.length(); + for (int counter = 0; counter < length; counter++) { + char c = chars[counter]; + switch (c) { + case '<': + if (counter > last) { + _out.write(chars, last, counter - last); + } + last = counter + 1; + _out.write("<"); + break; + case '>': + if (counter > last) { + _out.write(chars, last, counter - last); + } + last = counter + 1; + _out.write(">"); + break; + case '&': + if (counter > last) { + _out.write(chars, last, counter - last); + } + last = counter + 1; + _out.write("&"); + break; + case '"': + if (counter > last) { + _out.write(chars, last, counter - last); + } + last = counter + 1; + _out.write("""); + break; + // Special characters + case '\n': + case '\r': + if (counter > last) { + _out.write(chars, last, counter - last); + } + _out.write(" "); + last = counter + 1; + break; + case '\t': + if (counter > last) { + _out.write(chars, last, counter - last); + } + _out.write(" "); + last = counter + 1; + break; + case 0xa0: + if (counter > last) { + _out.write(chars, last, counter - last); + } + _out.write(" "); + last = counter + 1; + break; + default: + // YK: XmlBeans silently replaces all ISO control characters ( < 32) with question marks. + // the same rule applies to unicode surrogates and "not a character" symbols. + if( c < ' ' || Character.isLowSurrogate(c) || Character.isHighSurrogate(c) || + ('\uFFFE' <= c && c <= '\uFFFF')) { + if (counter > last) { + _out.write(chars, last, counter - last); + } + _out.write('?'); + last = counter + 1; + } + else if (c > 127) { + if (counter > last) { + _out.write(chars, last, counter - last); + } + last = counter + 1; + // If the character is outside of ascii, write the + // numeric value. + _out.write("&#"); + _out.write(String.valueOf((int) c)); + _out.write(";"); + } + break; + } + } + if (last < length) { + _out.write(chars, last, length - last); + } + } + + /** + * Deletes the temporary file that backed this sheet on disk. + * @return true if the file was deleted, false if it wasn't. + */ + boolean dispose() throws IOException { + final boolean ret; + try { + _out.close(); + } finally { + ret = _fd.delete(); + } + return ret; + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java index edea8cda9d..f700aecf6a 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java @@ -1,367 +1,367 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.ss.usermodel.BorderFormatting; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.Color; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; - -/** - * XSSF high level representation for Border Formatting component - * of Conditional Formatting settings - */ -public class XSSFBorderFormatting implements BorderFormatting { - CTBorder _border; - - /*package*/ XSSFBorderFormatting(CTBorder border) { - _border = border; - } - - /** - * @deprecated POI 3.15. Use {@link #getBorderBottomEnum()}. - * This method will return an BorderStyle enum in the future. - */ - @Override - public short getBorderBottom() { - return getBorderBottomEnum().getCode(); - } - /** - * @since POI 3.15 - */ - @Override - public BorderStyle getBorderBottomEnum() { - STBorderStyle.Enum ptrn = _border.isSetBottom() ? _border.getBottom().getStyle() : null; - return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - /** - * @deprecated POI 3.15. Use {@link #getBorderDiagonalEnum()}. - * This method will return an BorderStyle enum in the future. - */ - @Override - public short getBorderDiagonal() { - return getBorderDiagonalEnum().getCode(); - } - /** - * @since POI 3.15 - */ - @Override - public BorderStyle getBorderDiagonalEnum() { - STBorderStyle.Enum ptrn = _border.isSetDiagonal() ? _border.getDiagonal().getStyle() : null; - return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - /** - * @deprecated POI 3.15. Use {@link #getBorderLeftEnum()}. - * This method will return an BorderStyle enum in the future. - */ - @Override - public short getBorderLeft() { - return getBorderLeftEnum().getCode(); - } - /** - * @since POI 3.15 - */ - @Override - public BorderStyle getBorderLeftEnum() { - STBorderStyle.Enum ptrn = _border.isSetLeft() ? _border.getLeft().getStyle() : null; - return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - /** - * @deprecated POI 3.15. Use {@link #getBorderRightEnum()}. - * This method will return an BorderStyle enum in the future. - */ - @Override - public short getBorderRight() { - return getBorderRightEnum().getCode(); - } - /** - * @since POI 3.15 - */ - @Override - public BorderStyle getBorderRightEnum() { - STBorderStyle.Enum ptrn = _border.isSetRight() ? _border.getRight().getStyle() : null; - return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - /** - * @deprecated POI 3.15. Use {@link #getBorderTopEnum()}. - * This method will return an BorderStyle enum in the future. - */ - @Override - public short getBorderTop() { - return getBorderTopEnum().getCode(); - } - /** - * @since POI 3.15 - */ - @Override - public BorderStyle getBorderTopEnum() { - STBorderStyle.Enum ptrn = _border.isSetTop() ? _border.getTop().getStyle() : null; - return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - @Override - public XSSFColor getBottomBorderColorColor() { - if(!_border.isSetBottom()) return null; - - CTBorderPr pr = _border.getBottom(); - return new XSSFColor(pr.getColor()); - } - @Override - public short getBottomBorderColor() { - XSSFColor color = getBottomBorderColorColor(); - if (color == null) return 0; - return color.getIndexed(); - } - - @Override - public XSSFColor getDiagonalBorderColorColor() { - if(!_border.isSetDiagonal()) return null; - - CTBorderPr pr = _border.getDiagonal(); - return new XSSFColor(pr.getColor()); - } - @Override - public short getDiagonalBorderColor() { - XSSFColor color = getDiagonalBorderColorColor(); - if (color == null) return 0; - return color.getIndexed(); - } - - @Override - public XSSFColor getLeftBorderColorColor() { - if(!_border.isSetLeft()) return null; - - CTBorderPr pr = _border.getLeft(); - return new XSSFColor(pr.getColor()); - } - @Override - public short getLeftBorderColor() { - XSSFColor color = getLeftBorderColorColor(); - if (color == null) return 0; - return color.getIndexed(); - } - - @Override - public XSSFColor getRightBorderColorColor() { - if(!_border.isSetRight()) return null; - - CTBorderPr pr = _border.getRight(); - return new XSSFColor(pr.getColor()); - } - @Override - public short getRightBorderColor() { - XSSFColor color = getRightBorderColorColor(); - if (color == null) return 0; - return color.getIndexed(); - } - - @Override - public XSSFColor getTopBorderColorColor() { - if(!_border.isSetTop()) return null; - - CTBorderPr pr = _border.getTop(); - return new XSSFColor(pr.getColor()); - } - @Override - public short getTopBorderColor() { - XSSFColor color = getRightBorderColorColor(); - if (color == null) return 0; - return color.getIndexed(); - } - - /** - * @deprecated 3.15 beta 2. Use {@link #setBorderBottom(BorderStyle)} - */ - @Override - public void setBorderBottom(short border) { - setBorderBottom(BorderStyle.valueOf(border)); - } - @Override - public void setBorderBottom(BorderStyle border) { - CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); - if(border == BorderStyle.NONE) _border.unsetBottom(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - /** - * @deprecated 3.15 beta 2. Use {@link #setBorderDiagonal(BorderStyle)} - */ - @Override - public void setBorderDiagonal(short border) { - setBorderDiagonal(BorderStyle.valueOf(border)); - } - @Override - public void setBorderDiagonal(BorderStyle border) { - CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); - if(border == BorderStyle.NONE) _border.unsetDiagonal(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - /** - * @deprecated 3.15 beta 2. Use {@link #setBorderLeft(BorderStyle)} - */ - @Override - public void setBorderLeft(short border) { - setBorderLeft(BorderStyle.valueOf(border)); - } - @Override - public void setBorderLeft(BorderStyle border) { - CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); - if(border == BorderStyle.NONE) _border.unsetLeft(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - /** - * @deprecated 3.15 beta 2. Use {@link #setBorderRight(BorderStyle)} - */ - @Override - public void setBorderRight(short border) { - setBorderRight(BorderStyle.valueOf(border)); - } - @Override - public void setBorderRight(BorderStyle border) { - CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); - if(border == BorderStyle.NONE) _border.unsetRight(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - /** - * @deprecated 3.15 beta 2. Use {@link #setBorderTop(BorderStyle)} - */ - @Override - public void setBorderTop(short border) { - setBorderTop(BorderStyle.valueOf(border)); - } - @Override - public void setBorderTop(BorderStyle border) { - CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); - if(border == BorderStyle.NONE) _border.unsetTop(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - @Override - public void setBottomBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setBottomBorderColor((CTColor)null); - else setBottomBorderColor(xcolor.getCTColor()); - } - @Override - public void setBottomBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setBottomBorderColor(ctColor); - } - public void setBottomBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setDiagonalBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setDiagonalBorderColor((CTColor)null); - else setDiagonalBorderColor(xcolor.getCTColor()); - } - @Override - public void setDiagonalBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setDiagonalBorderColor(ctColor); - } - public void setDiagonalBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setLeftBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setLeftBorderColor((CTColor)null); - else setLeftBorderColor(xcolor.getCTColor()); - } - @Override - public void setLeftBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setLeftBorderColor(ctColor); - } - public void setLeftBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setRightBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setRightBorderColor((CTColor)null); - else setRightBorderColor(xcolor.getCTColor()); - } - @Override - public void setRightBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setRightBorderColor(ctColor); - } - public void setRightBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setTopBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setTopBorderColor((CTColor)null); - else setTopBorderColor(xcolor.getCTColor()); - } - @Override - public void setTopBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setTopBorderColor(ctColor); - } - public void setTopBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.usermodel.BorderFormatting; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Color; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; + +/** + * XSSF high level representation for Border Formatting component + * of Conditional Formatting settings + */ +public class XSSFBorderFormatting implements BorderFormatting { + CTBorder _border; + + /*package*/ XSSFBorderFormatting(CTBorder border) { + _border = border; + } + + /** + * @deprecated POI 3.15. Use {@link #getBorderBottomEnum()}. + * This method will return an BorderStyle enum in the future. + */ + @Override + public short getBorderBottom() { + return getBorderBottomEnum().getCode(); + } + /** + * @since POI 3.15 + */ + @Override + public BorderStyle getBorderBottomEnum() { + STBorderStyle.Enum ptrn = _border.isSetBottom() ? _border.getBottom().getStyle() : null; + return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); + } + + /** + * @deprecated POI 3.15. Use {@link #getBorderDiagonalEnum()}. + * This method will return an BorderStyle enum in the future. + */ + @Override + public short getBorderDiagonal() { + return getBorderDiagonalEnum().getCode(); + } + /** + * @since POI 3.15 + */ + @Override + public BorderStyle getBorderDiagonalEnum() { + STBorderStyle.Enum ptrn = _border.isSetDiagonal() ? _border.getDiagonal().getStyle() : null; + return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); + } + + /** + * @deprecated POI 3.15. Use {@link #getBorderLeftEnum()}. + * This method will return an BorderStyle enum in the future. + */ + @Override + public short getBorderLeft() { + return getBorderLeftEnum().getCode(); + } + /** + * @since POI 3.15 + */ + @Override + public BorderStyle getBorderLeftEnum() { + STBorderStyle.Enum ptrn = _border.isSetLeft() ? _border.getLeft().getStyle() : null; + return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); + } + + /** + * @deprecated POI 3.15. Use {@link #getBorderRightEnum()}. + * This method will return an BorderStyle enum in the future. + */ + @Override + public short getBorderRight() { + return getBorderRightEnum().getCode(); + } + /** + * @since POI 3.15 + */ + @Override + public BorderStyle getBorderRightEnum() { + STBorderStyle.Enum ptrn = _border.isSetRight() ? _border.getRight().getStyle() : null; + return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); + } + + /** + * @deprecated POI 3.15. Use {@link #getBorderTopEnum()}. + * This method will return an BorderStyle enum in the future. + */ + @Override + public short getBorderTop() { + return getBorderTopEnum().getCode(); + } + /** + * @since POI 3.15 + */ + @Override + public BorderStyle getBorderTopEnum() { + STBorderStyle.Enum ptrn = _border.isSetTop() ? _border.getTop().getStyle() : null; + return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); + } + + @Override + public XSSFColor getBottomBorderColorColor() { + if(!_border.isSetBottom()) return null; + + CTBorderPr pr = _border.getBottom(); + return new XSSFColor(pr.getColor()); + } + @Override + public short getBottomBorderColor() { + XSSFColor color = getBottomBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); + } + + @Override + public XSSFColor getDiagonalBorderColorColor() { + if(!_border.isSetDiagonal()) return null; + + CTBorderPr pr = _border.getDiagonal(); + return new XSSFColor(pr.getColor()); + } + @Override + public short getDiagonalBorderColor() { + XSSFColor color = getDiagonalBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); + } + + @Override + public XSSFColor getLeftBorderColorColor() { + if(!_border.isSetLeft()) return null; + + CTBorderPr pr = _border.getLeft(); + return new XSSFColor(pr.getColor()); + } + @Override + public short getLeftBorderColor() { + XSSFColor color = getLeftBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); + } + + @Override + public XSSFColor getRightBorderColorColor() { + if(!_border.isSetRight()) return null; + + CTBorderPr pr = _border.getRight(); + return new XSSFColor(pr.getColor()); + } + @Override + public short getRightBorderColor() { + XSSFColor color = getRightBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); + } + + @Override + public XSSFColor getTopBorderColorColor() { + if(!_border.isSetTop()) return null; + + CTBorderPr pr = _border.getTop(); + return new XSSFColor(pr.getColor()); + } + @Override + public short getTopBorderColor() { + XSSFColor color = getRightBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); + } + + /** + * @deprecated 3.15 beta 2. Use {@link #setBorderBottom(BorderStyle)} + */ + @Override + public void setBorderBottom(short border) { + setBorderBottom(BorderStyle.valueOf(border)); + } + @Override + public void setBorderBottom(BorderStyle border) { + CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); + if(border == BorderStyle.NONE) _border.unsetBottom(); + else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); + } + + /** + * @deprecated 3.15 beta 2. Use {@link #setBorderDiagonal(BorderStyle)} + */ + @Override + public void setBorderDiagonal(short border) { + setBorderDiagonal(BorderStyle.valueOf(border)); + } + @Override + public void setBorderDiagonal(BorderStyle border) { + CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); + if(border == BorderStyle.NONE) _border.unsetDiagonal(); + else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); + } + + /** + * @deprecated 3.15 beta 2. Use {@link #setBorderLeft(BorderStyle)} + */ + @Override + public void setBorderLeft(short border) { + setBorderLeft(BorderStyle.valueOf(border)); + } + @Override + public void setBorderLeft(BorderStyle border) { + CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); + if(border == BorderStyle.NONE) _border.unsetLeft(); + else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); + } + + /** + * @deprecated 3.15 beta 2. Use {@link #setBorderRight(BorderStyle)} + */ + @Override + public void setBorderRight(short border) { + setBorderRight(BorderStyle.valueOf(border)); + } + @Override + public void setBorderRight(BorderStyle border) { + CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); + if(border == BorderStyle.NONE) _border.unsetRight(); + else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); + } + + /** + * @deprecated 3.15 beta 2. Use {@link #setBorderTop(BorderStyle)} + */ + @Override + public void setBorderTop(short border) { + setBorderTop(BorderStyle.valueOf(border)); + } + @Override + public void setBorderTop(BorderStyle border) { + CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); + if(border == BorderStyle.NONE) _border.unsetTop(); + else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); + } + + @Override + public void setBottomBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setBottomBorderColor((CTColor)null); + else setBottomBorderColor(xcolor.getCTColor()); + } + @Override + public void setBottomBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setBottomBorderColor(ctColor); + } + public void setBottomBorderColor(CTColor color) { + CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } + } + + @Override + public void setDiagonalBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setDiagonalBorderColor((CTColor)null); + else setDiagonalBorderColor(xcolor.getCTColor()); + } + @Override + public void setDiagonalBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setDiagonalBorderColor(ctColor); + } + public void setDiagonalBorderColor(CTColor color) { + CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } + } + + @Override + public void setLeftBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setLeftBorderColor((CTColor)null); + else setLeftBorderColor(xcolor.getCTColor()); + } + @Override + public void setLeftBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setLeftBorderColor(ctColor); + } + public void setLeftBorderColor(CTColor color) { + CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } + } + + @Override + public void setRightBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setRightBorderColor((CTColor)null); + else setRightBorderColor(xcolor.getCTColor()); + } + @Override + public void setRightBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setRightBorderColor(ctColor); + } + public void setRightBorderColor(CTColor color) { + CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } + } + + @Override + public void setTopBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setTopBorderColor((CTColor)null); + else setTopBorderColor(xcolor.getCTColor()); + } + @Override + public void setTopBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setTopBorderColor(ctColor); + } + public void setTopBorderColor(CTColor color) { + CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColorScaleFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColorScaleFormatting.java index eb15001b0a..910e8b297e 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColorScaleFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColorScaleFormatting.java @@ -1,92 +1,92 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.ColorScaleFormatting; -import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColorScale; - -/** - * High level representation for Color Scale / Color Gradient Formatting - * component of Conditional Formatting settings - */ -public class XSSFColorScaleFormatting implements ColorScaleFormatting { - CTColorScale _scale; - - /*package*/ XSSFColorScaleFormatting(CTColorScale scale){ - _scale = scale; - } - - public int getNumControlPoints() { - return _scale.sizeOfCfvoArray(); - } - public void setNumControlPoints(int num) { - while (num < _scale.sizeOfCfvoArray()) { - _scale.removeCfvo(_scale.sizeOfCfvoArray()-1); - _scale.removeColor(_scale.sizeOfColorArray()-1); - } - while (num > _scale.sizeOfCfvoArray()) { - _scale.addNewCfvo(); - _scale.addNewColor(); - } - } - - public XSSFColor[] getColors() { - CTColor[] ctcols = _scale.getColorArray(); - XSSFColor[] c = new XSSFColor[ctcols.length]; - for (int i=0; i _scale.sizeOfCfvoArray()) { + _scale.addNewCfvo(); + _scale.addNewColor(); + } + } + + public XSSFColor[] getColors() { + CTColor[] ctcols = _scale.getColorArray(); + XSSFColor[] c = new XSSFColor[ctcols.length]; + for (int i=0; iCellRangeAddresss. Never null - */ - @Override - public CellRangeAddress[] getFormattingRanges() { - ArrayList lst = new ArrayList(); - for (Object stRef : _cf.getSqref()) { - String[] regions = stRef.toString().split(" "); - for (final String region : regions) { - lst.add(CellRangeAddress.valueOf(region)); - } - } - return lst.toArray(new CellRangeAddress[lst.size()]); - } - - @Override - public void setFormattingRanges(CellRangeAddress[] ranges) { - if (ranges == null) { - throw new IllegalArgumentException("cellRanges must not be null"); - } - final StringBuilder sb = new StringBuilder(); - boolean first = true; - for (CellRangeAddress range : ranges) { - if (!first) { - sb.append(" "); - } else { - first = false; - } - sb.append(range.formatAsString()); - } - _cf.setSqref(Collections.singletonList(sb.toString())); - } - - /** - * Replaces an existing Conditional Formatting rule at position idx. - * Excel allows to create up to 3 Conditional Formatting rules. - * This method can be useful to modify existing Conditional Formatting rules. - * - * @param idx position of the rule. Should be between 0 and 2. - * @param cfRule - Conditional Formatting rule - */ - @Override - public void setRule(int idx, ConditionalFormattingRule cfRule) { - XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule) cfRule; - _cf.getCfRuleArray(idx).set(xRule.getCTCfRule()); - } - - /** - * Add a Conditional Formatting rule. - * Excel allows to create up to 3 Conditional Formatting rules. - * - * @param cfRule - Conditional Formatting rule - */ - @Override - public void addRule(ConditionalFormattingRule cfRule) { - XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule) cfRule; - _cf.addNewCfRule().set(xRule.getCTCfRule()); - } - - /** - * @return the Conditional Formatting rule at position idx. - */ - @Override - public XSSFConditionalFormattingRule getRule(int idx) { - return new XSSFConditionalFormattingRule(_sh, _cf.getCfRuleArray(idx)); - } - - /** - * @return number of Conditional Formatting rules. - */ - @Override - public int getNumberOfRules() { - return _cf.sizeOfCfRuleArray(); - } - - @Override - public String toString() { - return _cf.toString(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.usermodel.ConditionalFormatting; +import org.apache.poi.ss.usermodel.ConditionalFormattingRule; +import org.apache.poi.ss.util.CellRangeAddress; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTConditionalFormatting; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * @author Yegor Kozlov + */ +public class XSSFConditionalFormatting implements ConditionalFormatting { + private final CTConditionalFormatting _cf; + private final XSSFSheet _sh; + + /*package*/ XSSFConditionalFormatting(XSSFSheet sh) { + _cf = CTConditionalFormatting.Factory.newInstance(); + _sh = sh; + } + + /*package*/ XSSFConditionalFormatting( + XSSFSheet sh, CTConditionalFormatting cf) { + _cf = cf; + _sh = sh; + } + + /*package*/ CTConditionalFormatting getCTConditionalFormatting() { + return _cf; + } + + /** + * @return array of CellRangeAddresss. Never null + */ + @Override + public CellRangeAddress[] getFormattingRanges() { + ArrayList lst = new ArrayList(); + for (Object stRef : _cf.getSqref()) { + String[] regions = stRef.toString().split(" "); + for (final String region : regions) { + lst.add(CellRangeAddress.valueOf(region)); + } + } + return lst.toArray(new CellRangeAddress[lst.size()]); + } + + @Override + public void setFormattingRanges(CellRangeAddress[] ranges) { + if (ranges == null) { + throw new IllegalArgumentException("cellRanges must not be null"); + } + final StringBuilder sb = new StringBuilder(); + boolean first = true; + for (CellRangeAddress range : ranges) { + if (!first) { + sb.append(" "); + } else { + first = false; + } + sb.append(range.formatAsString()); + } + _cf.setSqref(Collections.singletonList(sb.toString())); + } + + /** + * Replaces an existing Conditional Formatting rule at position idx. + * Excel allows to create up to 3 Conditional Formatting rules. + * This method can be useful to modify existing Conditional Formatting rules. + * + * @param idx position of the rule. Should be between 0 and 2. + * @param cfRule - Conditional Formatting rule + */ + @Override + public void setRule(int idx, ConditionalFormattingRule cfRule) { + XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule) cfRule; + _cf.getCfRuleArray(idx).set(xRule.getCTCfRule()); + } + + /** + * Add a Conditional Formatting rule. + * Excel allows to create up to 3 Conditional Formatting rules. + * + * @param cfRule - Conditional Formatting rule + */ + @Override + public void addRule(ConditionalFormattingRule cfRule) { + XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule) cfRule; + _cf.addNewCfRule().set(xRule.getCTCfRule()); + } + + /** + * @return the Conditional Formatting rule at position idx. + */ + @Override + public XSSFConditionalFormattingRule getRule(int idx) { + return new XSSFConditionalFormattingRule(_sh, _cf.getCfRuleArray(idx)); + } + + /** + * @return number of Conditional Formatting rules. + */ + @Override + public int getNumberOfRules() { + return _cf.sizeOfCfRuleArray(); + } + + @Override + public String toString() { + return _cf.toString(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java index a639f2c271..6c5c36479d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java @@ -1,361 +1,361 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xssf.usermodel; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; -import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; -import org.apache.poi.xssf.usermodel.XSSFFontFormatting; -import org.apache.poi.xssf.model.StylesTable; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; - -/** - * XSSF suport for Conditional Formatting rules - */ -public class XSSFConditionalFormattingRule implements ConditionalFormattingRule { - private final CTCfRule _cfRule; - private XSSFSheet _sh; - - private static Map typeLookup = new HashMap(); - static { - typeLookup.put(STCfType.CELL_IS, ConditionType.CELL_VALUE_IS); - typeLookup.put(STCfType.EXPRESSION, ConditionType.FORMULA); - typeLookup.put(STCfType.COLOR_SCALE, ConditionType.COLOR_SCALE); - typeLookup.put(STCfType.DATA_BAR, ConditionType.DATA_BAR); - typeLookup.put(STCfType.ICON_SET, ConditionType.ICON_SET); - - // These are all subtypes of Filter, we think... - typeLookup.put(STCfType.TOP_10, ConditionType.FILTER); - typeLookup.put(STCfType.UNIQUE_VALUES, ConditionType.FILTER); - typeLookup.put(STCfType.DUPLICATE_VALUES, ConditionType.FILTER); - typeLookup.put(STCfType.CONTAINS_TEXT, ConditionType.FILTER); - typeLookup.put(STCfType.NOT_CONTAINS_TEXT, ConditionType.FILTER); - typeLookup.put(STCfType.BEGINS_WITH, ConditionType.FILTER); - typeLookup.put(STCfType.ENDS_WITH, ConditionType.FILTER); - typeLookup.put(STCfType.CONTAINS_BLANKS, ConditionType.FILTER); - typeLookup.put(STCfType.NOT_CONTAINS_BLANKS, ConditionType.FILTER); - typeLookup.put(STCfType.CONTAINS_ERRORS, ConditionType.FILTER); - typeLookup.put(STCfType.NOT_CONTAINS_ERRORS, ConditionType.FILTER); - typeLookup.put(STCfType.TIME_PERIOD, ConditionType.FILTER); - typeLookup.put(STCfType.ABOVE_AVERAGE, ConditionType.FILTER); - } - - /*package*/ XSSFConditionalFormattingRule(XSSFSheet sh){ - _cfRule = CTCfRule.Factory.newInstance(); - _sh = sh; - } - - /*package*/ XSSFConditionalFormattingRule(XSSFSheet sh, CTCfRule cfRule){ - _cfRule = cfRule; - _sh = sh; - } - - /*package*/ CTCfRule getCTCfRule(){ - return _cfRule; - } - - /*package*/ CTDxf getDxf(boolean create){ - StylesTable styles = _sh.getWorkbook().getStylesSource(); - CTDxf dxf = null; - if(styles._getDXfsSize() > 0 && _cfRule.isSetDxfId()){ - int dxfId = (int)_cfRule.getDxfId(); - dxf = styles.getDxfAt(dxfId); - } - if(create && dxf == null) { - dxf = CTDxf.Factory.newInstance(); - int dxfId = styles.putDxf(dxf); - _cfRule.setDxfId(dxfId - 1); - } - return dxf; - } - - /** - * Create a new border formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - border formatting object, never returns null. - */ - public XSSFBorderFormatting createBorderFormatting(){ - CTDxf dxf = getDxf(true); - CTBorder border; - if(!dxf.isSetBorder()) { - border = dxf.addNewBorder(); - } else { - border = dxf.getBorder(); - } - - return new XSSFBorderFormatting(border); - } - - /** - * @return - border formatting object if defined, null otherwise - */ - public XSSFBorderFormatting getBorderFormatting(){ - CTDxf dxf = getDxf(false); - if(dxf == null || !dxf.isSetBorder()) return null; - - return new XSSFBorderFormatting(dxf.getBorder()); - } - - /** - * Create a new font formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - font formatting object, never returns null. - */ - public XSSFFontFormatting createFontFormatting(){ - CTDxf dxf = getDxf(true); - CTFont font; - if(!dxf.isSetFont()) { - font = dxf.addNewFont(); - } else { - font = dxf.getFont(); - } - - return new XSSFFontFormatting(font); - } - - /** - * @return - font formatting object if defined, null otherwise - */ - public XSSFFontFormatting getFontFormatting(){ - CTDxf dxf = getDxf(false); - if(dxf == null || !dxf.isSetFont()) return null; - - return new XSSFFontFormatting(dxf.getFont()); - } - - /** - * Create a new pattern formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - pattern formatting object, never returns null. - */ - public XSSFPatternFormatting createPatternFormatting(){ - CTDxf dxf = getDxf(true); - CTFill fill; - if(!dxf.isSetFill()) { - fill = dxf.addNewFill(); - } else { - fill = dxf.getFill(); - } - - return new XSSFPatternFormatting(fill); - } - - /** - * @return - pattern formatting object if defined, null otherwise - */ - public XSSFPatternFormatting getPatternFormatting(){ - CTDxf dxf = getDxf(false); - if(dxf == null || !dxf.isSetFill()) return null; - - return new XSSFPatternFormatting(dxf.getFill()); - } - - public XSSFDataBarFormatting createDataBarFormatting(XSSFColor color) { - // Is it already there? - if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR) - return getDataBarFormatting(); - - // Mark it as being a Data Bar - _cfRule.setType(STCfType.DATA_BAR); - - // Ensure the right element - CTDataBar bar = null; - if (_cfRule.isSetDataBar()) { - bar = _cfRule.getDataBar(); - } else { - bar = _cfRule.addNewDataBar(); - } - // Set the color - bar.setColor(color.getCTColor()); - - // Add the default thresholds - CTCfvo min = bar.addNewCfvo(); - min.setType(STCfvoType.Enum.forString(RangeType.MIN.name)); - CTCfvo max = bar.addNewCfvo(); - max.setType(STCfvoType.Enum.forString(RangeType.MAX.name)); - - // Wrap and return - return new XSSFDataBarFormatting(bar); - } - public XSSFDataBarFormatting getDataBarFormatting() { - if (_cfRule.isSetDataBar()) { - CTDataBar bar = _cfRule.getDataBar(); - return new XSSFDataBarFormatting(bar); - } else { - return null; - } - } - - public XSSFIconMultiStateFormatting createMultiStateFormatting(IconSet iconSet) { - // Is it already there? - if (_cfRule.isSetIconSet() && _cfRule.getType() == STCfType.ICON_SET) - return getMultiStateFormatting(); - - // Mark it as being an Icon Set - _cfRule.setType(STCfType.ICON_SET); - - // Ensure the right element - CTIconSet icons = null; - if (_cfRule.isSetIconSet()) { - icons = _cfRule.getIconSet(); - } else { - icons = _cfRule.addNewIconSet(); - } - // Set the type of the icon set - if (iconSet.name != null) { - STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(iconSet.name); - icons.setIconSet(xIconSet); - } - - // Add a default set of thresholds - int jump = 100 / iconSet.num; - STCfvoType.Enum type = STCfvoType.Enum.forString(RangeType.PERCENT.name); - for (int i=0; i - * MUST be a constant from {@link org.apache.poi.ss.usermodel.ComparisonOperator} - *

- * - * @return the conditional format operator - */ - @Override - public byte getComparisonOperation(){ - STConditionalFormattingOperator.Enum op = _cfRule.getOperator(); - if(op == null) return ComparisonOperator.NO_COMPARISON; - - switch(op.intValue()){ - case STConditionalFormattingOperator.INT_LESS_THAN: return ComparisonOperator.LT; - case STConditionalFormattingOperator.INT_LESS_THAN_OR_EQUAL: return ComparisonOperator.LE; - case STConditionalFormattingOperator.INT_GREATER_THAN: return ComparisonOperator.GT; - case STConditionalFormattingOperator.INT_GREATER_THAN_OR_EQUAL: return ComparisonOperator.GE; - case STConditionalFormattingOperator.INT_EQUAL: return ComparisonOperator.EQUAL; - case STConditionalFormattingOperator.INT_NOT_EQUAL: return ComparisonOperator.NOT_EQUAL; - case STConditionalFormattingOperator.INT_BETWEEN: return ComparisonOperator.BETWEEN; - case STConditionalFormattingOperator.INT_NOT_BETWEEN: return ComparisonOperator.NOT_BETWEEN; - } - return ComparisonOperator.NO_COMPARISON; - } - - /** - * The formula used to evaluate the first operand for the conditional formatting rule. - *

- * If the condition type is {@link ConditionType#CELL_VALUE_IS}, - * this field is the first operand of the comparison. - * If type is {@link ConditionType#FORMULA}, this formula is used - * to determine if the conditional formatting is applied. - *

- *

- * If comparison type is {@link ConditionType#FORMULA} the formula MUST be a Boolean function - *

- * - * @return the first formula - */ - public String getFormula1(){ - return _cfRule.sizeOfFormulaArray() > 0 ? _cfRule.getFormulaArray(0) : null; - } - - /** - * The formula used to evaluate the second operand of the comparison when - * comparison type is {@link ConditionType#CELL_VALUE_IS} and operator - * is either {@link org.apache.poi.ss.usermodel.ComparisonOperator#BETWEEN} or {@link org.apache.poi.ss.usermodel.ComparisonOperator#NOT_BETWEEN} - * - * @return the second formula - */ - public String getFormula2(){ - return _cfRule.sizeOfFormulaArray() == 2 ? _cfRule.getFormulaArray(1) : null; - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xssf.usermodel; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; +import org.apache.poi.xssf.usermodel.XSSFFontFormatting; +import org.apache.poi.xssf.model.StylesTable; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; + +/** + * XSSF suport for Conditional Formatting rules + */ +public class XSSFConditionalFormattingRule implements ConditionalFormattingRule { + private final CTCfRule _cfRule; + private XSSFSheet _sh; + + private static Map typeLookup = new HashMap(); + static { + typeLookup.put(STCfType.CELL_IS, ConditionType.CELL_VALUE_IS); + typeLookup.put(STCfType.EXPRESSION, ConditionType.FORMULA); + typeLookup.put(STCfType.COLOR_SCALE, ConditionType.COLOR_SCALE); + typeLookup.put(STCfType.DATA_BAR, ConditionType.DATA_BAR); + typeLookup.put(STCfType.ICON_SET, ConditionType.ICON_SET); + + // These are all subtypes of Filter, we think... + typeLookup.put(STCfType.TOP_10, ConditionType.FILTER); + typeLookup.put(STCfType.UNIQUE_VALUES, ConditionType.FILTER); + typeLookup.put(STCfType.DUPLICATE_VALUES, ConditionType.FILTER); + typeLookup.put(STCfType.CONTAINS_TEXT, ConditionType.FILTER); + typeLookup.put(STCfType.NOT_CONTAINS_TEXT, ConditionType.FILTER); + typeLookup.put(STCfType.BEGINS_WITH, ConditionType.FILTER); + typeLookup.put(STCfType.ENDS_WITH, ConditionType.FILTER); + typeLookup.put(STCfType.CONTAINS_BLANKS, ConditionType.FILTER); + typeLookup.put(STCfType.NOT_CONTAINS_BLANKS, ConditionType.FILTER); + typeLookup.put(STCfType.CONTAINS_ERRORS, ConditionType.FILTER); + typeLookup.put(STCfType.NOT_CONTAINS_ERRORS, ConditionType.FILTER); + typeLookup.put(STCfType.TIME_PERIOD, ConditionType.FILTER); + typeLookup.put(STCfType.ABOVE_AVERAGE, ConditionType.FILTER); + } + + /*package*/ XSSFConditionalFormattingRule(XSSFSheet sh){ + _cfRule = CTCfRule.Factory.newInstance(); + _sh = sh; + } + + /*package*/ XSSFConditionalFormattingRule(XSSFSheet sh, CTCfRule cfRule){ + _cfRule = cfRule; + _sh = sh; + } + + /*package*/ CTCfRule getCTCfRule(){ + return _cfRule; + } + + /*package*/ CTDxf getDxf(boolean create){ + StylesTable styles = _sh.getWorkbook().getStylesSource(); + CTDxf dxf = null; + if(styles._getDXfsSize() > 0 && _cfRule.isSetDxfId()){ + int dxfId = (int)_cfRule.getDxfId(); + dxf = styles.getDxfAt(dxfId); + } + if(create && dxf == null) { + dxf = CTDxf.Factory.newInstance(); + int dxfId = styles.putDxf(dxf); + _cfRule.setDxfId(dxfId - 1); + } + return dxf; + } + + /** + * Create a new border formatting structure if it does not exist, + * otherwise just return existing object. + * + * @return - border formatting object, never returns null. + */ + public XSSFBorderFormatting createBorderFormatting(){ + CTDxf dxf = getDxf(true); + CTBorder border; + if(!dxf.isSetBorder()) { + border = dxf.addNewBorder(); + } else { + border = dxf.getBorder(); + } + + return new XSSFBorderFormatting(border); + } + + /** + * @return - border formatting object if defined, null otherwise + */ + public XSSFBorderFormatting getBorderFormatting(){ + CTDxf dxf = getDxf(false); + if(dxf == null || !dxf.isSetBorder()) return null; + + return new XSSFBorderFormatting(dxf.getBorder()); + } + + /** + * Create a new font formatting structure if it does not exist, + * otherwise just return existing object. + * + * @return - font formatting object, never returns null. + */ + public XSSFFontFormatting createFontFormatting(){ + CTDxf dxf = getDxf(true); + CTFont font; + if(!dxf.isSetFont()) { + font = dxf.addNewFont(); + } else { + font = dxf.getFont(); + } + + return new XSSFFontFormatting(font); + } + + /** + * @return - font formatting object if defined, null otherwise + */ + public XSSFFontFormatting getFontFormatting(){ + CTDxf dxf = getDxf(false); + if(dxf == null || !dxf.isSetFont()) return null; + + return new XSSFFontFormatting(dxf.getFont()); + } + + /** + * Create a new pattern formatting structure if it does not exist, + * otherwise just return existing object. + * + * @return - pattern formatting object, never returns null. + */ + public XSSFPatternFormatting createPatternFormatting(){ + CTDxf dxf = getDxf(true); + CTFill fill; + if(!dxf.isSetFill()) { + fill = dxf.addNewFill(); + } else { + fill = dxf.getFill(); + } + + return new XSSFPatternFormatting(fill); + } + + /** + * @return - pattern formatting object if defined, null otherwise + */ + public XSSFPatternFormatting getPatternFormatting(){ + CTDxf dxf = getDxf(false); + if(dxf == null || !dxf.isSetFill()) return null; + + return new XSSFPatternFormatting(dxf.getFill()); + } + + public XSSFDataBarFormatting createDataBarFormatting(XSSFColor color) { + // Is it already there? + if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR) + return getDataBarFormatting(); + + // Mark it as being a Data Bar + _cfRule.setType(STCfType.DATA_BAR); + + // Ensure the right element + CTDataBar bar = null; + if (_cfRule.isSetDataBar()) { + bar = _cfRule.getDataBar(); + } else { + bar = _cfRule.addNewDataBar(); + } + // Set the color + bar.setColor(color.getCTColor()); + + // Add the default thresholds + CTCfvo min = bar.addNewCfvo(); + min.setType(STCfvoType.Enum.forString(RangeType.MIN.name)); + CTCfvo max = bar.addNewCfvo(); + max.setType(STCfvoType.Enum.forString(RangeType.MAX.name)); + + // Wrap and return + return new XSSFDataBarFormatting(bar); + } + public XSSFDataBarFormatting getDataBarFormatting() { + if (_cfRule.isSetDataBar()) { + CTDataBar bar = _cfRule.getDataBar(); + return new XSSFDataBarFormatting(bar); + } else { + return null; + } + } + + public XSSFIconMultiStateFormatting createMultiStateFormatting(IconSet iconSet) { + // Is it already there? + if (_cfRule.isSetIconSet() && _cfRule.getType() == STCfType.ICON_SET) + return getMultiStateFormatting(); + + // Mark it as being an Icon Set + _cfRule.setType(STCfType.ICON_SET); + + // Ensure the right element + CTIconSet icons = null; + if (_cfRule.isSetIconSet()) { + icons = _cfRule.getIconSet(); + } else { + icons = _cfRule.addNewIconSet(); + } + // Set the type of the icon set + if (iconSet.name != null) { + STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(iconSet.name); + icons.setIconSet(xIconSet); + } + + // Add a default set of thresholds + int jump = 100 / iconSet.num; + STCfvoType.Enum type = STCfvoType.Enum.forString(RangeType.PERCENT.name); + for (int i=0; i + * MUST be a constant from {@link org.apache.poi.ss.usermodel.ComparisonOperator} + *

+ * + * @return the conditional format operator + */ + @Override + public byte getComparisonOperation(){ + STConditionalFormattingOperator.Enum op = _cfRule.getOperator(); + if(op == null) return ComparisonOperator.NO_COMPARISON; + + switch(op.intValue()){ + case STConditionalFormattingOperator.INT_LESS_THAN: return ComparisonOperator.LT; + case STConditionalFormattingOperator.INT_LESS_THAN_OR_EQUAL: return ComparisonOperator.LE; + case STConditionalFormattingOperator.INT_GREATER_THAN: return ComparisonOperator.GT; + case STConditionalFormattingOperator.INT_GREATER_THAN_OR_EQUAL: return ComparisonOperator.GE; + case STConditionalFormattingOperator.INT_EQUAL: return ComparisonOperator.EQUAL; + case STConditionalFormattingOperator.INT_NOT_EQUAL: return ComparisonOperator.NOT_EQUAL; + case STConditionalFormattingOperator.INT_BETWEEN: return ComparisonOperator.BETWEEN; + case STConditionalFormattingOperator.INT_NOT_BETWEEN: return ComparisonOperator.NOT_BETWEEN; + } + return ComparisonOperator.NO_COMPARISON; + } + + /** + * The formula used to evaluate the first operand for the conditional formatting rule. + *

+ * If the condition type is {@link ConditionType#CELL_VALUE_IS}, + * this field is the first operand of the comparison. + * If type is {@link ConditionType#FORMULA}, this formula is used + * to determine if the conditional formatting is applied. + *

+ *

+ * If comparison type is {@link ConditionType#FORMULA} the formula MUST be a Boolean function + *

+ * + * @return the first formula + */ + public String getFormula1(){ + return _cfRule.sizeOfFormulaArray() > 0 ? _cfRule.getFormulaArray(0) : null; + } + + /** + * The formula used to evaluate the second operand of the comparison when + * comparison type is {@link ConditionType#CELL_VALUE_IS} and operator + * is either {@link org.apache.poi.ss.usermodel.ComparisonOperator#BETWEEN} or {@link org.apache.poi.ss.usermodel.ComparisonOperator#NOT_BETWEEN} + * + * @return the second formula + */ + public String getFormula2(){ + return _cfRule.sizeOfFormulaArray() == 2 ? _cfRule.getFormulaArray(1) : null; + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java index bfdd87807d..f868f14a2b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java @@ -1,77 +1,77 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfvoType; - -/** - * High level representation for Icon / Multi-State / Databar / - * Colour Scale change thresholds - */ -public class XSSFConditionalFormattingThreshold implements org.apache.poi.ss.usermodel.ConditionalFormattingThreshold { - private CTCfvo cfvo; - - protected XSSFConditionalFormattingThreshold(CTCfvo cfvo) { - this.cfvo = cfvo; - } - - protected CTCfvo getCTCfvo() { - return cfvo; - } - - public RangeType getRangeType() { - return RangeType.byName(cfvo.getType().toString()); - } - public void setRangeType(RangeType type) { - STCfvoType.Enum xtype = STCfvoType.Enum.forString(type.name); - cfvo.setType(xtype); - } - - public String getFormula() { - if (cfvo.getType() == STCfvoType.FORMULA) { - return cfvo.getVal(); - } - return null; - } - public void setFormula(String formula) { - cfvo.setVal(formula); - } - - public Double getValue() { - if (cfvo.getType() == STCfvoType.FORMULA || - cfvo.getType() == STCfvoType.MIN || - cfvo.getType() == STCfvoType.MAX) { - return null; - } - if (cfvo.isSetVal()) { - return Double.parseDouble(cfvo.getVal()); - } else { - return null; - } - } - public void setValue(Double value) { - if (value == null) { - cfvo.unsetVal(); - } else { - cfvo.setVal(value.toString()); - } - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfvoType; + +/** + * High level representation for Icon / Multi-State / Databar / + * Colour Scale change thresholds + */ +public class XSSFConditionalFormattingThreshold implements org.apache.poi.ss.usermodel.ConditionalFormattingThreshold { + private CTCfvo cfvo; + + protected XSSFConditionalFormattingThreshold(CTCfvo cfvo) { + this.cfvo = cfvo; + } + + protected CTCfvo getCTCfvo() { + return cfvo; + } + + public RangeType getRangeType() { + return RangeType.byName(cfvo.getType().toString()); + } + public void setRangeType(RangeType type) { + STCfvoType.Enum xtype = STCfvoType.Enum.forString(type.name); + cfvo.setType(xtype); + } + + public String getFormula() { + if (cfvo.getType() == STCfvoType.FORMULA) { + return cfvo.getVal(); + } + return null; + } + public void setFormula(String formula) { + cfvo.setVal(formula); + } + + public Double getValue() { + if (cfvo.getType() == STCfvoType.FORMULA || + cfvo.getType() == STCfvoType.MIN || + cfvo.getType() == STCfvoType.MAX) { + return null; + } + if (cfvo.isSetVal()) { + return Double.parseDouble(cfvo.getVal()); + } else { + return null; + } + } + public void setValue(Double value) { + if (value == null) { + cfvo.unsetVal(); + } else { + cfvo.setVal(value.toString()); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java index bc7b9cf718..552d5e32f0 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java @@ -1,83 +1,83 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.DataBarFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar; - -/** - * High level representation for DataBar / Data Bar Formatting - * component of Conditional Formatting settings - */ -public class XSSFDataBarFormatting implements DataBarFormatting { - CTDataBar _databar; - - /*package*/ XSSFDataBarFormatting(CTDataBar databar){ - _databar = databar; - } - - public boolean isIconOnly() { - if (_databar.isSetShowValue()) - return !_databar.getShowValue(); - return false; - } - public void setIconOnly(boolean only) { - _databar.setShowValue(!only); - } - - public boolean isLeftToRight() { - return true; - } - public void setLeftToRight(boolean ltr) { - // TODO How does XSSF encode this? - } - - public int getWidthMin() { - return 0; - } - public void setWidthMin(int width) { - // TODO How does XSSF encode this? - } - - public int getWidthMax() { - return 100; - } - public void setWidthMax(int width) { - // TODO How does XSSF encode this? - } - - public XSSFColor getColor() { - return new XSSFColor(_databar.getColor()); - } - public void setColor(Color color) { - _databar.setColor( ((XSSFColor)color).getCTColor() ); - } - - public XSSFConditionalFormattingThreshold getMinThreshold() { - return new XSSFConditionalFormattingThreshold(_databar.getCfvoArray(0)); - } - public XSSFConditionalFormattingThreshold getMaxThreshold() { - return new XSSFConditionalFormattingThreshold(_databar.getCfvoArray(1)); - } - - public XSSFConditionalFormattingThreshold createThreshold() { - return new XSSFConditionalFormattingThreshold(_databar.addNewCfvo()); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.usermodel.Color; +import org.apache.poi.ss.usermodel.DataBarFormatting; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar; + +/** + * High level representation for DataBar / Data Bar Formatting + * component of Conditional Formatting settings + */ +public class XSSFDataBarFormatting implements DataBarFormatting { + CTDataBar _databar; + + /*package*/ XSSFDataBarFormatting(CTDataBar databar){ + _databar = databar; + } + + public boolean isIconOnly() { + if (_databar.isSetShowValue()) + return !_databar.getShowValue(); + return false; + } + public void setIconOnly(boolean only) { + _databar.setShowValue(!only); + } + + public boolean isLeftToRight() { + return true; + } + public void setLeftToRight(boolean ltr) { + // TODO How does XSSF encode this? + } + + public int getWidthMin() { + return 0; + } + public void setWidthMin(int width) { + // TODO How does XSSF encode this? + } + + public int getWidthMax() { + return 100; + } + public void setWidthMax(int width) { + // TODO How does XSSF encode this? + } + + public XSSFColor getColor() { + return new XSSFColor(_databar.getColor()); + } + public void setColor(Color color) { + _databar.setColor( ((XSSFColor)color).getCTColor() ); + } + + public XSSFConditionalFormattingThreshold getMinThreshold() { + return new XSSFConditionalFormattingThreshold(_databar.getCfvoArray(0)); + } + public XSSFConditionalFormattingThreshold getMaxThreshold() { + return new XSSFConditionalFormattingThreshold(_databar.getCfvoArray(1)); + } + + public XSSFConditionalFormattingThreshold createThreshold() { + return new XSSFConditionalFormattingThreshold(_databar.addNewCfvo()); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java index 8e8a3d85c5..f3b8fd41d3 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java @@ -1,224 +1,224 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.ss.usermodel.*; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTUnderlineProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontSize; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTVerticalAlignFontProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STVerticalAlignRun; - - -/** - * @author Yegor Kozlov - */ -public class XSSFFontFormatting implements FontFormatting { - CTFont _font; - - /*package*/ XSSFFontFormatting(CTFont font){ - _font = font; - } - - /** - * get the type of super or subscript for the font - * - * @return super or subscript option - * @see #SS_NONE - * @see #SS_SUPER - * @see #SS_SUB - */ - @Override - public short getEscapementType(){ - if(_font.sizeOfVertAlignArray() == 0) return SS_NONE; - - CTVerticalAlignFontProperty prop = _font.getVertAlignArray(0); - return (short)(prop.getVal().intValue() - 1); - } - - /** - * set the escapement type for the font - * - * @param escapementType super or subscript option - * @see #SS_NONE - * @see #SS_SUPER - * @see #SS_SUB - */ - @Override - public void setEscapementType(short escapementType){ - _font.setVertAlignArray(null); - if(escapementType != SS_NONE){ - _font.addNewVertAlign().setVal(STVerticalAlignRun.Enum.forInt(escapementType + 1)); - } - } - - /** - * @return font color index - */ - @Override - public short getFontColorIndex(){ - if(_font.sizeOfColorArray() == 0) return -1; - - int idx = 0; - CTColor color = _font.getColorArray(0); - if(color.isSetIndexed()) idx = (int)color.getIndexed(); - return (short)idx; - } - - /** - * @param color font color index - */ - @Override - public void setFontColorIndex(short color){ - _font.setColorArray(null); - if(color != -1){ - _font.addNewColor().setIndexed(color); - } - } - - @Override - public XSSFColor getFontColor() { - if(_font.sizeOfColorArray() == 0) return null; - - return new XSSFColor(_font.getColorArray(0)); - } - - @Override - public void setFontColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) { - _font.getColorList().clear(); - } else { - _font.setColorArray(0, xcolor.getCTColor()); - } - } - - /** - * gets the height of the font in 1/20th point units - * - * @return fontheight (in points/20); or -1 if not modified - */ - @Override - public int getFontHeight(){ - if(_font.sizeOfSzArray() == 0) return -1; - - CTFontSize sz = _font.getSzArray(0); - return (short)(20*sz.getVal()); - } - - /** - * Sets the height of the font in 1/20th point units - * - * @param height the height in twips (in points/20) - */ - @Override - public void setFontHeight(int height){ - _font.setSzArray(null); - if(height != -1){ - _font.addNewSz().setVal((double)height / 20); - } - } - - /** - * get the type of underlining for the font - * - * @return font underlining type - * - * @see #U_NONE - * @see #U_SINGLE - * @see #U_DOUBLE - * @see #U_SINGLE_ACCOUNTING - * @see #U_DOUBLE_ACCOUNTING - */ - @Override - public short getUnderlineType(){ - if(_font.sizeOfUArray() == 0) return U_NONE; - CTUnderlineProperty u = _font.getUArray(0); - switch(u.getVal().intValue()){ - case STUnderlineValues.INT_SINGLE: return U_SINGLE; - case STUnderlineValues.INT_DOUBLE: return U_DOUBLE; - case STUnderlineValues.INT_SINGLE_ACCOUNTING: return U_SINGLE_ACCOUNTING; - case STUnderlineValues.INT_DOUBLE_ACCOUNTING: return U_DOUBLE_ACCOUNTING; - default: return U_NONE; - } - } - - /** - * set the type of underlining type for the font - * - * @param underlineType super or subscript option - * - * @see #U_NONE - * @see #U_SINGLE - * @see #U_DOUBLE - * @see #U_SINGLE_ACCOUNTING - * @see #U_DOUBLE_ACCOUNTING - */ - @Override - public void setUnderlineType(short underlineType){ - _font.setUArray(null); - if(underlineType != U_NONE){ - FontUnderline fenum = FontUnderline.valueOf(underlineType); - STUnderlineValues.Enum val = STUnderlineValues.Enum.forInt(fenum.getValue()); - _font.addNewU().setVal(val); - } - } - - /** - * get whether the font weight is set to bold or not - * - * @return bold - whether the font is bold or not - */ - @Override - public boolean isBold(){ - return _font.sizeOfBArray() == 1 && _font.getBArray(0).getVal(); - } - - /** - * @return true if font style was set to italic - */ - @Override - public boolean isItalic(){ - return _font.sizeOfIArray() == 1 && _font.getIArray(0).getVal(); - } - - /** - * set font style options. - * - * @param italic - if true, set posture style to italic, otherwise to normal - * @param bold if true, set font weight to bold, otherwise to normal - */ - @Override - public void setFontStyle(boolean italic, boolean bold){ - _font.setIArray(null); - _font.setBArray(null); - if(italic) _font.addNewI().setVal(true); - if(bold) _font.addNewB().setVal(true); - } - - /** - * set font style options to default values (non-italic, non-bold) - */ - @Override - public void resetFontStyle(){ - _font.set(CTFont.Factory.newInstance()); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.usermodel.*; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTUnderlineProperty; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontSize; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTVerticalAlignFontProperty; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STVerticalAlignRun; + + +/** + * @author Yegor Kozlov + */ +public class XSSFFontFormatting implements FontFormatting { + CTFont _font; + + /*package*/ XSSFFontFormatting(CTFont font){ + _font = font; + } + + /** + * get the type of super or subscript for the font + * + * @return super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + @Override + public short getEscapementType(){ + if(_font.sizeOfVertAlignArray() == 0) return SS_NONE; + + CTVerticalAlignFontProperty prop = _font.getVertAlignArray(0); + return (short)(prop.getVal().intValue() - 1); + } + + /** + * set the escapement type for the font + * + * @param escapementType super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + @Override + public void setEscapementType(short escapementType){ + _font.setVertAlignArray(null); + if(escapementType != SS_NONE){ + _font.addNewVertAlign().setVal(STVerticalAlignRun.Enum.forInt(escapementType + 1)); + } + } + + /** + * @return font color index + */ + @Override + public short getFontColorIndex(){ + if(_font.sizeOfColorArray() == 0) return -1; + + int idx = 0; + CTColor color = _font.getColorArray(0); + if(color.isSetIndexed()) idx = (int)color.getIndexed(); + return (short)idx; + } + + /** + * @param color font color index + */ + @Override + public void setFontColorIndex(short color){ + _font.setColorArray(null); + if(color != -1){ + _font.addNewColor().setIndexed(color); + } + } + + @Override + public XSSFColor getFontColor() { + if(_font.sizeOfColorArray() == 0) return null; + + return new XSSFColor(_font.getColorArray(0)); + } + + @Override + public void setFontColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) { + _font.getColorList().clear(); + } else { + _font.setColorArray(0, xcolor.getCTColor()); + } + } + + /** + * gets the height of the font in 1/20th point units + * + * @return fontheight (in points/20); or -1 if not modified + */ + @Override + public int getFontHeight(){ + if(_font.sizeOfSzArray() == 0) return -1; + + CTFontSize sz = _font.getSzArray(0); + return (short)(20*sz.getVal()); + } + + /** + * Sets the height of the font in 1/20th point units + * + * @param height the height in twips (in points/20) + */ + @Override + public void setFontHeight(int height){ + _font.setSzArray(null); + if(height != -1){ + _font.addNewSz().setVal((double)height / 20); + } + } + + /** + * get the type of underlining for the font + * + * @return font underlining type + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + @Override + public short getUnderlineType(){ + if(_font.sizeOfUArray() == 0) return U_NONE; + CTUnderlineProperty u = _font.getUArray(0); + switch(u.getVal().intValue()){ + case STUnderlineValues.INT_SINGLE: return U_SINGLE; + case STUnderlineValues.INT_DOUBLE: return U_DOUBLE; + case STUnderlineValues.INT_SINGLE_ACCOUNTING: return U_SINGLE_ACCOUNTING; + case STUnderlineValues.INT_DOUBLE_ACCOUNTING: return U_DOUBLE_ACCOUNTING; + default: return U_NONE; + } + } + + /** + * set the type of underlining type for the font + * + * @param underlineType super or subscript option + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + @Override + public void setUnderlineType(short underlineType){ + _font.setUArray(null); + if(underlineType != U_NONE){ + FontUnderline fenum = FontUnderline.valueOf(underlineType); + STUnderlineValues.Enum val = STUnderlineValues.Enum.forInt(fenum.getValue()); + _font.addNewU().setVal(val); + } + } + + /** + * get whether the font weight is set to bold or not + * + * @return bold - whether the font is bold or not + */ + @Override + public boolean isBold(){ + return _font.sizeOfBArray() == 1 && _font.getBArray(0).getVal(); + } + + /** + * @return true if font style was set to italic + */ + @Override + public boolean isItalic(){ + return _font.sizeOfIArray() == 1 && _font.getIArray(0).getVal(); + } + + /** + * set font style options. + * + * @param italic - if true, set posture style to italic, otherwise to normal + * @param bold if true, set font weight to bold, otherwise to normal + */ + @Override + public void setFontStyle(boolean italic, boolean bold){ + _font.setIArray(null); + _font.setBArray(null); + if(italic) _font.addNewI().setVal(true); + if(bold) _font.addNewB().setVal(true); + } + + /** + * set font style options to default values (non-italic, non-bold) + */ + @Override + public void resetFontStyle(){ + _font.set(CTFont.Factory.newInstance()); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java index c2e26911af..29062ee06f 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java @@ -1,84 +1,84 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold; -import org.apache.poi.ss.usermodel.IconMultiStateFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIconSet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STIconSetType; - -/** - * High level representation for Icon / Multi-State Formatting - * component of Conditional Formatting settings - */ -public class XSSFIconMultiStateFormatting implements IconMultiStateFormatting { - CTIconSet _iconset; - - /*package*/ XSSFIconMultiStateFormatting(CTIconSet iconset){ - _iconset = iconset; - } - - public IconSet getIconSet() { - String set = _iconset.getIconSet().toString(); - return IconSet.byName(set); - } - public void setIconSet(IconSet set) { - STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(set.name); - _iconset.setIconSet(xIconSet); - } - - public boolean isIconOnly() { - if (_iconset.isSetShowValue()) - return !_iconset.getShowValue(); - return false; - } - public void setIconOnly(boolean only) { - _iconset.setShowValue(!only); - } - - public boolean isReversed() { - if (_iconset.isSetReverse()) - return _iconset.getReverse(); - return false; - } - public void setReversed(boolean reversed) { - _iconset.setReverse(reversed); - } - - public XSSFConditionalFormattingThreshold[] getThresholds() { - CTCfvo[] cfvos = _iconset.getCfvoArray(); - XSSFConditionalFormattingThreshold[] t = - new XSSFConditionalFormattingThreshold[cfvos.length]; - for (int i=0; i - * TODO - formulas containing cell references are currently not parsed properly - * - * @param comparisonOperation - a constant value from - * {@link org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator}:

- *

    - *
  • BETWEEN
  • - *
  • NOT_BETWEEN
  • - *
  • EQUAL
  • - *
  • NOT_EQUAL
  • - *
  • GT
  • - *
  • LT
  • - *
  • GE
  • - *
  • LE
  • - *
- *

- * @param formula1 - formula for the valued, compared with the cell - * @param formula2 - second formula (only used with - * {@link org.apache.poi.ss.usermodel.ComparisonOperator#BETWEEN}) and - * {@link org.apache.poi.ss.usermodel.ComparisonOperator#NOT_BETWEEN} operations) - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule( - byte comparisonOperation, - String formula1, - String formula2) { - - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - CTCfRule cfRule = rule.getCTCfRule(); - cfRule.addFormula(formula1); - if(formula2 != null) cfRule.addFormula(formula2); - cfRule.setType(STCfType.CELL_IS); - STConditionalFormattingOperator.Enum operator; - switch (comparisonOperation){ - case ComparisonOperator.BETWEEN: operator = STConditionalFormattingOperator.BETWEEN; break; - case ComparisonOperator.NOT_BETWEEN: operator = STConditionalFormattingOperator.NOT_BETWEEN; break; - case ComparisonOperator.LT: operator = STConditionalFormattingOperator.LESS_THAN; break; - case ComparisonOperator.LE: operator = STConditionalFormattingOperator.LESS_THAN_OR_EQUAL; break; - case ComparisonOperator.GT: operator = STConditionalFormattingOperator.GREATER_THAN; break; - case ComparisonOperator.GE: operator = STConditionalFormattingOperator.GREATER_THAN_OR_EQUAL; break; - case ComparisonOperator.EQUAL: operator = STConditionalFormattingOperator.EQUAL; break; - case ComparisonOperator.NOT_EQUAL: operator = STConditionalFormattingOperator.NOT_EQUAL; break; - default: throw new IllegalArgumentException("Unknown comparison operator: " + comparisonOperation); - } - cfRule.setOperator(operator); - - return rule; - } - - public XSSFConditionalFormattingRule createConditionalFormattingRule( - byte comparisonOperation, - String formula) { - - return createConditionalFormattingRule(comparisonOperation, formula, null); - } - - /** - * A factory method allowing to create a conditional formatting rule with a formula.
- * - * @param formula - formula for the valued, compared with the cell - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule(String formula) { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - CTCfRule cfRule = rule.getCTCfRule(); - cfRule.addFormula(formula); - cfRule.setType(STCfType.EXPRESSION); - return rule; - } - - /** - * Create a Databar conditional formatting rule. - *

The thresholds and colour for it will be created, but will be - * empty and require configuring with - * {@link XSSFConditionalFormattingRule#getDataBarFormatting()} - * then - * {@link XSSFDataBarFormatting#getMinThreshold()} - * and - * {@link XSSFDataBarFormatting#getMaxThreshold()} - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule(XSSFColor color) { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - - // Have it setup, with suitable defaults - rule.createDataBarFormatting(color); - - // All done! - return rule; - } - public XSSFConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color) { - return createConditionalFormattingRule((XSSFColor)color); - } - - /** - * A factory method allowing the creation of conditional formatting - * rules using an Icon Set / Multi-State formatting. - * The thresholds for it will be created, but will be empty - * and require configuring with - * {@link XSSFConditionalFormattingRule#getMultiStateFormatting()} - * then - * {@link XSSFIconMultiStateFormatting#getThresholds()} - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule(IconSet iconSet) { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - - // Have it setup, with suitable defaults - rule.createMultiStateFormatting(iconSet); - - // All done! - return rule; - } - - /** - * Create a Color Scale / Color Gradient conditional formatting rule. - *

The thresholds and colours for it will be created, but will be - * empty and require configuring with - * {@link XSSFConditionalFormattingRule#getColorScaleFormatting()} - * then - * {@link XSSFColorScaleFormatting#getThresholds()} - * and - * {@link XSSFColorScaleFormatting#getColors()} - */ - public XSSFConditionalFormattingRule createConditionalFormattingColorScaleRule() { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - - // Have it setup, with suitable defaults - rule.createColorScaleFormatting(); - - // All done! - return rule; - } - - public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) { - if (regions == null) { - throw new IllegalArgumentException("regions must not be null"); - } - for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL2007); - - if (cfRules == null) { - throw new IllegalArgumentException("cfRules must not be null"); - } - if (cfRules.length == 0) { - throw new IllegalArgumentException("cfRules must not be empty"); - } - if (cfRules.length > 3) { - throw new IllegalArgumentException("Number of rules must not exceed 3"); - } - - CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(regions); - CTConditionalFormatting cf = _sheet.getCTWorksheet().addNewConditionalFormatting(); - List refs = new ArrayList(); - for(CellRangeAddress a : mergeCellRanges) refs.add(a.formatAsString()); - cf.setSqref(refs); - - int priority = 1; - for(CTConditionalFormatting c : _sheet.getCTWorksheet().getConditionalFormattingArray()){ - priority += c.sizeOfCfRuleArray(); - } - - for(ConditionalFormattingRule rule : cfRules){ - XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule)rule; - xRule.getCTCfRule().setPriority(priority++); - cf.addNewCfRule().set(xRule.getCTCfRule()); - } - return _sheet.getCTWorksheet().sizeOfConditionalFormattingArray() - 1; - } - - public int addConditionalFormatting(CellRangeAddress[] regions, - ConditionalFormattingRule rule1) - { - return addConditionalFormatting(regions, - rule1 == null ? null : new XSSFConditionalFormattingRule[] { - (XSSFConditionalFormattingRule)rule1 - }); - } - - public int addConditionalFormatting(CellRangeAddress[] regions, - ConditionalFormattingRule rule1, ConditionalFormattingRule rule2) - { - return addConditionalFormatting(regions, - rule1 == null ? null : new XSSFConditionalFormattingRule[] { - (XSSFConditionalFormattingRule)rule1, - (XSSFConditionalFormattingRule)rule2 - }); - } - - /** - * Adds a copy of HSSFConditionalFormatting object to the sheet - *

This method could be used to copy HSSFConditionalFormatting object - * from one sheet to another. For example: - *

-     * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
-     * newSheet.addConditionalFormatting(cf);
-     * 
- * - * @param cf HSSFConditionalFormatting object - * @return index of the new Conditional Formatting object - */ - public int addConditionalFormatting( ConditionalFormatting cf ) { - XSSFConditionalFormatting xcf = (XSSFConditionalFormatting)cf; - CTWorksheet sh = _sheet.getCTWorksheet(); - sh.addNewConditionalFormatting().set(xcf.getCTConditionalFormatting().copy()); - return sh.sizeOfConditionalFormattingArray() - 1; - } - - /** - * gets Conditional Formatting object at a particular index - * - * @param index - * of the Conditional Formatting object to fetch - * @return Conditional Formatting object - */ - public XSSFConditionalFormatting getConditionalFormattingAt(int index) { - checkIndex(index); - CTConditionalFormatting cf = _sheet.getCTWorksheet().getConditionalFormattingArray(index); - return new XSSFConditionalFormatting(_sheet, cf); - } - - /** - * @return number of Conditional Formatting objects of the sheet - */ - public int getNumConditionalFormattings() { - return _sheet.getCTWorksheet().sizeOfConditionalFormattingArray(); - } - - /** - * removes a Conditional Formatting object by index - * @param index of a Conditional Formatting object to remove - */ - public void removeConditionalFormatting(int index) { - checkIndex(index); - _sheet.getCTWorksheet().removeConditionalFormatting(index); - } - - private void checkIndex(int index) { - int cnt = getNumConditionalFormattings(); - if (index < 0 || index >= cnt) { - throw new IllegalArgumentException("Specified CF index " + index - + " is outside the allowable range (0.." + (cnt - 1) + ")"); - } - } - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xssf.usermodel; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.usermodel.ComparisonOperator; +import org.apache.poi.ss.usermodel.ConditionalFormatting; +import org.apache.poi.ss.usermodel.ConditionalFormattingRule; +import org.apache.poi.ss.usermodel.ExtendedColor; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; +import org.apache.poi.ss.usermodel.SheetConditionalFormatting; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeUtil; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTConditionalFormatting; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfType; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STConditionalFormattingOperator; + +/** + * XSSF Conditional Formattings + */ +public class XSSFSheetConditionalFormatting implements SheetConditionalFormatting { + /** Office 2010 Conditional Formatting extensions namespace */ + protected static final String CF_EXT_2009_NS_X14 = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"; + + private final XSSFSheet _sheet; + + /* package */ XSSFSheetConditionalFormatting(XSSFSheet sheet) { + _sheet = sheet; + } + + /** + * A factory method allowing to create a conditional formatting rule + * with a cell comparison operator

+ * TODO - formulas containing cell references are currently not parsed properly + * + * @param comparisonOperation - a constant value from + * {@link org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator}:

+ *

    + *
  • BETWEEN
  • + *
  • NOT_BETWEEN
  • + *
  • EQUAL
  • + *
  • NOT_EQUAL
  • + *
  • GT
  • + *
  • LT
  • + *
  • GE
  • + *
  • LE
  • + *
+ *

+ * @param formula1 - formula for the valued, compared with the cell + * @param formula2 - second formula (only used with + * {@link org.apache.poi.ss.usermodel.ComparisonOperator#BETWEEN}) and + * {@link org.apache.poi.ss.usermodel.ComparisonOperator#NOT_BETWEEN} operations) + */ + public XSSFConditionalFormattingRule createConditionalFormattingRule( + byte comparisonOperation, + String formula1, + String formula2) { + + XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); + CTCfRule cfRule = rule.getCTCfRule(); + cfRule.addFormula(formula1); + if(formula2 != null) cfRule.addFormula(formula2); + cfRule.setType(STCfType.CELL_IS); + STConditionalFormattingOperator.Enum operator; + switch (comparisonOperation){ + case ComparisonOperator.BETWEEN: operator = STConditionalFormattingOperator.BETWEEN; break; + case ComparisonOperator.NOT_BETWEEN: operator = STConditionalFormattingOperator.NOT_BETWEEN; break; + case ComparisonOperator.LT: operator = STConditionalFormattingOperator.LESS_THAN; break; + case ComparisonOperator.LE: operator = STConditionalFormattingOperator.LESS_THAN_OR_EQUAL; break; + case ComparisonOperator.GT: operator = STConditionalFormattingOperator.GREATER_THAN; break; + case ComparisonOperator.GE: operator = STConditionalFormattingOperator.GREATER_THAN_OR_EQUAL; break; + case ComparisonOperator.EQUAL: operator = STConditionalFormattingOperator.EQUAL; break; + case ComparisonOperator.NOT_EQUAL: operator = STConditionalFormattingOperator.NOT_EQUAL; break; + default: throw new IllegalArgumentException("Unknown comparison operator: " + comparisonOperation); + } + cfRule.setOperator(operator); + + return rule; + } + + public XSSFConditionalFormattingRule createConditionalFormattingRule( + byte comparisonOperation, + String formula) { + + return createConditionalFormattingRule(comparisonOperation, formula, null); + } + + /** + * A factory method allowing to create a conditional formatting rule with a formula.
+ * + * @param formula - formula for the valued, compared with the cell + */ + public XSSFConditionalFormattingRule createConditionalFormattingRule(String formula) { + XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); + CTCfRule cfRule = rule.getCTCfRule(); + cfRule.addFormula(formula); + cfRule.setType(STCfType.EXPRESSION); + return rule; + } + + /** + * Create a Databar conditional formatting rule. + *

The thresholds and colour for it will be created, but will be + * empty and require configuring with + * {@link XSSFConditionalFormattingRule#getDataBarFormatting()} + * then + * {@link XSSFDataBarFormatting#getMinThreshold()} + * and + * {@link XSSFDataBarFormatting#getMaxThreshold()} + */ + public XSSFConditionalFormattingRule createConditionalFormattingRule(XSSFColor color) { + XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); + + // Have it setup, with suitable defaults + rule.createDataBarFormatting(color); + + // All done! + return rule; + } + public XSSFConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color) { + return createConditionalFormattingRule((XSSFColor)color); + } + + /** + * A factory method allowing the creation of conditional formatting + * rules using an Icon Set / Multi-State formatting. + * The thresholds for it will be created, but will be empty + * and require configuring with + * {@link XSSFConditionalFormattingRule#getMultiStateFormatting()} + * then + * {@link XSSFIconMultiStateFormatting#getThresholds()} + */ + public XSSFConditionalFormattingRule createConditionalFormattingRule(IconSet iconSet) { + XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); + + // Have it setup, with suitable defaults + rule.createMultiStateFormatting(iconSet); + + // All done! + return rule; + } + + /** + * Create a Color Scale / Color Gradient conditional formatting rule. + *

The thresholds and colours for it will be created, but will be + * empty and require configuring with + * {@link XSSFConditionalFormattingRule#getColorScaleFormatting()} + * then + * {@link XSSFColorScaleFormatting#getThresholds()} + * and + * {@link XSSFColorScaleFormatting#getColors()} + */ + public XSSFConditionalFormattingRule createConditionalFormattingColorScaleRule() { + XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); + + // Have it setup, with suitable defaults + rule.createColorScaleFormatting(); + + // All done! + return rule; + } + + public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) { + if (regions == null) { + throw new IllegalArgumentException("regions must not be null"); + } + for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL2007); + + if (cfRules == null) { + throw new IllegalArgumentException("cfRules must not be null"); + } + if (cfRules.length == 0) { + throw new IllegalArgumentException("cfRules must not be empty"); + } + if (cfRules.length > 3) { + throw new IllegalArgumentException("Number of rules must not exceed 3"); + } + + CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(regions); + CTConditionalFormatting cf = _sheet.getCTWorksheet().addNewConditionalFormatting(); + List refs = new ArrayList(); + for(CellRangeAddress a : mergeCellRanges) refs.add(a.formatAsString()); + cf.setSqref(refs); + + int priority = 1; + for(CTConditionalFormatting c : _sheet.getCTWorksheet().getConditionalFormattingArray()){ + priority += c.sizeOfCfRuleArray(); + } + + for(ConditionalFormattingRule rule : cfRules){ + XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule)rule; + xRule.getCTCfRule().setPriority(priority++); + cf.addNewCfRule().set(xRule.getCTCfRule()); + } + return _sheet.getCTWorksheet().sizeOfConditionalFormattingArray() - 1; + } + + public int addConditionalFormatting(CellRangeAddress[] regions, + ConditionalFormattingRule rule1) + { + return addConditionalFormatting(regions, + rule1 == null ? null : new XSSFConditionalFormattingRule[] { + (XSSFConditionalFormattingRule)rule1 + }); + } + + public int addConditionalFormatting(CellRangeAddress[] regions, + ConditionalFormattingRule rule1, ConditionalFormattingRule rule2) + { + return addConditionalFormatting(regions, + rule1 == null ? null : new XSSFConditionalFormattingRule[] { + (XSSFConditionalFormattingRule)rule1, + (XSSFConditionalFormattingRule)rule2 + }); + } + + /** + * Adds a copy of HSSFConditionalFormatting object to the sheet + *

This method could be used to copy HSSFConditionalFormatting object + * from one sheet to another. For example: + *

+     * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
+     * newSheet.addConditionalFormatting(cf);
+     * 
+ * + * @param cf HSSFConditionalFormatting object + * @return index of the new Conditional Formatting object + */ + public int addConditionalFormatting( ConditionalFormatting cf ) { + XSSFConditionalFormatting xcf = (XSSFConditionalFormatting)cf; + CTWorksheet sh = _sheet.getCTWorksheet(); + sh.addNewConditionalFormatting().set(xcf.getCTConditionalFormatting().copy()); + return sh.sizeOfConditionalFormattingArray() - 1; + } + + /** + * gets Conditional Formatting object at a particular index + * + * @param index + * of the Conditional Formatting object to fetch + * @return Conditional Formatting object + */ + public XSSFConditionalFormatting getConditionalFormattingAt(int index) { + checkIndex(index); + CTConditionalFormatting cf = _sheet.getCTWorksheet().getConditionalFormattingArray(index); + return new XSSFConditionalFormatting(_sheet, cf); + } + + /** + * @return number of Conditional Formatting objects of the sheet + */ + public int getNumConditionalFormattings() { + return _sheet.getCTWorksheet().sizeOfConditionalFormattingArray(); + } + + /** + * removes a Conditional Formatting object by index + * @param index of a Conditional Formatting object to remove + */ + public void removeConditionalFormatting(int index) { + checkIndex(index); + _sheet.getCTWorksheet().removeConditionalFormatting(index); + } + + private void checkIndex(int index) { + int cnt = getNumConditionalFormattings(); + if (index < 0 || index >= cnt) { + throw new IllegalArgumentException("Specified CF index " + index + + " is outside the allowable range (0.." + (cnt - 1) + ")"); + } + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/AbstractXSSFChartSeries.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/AbstractXSSFChartSeries.java index 09393e51a5..65bcfd774f 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/AbstractXSSFChartSeries.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/AbstractXSSFChartSeries.java @@ -1,79 +1,79 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xssf.usermodel.charts; - -import org.apache.poi.ss.usermodel.charts.ChartSeries; -import org.apache.poi.ss.usermodel.charts.TitleType; -import org.apache.poi.ss.util.CellReference; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx; - -/** - * Base of all XSSF Chart Series - */ -public abstract class AbstractXSSFChartSeries implements ChartSeries { - - private String titleValue; - private CellReference titleRef; - private TitleType titleType; - - public void setTitle(CellReference titleReference) { - titleType = TitleType.CELL_REFERENCE; - titleRef = titleReference; - } - - public void setTitle(String title) { - titleType = TitleType.STRING; - titleValue = title; - } - - public CellReference getTitleCellReference() { - if (TitleType.CELL_REFERENCE.equals(titleType)) { - return titleRef; - } - throw new IllegalStateException("Title type is not CellReference."); - } - - public String getTitleString() { - if (TitleType.STRING.equals(titleType)) { - return titleValue; - } - throw new IllegalStateException("Title type is not String."); - } - - public TitleType getTitleType() { - return titleType; - } - - protected boolean isTitleSet() { - return titleType != null; - } - - protected CTSerTx getCTSerTx() { - CTSerTx tx = CTSerTx.Factory.newInstance(); - switch (titleType) { - case CELL_REFERENCE: - tx.addNewStrRef().setF(titleRef.formatAsString()); - return tx; - case STRING: - tx.setV(titleValue); - return tx; - default: - throw new IllegalStateException("Unkown title type: " + titleType); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel.charts; + +import org.apache.poi.ss.usermodel.charts.ChartSeries; +import org.apache.poi.ss.usermodel.charts.TitleType; +import org.apache.poi.ss.util.CellReference; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx; + +/** + * Base of all XSSF Chart Series + */ +public abstract class AbstractXSSFChartSeries implements ChartSeries { + + private String titleValue; + private CellReference titleRef; + private TitleType titleType; + + public void setTitle(CellReference titleReference) { + titleType = TitleType.CELL_REFERENCE; + titleRef = titleReference; + } + + public void setTitle(String title) { + titleType = TitleType.STRING; + titleValue = title; + } + + public CellReference getTitleCellReference() { + if (TitleType.CELL_REFERENCE.equals(titleType)) { + return titleRef; + } + throw new IllegalStateException("Title type is not CellReference."); + } + + public String getTitleString() { + if (TitleType.STRING.equals(titleType)) { + return titleValue; + } + throw new IllegalStateException("Title type is not String."); + } + + public TitleType getTitleType() { + return titleType; + } + + protected boolean isTitleSet() { + return titleType != null; + } + + protected CTSerTx getCTSerTx() { + CTSerTx tx = CTSerTx.Factory.newInstance(); + switch (titleType) { + case CELL_REFERENCE: + tx.addNewStrRef().setF(titleRef.formatAsString()); + return tx; + case STRING: + tx.setV(titleValue); + return tx; + default: + throw new IllegalStateException("Unkown title type: " + titleType); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFLineChartData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFLineChartData.java index 54bba03bb2..64c72c250e 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFLineChartData.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFLineChartData.java @@ -1,126 +1,126 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ==================================================================== */ - -package org.apache.poi.xssf.usermodel.charts; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.poi.ss.usermodel.Chart; -import org.apache.poi.ss.usermodel.charts.ChartAxis; -import org.apache.poi.ss.usermodel.charts.ChartDataSource; -import org.apache.poi.ss.usermodel.charts.LineChartData; -import org.apache.poi.ss.usermodel.charts.LineChartSeries; -import org.apache.poi.util.Beta; -import org.apache.poi.xssf.usermodel.XSSFChart; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea; -import org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle; - -/** - * Holds data for a XSSF Line Chart - */ -@Beta -public class XSSFLineChartData implements LineChartData { - - /** - * List of all data series. - */ - private List series; - - public XSSFLineChartData() { - series = new ArrayList(); - } - - static class Series extends AbstractXSSFChartSeries implements LineChartSeries { - private int id; - private int order; - private ChartDataSource categories; - private ChartDataSource values; - - protected Series(int id, int order, - ChartDataSource categories, - ChartDataSource values) { - this.id = id; - this.order = order; - this.categories = categories; - this.values = values; - } - - public ChartDataSource getCategoryAxisData() { - return categories; - } - - public ChartDataSource getValues() { - return values; - } - - protected void addToChart(CTLineChart ctLineChart) { - CTLineSer ctLineSer = ctLineChart.addNewSer(); - ctLineSer.addNewIdx().setVal(id); - ctLineSer.addNewOrder().setVal(order); - - // No marker symbol on the chart line. - ctLineSer.addNewMarker().addNewSymbol().setVal(STMarkerStyle.NONE); - - CTAxDataSource catDS = ctLineSer.addNewCat(); - XSSFChartUtil.buildAxDataSource(catDS, categories); - CTNumDataSource valueDS = ctLineSer.addNewVal(); - XSSFChartUtil.buildNumDataSource(valueDS, values); - - if (isTitleSet()) { - ctLineSer.setTx(getCTSerTx()); - } - } - } - - public LineChartSeries addSeries(ChartDataSource categoryAxisData, ChartDataSource values) { - if (!values.isNumeric()) { - throw new IllegalArgumentException("Value data source must be numeric."); - } - int numOfSeries = series.size(); - Series newSeries = new Series(numOfSeries, numOfSeries, categoryAxisData, values); - series.add(newSeries); - return newSeries; - } - - public List getSeries() { - return series; - } - - public void fillChart(Chart chart, ChartAxis... axis) { - if (!(chart instanceof XSSFChart)) { - throw new IllegalArgumentException("Chart must be instance of XSSFChart"); - } - - XSSFChart xssfChart = (XSSFChart) chart; - CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea(); - CTLineChart lineChart = plotArea.addNewLineChart(); - lineChart.addNewVaryColors().setVal(false); - - for (Series s : series) { - s.addToChart(lineChart); - } - - for (ChartAxis ax : axis) { - lineChart.addNewAxId().setVal(ax.getId()); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==================================================================== */ + +package org.apache.poi.xssf.usermodel.charts; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.usermodel.Chart; +import org.apache.poi.ss.usermodel.charts.ChartAxis; +import org.apache.poi.ss.usermodel.charts.ChartDataSource; +import org.apache.poi.ss.usermodel.charts.LineChartData; +import org.apache.poi.ss.usermodel.charts.LineChartSeries; +import org.apache.poi.util.Beta; +import org.apache.poi.xssf.usermodel.XSSFChart; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea; +import org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle; + +/** + * Holds data for a XSSF Line Chart + */ +@Beta +public class XSSFLineChartData implements LineChartData { + + /** + * List of all data series. + */ + private List series; + + public XSSFLineChartData() { + series = new ArrayList(); + } + + static class Series extends AbstractXSSFChartSeries implements LineChartSeries { + private int id; + private int order; + private ChartDataSource categories; + private ChartDataSource values; + + protected Series(int id, int order, + ChartDataSource categories, + ChartDataSource values) { + this.id = id; + this.order = order; + this.categories = categories; + this.values = values; + } + + public ChartDataSource getCategoryAxisData() { + return categories; + } + + public ChartDataSource getValues() { + return values; + } + + protected void addToChart(CTLineChart ctLineChart) { + CTLineSer ctLineSer = ctLineChart.addNewSer(); + ctLineSer.addNewIdx().setVal(id); + ctLineSer.addNewOrder().setVal(order); + + // No marker symbol on the chart line. + ctLineSer.addNewMarker().addNewSymbol().setVal(STMarkerStyle.NONE); + + CTAxDataSource catDS = ctLineSer.addNewCat(); + XSSFChartUtil.buildAxDataSource(catDS, categories); + CTNumDataSource valueDS = ctLineSer.addNewVal(); + XSSFChartUtil.buildNumDataSource(valueDS, values); + + if (isTitleSet()) { + ctLineSer.setTx(getCTSerTx()); + } + } + } + + public LineChartSeries addSeries(ChartDataSource categoryAxisData, ChartDataSource values) { + if (!values.isNumeric()) { + throw new IllegalArgumentException("Value data source must be numeric."); + } + int numOfSeries = series.size(); + Series newSeries = new Series(numOfSeries, numOfSeries, categoryAxisData, values); + series.add(newSeries); + return newSeries; + } + + public List getSeries() { + return series; + } + + public void fillChart(Chart chart, ChartAxis... axis) { + if (!(chart instanceof XSSFChart)) { + throw new IllegalArgumentException("Chart must be instance of XSSFChart"); + } + + XSSFChart xssfChart = (XSSFChart) chart; + CTPlotArea plotArea = xssfChart.getCTChart().getPlotArea(); + CTLineChart lineChart = plotArea.addNewLineChart(); + lineChart.addNewVaryColors().setVal(false); + + for (Series s : series) { + s.addToChart(lineChart); + } + + for (ChartAxis ax : axis) { + lineChart.addNewAxId().setVal(ax.getId()); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java index b71d0c9c1a..76eaa45f9d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/charts/XSSFManualLayout.java @@ -1,247 +1,247 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ==================================================================== */ - -package org.apache.poi.xssf.usermodel.charts; - -import org.apache.poi.util.Beta; -import org.apache.poi.util.Internal; -import org.apache.poi.ss.usermodel.charts.ManualLayout; -import org.apache.poi.ss.usermodel.charts.LayoutMode; -import org.apache.poi.ss.usermodel.charts.LayoutTarget; -import org.apache.poi.xssf.usermodel.XSSFChart; -import org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutTarget; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTLayout; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTManualLayout; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTLayoutMode; -import org.openxmlformats.schemas.drawingml.x2006.chart.CTLayoutTarget; -import org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutMode; - -/** - * Represents a SpreadsheetML manual layout. - * @author Roman Kashitsyn - */ -@Beta -public final class XSSFManualLayout implements ManualLayout { - - /** - * Underlaying CTManualLayout bean. - */ - private CTManualLayout layout; - - private static final LayoutMode defaultLayoutMode = LayoutMode.EDGE; - private static final LayoutTarget defaultLayoutTarget = LayoutTarget.INNER; - - /** - * Create a new SpreadsheetML manual layout. - * @param ctLayout a Spreadsheet ML layout that should be used as base. - */ - public XSSFManualLayout(CTLayout ctLayout) { - initLayout(ctLayout); - } - - /** - * Create a new SpreadsheetML manual layout for chart. - * @param chart a chart to create layout for. - */ - public XSSFManualLayout(XSSFChart chart) { - CTPlotArea ctPlotArea = chart.getCTChart().getPlotArea(); - CTLayout ctLayout = ctPlotArea.isSetLayout() ? - ctPlotArea.getLayout() : ctPlotArea.addNewLayout(); - - initLayout(ctLayout); - } - - /** - * Return the underlying CTManualLayout bean. - * - * @return the underlying CTManualLayout bean. - */ - @Internal public CTManualLayout getCTManualLayout(){ - return layout; - } - - public void setWidthRatio(double ratio) { - if (!layout.isSetW()) { - layout.addNewW(); - } - layout.getW().setVal(ratio); - } - - public double getWidthRatio() { - if (!layout.isSetW()) { - return 0.0; - } - return layout.getW().getVal(); - } - - public void setHeightRatio(double ratio) { - if (!layout.isSetH()) { - layout.addNewH(); - } - layout.getH().setVal(ratio); - } - - public double getHeightRatio() { - if (!layout.isSetH()) { - return 0.0; - } - return layout.getH().getVal(); - } - - public LayoutTarget getTarget() { - if (!layout.isSetLayoutTarget()) { - return defaultLayoutTarget; - } - return toLayoutTarget(layout.getLayoutTarget()); - } - - public void setTarget(LayoutTarget target) { - if (!layout.isSetLayoutTarget()) { - layout.addNewLayoutTarget(); - } - layout.getLayoutTarget().setVal(fromLayoutTarget(target)); - } - - public LayoutMode getXMode() { - if (!layout.isSetXMode()) { - return defaultLayoutMode; - } - return toLayoutMode(layout.getXMode()); - } - - public void setXMode(LayoutMode mode) { - if (!layout.isSetXMode()) { - layout.addNewXMode(); - } - layout.getXMode().setVal(fromLayoutMode(mode)); - } - - public LayoutMode getYMode() { - if (!layout.isSetYMode()) { - return defaultLayoutMode; - } - return toLayoutMode(layout.getYMode()); - } - - public void setYMode(LayoutMode mode) { - if (!layout.isSetYMode()) { - layout.addNewYMode(); - } - layout.getYMode().setVal(fromLayoutMode(mode)); - } - - public double getX() { - if (!layout.isSetX()) { - return 0.0; - } - return layout.getX().getVal(); - } - - public void setX(double x) { - if (!layout.isSetX()) { - layout.addNewX(); - } - layout.getX().setVal(x); - } - - public double getY() { - if (!layout.isSetY()) { - return 0.0; - } - return layout.getY().getVal(); - } - - public void setY(double y) { - if (!layout.isSetY()) { - layout.addNewY(); - } - layout.getY().setVal(y); - } - - public LayoutMode getWidthMode() { - if (!layout.isSetWMode()) { - return defaultLayoutMode; - } - return toLayoutMode(layout.getWMode()); - } - - public void setWidthMode(LayoutMode mode) { - if (!layout.isSetWMode()) { - layout.addNewWMode(); - } - layout.getWMode().setVal(fromLayoutMode(mode)); - } - - public LayoutMode getHeightMode() { - if (!layout.isSetHMode()) { - return defaultLayoutMode; - } - return toLayoutMode(layout.getHMode()); - } - - public void setHeightMode(LayoutMode mode) { - if (!layout.isSetHMode()) { - layout.addNewHMode(); - } - layout.getHMode().setVal(fromLayoutMode(mode)); - } - - private void initLayout(CTLayout ctLayout) { - if (ctLayout.isSetManualLayout()) { - this.layout = ctLayout.getManualLayout(); - } else { - this.layout = ctLayout.addNewManualLayout(); - } - } - - private STLayoutMode.Enum fromLayoutMode(LayoutMode mode) { - switch (mode) { - case EDGE: return STLayoutMode.EDGE; - case FACTOR: return STLayoutMode.FACTOR; - default: - throw new IllegalArgumentException(); - } - } - - private LayoutMode toLayoutMode(CTLayoutMode ctLayoutMode) { - switch (ctLayoutMode.getVal().intValue()) { - case STLayoutMode.INT_EDGE: return LayoutMode.EDGE; - case STLayoutMode.INT_FACTOR: return LayoutMode.FACTOR; - default: - throw new IllegalArgumentException(); - } - } - - private STLayoutTarget.Enum fromLayoutTarget(LayoutTarget target) { - switch (target) { - case INNER: return STLayoutTarget.INNER; - case OUTER: return STLayoutTarget.OUTER; - default: - throw new IllegalArgumentException(); - } - } - - private LayoutTarget toLayoutTarget(CTLayoutTarget ctLayoutTarget) { - switch (ctLayoutTarget.getVal().intValue()) { - case STLayoutTarget.INT_INNER: return LayoutTarget.INNER; - case STLayoutTarget.INT_OUTER: return LayoutTarget.OUTER; - default: - throw new IllegalArgumentException(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==================================================================== */ + +package org.apache.poi.xssf.usermodel.charts; + +import org.apache.poi.util.Beta; +import org.apache.poi.util.Internal; +import org.apache.poi.ss.usermodel.charts.ManualLayout; +import org.apache.poi.ss.usermodel.charts.LayoutMode; +import org.apache.poi.ss.usermodel.charts.LayoutTarget; +import org.apache.poi.xssf.usermodel.XSSFChart; +import org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutTarget; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTLayout; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTManualLayout; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTLayoutMode; +import org.openxmlformats.schemas.drawingml.x2006.chart.CTLayoutTarget; +import org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutMode; + +/** + * Represents a SpreadsheetML manual layout. + * @author Roman Kashitsyn + */ +@Beta +public final class XSSFManualLayout implements ManualLayout { + + /** + * Underlaying CTManualLayout bean. + */ + private CTManualLayout layout; + + private static final LayoutMode defaultLayoutMode = LayoutMode.EDGE; + private static final LayoutTarget defaultLayoutTarget = LayoutTarget.INNER; + + /** + * Create a new SpreadsheetML manual layout. + * @param ctLayout a Spreadsheet ML layout that should be used as base. + */ + public XSSFManualLayout(CTLayout ctLayout) { + initLayout(ctLayout); + } + + /** + * Create a new SpreadsheetML manual layout for chart. + * @param chart a chart to create layout for. + */ + public XSSFManualLayout(XSSFChart chart) { + CTPlotArea ctPlotArea = chart.getCTChart().getPlotArea(); + CTLayout ctLayout = ctPlotArea.isSetLayout() ? + ctPlotArea.getLayout() : ctPlotArea.addNewLayout(); + + initLayout(ctLayout); + } + + /** + * Return the underlying CTManualLayout bean. + * + * @return the underlying CTManualLayout bean. + */ + @Internal public CTManualLayout getCTManualLayout(){ + return layout; + } + + public void setWidthRatio(double ratio) { + if (!layout.isSetW()) { + layout.addNewW(); + } + layout.getW().setVal(ratio); + } + + public double getWidthRatio() { + if (!layout.isSetW()) { + return 0.0; + } + return layout.getW().getVal(); + } + + public void setHeightRatio(double ratio) { + if (!layout.isSetH()) { + layout.addNewH(); + } + layout.getH().setVal(ratio); + } + + public double getHeightRatio() { + if (!layout.isSetH()) { + return 0.0; + } + return layout.getH().getVal(); + } + + public LayoutTarget getTarget() { + if (!layout.isSetLayoutTarget()) { + return defaultLayoutTarget; + } + return toLayoutTarget(layout.getLayoutTarget()); + } + + public void setTarget(LayoutTarget target) { + if (!layout.isSetLayoutTarget()) { + layout.addNewLayoutTarget(); + } + layout.getLayoutTarget().setVal(fromLayoutTarget(target)); + } + + public LayoutMode getXMode() { + if (!layout.isSetXMode()) { + return defaultLayoutMode; + } + return toLayoutMode(layout.getXMode()); + } + + public void setXMode(LayoutMode mode) { + if (!layout.isSetXMode()) { + layout.addNewXMode(); + } + layout.getXMode().setVal(fromLayoutMode(mode)); + } + + public LayoutMode getYMode() { + if (!layout.isSetYMode()) { + return defaultLayoutMode; + } + return toLayoutMode(layout.getYMode()); + } + + public void setYMode(LayoutMode mode) { + if (!layout.isSetYMode()) { + layout.addNewYMode(); + } + layout.getYMode().setVal(fromLayoutMode(mode)); + } + + public double getX() { + if (!layout.isSetX()) { + return 0.0; + } + return layout.getX().getVal(); + } + + public void setX(double x) { + if (!layout.isSetX()) { + layout.addNewX(); + } + layout.getX().setVal(x); + } + + public double getY() { + if (!layout.isSetY()) { + return 0.0; + } + return layout.getY().getVal(); + } + + public void setY(double y) { + if (!layout.isSetY()) { + layout.addNewY(); + } + layout.getY().setVal(y); + } + + public LayoutMode getWidthMode() { + if (!layout.isSetWMode()) { + return defaultLayoutMode; + } + return toLayoutMode(layout.getWMode()); + } + + public void setWidthMode(LayoutMode mode) { + if (!layout.isSetWMode()) { + layout.addNewWMode(); + } + layout.getWMode().setVal(fromLayoutMode(mode)); + } + + public LayoutMode getHeightMode() { + if (!layout.isSetHMode()) { + return defaultLayoutMode; + } + return toLayoutMode(layout.getHMode()); + } + + public void setHeightMode(LayoutMode mode) { + if (!layout.isSetHMode()) { + layout.addNewHMode(); + } + layout.getHMode().setVal(fromLayoutMode(mode)); + } + + private void initLayout(CTLayout ctLayout) { + if (ctLayout.isSetManualLayout()) { + this.layout = ctLayout.getManualLayout(); + } else { + this.layout = ctLayout.addNewManualLayout(); + } + } + + private STLayoutMode.Enum fromLayoutMode(LayoutMode mode) { + switch (mode) { + case EDGE: return STLayoutMode.EDGE; + case FACTOR: return STLayoutMode.FACTOR; + default: + throw new IllegalArgumentException(); + } + } + + private LayoutMode toLayoutMode(CTLayoutMode ctLayoutMode) { + switch (ctLayoutMode.getVal().intValue()) { + case STLayoutMode.INT_EDGE: return LayoutMode.EDGE; + case STLayoutMode.INT_FACTOR: return LayoutMode.FACTOR; + default: + throw new IllegalArgumentException(); + } + } + + private STLayoutTarget.Enum fromLayoutTarget(LayoutTarget target) { + switch (target) { + case INNER: return STLayoutTarget.INNER; + case OUTER: return STLayoutTarget.OUTER; + default: + throw new IllegalArgumentException(); + } + } + + private LayoutTarget toLayoutTarget(CTLayoutTarget ctLayoutTarget) { + switch (ctLayoutTarget.getVal().intValue()) { + case STLayoutTarget.INT_INNER: return LayoutTarget.INNER; + case STLayoutTarget.INT_OUTER: return LayoutTarget.OUTER; + default: + throw new IllegalArgumentException(); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java index 4db163de2d..cb9bc35dda 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java @@ -1,107 +1,107 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -import org.apache.poi.POIXMLDocumentPart; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtPr; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString; - -/** - * Experimental abstract class that is a base for XWPFSDT and XWPFSDTCell - *

- * WARNING - APIs expected to change rapidly. - *

- * These classes have so far been built only for read-only processing. - */ -public abstract class AbstractXWPFSDT implements ISDTContents { - private final String title; - private final String tag; - private final IBody part; - - public AbstractXWPFSDT(CTSdtPr pr, IBody part) { - if (pr == null) { - title = ""; - tag = ""; - } else { - CTString[] aliases = pr.getAliasArray(); - if (aliases != null && aliases.length > 0) { - title = aliases[0].getVal(); - } else { - title = ""; - } - CTString[] tags = pr.getTagArray(); - if (tags != null && tags.length > 0) { - tag = tags[0].getVal(); - } else { - tag = ""; - } - } - this.part = part; - - } - - /** - * @return first SDT Title - */ - public String getTitle() { - return title; - } - - /** - * @return first SDT Tag - */ - public String getTag() { - return tag; - } - - /** - * @return the content object - */ - public abstract ISDTContent getContent(); - - /** - * @return null - */ - public IBody getBody() { - return null; - } - - /** - * @return document part - */ - public POIXMLDocumentPart getPart() { - return part.getPart(); - } - - /** - * @return partType - */ - public BodyType getPartType() { - return BodyType.CONTENTCONTROL; - } - - /** - * @return element type - */ - public BodyElementType getElementType() { - return BodyElementType.CONTENTCONTROL; - } - - public XWPFDocument getDocument() { - return part.getXWPFDocument(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xwpf.usermodel; + +import org.apache.poi.POIXMLDocumentPart; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString; + +/** + * Experimental abstract class that is a base for XWPFSDT and XWPFSDTCell + *

+ * WARNING - APIs expected to change rapidly. + *

+ * These classes have so far been built only for read-only processing. + */ +public abstract class AbstractXWPFSDT implements ISDTContents { + private final String title; + private final String tag; + private final IBody part; + + public AbstractXWPFSDT(CTSdtPr pr, IBody part) { + if (pr == null) { + title = ""; + tag = ""; + } else { + CTString[] aliases = pr.getAliasArray(); + if (aliases != null && aliases.length > 0) { + title = aliases[0].getVal(); + } else { + title = ""; + } + CTString[] tags = pr.getTagArray(); + if (tags != null && tags.length > 0) { + tag = tags[0].getVal(); + } else { + tag = ""; + } + } + this.part = part; + + } + + /** + * @return first SDT Title + */ + public String getTitle() { + return title; + } + + /** + * @return first SDT Tag + */ + public String getTag() { + return tag; + } + + /** + * @return the content object + */ + public abstract ISDTContent getContent(); + + /** + * @return null + */ + public IBody getBody() { + return null; + } + + /** + * @return document part + */ + public POIXMLDocumentPart getPart() { + return part.getPart(); + } + + /** + * @return partType + */ + public BodyType getPartType() { + return BodyType.CONTENTCONTROL; + } + + /** + * @return element type + */ + public BodyElementType getElementType() { + return BodyElementType.CONTENTCONTROL; + } + + public XWPFDocument getDocument() { + return part.getXWPFDocument(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java index 5a1df0e218..d93ba9d0b6 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java @@ -21,14 +21,14 @@ package org.apache.poi.xwpf.usermodel; *

* 9 Jan 2010 *

- *

- * // TODO insert Javadoc here! - *

- * - * @author epp - */ -public enum BodyElementType { - CONTENTCONTROL, - PARAGRAPH, - TABLE, -} + *

+ * // TODO insert Javadoc here! + *

+ * + * @author epp + */ +public enum BodyElementType { + CONTENTCONTROL, + PARAGRAPH, + TABLE, +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java index b7937e5282..69e039120e 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java @@ -29,15 +29,15 @@ import java.util.Map; * *
  • Art borders: which specify a repeated image to be used * when drawing a border around the specified object. Line borders may be - * specified on any object which allows a border, however, art borders may only - * be used as a border at the page level - the borders under the pgBorders - * element - *
  • - * - * - * @author Gisella Bronzetti - */ -public enum Borders { + * specified on any object which allows a border, however, art borders may only + * be used as a border at the page level - the borders under the pgBorders + * element + * + * + * + * @author Gisella Bronzetti + */ +public enum Borders { NIL(1), @@ -597,32 +597,32 @@ public enum Borders { ZANY_TRIANGLES(189), ZIG_ZAG(190), - - ZIG_ZAG_STITCH(191); - - private static Map imap = new HashMap(); - - static { - for (Borders p : values()) { - imap.put(Integer.valueOf(p.getValue()), p); - } - } - - private final int value; - - private Borders(int val) { - value = val; - } - - public static Borders valueOf(int type) { - Borders pBorder = imap.get(Integer.valueOf(type)); - if (pBorder == null) { - throw new IllegalArgumentException("Unknown paragraph border: " + type); - } - return pBorder; - } - - public int getValue() { - return value; - } -} + + ZIG_ZAG_STITCH(191); + + private static Map imap = new HashMap(); + + static { + for (Borders p : values()) { + imap.put(Integer.valueOf(p.getValue()), p); + } + } + + private final int value; + + private Borders(int val) { + value = val; + } + + public static Borders valueOf(int type) { + Borders pBorder = imap.get(Integer.valueOf(type)); + if (pBorder == null) { + throw new IllegalArgumentException("Unknown paragraph border: " + type); + } + return pBorder; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java index e44bb3b0f4..0f44f21f75 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java @@ -20,23 +20,23 @@ import java.util.HashMap; import java.util.Map; /** - * Specifies the set of possible restart locations which may be used as to - * determine the next available line when a break's type attribute has a value - * of textWrapping. - * - * @author Gisella Bronzetti - */ -public enum BreakClear { + * Specifies the set of possible restart locations which may be used as to + * determine the next available line when a break's type attribute has a value + * of textWrapping. + * + * @author Gisella Bronzetti + */ +public enum BreakClear { /** * Specifies that the text wrapping break shall advance the text to the next - * line in the WordprocessingML document, regardless of its position left to - * right or the presence of any floating objects which intersect with the - * line, - *

    - * This is the setting for a typical line break in a document. - */ - + * line in the WordprocessingML document, regardless of its position left to + * right or the presence of any floating objects which intersect with the + * line, + *

    + * This is the setting for a typical line break in a document. + */ + NONE(1), /** @@ -80,32 +80,32 @@ public enum BreakClear { * Specifies that the text wrapping break shall advance the text to the next * line in the WordprocessingML document which spans the full width of the * line. - */ - ALL(4); - - private static Map imap = new HashMap(); - - static { - for (BreakClear p : values()) { - imap.put(p.getValue(), p); - } - } - - private final int value; - - private BreakClear(int val) { - value = val; - } - - public static BreakClear valueOf(int type) { - BreakClear bType = imap.get(type); - if (bType == null) - throw new IllegalArgumentException("Unknown break clear type: " - + type); - return bType; - } - - public int getValue() { - return value; - } -} + */ + ALL(4); + + private static Map imap = new HashMap(); + + static { + for (BreakClear p : values()) { + imap.put(p.getValue(), p); + } + } + + private final int value; + + private BreakClear(int val) { + value = val; + } + + public static BreakClear valueOf(int type) { + BreakClear bType = imap.get(type); + if (bType == null) + throw new IllegalArgumentException("Unknown break clear type: " + + type); + return bType; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java index 30fc939cb0..3a6054b011 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java @@ -21,18 +21,18 @@ import java.util.Map; /** * Specifies the possible types of break characters in a WordprocessingML - * document. - * The break type determines the next location where text shall be - * placed after this manual break is applied to the text contents - * - * @author Gisella Bronzetti - */ -public enum BreakType { - - - /** - * Specifies that the current break shall restart itself on the next page of - * the document when the document is displayed in page view. + * document. + * The break type determines the next location where text shall be + * placed after this manual break is applied to the text contents + * + * @author Gisella Bronzetti + */ +public enum BreakType { + + + /** + * Specifies that the current break shall restart itself on the next page of + * the document when the document is displayed in page view. */ PAGE(1), @@ -53,32 +53,32 @@ public enum BreakType { * the document when the document is displayed in page view. * The determine of the next line shall be done subject to the value of the clear * attribute on the specified break character. - */ - TEXT_WRAPPING(3); - - private static Map imap = new HashMap(); - - static { - for (BreakType p : values()) { - imap.put(p.getValue(), p); - } - } - - private final int value; - - private BreakType(int val) { - value = val; - } - - public static BreakType valueOf(int type) { - BreakType bType = imap.get(type); - if (bType == null) - throw new IllegalArgumentException("Unknown break type: " - + type); - return bType; - } - - public int getValue() { - return value; - } -} + */ + TEXT_WRAPPING(3); + + private static Map imap = new HashMap(); + + static { + for (BreakType p : values()) { + imap.put(p.getValue(), p); + } + } + + private final int value; + + private BreakType(int val) { + value = val; + } + + public static BreakType valueOf(int type) { + BreakType bType = imap.get(type); + if (bType == null) + throw new IllegalArgumentException("Unknown break type: " + + type); + return bType; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java index 077697a167..0bd4175f9b 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java @@ -14,45 +14,45 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -public interface Document { - /** - * Extended windows meta file - */ - public static final int PICTURE_TYPE_EMF = 2; - - /** - * Windows Meta File - */ - public static final int PICTURE_TYPE_WMF = 3; - - /** - * Mac PICT format - */ - public static final int PICTURE_TYPE_PICT = 4; - - /** - * JPEG format - */ - public static final int PICTURE_TYPE_JPEG = 5; - - /** - * PNG format - */ - public static final int PICTURE_TYPE_PNG = 6; - - /** - * Device independent bitmap - */ - public static final int PICTURE_TYPE_DIB = 7; - - /** - * GIF image format - */ - public static final int PICTURE_TYPE_GIF = 8; - - /** +package org.apache.poi.xwpf.usermodel; + +public interface Document { + /** + * Extended windows meta file + */ + public static final int PICTURE_TYPE_EMF = 2; + + /** + * Windows Meta File + */ + public static final int PICTURE_TYPE_WMF = 3; + + /** + * Mac PICT format + */ + public static final int PICTURE_TYPE_PICT = 4; + + /** + * JPEG format + */ + public static final int PICTURE_TYPE_JPEG = 5; + + /** + * PNG format + */ + public static final int PICTURE_TYPE_PNG = 6; + + /** + * Device independent bitmap + */ + public static final int PICTURE_TYPE_DIB = 7; + + /** + * GIF image format + */ + public static final int PICTURE_TYPE_GIF = 8; + + /** * Tag Image File (.tiff) */ public static final int PICTURE_TYPE_TIFF = 9; diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java index 6e9ce05e4d..e7196d9a87 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java @@ -27,68 +27,68 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; /** *

    An IBody represents the different parts of the document which - * can contain collections of Paragraphs and Tables. It provides a - * common way to work with these and their contents.

    - *

    Typically, this is something like a XWPFDocument, or one of - * the parts in it like XWPFHeader, XWPFFooter, XWPFTableCell - *

    - */ -public interface IBody { + * can contain collections of Paragraphs and Tables. It provides a + * common way to work with these and their contents.

    + *

    Typically, this is something like a XWPFDocument, or one of + * the parts in it like XWPFHeader, XWPFFooter, XWPFTableCell + *

    + */ +public interface IBody { /** - * returns the Part, to which the body belongs, which you need for adding relationship to other parts - * Actually it is needed of the class XWPFTableCell. Because you have to know to which part the tableCell - * belongs. - * - * @return the Part, to which the body belongs - */ - public POIXMLDocumentPart getPart(); - - /** - * get the PartType of the body, for example - * DOCUMENT, HEADER, FOOTER, FOOTNOTE, - * - * @return the PartType of the body - */ - public BodyType getPartType(); - - /** - * Returns an Iterator with paragraphs and tables, - * in the order that they occur in the text. - */ - public List getBodyElements(); - - /** - * Returns the paragraph(s) that holds - * the text of the header or footer. - */ - public List getParagraphs(); - - /** - * Return the table(s) that holds the text - * of the IBodyPart, for complex cases - * where a paragraph isn't used. - */ - public List getTables(); - - /** - * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer - * the method will return this paragraph - * if there is no corresponding {@link XWPFParagraph} the method will return null - * - * @param p is instance of CTP and is searching for an XWPFParagraph - * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer - * XWPFParagraph with the correspondig CTP p - */ - public XWPFParagraph getParagraph(CTP p); - - /** - * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header - * the method will return this table - * if there is no corresponding {@link XWPFTable} the method will return null - * - * @param ctTable - */ - public XWPFTable getTable(CTTbl ctTable); + * returns the Part, to which the body belongs, which you need for adding relationship to other parts + * Actually it is needed of the class XWPFTableCell. Because you have to know to which part the tableCell + * belongs. + * + * @return the Part, to which the body belongs + */ + public POIXMLDocumentPart getPart(); + + /** + * get the PartType of the body, for example + * DOCUMENT, HEADER, FOOTER, FOOTNOTE, + * + * @return the PartType of the body + */ + public BodyType getPartType(); + + /** + * Returns an Iterator with paragraphs and tables, + * in the order that they occur in the text. + */ + public List getBodyElements(); + + /** + * Returns the paragraph(s) that holds + * the text of the header or footer. + */ + public List getParagraphs(); + + /** + * Return the table(s) that holds the text + * of the IBodyPart, for complex cases + * where a paragraph isn't used. + */ + public List getTables(); + + /** + * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer + * the method will return this paragraph + * if there is no corresponding {@link XWPFParagraph} the method will return null + * + * @param p is instance of CTP and is searching for an XWPFParagraph + * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer + * XWPFParagraph with the correspondig CTP p + */ + public XWPFParagraph getParagraph(CTP p); + + /** + * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header + * the method will return this table + * if there is no corresponding {@link XWPFTable} the method will return null + * + * @param ctTable + */ + public XWPFTable getTable(CTTbl ctTable); /** * Returns the paragraph that of position pos @@ -98,36 +98,36 @@ public interface IBody { /** * Returns the table at position pos */ - public XWPFTable getTableArray(int pos); - - /** - * inserts a new paragraph at position of the cursor - * - * @param cursor - */ - public XWPFParagraph insertNewParagraph(XmlCursor cursor); - - /** - * inserts a new Table at the cursor position. - * - * @param cursor - */ - public XWPFTable insertNewTbl(XmlCursor cursor); - - /** - * inserts a new Table at position pos - * - * @param pos - * @param table - */ + public XWPFTable getTableArray(int pos); + + /** + * inserts a new paragraph at position of the cursor + * + * @param cursor + */ + public XWPFParagraph insertNewParagraph(XmlCursor cursor); + + /** + * inserts a new Table at the cursor position. + * + * @param cursor + */ + public XWPFTable insertNewTbl(XmlCursor cursor); + + /** + * inserts a new Table at position pos + * + * @param pos + * @param table + */ void insertTable(int pos, XWPFTable table); - - /** - * returns the TableCell to which the Table belongs - * - * @param cell - */ - public XWPFTableCell getTableCell(CTTc cell); + + /** + * returns the TableCell to which the Table belongs + * + * @param cell + */ + public XWPFTableCell getTableCell(CTTc cell); /** * Return XWPFDocument diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java index 312ea493fc..11020f4443 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java @@ -18,18 +18,18 @@ package org.apache.poi.xwpf.usermodel; import org.apache.poi.POIXMLDocumentPart; - -/** - * 9 Jan 2010 - * - * @author Philipp Epp - */ -public interface IBodyElement { - IBody getBody(); - - POIXMLDocumentPart getPart(); - - BodyType getPartType(); - - BodyElementType getElementType(); -} + +/** + * 9 Jan 2010 + * + * @author Philipp Epp + */ +public interface IBodyElement { + IBody getBody(); + + POIXMLDocumentPart getPart(); + + BodyType getPartType(); + + BodyElementType getElementType(); +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java index 0ac12c7937..d5a76429dc 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java @@ -15,13 +15,13 @@ limitations under the License. ==================================================================== */ package org.apache.poi.xwpf.usermodel; - -/** - * Interface for anything that can be at a table cell level: - * {@link XWPFTableCell}, {@link XWPFSDTCell} - *

    - * Schematically something like this: - * <tr><tc/><tc/><sdt><tc/></sdt></tr> - */ -public interface ICell { -} + +/** + * Interface for anything that can be at a table cell level: + * {@link XWPFTableCell}, {@link XWPFSDTCell} + *

    + * Schematically something like this: + * <tr><tc/><tc/><sdt><tc/></sdt></tr> + */ +public interface ICell { +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java index 5493ff3bdb..dad119e003 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java @@ -15,20 +15,20 @@ limitations under the License. ==================================================================== */ package org.apache.poi.xwpf.usermodel; - - -/** - * Experimental interface to offer rudimentary read-only processing of - * of the contentblock of an SDT/ContentControl. - *

    - *

    - *

    - * WARNING - APIs expected to change rapidly - */ -public interface ISDTContent { - - public String getText(); - - public String toString(); - -} + + +/** + * Experimental interface to offer rudimentary read-only processing of + * of the contentblock of an SDT/ContentControl. + *

    + *

    + *

    + * WARNING - APIs expected to change rapidly + */ +public interface ISDTContent { + + public String getText(); + + public String toString(); + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java index b52d2c34f9..10a34418f1 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java @@ -19,13 +19,13 @@ package org.apache.poi.xwpf.usermodel; import java.util.HashMap; import java.util.Map; -/** - * Specifies the logic which shall be used to calculate the line spacing of the - * parent object when it is displayed in the document. - * - * @author Gisella Bronzetti - */ -public enum LineSpacingRule { +/** + * Specifies the logic which shall be used to calculate the line spacing of the + * parent object when it is displayed in the document. + * + * @author Gisella Bronzetti + */ +public enum LineSpacingRule { /** * Specifies that the line spacing of the parent object shall be @@ -45,32 +45,32 @@ public enum LineSpacingRule { /** * Specifies that the height of the line shall be at least the value * specified, but may be expanded to fit its content as needed. - */ - AT_LEAST(3); - - - private static Map imap = new HashMap(); - - static { - for (LineSpacingRule p : values()) { - imap.put(p.getValue(), p); - } - } - - private final int value; - - private LineSpacingRule(int val) { - value = val; - } - - public static LineSpacingRule valueOf(int type) { - LineSpacingRule lineType = imap.get(type); - if (lineType == null) - throw new IllegalArgumentException("Unknown line type: " + type); - return lineType; - } - - public int getValue() { - return value; - } -} + */ + AT_LEAST(3); + + + private static Map imap = new HashMap(); + + static { + for (LineSpacingRule p : values()) { + imap.put(p.getValue(), p); + } + } + + private final int value; + + private LineSpacingRule(int val) { + value = val; + } + + public static LineSpacingRule valueOf(int type) { + LineSpacingRule lineType = imap.get(type); + if (lineType == null) + throw new IllegalArgumentException("Unknown line type: " + type); + return lineType; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java index 7cffb30a58..f39d533508 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java @@ -37,31 +37,31 @@ public enum ParagraphAlignment { DISTRIBUTE(6), NUM_TAB(7), HIGH_KASHIDA(8), - LOW_KASHIDA(9), - THAI_DISTRIBUTE(10); - - private static Map imap = new HashMap(); - - static { - for (ParagraphAlignment p : values()) { - imap.put(p.getValue(), p); - } - } - - private final int value; - - private ParagraphAlignment(int val) { - value = val; - } - - public static ParagraphAlignment valueOf(int type) { - ParagraphAlignment err = imap.get(type); - if (err == null) throw new IllegalArgumentException("Unknown paragraph alignment: " + type); - return err; - } - - public int getValue() { - return value; - } - -} + LOW_KASHIDA(9), + THAI_DISTRIBUTE(10); + + private static Map imap = new HashMap(); + + static { + for (ParagraphAlignment p : values()) { + imap.put(p.getValue(), p); + } + } + + private final int value; + + private ParagraphAlignment(int val) { + value = val; + } + + public static ParagraphAlignment valueOf(int type) { + ParagraphAlignment err = imap.get(type); + if (err == null) throw new IllegalArgumentException("Unknown paragraph alignment: " + type); + return err; + } + + public int getValue() { + return value; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java index 4eebe412e1..f0f2d316a0 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java @@ -17,47 +17,47 @@ package org.apache.poi.xwpf.usermodel; - -/** - * postion of a character in a paragrapho - * 1st RunPositon - * 2nd TextPosition - * 3rd CharacterPosition - */ -public class PositionInParagraph { - private int posRun = 0, posText = 0, posChar = 0; - - public PositionInParagraph() { - } - - public PositionInParagraph(int posRun, int posText, int posChar) { - this.posRun = posRun; - this.posChar = posChar; - this.posText = posText; - } - - public int getRun() { - return posRun; - } - - public void setRun(int beginRun) { - this.posRun = beginRun; - } - - public int getText() { - return posText; - } - - public void setText(int beginText) { - this.posText = beginText; - } - - public int getChar() { - return posChar; - } - - public void setChar(int beginChar) { - this.posChar = beginChar; - } - -} + +/** + * postion of a character in a paragrapho + * 1st RunPositon + * 2nd TextPosition + * 3rd CharacterPosition + */ +public class PositionInParagraph { + private int posRun = 0, posText = 0, posChar = 0; + + public PositionInParagraph() { + } + + public PositionInParagraph(int posRun, int posText, int posChar) { + this.posRun = posRun; + this.posChar = posChar; + this.posText = posText; + } + + public int getRun() { + return posRun; + } + + public void setRun(int beginRun) { + this.posRun = beginRun; + } + + public int getText() { + return posText; + } + + public void setText(int beginText) { + this.posText = beginText; + } + + public int getChar() { + return posChar; + } + + public void setChar(int beginChar) { + this.posChar = beginChar; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java index a75fc84857..e7e9b8e985 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java @@ -39,85 +39,85 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabJc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabTlc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTheme; - -public class TOC { - - CTSdtBlock block; - - public TOC() { - this(CTSdtBlock.Factory.newInstance()); - } - - public TOC(CTSdtBlock block) { - this.block = block; - CTSdtPr sdtPr = block.addNewSdtPr(); - CTDecimalNumber id = sdtPr.addNewId(); - id.setVal(new BigInteger("4844945")); - sdtPr.addNewDocPartObj().addNewDocPartGallery().setVal("Table of contents"); - CTSdtEndPr sdtEndPr = block.addNewSdtEndPr(); - CTRPr rPr = sdtEndPr.addNewRPr(); - CTFonts fonts = rPr.addNewRFonts(); - fonts.setAsciiTheme(STTheme.MINOR_H_ANSI); - fonts.setEastAsiaTheme(STTheme.MINOR_H_ANSI); - fonts.setHAnsiTheme(STTheme.MINOR_H_ANSI); - fonts.setCstheme(STTheme.MINOR_BIDI); - rPr.addNewB().setVal(STOnOff.OFF); - rPr.addNewBCs().setVal(STOnOff.OFF); - rPr.addNewColor().setVal("auto"); - rPr.addNewSz().setVal(new BigInteger("24")); - rPr.addNewSzCs().setVal(new BigInteger("24")); - CTSdtContentBlock content = block.addNewSdtContent(); - CTP p = content.addNewP(); - p.setRsidR("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); - p.setRsidRDefault("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); - p.addNewPPr().addNewPStyle().setVal("TOCHeading"); - p.addNewR().addNewT().setStringValue("Table of Contents"); - } - - @Internal - public CTSdtBlock getBlock() { - return this.block; - } - - public void addRow(int level, String title, int page, String bookmarkRef) { - CTSdtContentBlock contentBlock = this.block.getSdtContent(); - CTP p = contentBlock.addNewP(); - p.setRsidR("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); - p.setRsidRDefault("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); - CTPPr pPr = p.addNewPPr(); - pPr.addNewPStyle().setVal("TOC" + level); - CTTabs tabs = pPr.addNewTabs(); - CTTabStop tab = tabs.addNewTab(); - tab.setVal(STTabJc.RIGHT); - tab.setLeader(STTabTlc.DOT); - tab.setPos(new BigInteger("8290")); - pPr.addNewRPr().addNewNoProof(); - CTR run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewT().setStringValue(title); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewTab(); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewFldChar().setFldCharType(STFldCharType.BEGIN); - // pageref run - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - CTText text = run.addNewInstrText(); - text.setSpace(Space.PRESERVE); - // bookmark reference - text.setStringValue(" PAGEREF _Toc" + bookmarkRef + " \\h "); - p.addNewR().addNewRPr().addNewNoProof(); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewFldChar().setFldCharType(STFldCharType.SEPARATE); - // page number run - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewT().setStringValue(Integer.toString(page)); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewFldChar().setFldCharType(STFldCharType.END); - } -} + +public class TOC { + + CTSdtBlock block; + + public TOC() { + this(CTSdtBlock.Factory.newInstance()); + } + + public TOC(CTSdtBlock block) { + this.block = block; + CTSdtPr sdtPr = block.addNewSdtPr(); + CTDecimalNumber id = sdtPr.addNewId(); + id.setVal(new BigInteger("4844945")); + sdtPr.addNewDocPartObj().addNewDocPartGallery().setVal("Table of contents"); + CTSdtEndPr sdtEndPr = block.addNewSdtEndPr(); + CTRPr rPr = sdtEndPr.addNewRPr(); + CTFonts fonts = rPr.addNewRFonts(); + fonts.setAsciiTheme(STTheme.MINOR_H_ANSI); + fonts.setEastAsiaTheme(STTheme.MINOR_H_ANSI); + fonts.setHAnsiTheme(STTheme.MINOR_H_ANSI); + fonts.setCstheme(STTheme.MINOR_BIDI); + rPr.addNewB().setVal(STOnOff.OFF); + rPr.addNewBCs().setVal(STOnOff.OFF); + rPr.addNewColor().setVal("auto"); + rPr.addNewSz().setVal(new BigInteger("24")); + rPr.addNewSzCs().setVal(new BigInteger("24")); + CTSdtContentBlock content = block.addNewSdtContent(); + CTP p = content.addNewP(); + p.setRsidR("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); + p.setRsidRDefault("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); + p.addNewPPr().addNewPStyle().setVal("TOCHeading"); + p.addNewR().addNewT().setStringValue("Table of Contents"); + } + + @Internal + public CTSdtBlock getBlock() { + return this.block; + } + + public void addRow(int level, String title, int page, String bookmarkRef) { + CTSdtContentBlock contentBlock = this.block.getSdtContent(); + CTP p = contentBlock.addNewP(); + p.setRsidR("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); + p.setRsidRDefault("00EF7E24".getBytes(LocaleUtil.CHARSET_1252)); + CTPPr pPr = p.addNewPPr(); + pPr.addNewPStyle().setVal("TOC" + level); + CTTabs tabs = pPr.addNewTabs(); + CTTabStop tab = tabs.addNewTab(); + tab.setVal(STTabJc.RIGHT); + tab.setLeader(STTabTlc.DOT); + tab.setPos(new BigInteger("8290")); + pPr.addNewRPr().addNewNoProof(); + CTR run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewT().setStringValue(title); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewTab(); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewFldChar().setFldCharType(STFldCharType.BEGIN); + // pageref run + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + CTText text = run.addNewInstrText(); + text.setSpace(Space.PRESERVE); + // bookmark reference + text.setStringValue(" PAGEREF _Toc" + bookmarkRef + " \\h "); + p.addNewR().addNewRPr().addNewNoProof(); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewFldChar().setFldCharType(STFldCharType.SEPARATE); + // page number run + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewT().setStringValue(Integer.toString(page)); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewFldChar().setFldCharType(STFldCharType.END); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java index 1cc6434c91..b8511a3bbc 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java @@ -17,25 +17,25 @@ package org.apache.poi.xwpf.usermodel; import java.util.HashMap; -import java.util.Map; - -/** - * Specifies all types of vertical alignment which are available to be applied to of all text - * on each line displayed within a paragraph. - * - * @author Gisella Bronzetti - */ -public enum TextAlignment { - /** - * Specifies that all text in the parent object shall be - * aligned to the top of each character when displayed - */ - TOP(1), - /** - * Specifies that all text in the parent object shall be - * aligned to the center of each character when displayed. - */ - CENTER(2), +import java.util.Map; + +/** + * Specifies all types of vertical alignment which are available to be applied to of all text + * on each line displayed within a paragraph. + * + * @author Gisella Bronzetti + */ +public enum TextAlignment { + /** + * Specifies that all text in the parent object shall be + * aligned to the top of each character when displayed + */ + TOP(1), + /** + * Specifies that all text in the parent object shall be + * aligned to the center of each character when displayed. + */ + CENTER(2), /** * Specifies that all text in the parent object shall be * aligned to the baseline of each character when displayed. @@ -44,35 +44,35 @@ public enum TextAlignment { /** * Specifies that all text in the parent object shall be * aligned to the bottom of each character when displayed. - */ - BOTTOM(4), - /** - * Specifies that all text in the parent object shall be - * aligned automatically when displayed. - */ - AUTO(5); - - private static Map imap = new HashMap(); - - static { - for (TextAlignment p : values()) { - imap.put(p.getValue(), p); - } - } - - private final int value; - - private TextAlignment(int val) { - value = val; - } - - public static TextAlignment valueOf(int type) { - TextAlignment align = imap.get(type); - if (align == null) throw new IllegalArgumentException("Unknown text alignment: " + type); - return align; - } - - public int getValue() { - return value; - } -} + */ + BOTTOM(4), + /** + * Specifies that all text in the parent object shall be + * aligned automatically when displayed. + */ + AUTO(5); + + private static Map imap = new HashMap(); + + static { + for (TextAlignment p : values()) { + imap.put(p.getValue(), p); + } + } + + private final int value; + + private TextAlignment(int val) { + value = val; + } + + public static TextAlignment valueOf(int type) { + TextAlignment align = imap.get(type); + if (align == null) throw new IllegalArgumentException("Unknown text alignment: " + type); + return align; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java index 44477daf87..46b272703f 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java @@ -16,84 +16,84 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; - -/** - * saves the begin and end position of a text in a Paragraph - */ -public class TextSegement { - private PositionInParagraph beginPos; - private PositionInParagraph endPos; - - public TextSegement() { - this.beginPos = new PositionInParagraph(); - this.endPos = new PositionInParagraph(); - } - - public TextSegement(int beginRun, int endRun, int beginText, int endText, int beginChar, int endChar) { - PositionInParagraph beginPos = new PositionInParagraph(beginRun, beginText, beginChar); - PositionInParagraph endPos = new PositionInParagraph(endRun, endText, endChar); - this.beginPos = beginPos; - this.endPos = endPos; - } - - public TextSegement(PositionInParagraph beginPos, PositionInParagraph endPos) { - this.beginPos = beginPos; - this.endPos = endPos; - } - - public PositionInParagraph getBeginPos() { - return beginPos; - } - - public PositionInParagraph getEndPos() { - return endPos; - } - - public int getBeginRun() { - return beginPos.getRun(); - } - - public void setBeginRun(int beginRun) { - beginPos.setRun(beginRun); - } - - public int getBeginText() { - return beginPos.getText(); - } - - public void setBeginText(int beginText) { - beginPos.setText(beginText); - } - - public int getBeginChar() { - return beginPos.getChar(); - } - - public void setBeginChar(int beginChar) { - beginPos.setChar(beginChar); - } - - public int getEndRun() { - return endPos.getRun(); - } - - public void setEndRun(int endRun) { - endPos.setRun(endRun); - } - - public int getEndText() { - return endPos.getText(); - } - - public void setEndText(int endText) { - endPos.setText(endText); - } - - public int getEndChar() { - return endPos.getChar(); - } - - public void setEndChar(int endChar) { - endPos.setChar(endChar); - } -} + +/** + * saves the begin and end position of a text in a Paragraph + */ +public class TextSegement { + private PositionInParagraph beginPos; + private PositionInParagraph endPos; + + public TextSegement() { + this.beginPos = new PositionInParagraph(); + this.endPos = new PositionInParagraph(); + } + + public TextSegement(int beginRun, int endRun, int beginText, int endText, int beginChar, int endChar) { + PositionInParagraph beginPos = new PositionInParagraph(beginRun, beginText, beginChar); + PositionInParagraph endPos = new PositionInParagraph(endRun, endText, endChar); + this.beginPos = beginPos; + this.endPos = endPos; + } + + public TextSegement(PositionInParagraph beginPos, PositionInParagraph endPos) { + this.beginPos = beginPos; + this.endPos = endPos; + } + + public PositionInParagraph getBeginPos() { + return beginPos; + } + + public PositionInParagraph getEndPos() { + return endPos; + } + + public int getBeginRun() { + return beginPos.getRun(); + } + + public void setBeginRun(int beginRun) { + beginPos.setRun(beginRun); + } + + public int getBeginText() { + return beginPos.getText(); + } + + public void setBeginText(int beginText) { + beginPos.setText(beginText); + } + + public int getBeginChar() { + return beginPos.getChar(); + } + + public void setBeginChar(int beginChar) { + beginPos.setChar(beginChar); + } + + public int getEndRun() { + return endPos.getRun(); + } + + public void setEndRun(int endRun) { + endPos.setRun(endRun); + } + + public int getEndText() { + return endPos.getText(); + } + + public void setEndText(int endText) { + endPos.setText(endText); + } + + public int getEndChar() { + return endPos.getChar(); + } + + public void setEndChar(int endChar) { + endPos.setChar(endChar); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java index c99b17bd7a..132444796a 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java @@ -19,13 +19,13 @@ package org.apache.poi.xwpf.usermodel; import java.util.HashMap; import java.util.Map; -/** - * Specifies the types of patterns which may be used to create the underline - * applied beneath the text in a run. - * - * @author Gisella Bronzetti - */ -public enum UnderlinePatterns { +/** + * Specifies the types of patterns which may be used to create the underline + * applied beneath the text in a run. + * + * @author Gisella Bronzetti + */ +public enum UnderlinePatterns { /** * Specifies an underline consisting of a single line beneath all characters @@ -132,32 +132,32 @@ public enum UnderlinePatterns { /** * Specifies no underline beneath this run. - */ - NONE(18); - - private static Map imap = new HashMap(); - - static { - for (UnderlinePatterns p : values()) { - imap.put(p.getValue(), p); - } - } - - private final int value; - - private UnderlinePatterns(int val) { - value = val; - } - - public static UnderlinePatterns valueOf(int type) { - UnderlinePatterns align = imap.get(type); - if (align == null) - throw new IllegalArgumentException("Unknown underline pattern: " - + type); - return align; - } - - public int getValue() { - return value; - } -} + */ + NONE(18); + + private static Map imap = new HashMap(); + + static { + for (UnderlinePatterns p : values()) { + imap.put(p.getValue(), p); + } + } + + private final int value; + + private UnderlinePatterns(int val) { + value = val; + } + + public static UnderlinePatterns valueOf(int type) { + UnderlinePatterns align = imap.get(type); + if (align == null) + throw new IllegalArgumentException("Unknown underline pattern: " + + type); + return align; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java index 7b7538d192..57b2797165 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java @@ -21,13 +21,13 @@ import java.util.Map; /** * Specifies possible values for the alignment of the contents of this run in - * relation to the default appearance of the run's text. This allows the text to - * be repositioned as subscript or superscript without altering the font size of - * the run properties. - * - * @author Gisella Bronzetti - */ -public enum VerticalAlign { + * relation to the default appearance of the run's text. This allows the text to + * be repositioned as subscript or superscript without altering the font size of + * the run properties. + * + * @author Gisella Bronzetti + */ +public enum VerticalAlign { /** * Specifies that the text in the parent run shall be located at the @@ -44,32 +44,32 @@ public enum VerticalAlign { * Specifies that this text should be superscript. This setting shall raise * the text in this run above the baseline and change it to a smaller size, * if a smaller size is available. - */ - SUBSCRIPT(3); - - private static Map imap = new HashMap(); - - static { - for (VerticalAlign p : values()) { - imap.put(p.getValue(), p); - } - } - - private final int value; - - private VerticalAlign(int val) { - value = val; - } - - public static VerticalAlign valueOf(int type) { - VerticalAlign align = imap.get(type); - if (align == null) - throw new IllegalArgumentException("Unknown vertical alignment: " - + type); - return align; - } - - public int getValue() { - return value; - } -} + */ + SUBSCRIPT(3); + + private static Map imap = new HashMap(); + + static { + for (VerticalAlign p : values()) { + imap.put(p.getValue(), p); + } + } + + private final int value; + + private VerticalAlign(int val) { + value = val; + } + + public static VerticalAlign valueOf(int type) { + VerticalAlign align = imap.get(type); + if (align == null) + throw new IllegalArgumentException("Unknown vertical alignment: " + + type); + return align; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java index 8d4886b909..c8c3caf00f 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java @@ -18,43 +18,43 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; - -/** - * @author Philipp Epp - */ -public class XWPFAbstractNum { - protected XWPFNumbering numbering; - private CTAbstractNum ctAbstractNum; - - protected XWPFAbstractNum() { - this.ctAbstractNum = null; - this.numbering = null; - - } - - public XWPFAbstractNum(CTAbstractNum abstractNum) { - this.ctAbstractNum = abstractNum; - } - - public XWPFAbstractNum(CTAbstractNum ctAbstractNum, XWPFNumbering numbering) { - this.ctAbstractNum = ctAbstractNum; - this.numbering = numbering; - } - - public CTAbstractNum getAbstractNum() { - return ctAbstractNum; - } - - public XWPFNumbering getNumbering() { - return numbering; - } - - public void setNumbering(XWPFNumbering numbering) { - this.numbering = numbering; - } - - public CTAbstractNum getCTAbstractNum() { - return ctAbstractNum; - } - -} + +/** + * @author Philipp Epp + */ +public class XWPFAbstractNum { + protected XWPFNumbering numbering; + private CTAbstractNum ctAbstractNum; + + protected XWPFAbstractNum() { + this.ctAbstractNum = null; + this.numbering = null; + + } + + public XWPFAbstractNum(CTAbstractNum abstractNum) { + this.ctAbstractNum = abstractNum; + } + + public XWPFAbstractNum(CTAbstractNum ctAbstractNum, XWPFNumbering numbering) { + this.ctAbstractNum = ctAbstractNum; + this.numbering = numbering; + } + + public CTAbstractNum getAbstractNum() { + return ctAbstractNum; + } + + public XWPFNumbering getNumbering() { + return numbering; + } + + public void setNumbering(XWPFNumbering numbering) { + this.numbering = numbering; + } + + public CTAbstractNum getCTAbstractNum() { + return ctAbstractNum; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultParagraphStyle.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultParagraphStyle.java index a430c87e52..9a1a973e8b 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultParagraphStyle.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultParagraphStyle.java @@ -22,21 +22,21 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr; /** * Default Paragraph style, from which other styles will override * TODO Share logic with {@link XWPFParagraph} which also uses CTPPr - */ -public class XWPFDefaultParagraphStyle { - private CTPPr ppr; - - public XWPFDefaultParagraphStyle(CTPPr ppr) { - this.ppr = ppr; - } - - protected CTPPr getPPr() { - return ppr; - } - - public int getSpacingAfter() { - if (ppr.isSetSpacing()) - return ppr.getSpacing().getAfter().intValue(); + */ +public class XWPFDefaultParagraphStyle { + private CTPPr ppr; + + public XWPFDefaultParagraphStyle(CTPPr ppr) { + this.ppr = ppr; + } + + protected CTPPr getPPr() { + return ppr; + } + + public int getSpacingAfter() { + if (ppr.isSetSpacing()) + return ppr.getSpacing().getAfter().intValue(); return -1; } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultRunStyle.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultRunStyle.java index 459335de6d..60c2f272dc 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultRunStyle.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultRunStyle.java @@ -22,21 +22,21 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; /** * Default Character Run style, from which other styles will override * TODO Share logic with {@link XWPFRun} which also uses CTRPr - */ -public class XWPFDefaultRunStyle { - private CTRPr rpr; - - public XWPFDefaultRunStyle(CTRPr rpr) { - this.rpr = rpr; - } - - protected CTRPr getRPr() { - return rpr; - } - - public int getFontSize() { - if (rpr.isSetSz()) - return rpr.getSz().getVal().intValue() / 2; + */ +public class XWPFDefaultRunStyle { + private CTRPr rpr; + + public XWPFDefaultRunStyle(CTRPr rpr) { + this.rpr = rpr; + } + + protected CTRPr getRPr() { + return rpr; + } + + public int getFontSize() { + if (rpr.isSetSz()) + return rpr.getSz().getVal().intValue() / 2; return -1; } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFieldRun.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFieldRun.java index 997c7d0cb3..1f1559b3a0 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFieldRun.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFieldRun.java @@ -22,27 +22,27 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSimpleField; /** * A run of text which is part of a field, such as Title - * of Page number or Author. - * Any given Field may be made up of multiple of these. - */ -public class XWPFFieldRun extends XWPFRun { - private CTSimpleField field; - - public XWPFFieldRun(CTSimpleField field, CTR run, IRunBody p) { - super(run, p); - this.field = field; - } - - @Internal + * of Page number or Author. + * Any given Field may be made up of multiple of these. + */ +public class XWPFFieldRun extends XWPFRun { + private CTSimpleField field; + + public XWPFFieldRun(CTSimpleField field, CTR run, IRunBody p) { + super(run, p); + this.field = field; + } + + @Internal public CTSimpleField getCTField() { - return field; - } - - public String getFieldInstruction() { - return field.getInstr(); - } - + return field; + } + + public String getFieldInstruction() { + return field.getInstr(); + } + public void setFieldInstruction(String instruction) { - field.setInstr(instruction); - } -} + field.setInstr(instruction); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java index b5f24dd718..8c89bf7478 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java @@ -1,377 +1,377 @@ -/* ==================================================================== -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.POIXMLDocumentPart; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; - -public class XWPFFootnote implements Iterable, IBody { - private List paragraphs = new ArrayList(); - private List tables = new ArrayList(); - private List pictures = new ArrayList(); - private List bodyElements = new ArrayList(); - - private CTFtnEdn ctFtnEdn; - private XWPFFootnotes footnotes; - private XWPFDocument document; - - public XWPFFootnote(CTFtnEdn note, XWPFFootnotes xFootnotes) { - footnotes = xFootnotes; - ctFtnEdn = note; - document = xFootnotes.getXWPFDocument(); - init(); - } - - public XWPFFootnote(XWPFDocument document, CTFtnEdn body) { - ctFtnEdn = body; - this.document = document; - init(); - } - - private void init() { - XmlCursor cursor = ctFtnEdn.newCursor(); - //copied from XWPFDocument...should centralize this code - //to avoid duplication - cursor.selectPath("./*"); - while (cursor.toNextSelection()) { - XmlObject o = cursor.getObject(); - if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP) o, this); - bodyElements.add(p); - paragraphs.add(p); - } else if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl) o, this); - bodyElements.add(t); - tables.add(t); - } else if (o instanceof CTSdtBlock) { - XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); - bodyElements.add(c); - } - - } - cursor.dispose(); - } - - public List getParagraphs() { - return paragraphs; - } - - public Iterator iterator() { - return paragraphs.iterator(); - } - - public List getTables() { - return tables; - } - - public List getPictures() { - return pictures; - } - - public List getBodyElements() { - return bodyElements; - } - - public CTFtnEdn getCTFtnEdn() { - return ctFtnEdn; - } - - public void setCTFtnEdn(CTFtnEdn footnote) { - ctFtnEdn = footnote; - } - - /** - * @param pos in table array - * @return The table at position pos - * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) - */ - public XWPFTable getTableArray(int pos) { - if (pos >= 0 && pos < tables.size()) { - return tables.get(pos); - } - return null; - } - - /** - * inserts an existing XWPFTable to the arrays bodyElements and tables - * - * @param pos - * @param table - * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int pos, XWPFTable table) - */ - public void insertTable(int pos, XWPFTable table) { - bodyElements.add(pos, table); - int i = 0; - for (CTTbl tbl : ctFtnEdn.getTblArray()) { - if (tbl == table.getCTTbl()) { - break; - } - i++; - } - tables.add(i, table); - - } - - /** - * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header - * the method will return this table - * if there is no corresponding {@link XWPFTable} the method will return null - * - * @param ctTable - * @see org.apache.poi.xwpf.usermodel.IBody#getTable(CTTbl ctTable) - */ - public XWPFTable getTable(CTTbl ctTable) { - for (XWPFTable table : tables) { - if (table == null) - return null; - if (table.getCTTbl().equals(ctTable)) - return table; - } - return null; - } - - /** - * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer - * the method will return this paragraph - * if there is no corresponding {@link XWPFParagraph} the method will return null - * - * @param p is instance of CTP and is searching for an XWPFParagraph - * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer - * XWPFParagraph with the correspondig CTP p - * @see org.apache.poi.xwpf.usermodel.IBody#getParagraph(CTP p) - */ - public XWPFParagraph getParagraph(CTP p) { - for (XWPFParagraph paragraph : paragraphs) { - if (paragraph.getCTP().equals(p)) - return paragraph; - } - return null; - } - - /** - * Returns the paragraph that holds - * the text of the header or footer. - * - * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int pos) - */ - public XWPFParagraph getParagraphArray(int pos) { - if(pos >=0 && pos < paragraphs.size()) { - return paragraphs.get(pos); - } - return null; - } - - /** - * get the TableCell which belongs to the TableCell - * - * @param cell - * @see org.apache.poi.xwpf.usermodel.IBody#getTableCell(CTTc cell) - */ - public XWPFTableCell getTableCell(CTTc cell) { - XmlCursor cursor = cell.newCursor(); - cursor.toParent(); - XmlObject o = cursor.getObject(); - if (!(o instanceof CTRow)) { - return null; - } - CTRow row = (CTRow) o; - cursor.toParent(); - o = cursor.getObject(); - cursor.dispose(); - if (!(o instanceof CTTbl)) { - return null; - } - CTTbl tbl = (CTTbl) o; - XWPFTable table = getTable(tbl); - if (table == null) { - return null; - } - XWPFTableRow tableRow = table.getRow(row); - if(tableRow == null){ - return null; - } - return tableRow.getTableCell(cell); - } - - /** - * verifies that cursor is on the right position - * - * @param cursor - */ - private boolean isCursorInFtn(XmlCursor cursor) { - XmlCursor verify = cursor.newCursor(); - verify.toParent(); - if (verify.getObject() == this.ctFtnEdn) { - return true; - } - return false; - } - - public POIXMLDocumentPart getOwner() { - return footnotes; - } - - /** - * @param cursor - * @return the inserted table - * @see org.apache.poi.xwpf.usermodel.IBody#insertNewTbl(XmlCursor cursor) - */ - public XWPFTable insertNewTbl(XmlCursor cursor) { - if (isCursorInFtn(cursor)) { - String uri = CTTbl.type.getName().getNamespaceURI(); - String localPart = "tbl"; - cursor.beginElement(localPart, uri); - cursor.toParent(); - CTTbl t = (CTTbl) cursor.getObject(); - XWPFTable newT = new XWPFTable(t, this); - cursor.removeXmlContents(); - XmlObject o = null; - while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) { - o = cursor.getObject(); - } - if (!(o instanceof CTTbl)) { - tables.add(0, newT); - } else { - int pos = tables.indexOf(getTable((CTTbl) o)) + 1; - tables.add(pos, newT); - } - int i = 0; - cursor = t.newCursor(); - while (cursor.toPrevSibling()) { - o = cursor.getObject(); - if (o instanceof CTP || o instanceof CTTbl) - i++; - } - bodyElements.add(i, newT); - XmlCursor c2 = t.newCursor(); - cursor.toCursor(c2); - cursor.toEndToken(); - c2.dispose(); - return newT; - } - return null; - } - - /** - * add a new paragraph at position of the cursor - * - * @param cursor - * @return the inserted paragraph - * @see org.apache.poi.xwpf.usermodel.IBody#insertNewParagraph(XmlCursor cursor) - */ - public XWPFParagraph insertNewParagraph(final XmlCursor cursor) { - if (isCursorInFtn(cursor)) { - String uri = CTP.type.getName().getNamespaceURI(); - String localPart = "p"; - cursor.beginElement(localPart, uri); - cursor.toParent(); - CTP p = (CTP) cursor.getObject(); - XWPFParagraph newP = new XWPFParagraph(p, this); - XmlObject o = null; - while (!(o instanceof CTP) && (cursor.toPrevSibling())) { - o = cursor.getObject(); - } - if ((!(o instanceof CTP)) || (CTP) o == p) { - paragraphs.add(0, newP); - } else { - int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1; - paragraphs.add(pos, newP); - } - int i = 0; - XmlCursor p2 = p.newCursor(); - cursor.toCursor(p2); - p2.dispose(); - while (cursor.toPrevSibling()) { - o = cursor.getObject(); - if (o instanceof CTP || o instanceof CTTbl) - i++; - } - bodyElements.add(i, newP); - p2 = p.newCursor(); - cursor.toCursor(p2); - cursor.toEndToken(); - p2.dispose(); - return newP; - } - return null; - } - - /** - * add a new table to the end of the footnote - * - * @param table - * @return the added XWPFTable - */ - public XWPFTable addNewTbl(CTTbl table) { - CTTbl newTable = ctFtnEdn.addNewTbl(); - newTable.set(table); - XWPFTable xTable = new XWPFTable(newTable, this); - tables.add(xTable); - return xTable; - } - - /** - * add a new paragraph to the end of the footnote - * - * @param paragraph - * @return the added XWPFParagraph - */ - public XWPFParagraph addNewParagraph(CTP paragraph) { - CTP newPara = ctFtnEdn.addNewP(); - newPara.set(paragraph); - XWPFParagraph xPara = new XWPFParagraph(newPara, this); - paragraphs.add(xPara); - return xPara; - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument() - */ - public XWPFDocument getXWPFDocument() { - return document; - } - - /** - * returns the Part, to which the body belongs, which you need for adding relationship to other parts - * - * @see org.apache.poi.xwpf.usermodel.IBody#getPart() - */ - public POIXMLDocumentPart getPart() { - return footnotes; - } - - /** - * get the PartType of the body - * - * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() - */ - public BodyType getPartType() { - return BodyType.FOOTNOTE; - } -} +/* ==================================================================== +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xwpf.usermodel; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; + +public class XWPFFootnote implements Iterable, IBody { + private List paragraphs = new ArrayList(); + private List tables = new ArrayList(); + private List pictures = new ArrayList(); + private List bodyElements = new ArrayList(); + + private CTFtnEdn ctFtnEdn; + private XWPFFootnotes footnotes; + private XWPFDocument document; + + public XWPFFootnote(CTFtnEdn note, XWPFFootnotes xFootnotes) { + footnotes = xFootnotes; + ctFtnEdn = note; + document = xFootnotes.getXWPFDocument(); + init(); + } + + public XWPFFootnote(XWPFDocument document, CTFtnEdn body) { + ctFtnEdn = body; + this.document = document; + init(); + } + + private void init() { + XmlCursor cursor = ctFtnEdn.newCursor(); + //copied from XWPFDocument...should centralize this code + //to avoid duplication + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { + XmlObject o = cursor.getObject(); + if (o instanceof CTP) { + XWPFParagraph p = new XWPFParagraph((CTP) o, this); + bodyElements.add(p); + paragraphs.add(p); + } else if (o instanceof CTTbl) { + XWPFTable t = new XWPFTable((CTTbl) o, this); + bodyElements.add(t); + tables.add(t); + } else if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); + bodyElements.add(c); + } + + } + cursor.dispose(); + } + + public List getParagraphs() { + return paragraphs; + } + + public Iterator iterator() { + return paragraphs.iterator(); + } + + public List getTables() { + return tables; + } + + public List getPictures() { + return pictures; + } + + public List getBodyElements() { + return bodyElements; + } + + public CTFtnEdn getCTFtnEdn() { + return ctFtnEdn; + } + + public void setCTFtnEdn(CTFtnEdn footnote) { + ctFtnEdn = footnote; + } + + /** + * @param pos in table array + * @return The table at position pos + * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) + */ + public XWPFTable getTableArray(int pos) { + if (pos >= 0 && pos < tables.size()) { + return tables.get(pos); + } + return null; + } + + /** + * inserts an existing XWPFTable to the arrays bodyElements and tables + * + * @param pos + * @param table + * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int pos, XWPFTable table) + */ + public void insertTable(int pos, XWPFTable table) { + bodyElements.add(pos, table); + int i = 0; + for (CTTbl tbl : ctFtnEdn.getTblArray()) { + if (tbl == table.getCTTbl()) { + break; + } + i++; + } + tables.add(i, table); + + } + + /** + * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header + * the method will return this table + * if there is no corresponding {@link XWPFTable} the method will return null + * + * @param ctTable + * @see org.apache.poi.xwpf.usermodel.IBody#getTable(CTTbl ctTable) + */ + public XWPFTable getTable(CTTbl ctTable) { + for (XWPFTable table : tables) { + if (table == null) + return null; + if (table.getCTTbl().equals(ctTable)) + return table; + } + return null; + } + + /** + * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer + * the method will return this paragraph + * if there is no corresponding {@link XWPFParagraph} the method will return null + * + * @param p is instance of CTP and is searching for an XWPFParagraph + * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer + * XWPFParagraph with the correspondig CTP p + * @see org.apache.poi.xwpf.usermodel.IBody#getParagraph(CTP p) + */ + public XWPFParagraph getParagraph(CTP p) { + for (XWPFParagraph paragraph : paragraphs) { + if (paragraph.getCTP().equals(p)) + return paragraph; + } + return null; + } + + /** + * Returns the paragraph that holds + * the text of the header or footer. + * + * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int pos) + */ + public XWPFParagraph getParagraphArray(int pos) { + if(pos >=0 && pos < paragraphs.size()) { + return paragraphs.get(pos); + } + return null; + } + + /** + * get the TableCell which belongs to the TableCell + * + * @param cell + * @see org.apache.poi.xwpf.usermodel.IBody#getTableCell(CTTc cell) + */ + public XWPFTableCell getTableCell(CTTc cell) { + XmlCursor cursor = cell.newCursor(); + cursor.toParent(); + XmlObject o = cursor.getObject(); + if (!(o instanceof CTRow)) { + return null; + } + CTRow row = (CTRow) o; + cursor.toParent(); + o = cursor.getObject(); + cursor.dispose(); + if (!(o instanceof CTTbl)) { + return null; + } + CTTbl tbl = (CTTbl) o; + XWPFTable table = getTable(tbl); + if (table == null) { + return null; + } + XWPFTableRow tableRow = table.getRow(row); + if(tableRow == null){ + return null; + } + return tableRow.getTableCell(cell); + } + + /** + * verifies that cursor is on the right position + * + * @param cursor + */ + private boolean isCursorInFtn(XmlCursor cursor) { + XmlCursor verify = cursor.newCursor(); + verify.toParent(); + if (verify.getObject() == this.ctFtnEdn) { + return true; + } + return false; + } + + public POIXMLDocumentPart getOwner() { + return footnotes; + } + + /** + * @param cursor + * @return the inserted table + * @see org.apache.poi.xwpf.usermodel.IBody#insertNewTbl(XmlCursor cursor) + */ + public XWPFTable insertNewTbl(XmlCursor cursor) { + if (isCursorInFtn(cursor)) { + String uri = CTTbl.type.getName().getNamespaceURI(); + String localPart = "tbl"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTTbl t = (CTTbl) cursor.getObject(); + XWPFTable newT = new XWPFTable(t, this); + cursor.removeXmlContents(); + XmlObject o = null; + while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if (!(o instanceof CTTbl)) { + tables.add(0, newT); + } else { + int pos = tables.indexOf(getTable((CTTbl) o)) + 1; + tables.add(pos, newT); + } + int i = 0; + cursor = t.newCursor(); + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + bodyElements.add(i, newT); + XmlCursor c2 = t.newCursor(); + cursor.toCursor(c2); + cursor.toEndToken(); + c2.dispose(); + return newT; + } + return null; + } + + /** + * add a new paragraph at position of the cursor + * + * @param cursor + * @return the inserted paragraph + * @see org.apache.poi.xwpf.usermodel.IBody#insertNewParagraph(XmlCursor cursor) + */ + public XWPFParagraph insertNewParagraph(final XmlCursor cursor) { + if (isCursorInFtn(cursor)) { + String uri = CTP.type.getName().getNamespaceURI(); + String localPart = "p"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTP p = (CTP) cursor.getObject(); + XWPFParagraph newP = new XWPFParagraph(p, this); + XmlObject o = null; + while (!(o instanceof CTP) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if ((!(o instanceof CTP)) || (CTP) o == p) { + paragraphs.add(0, newP); + } else { + int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1; + paragraphs.add(pos, newP); + } + int i = 0; + XmlCursor p2 = p.newCursor(); + cursor.toCursor(p2); + p2.dispose(); + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + bodyElements.add(i, newP); + p2 = p.newCursor(); + cursor.toCursor(p2); + cursor.toEndToken(); + p2.dispose(); + return newP; + } + return null; + } + + /** + * add a new table to the end of the footnote + * + * @param table + * @return the added XWPFTable + */ + public XWPFTable addNewTbl(CTTbl table) { + CTTbl newTable = ctFtnEdn.addNewTbl(); + newTable.set(table); + XWPFTable xTable = new XWPFTable(newTable, this); + tables.add(xTable); + return xTable; + } + + /** + * add a new paragraph to the end of the footnote + * + * @param paragraph + * @return the added XWPFParagraph + */ + public XWPFParagraph addNewParagraph(CTP paragraph) { + CTP newPara = ctFtnEdn.addNewP(); + newPara.set(paragraph); + XWPFParagraph xPara = new XWPFParagraph(newPara, this); + paragraphs.add(xPara); + return xPara; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument() + */ + public XWPFDocument getXWPFDocument() { + return document; + } + + /** + * returns the Part, to which the body belongs, which you need for adding relationship to other parts + * + * @see org.apache.poi.xwpf.usermodel.IBody#getPart() + */ + public POIXMLDocumentPart getPart() { + return footnotes; + } + + /** + * get the PartType of the body + * + * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() + */ + public BodyType getPartType() { + return BodyType.FOOTNOTE; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java index 0be7b195dd..c037bd7d4b 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java @@ -35,18 +35,18 @@ import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFootnotes; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument; - -/** - * Looks after the collection of Footnotes for a document - */ -public class XWPFFootnotes extends POIXMLDocumentPart { - protected XWPFDocument document; - private List listFootnote = new ArrayList(); - private CTFootnotes ctFootnotes; - - /** - * Construct XWPFFootnotes from a package part +import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument; + +/** + * Looks after the collection of Footnotes for a document + */ +public class XWPFFootnotes extends POIXMLDocumentPart { + protected XWPFDocument document; + private List listFootnote = new ArrayList(); + private CTFootnotes ctFootnotes; + + /** + * Construct XWPFFootnotes from a package part * * @param part the package part holding the data of the footnotes, * @@ -64,13 +64,13 @@ public class XWPFFootnotes extends POIXMLDocumentPart { /** * Read document - */ - @Override - protected void onDocumentRead() throws IOException { + */ + @Override + protected void onDocumentRead() throws IOException { FootnotesDocument notesDoc; - InputStream is = null; - try { - is = getPackagePart().getInputStream(); + InputStream is = null; + try { + is = getPackagePart().getInputStream(); notesDoc = FootnotesDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); ctFootnotes = notesDoc.getFootnotes(); } catch (XmlException e) { @@ -79,18 +79,18 @@ public class XWPFFootnotes extends POIXMLDocumentPart { if (is != null) { is.close(); } - } - - // Find our footnotes - for (CTFtnEdn note : ctFootnotes.getFootnoteArray()) { - listFootnote.add(new XWPFFootnote(note, this)); - } - } + } + + // Find our footnotes + for (CTFtnEdn note : ctFootnotes.getFootnoteArray()) { + listFootnote.add(new XWPFFootnote(note, this)); + } + } @Override - protected void commit() throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTFootnotes.type.getName().getNamespaceURI(), "footnotes")); + protected void commit() throws IOException { + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTFootnotes.type.getName().getNamespaceURI(), "footnotes")); PackagePart part = getPackagePart(); OutputStream out = part.getOutputStream(); ctFootnotes.save(out, xmlOptions); @@ -99,62 +99,62 @@ public class XWPFFootnotes extends POIXMLDocumentPart { public List getFootnotesList() { return listFootnote; - } - - public XWPFFootnote getFootnoteById(int id) { - for (XWPFFootnote note : listFootnote) { - if (note.getCTFtnEdn().getId().intValue() == id) - return note; - } - return null; } - - /** - * Sets the ctFootnotes - * - * @param footnotes - */ - public void setFootnotes(CTFootnotes footnotes) { + + public XWPFFootnote getFootnoteById(int id) { + for (XWPFFootnote note : listFootnote) { + if (note.getCTFtnEdn().getId().intValue() == id) + return note; + } + return null; + } + + /** + * Sets the ctFootnotes + * + * @param footnotes + */ + public void setFootnotes(CTFootnotes footnotes) { ctFootnotes = footnotes; } - - /** - * add an XWPFFootnote to the document - * - * @param footnote - * @throws IOException - */ - public void addFootnote(XWPFFootnote footnote) { - listFootnote.add(footnote); - ctFootnotes.addNewFootnote().set(footnote.getCTFtnEdn()); - } - - /** - * add a footnote to the document - * - * @param note - * @throws IOException - */ - public XWPFFootnote addFootnote(CTFtnEdn note) { - CTFtnEdn newNote = ctFootnotes.addNewFootnote(); - newNote.set(note); - XWPFFootnote xNote = new XWPFFootnote(newNote, this); + + /** + * add an XWPFFootnote to the document + * + * @param footnote + * @throws IOException + */ + public void addFootnote(XWPFFootnote footnote) { + listFootnote.add(footnote); + ctFootnotes.addNewFootnote().set(footnote.getCTFtnEdn()); + } + + /** + * add a footnote to the document + * + * @param note + * @throws IOException + */ + public XWPFFootnote addFootnote(CTFtnEdn note) { + CTFtnEdn newNote = ctFootnotes.addNewFootnote(); + newNote.set(note); + XWPFFootnote xNote = new XWPFFootnote(newNote, this); listFootnote.add(xNote); - return xNote; - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getPart() - */ - public XWPFDocument getXWPFDocument() { - if (document != null) { - return document; - } else { - return (XWPFDocument) getParent(); - } - } - - public void setXWPFDocument(XWPFDocument doc) { - document = doc; - } -} + return xNote; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getPart() + */ + public XWPFDocument getXWPFDocument() { + if (document != null) { + return document; + } else { + return (XWPFDocument) getParent(); + } + } + + public void setXWPFDocument(XWPFDocument doc) { + document = doc; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java index 9a79b20f0f..7a5ad06b89 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java @@ -21,46 +21,46 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; /** - * A run of text with a Hyperlink applied to it. - * Any given Hyperlink may be made up of multiple of these. - */ -public class XWPFHyperlinkRun extends XWPFRun { - private CTHyperlink hyperlink; - - public XWPFHyperlinkRun(CTHyperlink hyperlink, CTR run, IRunBody p) { - super(run, p); - this.hyperlink = hyperlink; - } + * A run of text with a Hyperlink applied to it. + * Any given Hyperlink may be made up of multiple of these. + */ +public class XWPFHyperlinkRun extends XWPFRun { + private CTHyperlink hyperlink; - @Internal - public CTHyperlink getCTHyperlink() { - return hyperlink; - } - - public String getAnchor() { - return hyperlink.getAnchor(); - } - - /** - * Returns the ID of the hyperlink, if one is set. - */ - public String getHyperlinkId() { - return hyperlink.getId(); - } - - public void setHyperlinkId(String id) { - hyperlink.setId(id); - } - - /** - * If this Hyperlink is an external reference hyperlink, - * return the object for it. - */ - public XWPFHyperlink getHyperlink(XWPFDocument document) { - String id = getHyperlinkId(); - if (id == null) - return null; - - return document.getHyperlinkByID(id); - } -} + public XWPFHyperlinkRun(CTHyperlink hyperlink, CTR run, IRunBody p) { + super(run, p); + this.hyperlink = hyperlink; + } + + @Internal + public CTHyperlink getCTHyperlink() { + return hyperlink; + } + + public String getAnchor() { + return hyperlink.getAnchor(); + } + + /** + * Returns the ID of the hyperlink, if one is set. + */ + public String getHyperlinkId() { + return hyperlink.getId(); + } + + public void setHyperlinkId(String id) { + hyperlink.setId(id); + } + + /** + * If this Hyperlink is an external reference hyperlink, + * return the object for it. + */ + public XWPFHyperlink getHyperlink(XWPFDocument document) { + String id = getHyperlinkId(); + if (id == null) + return null; + + return document.getHyperlinkByID(id); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java index da8b9836c5..465428d2fe 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java @@ -17,38 +17,38 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLatentStyles; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLsdException; - +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLsdException; + public class XWPFLatentStyles { - // As of 2016-06-10, POI does not contain a LatentStyle class, nor was one included in the patch for bug 48574. - protected XWPFStyles styles; //LatentStyle shall know styles - private CTLatentStyles latentStyles; - - protected XWPFLatentStyles() { - } - - protected XWPFLatentStyles(CTLatentStyles latentStyles) { - this(latentStyles, null); - } - - protected XWPFLatentStyles(CTLatentStyles latentStyles, XWPFStyles styles) { - this.latentStyles = latentStyles; - this.styles = styles; - } - - public int getNumberOfStyles() { + // As of 2016-06-10, POI does not contain a LatentStyle class, nor was one included in the patch for bug 48574. + protected XWPFStyles styles; //LatentStyle shall know styles + private CTLatentStyles latentStyles; + + protected XWPFLatentStyles() { + } + + protected XWPFLatentStyles(CTLatentStyles latentStyles) { + this(latentStyles, null); + } + + protected XWPFLatentStyles(CTLatentStyles latentStyles, XWPFStyles styles) { + this.latentStyles = latentStyles; + this.styles = styles; + } + + public int getNumberOfStyles() { return latentStyles.sizeOfLsdExceptionArray(); } /** - * checks whether specific LatentStyleID is a latentStyle - */ - protected boolean isLatentStyle(String latentStyleID) { - for (CTLsdException lsd : latentStyles.getLsdExceptionArray()) { - if (lsd.getName().equals(latentStyleID)) { - return true; - } - } - return false; - } -} + * checks whether specific LatentStyleID is a latentStyle + */ + protected boolean isLatentStyle(String latentStyleID) { + for (CTLsdException lsd : latentStyles.getLsdExceptionArray()) { + if (lsd.getName().equals(latentStyleID)) { + return true; + } + } + return false; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java index 7674510c1f..9fa8ab38da 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java @@ -18,47 +18,47 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNum; - + /** - * TODO Bring more of the logic over from XWPFParagraph - */ -public class XWPFNum { - protected XWPFNumbering numbering; - private CTNum ctNum; - - public XWPFNum() { - this.ctNum = null; - this.numbering = null; - } - - public XWPFNum(CTNum ctNum) { - this.ctNum = ctNum; - this.numbering = null; - } - - public XWPFNum(XWPFNumbering numbering) { - this.ctNum = null; - this.numbering = numbering; - } - - public XWPFNum(CTNum ctNum, XWPFNumbering numbering) { - this.ctNum = ctNum; - this.numbering = numbering; - } - - public XWPFNumbering getNumbering() { - return numbering; - } - - public void setNumbering(XWPFNumbering numbering) { - this.numbering = numbering; - } - - public CTNum getCTNum() { - return ctNum; - } - - public void setCTNum(CTNum ctNum) { - this.ctNum = ctNum; - } + * TODO Bring more of the logic over from XWPFParagraph + */ +public class XWPFNum { + protected XWPFNumbering numbering; + private CTNum ctNum; + + public XWPFNum() { + this.ctNum = null; + this.numbering = null; + } + + public XWPFNum(CTNum ctNum) { + this.ctNum = ctNum; + this.numbering = null; + } + + public XWPFNum(XWPFNumbering numbering) { + this.ctNum = null; + this.numbering = numbering; + } + + public XWPFNum(CTNum ctNum, XWPFNumbering numbering) { + this.ctNum = ctNum; + this.numbering = numbering; + } + + public XWPFNumbering getNumbering() { + return numbering; + } + + public void setNumbering(XWPFNumbering numbering) { + this.numbering = numbering; + } + + public CTNum getCTNum() { + return ctNum; + } + + public void setCTNum(CTNum ctNum) { + this.ctNum = ctNum; + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java index 37aac2b892..1b7162e004 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java @@ -37,15 +37,15 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering; import org.openxmlformats.schemas.wordprocessingml.x2006.main.NumberingDocument; - -/** - * @author Philipp Epp - */ -public class XWPFNumbering extends POIXMLDocumentPart { - protected List abstractNums = new ArrayList(); - protected List nums = new ArrayList(); - boolean isNew; - private CTNumbering ctNumbering; + +/** + * @author Philipp Epp + */ +public class XWPFNumbering extends POIXMLDocumentPart { + protected List abstractNums = new ArrayList(); + protected List nums = new ArrayList(); + boolean isNew; + private CTNumbering ctNumbering; /** * create a new styles object with an existing document @@ -61,29 +61,29 @@ public class XWPFNumbering extends POIXMLDocumentPart { * create a new XWPFNumbering object for use in a new document */ public XWPFNumbering() { - abstractNums = new ArrayList(); - nums = new ArrayList(); - isNew = true; - } - - /** - * read numbering form an existing package - */ - @Override - protected void onDocumentRead() throws IOException { - NumberingDocument numberingDoc = null; - InputStream is; - is = getPackagePart().getInputStream(); - try { - numberingDoc = NumberingDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); - ctNumbering = numberingDoc.getNumbering(); - //get any Nums - for (CTNum ctNum : ctNumbering.getNumArray()) { - nums.add(new XWPFNum(ctNum, this)); - } - for (CTAbstractNum ctAbstractNum : ctNumbering.getAbstractNumArray()) { - abstractNums.add(new XWPFAbstractNum(ctAbstractNum, this)); - } + abstractNums = new ArrayList(); + nums = new ArrayList(); + isNew = true; + } + + /** + * read numbering form an existing package + */ + @Override + protected void onDocumentRead() throws IOException { + NumberingDocument numberingDoc = null; + InputStream is; + is = getPackagePart().getInputStream(); + try { + numberingDoc = NumberingDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); + ctNumbering = numberingDoc.getNumbering(); + //get any Nums + for (CTNum ctNum : ctNumbering.getNumArray()) { + nums.add(new XWPFNum(ctNum, this)); + } + for (CTAbstractNum ctAbstractNum : ctNumbering.getAbstractNumArray()) { + abstractNums.add(new XWPFAbstractNum(ctAbstractNum, this)); + } isNew = false; } catch (XmlException e) { throw new POIXMLException(); @@ -92,193 +92,193 @@ public class XWPFNumbering extends POIXMLDocumentPart { } } - /** - * save and commit numbering - */ - @Override - protected void commit() throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "numbering")); + /** + * save and commit numbering + */ + @Override + protected void commit() throws IOException { + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "numbering")); PackagePart part = getPackagePart(); OutputStream out = part.getOutputStream(); ctNumbering.save(out, xmlOptions); out.close(); - } - - - /** - * Sets the ctNumbering - * - * @param numbering - */ - public void setNumbering(CTNumbering numbering) { - ctNumbering = numbering; - } - - - /** - * Checks whether number with numID exists - * - * @param numID - * @return boolean true if num exist, false if num not exist - */ - public boolean numExist(BigInteger numID) { - for (XWPFNum num : nums) { - if (num.getCTNum().getNumId().equals(numID)) - return true; - } - return false; - } - - /** - * add a new number to the numbering document - * - * @param num - */ - public BigInteger addNum(XWPFNum num) { - ctNumbering.addNewNum(); - int pos = ctNumbering.sizeOfNumArray() - 1; - ctNumbering.setNumArray(pos, num.getCTNum()); - nums.add(num); - return num.getCTNum().getNumId(); - } - - /** - * Add a new num with an abstractNumID - * - * @return return NumId of the added num - */ - public BigInteger addNum(BigInteger abstractNumID) { - CTNum ctNum = this.ctNumbering.addNewNum(); - ctNum.addNewAbstractNumId(); - ctNum.getAbstractNumId().setVal(abstractNumID); - ctNum.setNumId(BigInteger.valueOf(nums.size() + 1)); - XWPFNum num = new XWPFNum(ctNum, this); - nums.add(num); - return ctNum.getNumId(); - } - - /** - * Add a new num with an abstractNumID and a numID - * - * @param abstractNumID - * @param numID - */ - public void addNum(BigInteger abstractNumID, BigInteger numID) { - CTNum ctNum = this.ctNumbering.addNewNum(); - ctNum.addNewAbstractNumId(); - ctNum.getAbstractNumId().setVal(abstractNumID); - ctNum.setNumId(numID); - XWPFNum num = new XWPFNum(ctNum, this); - nums.add(num); - } - - /** - * get Num by NumID - * - * @param numID - * @return abstractNum with NumId if no Num exists with that NumID - * null will be returned - */ - public XWPFNum getNum(BigInteger numID) { - for (XWPFNum num : nums) { - if (num.getCTNum().getNumId().equals(numID)) - return num; - } - return null; - } - - /** - * get AbstractNum by abstractNumID - * - * @param abstractNumID - * @return abstractNum with abstractNumId if no abstractNum exists with that abstractNumID - * null will be returned - */ - public XWPFAbstractNum getAbstractNum(BigInteger abstractNumID) { - for (XWPFAbstractNum abstractNum : abstractNums) { - if (abstractNum.getAbstractNum().getAbstractNumId().equals(abstractNumID)) { - return abstractNum; - } - } - return null; - } - - /** - * Compare AbstractNum with abstractNums of this numbering document. - * If the content of abstractNum equals with an abstractNum of the List in numbering - * the BigInteger Value of it will be returned. - * If no equal abstractNum is existing null will be returned - * - * @param abstractNum - * @return BigInteger - */ - public BigInteger getIdOfAbstractNum(XWPFAbstractNum abstractNum) { - CTAbstractNum copy = (CTAbstractNum) abstractNum.getCTAbstractNum().copy(); - XWPFAbstractNum newAbstractNum = new XWPFAbstractNum(copy, this); - int i; - for (i = 0; i < abstractNums.size(); i++) { - newAbstractNum.getCTAbstractNum().setAbstractNumId(BigInteger.valueOf(i)); - newAbstractNum.setNumbering(this); - if (newAbstractNum.getCTAbstractNum().valueEquals(abstractNums.get(i).getCTAbstractNum())) { - return newAbstractNum.getCTAbstractNum().getAbstractNumId(); - } - } - return null; - } - - - /** - * add a new AbstractNum and return its AbstractNumID - * - * @param abstractNum - */ - public BigInteger addAbstractNum(XWPFAbstractNum abstractNum) { - int pos = abstractNums.size(); - if (abstractNum.getAbstractNum() != null) { // Use the current CTAbstractNum if it exists - ctNumbering.addNewAbstractNum().set(abstractNum.getAbstractNum()); - } else { - ctNumbering.addNewAbstractNum(); - abstractNum.getAbstractNum().setAbstractNumId(BigInteger.valueOf(pos)); - ctNumbering.setAbstractNumArray(pos, abstractNum.getAbstractNum()); - } - abstractNums.add(abstractNum); - return abstractNum.getCTAbstractNum().getAbstractNumId(); - } - - /** - * remove an existing abstractNum - * - * @param abstractNumID - * @return true if abstractNum with abstractNumID exists in NumberingArray, - * false if abstractNum with abstractNumID not exists - */ - public boolean removeAbstractNum(BigInteger abstractNumID) { - if (abstractNumID.byteValue() < abstractNums.size()) { - ctNumbering.removeAbstractNum(abstractNumID.byteValue()); - abstractNums.remove(abstractNumID.byteValue()); - return true; - } - return false; - } - - /** - * return the abstractNumID - * If the AbstractNumID not exists - * return null - * - * @param numID - * @return abstractNumID - */ - public BigInteger getAbstractNumID(BigInteger numID) { - XWPFNum num = getNum(numID); - if (num == null) - return null; - if (num.getCTNum() == null) - return null; - if (num.getCTNum().getAbstractNumId() == null) - return null; - return num.getCTNum().getAbstractNumId().getVal(); - } -} - + } + + + /** + * Sets the ctNumbering + * + * @param numbering + */ + public void setNumbering(CTNumbering numbering) { + ctNumbering = numbering; + } + + + /** + * Checks whether number with numID exists + * + * @param numID + * @return boolean true if num exist, false if num not exist + */ + public boolean numExist(BigInteger numID) { + for (XWPFNum num : nums) { + if (num.getCTNum().getNumId().equals(numID)) + return true; + } + return false; + } + + /** + * add a new number to the numbering document + * + * @param num + */ + public BigInteger addNum(XWPFNum num) { + ctNumbering.addNewNum(); + int pos = ctNumbering.sizeOfNumArray() - 1; + ctNumbering.setNumArray(pos, num.getCTNum()); + nums.add(num); + return num.getCTNum().getNumId(); + } + + /** + * Add a new num with an abstractNumID + * + * @return return NumId of the added num + */ + public BigInteger addNum(BigInteger abstractNumID) { + CTNum ctNum = this.ctNumbering.addNewNum(); + ctNum.addNewAbstractNumId(); + ctNum.getAbstractNumId().setVal(abstractNumID); + ctNum.setNumId(BigInteger.valueOf(nums.size() + 1)); + XWPFNum num = new XWPFNum(ctNum, this); + nums.add(num); + return ctNum.getNumId(); + } + + /** + * Add a new num with an abstractNumID and a numID + * + * @param abstractNumID + * @param numID + */ + public void addNum(BigInteger abstractNumID, BigInteger numID) { + CTNum ctNum = this.ctNumbering.addNewNum(); + ctNum.addNewAbstractNumId(); + ctNum.getAbstractNumId().setVal(abstractNumID); + ctNum.setNumId(numID); + XWPFNum num = new XWPFNum(ctNum, this); + nums.add(num); + } + + /** + * get Num by NumID + * + * @param numID + * @return abstractNum with NumId if no Num exists with that NumID + * null will be returned + */ + public XWPFNum getNum(BigInteger numID) { + for (XWPFNum num : nums) { + if (num.getCTNum().getNumId().equals(numID)) + return num; + } + return null; + } + + /** + * get AbstractNum by abstractNumID + * + * @param abstractNumID + * @return abstractNum with abstractNumId if no abstractNum exists with that abstractNumID + * null will be returned + */ + public XWPFAbstractNum getAbstractNum(BigInteger abstractNumID) { + for (XWPFAbstractNum abstractNum : abstractNums) { + if (abstractNum.getAbstractNum().getAbstractNumId().equals(abstractNumID)) { + return abstractNum; + } + } + return null; + } + + /** + * Compare AbstractNum with abstractNums of this numbering document. + * If the content of abstractNum equals with an abstractNum of the List in numbering + * the BigInteger Value of it will be returned. + * If no equal abstractNum is existing null will be returned + * + * @param abstractNum + * @return BigInteger + */ + public BigInteger getIdOfAbstractNum(XWPFAbstractNum abstractNum) { + CTAbstractNum copy = (CTAbstractNum) abstractNum.getCTAbstractNum().copy(); + XWPFAbstractNum newAbstractNum = new XWPFAbstractNum(copy, this); + int i; + for (i = 0; i < abstractNums.size(); i++) { + newAbstractNum.getCTAbstractNum().setAbstractNumId(BigInteger.valueOf(i)); + newAbstractNum.setNumbering(this); + if (newAbstractNum.getCTAbstractNum().valueEquals(abstractNums.get(i).getCTAbstractNum())) { + return newAbstractNum.getCTAbstractNum().getAbstractNumId(); + } + } + return null; + } + + + /** + * add a new AbstractNum and return its AbstractNumID + * + * @param abstractNum + */ + public BigInteger addAbstractNum(XWPFAbstractNum abstractNum) { + int pos = abstractNums.size(); + if (abstractNum.getAbstractNum() != null) { // Use the current CTAbstractNum if it exists + ctNumbering.addNewAbstractNum().set(abstractNum.getAbstractNum()); + } else { + ctNumbering.addNewAbstractNum(); + abstractNum.getAbstractNum().setAbstractNumId(BigInteger.valueOf(pos)); + ctNumbering.setAbstractNumArray(pos, abstractNum.getAbstractNum()); + } + abstractNums.add(abstractNum); + return abstractNum.getCTAbstractNum().getAbstractNumId(); + } + + /** + * remove an existing abstractNum + * + * @param abstractNumID + * @return true if abstractNum with abstractNumID exists in NumberingArray, + * false if abstractNum with abstractNumID not exists + */ + public boolean removeAbstractNum(BigInteger abstractNumID) { + if (abstractNumID.byteValue() < abstractNums.size()) { + ctNumbering.removeAbstractNum(abstractNumID.byteValue()); + abstractNums.remove(abstractNumID.byteValue()); + return true; + } + return false; + } + + /** + * return the abstractNumID + * If the AbstractNumID not exists + * return null + * + * @param numID + * @return abstractNumID + */ + public BigInteger getAbstractNumID(BigInteger numID) { + XWPFNum num = getNum(numID); + if (num == null) + return null; + if (num.getCTNum() == null) + return null; + if (num.getCTNum().getAbstractNumId() == null) + return null; + return num.getCTNum().getAbstractNumId().getVal(); + } +} + diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java index c69e8dd1b7..ba244f16c3 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java @@ -28,51 +28,51 @@ import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture; public class XWPFPicture { private CTPicture ctPic; - private String description; - private XWPFRun run; - - public XWPFPicture(CTPicture ctPic, XWPFRun run) { - this.run = run; - this.ctPic = ctPic; - description = ctPic.getNvPicPr().getCNvPr().getDescr(); + private String description; + private XWPFRun run; + + public XWPFPicture(CTPicture ctPic, XWPFRun run) { + this.run = run; + this.ctPic = ctPic; + description = ctPic.getNvPicPr().getCNvPr().getDescr(); } - - /** - * Link Picture with PictureData - * - * @param rel - */ - public void setPictureReference(PackageRelationship rel) { - ctPic.getBlipFill().getBlip().setEmbed(rel.getId()); - } - + + /** + * Link Picture with PictureData + * + * @param rel + */ + public void setPictureReference(PackageRelationship rel) { + ctPic.getBlipFill().getBlip().setEmbed(rel.getId()); + } + /** * Return the underlying CTPicture bean that holds all properties for this picture - * - * @return the underlying CTPicture bean - */ - public CTPicture getCTPicture() { - return ctPic; - } - + * + * @return the underlying CTPicture bean + */ + public CTPicture getCTPicture() { + return ctPic; + } + /** - * Get the PictureData of the Picture, if present. - * Note - not all kinds of picture have data - */ - public XWPFPictureData getPictureData() { - CTBlipFillProperties blipProps = ctPic.getBlipFill(); - - if (blipProps == null || !blipProps.isSetBlip()) { - // return null if Blip data is missing - return null; - } - - String blipId = blipProps.getBlip().getEmbed(); - POIXMLDocumentPart part = run.getParent().getPart(); - if (part != null) { - POIXMLDocumentPart relatedPart = part.getRelationById(blipId); - if (relatedPart instanceof XWPFPictureData) { - return (XWPFPictureData) relatedPart; + * Get the PictureData of the Picture, if present. + * Note - not all kinds of picture have data + */ + public XWPFPictureData getPictureData() { + CTBlipFillProperties blipProps = ctPic.getBlipFill(); + + if (blipProps == null || !blipProps.isSetBlip()) { + // return null if Blip data is missing + return null; + } + + String blipId = blipProps.getBlip().getEmbed(); + POIXMLDocumentPart part = run.getParent().getPart(); + if (part != null) { + POIXMLDocumentPart relatedPart = part.getRelationById(blipId); + if (relatedPart instanceof XWPFPictureData) { + return (XWPFPictureData) relatedPart; } } return null; diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java index fd8389ef56..355527019a 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java @@ -17,30 +17,30 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtRun; - -/** - * Experimental class to offer rudimentary read-only processing of - * of StructuredDocumentTags/ContentControl - *

    - * WARNING - APIs expected to change rapidly - */ -public class XWPFSDT extends AbstractXWPFSDT - implements IBodyElement, IRunBody, ISDTContents, IRunElement { - private final ISDTContent content; - - public XWPFSDT(CTSdtRun sdtRun, IBody part) { - super(sdtRun.getSdtPr(), part); - this.content = new XWPFSDTContent(sdtRun.getSdtContent(), part, this); - } - - public XWPFSDT(CTSdtBlock block, IBody part) { - super(block.getSdtPr(), part); - this.content = new XWPFSDTContent(block.getSdtContent(), part, this); - } - - public ISDTContent getContent() { - return content; - } - -} +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtRun; + +/** + * Experimental class to offer rudimentary read-only processing of + * of StructuredDocumentTags/ContentControl + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDT extends AbstractXWPFSDT + implements IBodyElement, IRunBody, ISDTContents, IRunElement { + private final ISDTContent content; + + public XWPFSDT(CTSdtRun sdtRun, IBody part) { + super(sdtRun.getSdtPr(), part); + this.content = new XWPFSDTContent(sdtRun.getSdtContent(), part, this); + } + + public XWPFSDT(CTSdtBlock block, IBody part) { + super(block.getSdtPr(), part); + this.content = new XWPFSDTContent(block.getSdtContent(), part, this); + } + + public ISDTContent getContent() { + return content; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java index fb40955efb..83548f7f26 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java @@ -16,28 +16,28 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtCell; - -/** - * Experimental class to offer rudimentary read-only processing of - * of StructuredDocumentTags/ContentControl that can appear - * in a table row as if a table cell. - *

    - * These can contain one or more cells or other SDTs within them. - *

    - * WARNING - APIs expected to change rapidly - */ -public class XWPFSDTCell extends AbstractXWPFSDT implements ICell { - private final XWPFSDTContentCell cellContent; - - public XWPFSDTCell(CTSdtCell sdtCell, XWPFTableRow xwpfTableRow, IBody part) { - super(sdtCell.getSdtPr(), part); - cellContent = new XWPFSDTContentCell(sdtCell.getSdtContent(), xwpfTableRow, part); - } - - @Override - public ISDTContent getContent() { - return cellContent; - } - -} +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtCell; + +/** + * Experimental class to offer rudimentary read-only processing of + * of StructuredDocumentTags/ContentControl that can appear + * in a table row as if a table cell. + *

    + * These can contain one or more cells or other SDTs within them. + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDTCell extends AbstractXWPFSDT implements ICell { + private final XWPFSDTContentCell cellContent; + + public XWPFSDTCell(CTSdtCell sdtCell, XWPFTableRow xwpfTableRow, IBody part) { + super(sdtCell.getSdtPr(), part); + cellContent = new XWPFSDTContentCell(sdtCell.getSdtContent(), xwpfTableRow, part); + } + + @Override + public ISDTContent getContent() { + return cellContent; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java index d160e662e3..545ef434ff 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java @@ -16,92 +16,92 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; -import java.util.ArrayList; -import java.util.List; - -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentRun; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; - -/** - * Experimental class to offer rudimentary read-only processing of - * of the contentblock of an SDT/ContentControl. - *

    - *

    - *

    - * WARNING - APIs expected to change rapidly - */ -public class XWPFSDTContent implements ISDTContent { - +import java.util.ArrayList; +import java.util.List; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentBlock; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentRun; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; + +/** + * Experimental class to offer rudimentary read-only processing of + * of the contentblock of an SDT/ContentControl. + *

    + *

    + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDTContent implements ISDTContent { + // private final IBody part; // private final XWPFDocument document; private List paragraphs = new ArrayList(); private List tables = new ArrayList(); private List runs = new ArrayList(); - private List contentControls = new ArrayList(); - private List bodyElements = new ArrayList(); - - public XWPFSDTContent(CTSdtContentRun sdtRun, IBody part, IRunBody parent) { - for (CTR ctr : sdtRun.getRArray()) { - XWPFRun run = new XWPFRun(ctr, parent); - runs.add(run); - bodyElements.add(run); - } - } - - public XWPFSDTContent(CTSdtContentBlock block, IBody part, IRunBody parent) { - XmlCursor cursor = block.newCursor(); - cursor.selectPath("./*"); - while (cursor.toNextSelection()) { + private List contentControls = new ArrayList(); + private List bodyElements = new ArrayList(); + + public XWPFSDTContent(CTSdtContentRun sdtRun, IBody part, IRunBody parent) { + for (CTR ctr : sdtRun.getRArray()) { + XWPFRun run = new XWPFRun(ctr, parent); + runs.add(run); + bodyElements.add(run); + } + } + + public XWPFSDTContent(CTSdtContentBlock block, IBody part, IRunBody parent) { + XmlCursor cursor = block.newCursor(); + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { XmlObject o = cursor.getObject(); if (o instanceof CTP) { XWPFParagraph p = new XWPFParagraph((CTP) o, part); bodyElements.add(p); paragraphs.add(p); } else if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl) o, part); - bodyElements.add(t); - tables.add(t); - } else if (o instanceof CTSdtBlock) { - XWPFSDT c = new XWPFSDT(((CTSdtBlock) o), part); - bodyElements.add(c); - contentControls.add(c); - } else if (o instanceof CTR) { + XWPFTable t = new XWPFTable((CTTbl) o, part); + bodyElements.add(t); + tables.add(t); + } else if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT(((CTSdtBlock) o), part); + bodyElements.add(c); + contentControls.add(c); + } else if (o instanceof CTR) { XWPFRun run = new XWPFRun((CTR) o, parent); runs.add(run); bodyElements.add(run); } } - cursor.dispose(); - } - - public String getText() { - StringBuilder text = new StringBuilder(); - boolean addNewLine = false; - for (int i = 0; i < bodyElements.size(); i++) { - Object o = bodyElements.get(i); - if (o instanceof XWPFParagraph) { - appendParagraph((XWPFParagraph) o, text); - addNewLine = true; - } else if (o instanceof XWPFTable) { - appendTable((XWPFTable) o, text); - addNewLine = true; - } else if (o instanceof XWPFSDT) { - text.append(((XWPFSDT) o).getContent().getText()); - addNewLine = true; - } else if (o instanceof XWPFRun) { - text.append(((XWPFRun) o).toString()); - addNewLine = false; - } - if (addNewLine == true && i < bodyElements.size() - 1) { - text.append("\n"); - } - } + cursor.dispose(); + } + + public String getText() { + StringBuilder text = new StringBuilder(); + boolean addNewLine = false; + for (int i = 0; i < bodyElements.size(); i++) { + Object o = bodyElements.get(i); + if (o instanceof XWPFParagraph) { + appendParagraph((XWPFParagraph) o, text); + addNewLine = true; + } else if (o instanceof XWPFTable) { + appendTable((XWPFTable) o, text); + addNewLine = true; + } else if (o instanceof XWPFSDT) { + text.append(((XWPFSDT) o).getContent().getText()); + addNewLine = true; + } else if (o instanceof XWPFRun) { + text.append(((XWPFRun) o).toString()); + addNewLine = false; + } + if (addNewLine == true && i < bodyElements.size() - 1) { + text.append("\n"); + } + } return text.toString(); } @@ -109,28 +109,28 @@ public class XWPFSDTContent implements ISDTContent { //this works recursively to pull embedded tables from within cells for (XWPFTableRow row : table.getRows()) { List cells = row.getTableICells(); - for (int i = 0; i < cells.size(); i++) { - ICell cell = cells.get(i); - if (cell instanceof XWPFTableCell) { - text.append(((XWPFTableCell) cell).getTextRecursively()); - } else if (cell instanceof XWPFSDTCell) { - text.append(((XWPFSDTCell) cell).getContent().getText()); - } - if (i < cells.size() - 1) { - text.append("\t"); - } - } - text.append('\n'); - } - } - - private void appendParagraph(XWPFParagraph paragraph, StringBuilder text) { - for (IRunElement run : paragraph.getRuns()) { - text.append(run.toString()); - } - } - - public String toString() { - return getText(); - } -} + for (int i = 0; i < cells.size(); i++) { + ICell cell = cells.get(i); + if (cell instanceof XWPFTableCell) { + text.append(((XWPFTableCell) cell).getTextRecursively()); + } else if (cell instanceof XWPFSDTCell) { + text.append(((XWPFSDTCell) cell).getContent().getText()); + } + if (i < cells.size() - 1) { + text.append("\t"); + } + } + text.append('\n'); + } + } + + private void appendParagraph(XWPFParagraph paragraph, StringBuilder text) { + for (IRunElement run : paragraph.getRuns()) { + text.append(run.toString()); + } + } + + public String toString() { + return getText(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java index c8246f6ddc..74645dc672 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java @@ -1,116 +1,116 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xwpf.usermodel; - - -import javax.xml.namespace.QName; - -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlCursor.TokenType; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentCell; - - -/** - * Experimental class to offer rudimentary read-only processing of - * of the XWPFSDTCellContent. - *

    - * WARNING - APIs expected to change rapidly - */ -public class XWPFSDTContentCell implements ISDTContent { - - //A full implementation would grab the icells - //that a content cell can contain. This would require - //significant changes, including changing the notion that the - //parent of a cell can be not just a row, but an sdt. - //For now we are just grabbing the text out of the text tokentypes. - - //private List cells = new ArrayList(). - - private String text = ""; - - public XWPFSDTContentCell(CTSdtContentCell sdtContentCell, - XWPFTableRow xwpfTableRow, IBody part) { - super(); - //sdtContentCell is allowed to be null: minOccurs="0" maxOccurs="1" - if (sdtContentCell == null) { - return; - } - StringBuilder sb = new StringBuilder(); - XmlCursor cursor = sdtContentCell.newCursor(); - - //keep track of the following, - //and add "\n" only before the start of a body - //element if it is not the first body element. - - //index of cell in row - int tcCnt = 0; - //count of body objects - int iBodyCnt = 0; - int depth = 1; - - while (cursor.hasNextToken() && depth > 0) { - TokenType t = cursor.toNextToken(); - if (t.isText()) { - sb.append(cursor.getTextValue()); - } else if (isStartToken(cursor, "tr")) { - tcCnt = 0; - iBodyCnt = 0; - } else if (isStartToken(cursor, "tc")) { - if (tcCnt++ > 0) { - sb.append("\t"); - } - iBodyCnt = 0; - } else if (isStartToken(cursor, "p") || - isStartToken(cursor, "tbl") || - isStartToken(cursor, "sdt")) { - if (iBodyCnt > 0) { - sb.append("\n"); - } - iBodyCnt++; - } - if (cursor.isStart()) { - depth++; - } else if (cursor.isEnd()) { - depth--; - } - } - text = sb.toString(); - cursor.dispose(); - } - - - private boolean isStartToken(XmlCursor cursor, String string) { - if (!cursor.isStart()) { - return false; - } - QName qName = cursor.getName(); - if (qName != null && qName.getLocalPart() != null && - qName.getLocalPart().equals(string)) { - return true; - } - return false; - } - - - public String getText() { - return text; - } - - public String toString() { - return getText(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xwpf.usermodel; + + +import javax.xml.namespace.QName; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlCursor.TokenType; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentCell; + + +/** + * Experimental class to offer rudimentary read-only processing of + * of the XWPFSDTCellContent. + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDTContentCell implements ISDTContent { + + //A full implementation would grab the icells + //that a content cell can contain. This would require + //significant changes, including changing the notion that the + //parent of a cell can be not just a row, but an sdt. + //For now we are just grabbing the text out of the text tokentypes. + + //private List cells = new ArrayList(). + + private String text = ""; + + public XWPFSDTContentCell(CTSdtContentCell sdtContentCell, + XWPFTableRow xwpfTableRow, IBody part) { + super(); + //sdtContentCell is allowed to be null: minOccurs="0" maxOccurs="1" + if (sdtContentCell == null) { + return; + } + StringBuilder sb = new StringBuilder(); + XmlCursor cursor = sdtContentCell.newCursor(); + + //keep track of the following, + //and add "\n" only before the start of a body + //element if it is not the first body element. + + //index of cell in row + int tcCnt = 0; + //count of body objects + int iBodyCnt = 0; + int depth = 1; + + while (cursor.hasNextToken() && depth > 0) { + TokenType t = cursor.toNextToken(); + if (t.isText()) { + sb.append(cursor.getTextValue()); + } else if (isStartToken(cursor, "tr")) { + tcCnt = 0; + iBodyCnt = 0; + } else if (isStartToken(cursor, "tc")) { + if (tcCnt++ > 0) { + sb.append("\t"); + } + iBodyCnt = 0; + } else if (isStartToken(cursor, "p") || + isStartToken(cursor, "tbl") || + isStartToken(cursor, "sdt")) { + if (iBodyCnt > 0) { + sb.append("\n"); + } + iBodyCnt++; + } + if (cursor.isStart()) { + depth++; + } else if (cursor.isEnd()) { + depth--; + } + } + text = sb.toString(); + cursor.dispose(); + } + + + private boolean isStartToken(XmlCursor cursor, String string) { + if (!cursor.isStart()) { + return false; + } + QName qName = cursor.getName(); + if (qName != null && qName.getLocalPart() != null && + qName.getLocalPart().equals(string)) { + return true; + } + return false; + } + + + public String getText() { + return text; + } + + public String toString() { + return getText(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java index a6ebdcc718..05f59189a5 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java @@ -19,141 +19,141 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType; - -/** - * @author Philipp Epp - */ -public class XWPFStyle { - - protected XWPFStyles styles; - private CTStyle ctStyle; - - /** - * constructor - * - * @param style - */ - public XWPFStyle(CTStyle style) { - this(style, null); - } - - /** - * constructor - * - * @param style - * @param styles - */ - public XWPFStyle(CTStyle style, XWPFStyles styles) { - this.ctStyle = style; - this.styles = styles; - } - - /** - * get StyleID of the style - * - * @return styleID StyleID of the style - */ - public String getStyleId() { - return ctStyle.getStyleId(); - } - - /** - * set styleID - * - * @param styleId - */ - public void setStyleId(String styleId) { - ctStyle.setStyleId(styleId); - } - - /** - * get Type of the Style - * - * @return ctType - */ - public STStyleType.Enum getType() { - return ctStyle.getType(); - } - - /** - * set styleType - * - * @param type - */ - public void setType(STStyleType.Enum type) { - ctStyle.setType(type); - } - - /** - * set style - * - * @param style - */ - public void setStyle(CTStyle style) { - this.ctStyle = style; - } - - /** - * get ctStyle - * - * @return ctStyle - */ - public CTStyle getCTStyle() { - return this.ctStyle; - } - - /** - * get styles - * - * @return styles the styles to which this style belongs - */ - public XWPFStyles getStyles() { - return styles; - } - - public String getBasisStyleID() { - if (ctStyle.getBasedOn() != null) - return ctStyle.getBasedOn().getVal(); - else - return null; - } - - - /** - * get StyleID of the linked Style - */ - public String getLinkStyleID() { - if (ctStyle.getLink() != null) - return ctStyle.getLink().getVal(); - else - return null; - } - - /** - * get StyleID of the next style - */ - public String getNextStyleID() { - if (ctStyle.getNext() != null) - return ctStyle.getNext().getVal(); - else - return null; - } - - public String getName() { - if (ctStyle.isSetName()) - return ctStyle.getName().getVal(); - return null; - } - - /** - * compares the names of the Styles - * - * @param compStyle - */ - public boolean hasSameName(XWPFStyle compStyle) { - CTStyle ctCompStyle = compStyle.getCTStyle(); - String name = ctCompStyle.getName().getVal(); - return name.equals(ctStyle.getName().getVal()); - } - -}//end class + +/** + * @author Philipp Epp + */ +public class XWPFStyle { + + protected XWPFStyles styles; + private CTStyle ctStyle; + + /** + * constructor + * + * @param style + */ + public XWPFStyle(CTStyle style) { + this(style, null); + } + + /** + * constructor + * + * @param style + * @param styles + */ + public XWPFStyle(CTStyle style, XWPFStyles styles) { + this.ctStyle = style; + this.styles = styles; + } + + /** + * get StyleID of the style + * + * @return styleID StyleID of the style + */ + public String getStyleId() { + return ctStyle.getStyleId(); + } + + /** + * set styleID + * + * @param styleId + */ + public void setStyleId(String styleId) { + ctStyle.setStyleId(styleId); + } + + /** + * get Type of the Style + * + * @return ctType + */ + public STStyleType.Enum getType() { + return ctStyle.getType(); + } + + /** + * set styleType + * + * @param type + */ + public void setType(STStyleType.Enum type) { + ctStyle.setType(type); + } + + /** + * set style + * + * @param style + */ + public void setStyle(CTStyle style) { + this.ctStyle = style; + } + + /** + * get ctStyle + * + * @return ctStyle + */ + public CTStyle getCTStyle() { + return this.ctStyle; + } + + /** + * get styles + * + * @return styles the styles to which this style belongs + */ + public XWPFStyles getStyles() { + return styles; + } + + public String getBasisStyleID() { + if (ctStyle.getBasedOn() != null) + return ctStyle.getBasedOn().getVal(); + else + return null; + } + + + /** + * get StyleID of the linked Style + */ + public String getLinkStyleID() { + if (ctStyle.getLink() != null) + return ctStyle.getLink().getVal(); + else + return null; + } + + /** + * get StyleID of the next style + */ + public String getNextStyleID() { + if (ctStyle.getNext() != null) + return ctStyle.getNext().getVal(); + else + return null; + } + + public String getName() { + if (ctStyle.isSetName()) + return ctStyle.getName().getVal(); + return null; + } + + /** + * compares the names of the Styles + * + * @param compStyle + */ + public boolean hasSameName(XWPFStyle compStyle) { + CTStyle ctCompStyle = compStyle.getCTStyle(); + String name = ctCompStyle.getName().getVal(); + return name.equals(ctStyle.getName().getVal()); + } + +}//end class diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java index ae2b1fd58e..511c85a6bd 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java @@ -41,21 +41,21 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPrDefault; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.StylesDocument; - -/** - * Holds details of built-in, default and user styles, which - * apply to tables / paragraphs / lists etc. - * Text within one of those with custom stylings has the style - * information stored in the {@link XWPFRun} - */ -public class XWPFStyles extends POIXMLDocumentPart { - private CTStyles ctStyles; - private List listStyle = new ArrayList(); - - private XWPFLatentStyles latentStyles; - private XWPFDefaultRunStyle defaultRunStyle; - private XWPFDefaultParagraphStyle defaultParaStyle; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.StylesDocument; + +/** + * Holds details of built-in, default and user styles, which + * apply to tables / paragraphs / lists etc. + * Text within one of those with custom stylings has the style + * information stored in the {@link XWPFRun} + */ +public class XWPFStyles extends POIXMLDocumentPart { + private CTStyles ctStyles; + private List listStyle = new ArrayList(); + + private XWPFLatentStyles latentStyles; + private XWPFDefaultRunStyle defaultRunStyle; + private XWPFDefaultParagraphStyle defaultParaStyle; /** * Construct XWPFStyles from a package part @@ -75,8 +75,8 @@ public class XWPFStyles extends POIXMLDocumentPart { } /** - * Read document - */ + * Read document + */ @Override protected void onDocumentRead() throws IOException { StylesDocument stylesDoc; @@ -97,48 +97,48 @@ public class XWPFStyles extends POIXMLDocumentPart { if (ctStyles == null) { throw new IllegalStateException("Unable to write out styles that were never read in!"); } - - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTStyles.type.getName().getNamespaceURI(), "styles")); + + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTStyles.type.getName().getNamespaceURI(), "styles")); PackagePart part = getPackagePart(); OutputStream out = part.getOutputStream(); ctStyles.save(out, xmlOptions); out.close(); - } - - protected void ensureDocDefaults() { - if (!ctStyles.isSetDocDefaults()) { - ctStyles.addNewDocDefaults(); - } - - CTDocDefaults docDefaults = ctStyles.getDocDefaults(); - if (!docDefaults.isSetPPrDefault()) - docDefaults.addNewPPrDefault(); - if (!docDefaults.isSetRPrDefault()) - docDefaults.addNewRPrDefault(); - - CTPPrDefault pprd = docDefaults.getPPrDefault(); - CTRPrDefault rprd = docDefaults.getRPrDefault(); - if (!pprd.isSetPPr()) pprd.addNewPPr(); - if (!rprd.isSetRPr()) rprd.addNewRPr(); - - defaultRunStyle = new XWPFDefaultRunStyle(rprd.getRPr()); - defaultParaStyle = new XWPFDefaultParagraphStyle(pprd.getPPr()); - } - - /** - * Sets the ctStyles - * - * @param styles - */ + } + + protected void ensureDocDefaults() { + if (!ctStyles.isSetDocDefaults()) { + ctStyles.addNewDocDefaults(); + } + + CTDocDefaults docDefaults = ctStyles.getDocDefaults(); + if (!docDefaults.isSetPPrDefault()) + docDefaults.addNewPPrDefault(); + if (!docDefaults.isSetRPrDefault()) + docDefaults.addNewRPrDefault(); + + CTPPrDefault pprd = docDefaults.getPPrDefault(); + CTRPrDefault rprd = docDefaults.getRPrDefault(); + if (!pprd.isSetPPr()) pprd.addNewPPr(); + if (!rprd.isSetRPr()) rprd.addNewRPr(); + + defaultRunStyle = new XWPFDefaultRunStyle(rprd.getRPr()); + defaultParaStyle = new XWPFDefaultParagraphStyle(pprd.getPPr()); + } + + /** + * Sets the ctStyles + * + * @param styles + */ public void setStyles(CTStyles styles) { - ctStyles = styles; - - // Build up all the style objects - for (CTStyle style : ctStyles.getStyleArray()) { - listStyle.add(new XWPFStyle(style, this)); - } - if (ctStyles.isSetDocDefaults()) { + ctStyles = styles; + + // Build up all the style objects + for (CTStyle style : ctStyles.getStyleArray()) { + listStyle.add(new XWPFStyle(style, this)); + } + if (ctStyles.isSetDocDefaults()) { CTDocDefaults docDefaults = ctStyles.getDocDefaults(); if (docDefaults.isSetRPrDefault() && docDefaults.getRPrDefault().isSetRPr()) { defaultRunStyle = new XWPFDefaultRunStyle( @@ -150,41 +150,41 @@ public class XWPFStyles extends POIXMLDocumentPart { } } } - - /** - * checks whether style with styleID exist - * - * @param styleID styleID of the Style in the style-Document - * @return true if style exist, false if style not exist - */ - public boolean styleExist(String styleID) { - for (XWPFStyle style : listStyle) { - if (style.getStyleId().equals(styleID)) - return true; - } - return false; - } - - /** - * add a style to the document - * - * @param style - * @throws IOException - */ - public void addStyle(XWPFStyle style) { - listStyle.add(style); - ctStyles.addNewStyle(); - int pos = ctStyles.sizeOfStyleArray() - 1; - ctStyles.setStyleArray(pos, style.getCTStyle()); - } - - /** - * Get style by a styleID - * - * @param styleID styleID of the searched style - * @return style - */ - public XWPFStyle getStyle(String styleID) { + + /** + * checks whether style with styleID exist + * + * @param styleID styleID of the Style in the style-Document + * @return true if style exist, false if style not exist + */ + public boolean styleExist(String styleID) { + for (XWPFStyle style : listStyle) { + if (style.getStyleId().equals(styleID)) + return true; + } + return false; + } + + /** + * add a style to the document + * + * @param style + * @throws IOException + */ + public void addStyle(XWPFStyle style) { + listStyle.add(style); + ctStyles.addNewStyle(); + int pos = ctStyles.sizeOfStyleArray() - 1; + ctStyles.setStyleArray(pos, style.getCTStyle()); + } + + /** + * Get style by a styleID + * + * @param styleID styleID of the searched style + * @return style + */ + public XWPFStyle getStyle(String styleID) { for (XWPFStyle style : listStyle) { try { if (style.getStyleId().equals(styleID)) @@ -192,114 +192,114 @@ public class XWPFStyles extends POIXMLDocumentPart { } catch (NullPointerException e) { // Ignore NPE } - } - return null; - } - - public int getNumberOfStyles() { - return listStyle.size(); - } - - /** - * get the styles which are related to the parameter style and their relatives - * this method can be used to copy all styles from one document to another document - * - * @param style - * @return a list of all styles which were used by this method - */ - public List getUsedStyleList(XWPFStyle style) { - List usedStyleList = new ArrayList(); - usedStyleList.add(style); - return getUsedStyleList(style, usedStyleList); - } - - /** - * get the styles which are related to parameter style - * - * @param style - * @return all Styles of the parameterList - */ - private List getUsedStyleList(XWPFStyle style, List usedStyleList) { - String basisStyleID = style.getBasisStyleID(); - XWPFStyle basisStyle = getStyle(basisStyleID); - if ((basisStyle != null) && (!usedStyleList.contains(basisStyle))) { - usedStyleList.add(basisStyle); - getUsedStyleList(basisStyle, usedStyleList); - } - String linkStyleID = style.getLinkStyleID(); - XWPFStyle linkStyle = getStyle(linkStyleID); - if ((linkStyle != null) && (!usedStyleList.contains(linkStyle))) { - usedStyleList.add(linkStyle); - getUsedStyleList(linkStyle, usedStyleList); - } - - String nextStyleID = style.getNextStyleID(); - XWPFStyle nextStyle = getStyle(nextStyleID); - if ((nextStyle != null) && (!usedStyleList.contains(nextStyle))) { - usedStyleList.add(linkStyle); - getUsedStyleList(linkStyle, usedStyleList); - } - return usedStyleList; - } - - protected CTLanguage getCTLanguage() { - ensureDocDefaults(); - - CTLanguage lang = null; - if (defaultRunStyle.getRPr().isSetLang()) { - lang = defaultRunStyle.getRPr().getLang(); - } else { - lang = defaultRunStyle.getRPr().addNewLang(); - } - - return lang; - } - - /** - * Sets the default spelling language on ctStyles DocDefaults parameter - * - * @param strSpellingLanguage - */ - public void setSpellingLanguage(String strSpellingLanguage) { + } + return null; + } + + public int getNumberOfStyles() { + return listStyle.size(); + } + + /** + * get the styles which are related to the parameter style and their relatives + * this method can be used to copy all styles from one document to another document + * + * @param style + * @return a list of all styles which were used by this method + */ + public List getUsedStyleList(XWPFStyle style) { + List usedStyleList = new ArrayList(); + usedStyleList.add(style); + return getUsedStyleList(style, usedStyleList); + } + + /** + * get the styles which are related to parameter style + * + * @param style + * @return all Styles of the parameterList + */ + private List getUsedStyleList(XWPFStyle style, List usedStyleList) { + String basisStyleID = style.getBasisStyleID(); + XWPFStyle basisStyle = getStyle(basisStyleID); + if ((basisStyle != null) && (!usedStyleList.contains(basisStyle))) { + usedStyleList.add(basisStyle); + getUsedStyleList(basisStyle, usedStyleList); + } + String linkStyleID = style.getLinkStyleID(); + XWPFStyle linkStyle = getStyle(linkStyleID); + if ((linkStyle != null) && (!usedStyleList.contains(linkStyle))) { + usedStyleList.add(linkStyle); + getUsedStyleList(linkStyle, usedStyleList); + } + + String nextStyleID = style.getNextStyleID(); + XWPFStyle nextStyle = getStyle(nextStyleID); + if ((nextStyle != null) && (!usedStyleList.contains(nextStyle))) { + usedStyleList.add(linkStyle); + getUsedStyleList(linkStyle, usedStyleList); + } + return usedStyleList; + } + + protected CTLanguage getCTLanguage() { + ensureDocDefaults(); + + CTLanguage lang = null; + if (defaultRunStyle.getRPr().isSetLang()) { + lang = defaultRunStyle.getRPr().getLang(); + } else { + lang = defaultRunStyle.getRPr().addNewLang(); + } + + return lang; + } + + /** + * Sets the default spelling language on ctStyles DocDefaults parameter + * + * @param strSpellingLanguage + */ + public void setSpellingLanguage(String strSpellingLanguage) { CTLanguage lang = getCTLanguage(); - lang.setVal(strSpellingLanguage); - lang.setBidi(strSpellingLanguage); - } - - /** - * Sets the default East Asia spelling language on ctStyles DocDefaults parameter - * - * @param strEastAsia - */ - public void setEastAsia(String strEastAsia) { + lang.setVal(strSpellingLanguage); + lang.setBidi(strSpellingLanguage); + } + + /** + * Sets the default East Asia spelling language on ctStyles DocDefaults parameter + * + * @param strEastAsia + */ + public void setEastAsia(String strEastAsia) { CTLanguage lang = getCTLanguage(); lang.setEastAsia(strEastAsia); } - /** - * Sets the default font on ctStyles DocDefaults parameter - * TODO Replace this with specific setters for each type, possibly - * on XWPFDefaultRunStyle - */ - public void setDefaultFonts(CTFonts fonts) { - ensureDocDefaults(); - - CTRPr runProps = defaultRunStyle.getRPr(); - runProps.setRFonts(fonts); - } + /** + * Sets the default font on ctStyles DocDefaults parameter + * TODO Replace this with specific setters for each type, possibly + * on XWPFDefaultRunStyle + */ + public void setDefaultFonts(CTFonts fonts) { + ensureDocDefaults(); + + CTRPr runProps = defaultRunStyle.getRPr(); + runProps.setRFonts(fonts); + } /** - * get the style with the same name - * if this style is not existing, return null - */ - public XWPFStyle getStyleWithSameName(XWPFStyle style) { - for (XWPFStyle ownStyle : listStyle) { - if (ownStyle.hasSameName(style)) { - return ownStyle; - } - } - return null; - } + * get the style with the same name + * if this style is not existing, return null + */ + public XWPFStyle getStyleWithSameName(XWPFStyle style) { + for (XWPFStyle ownStyle : listStyle) { + if (ownStyle.hasSameName(style)) { + return ownStyle; + } + } + return null; + } /** * Get the default style which applies text runs in the document diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java index f070b095e7..a20fe5220a 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java @@ -1,518 +1,518 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; - -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.util.Internal; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtRun; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.STShd; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; - -/** - * Represents a Cell within a {@link XWPFTable}. The - * Cell is the thing that holds the actual content (paragraphs etc) - */ -public class XWPFTableCell implements IBody, ICell { - private static EnumMap alignMap; - // Create a map from the STVerticalJc.Enum values to the XWPF-level enums - private static HashMap stVertAlignTypeMap; - - static { - // populate enum maps - alignMap = new EnumMap(XWPFVertAlign.class); - alignMap.put(XWPFVertAlign.TOP, STVerticalJc.Enum.forInt(STVerticalJc.INT_TOP)); - alignMap.put(XWPFVertAlign.CENTER, STVerticalJc.Enum.forInt(STVerticalJc.INT_CENTER)); - alignMap.put(XWPFVertAlign.BOTH, STVerticalJc.Enum.forInt(STVerticalJc.INT_BOTH)); - alignMap.put(XWPFVertAlign.BOTTOM, STVerticalJc.Enum.forInt(STVerticalJc.INT_BOTTOM)); - - stVertAlignTypeMap = new HashMap(); - stVertAlignTypeMap.put(STVerticalJc.INT_TOP, XWPFVertAlign.TOP); - stVertAlignTypeMap.put(STVerticalJc.INT_CENTER, XWPFVertAlign.CENTER); - stVertAlignTypeMap.put(STVerticalJc.INT_BOTH, XWPFVertAlign.BOTH); - stVertAlignTypeMap.put(STVerticalJc.INT_BOTTOM, XWPFVertAlign.BOTTOM); - - } - - private final CTTc ctTc; - protected List paragraphs = null; - protected List tables = null; - protected List bodyElements = null; - - protected IBody part; - private XWPFTableRow tableRow = null; - - /** - * If a table cell does not include at least one block-level element, then this document shall be considered corrupt - */ - public XWPFTableCell(CTTc cell, XWPFTableRow tableRow, IBody part) { - this.ctTc = cell; - this.part = part; - this.tableRow = tableRow; - // NB: If a table cell does not include at least one block-level element, then this document shall be considered corrupt. - if (cell.sizeOfPArray() < 1) - cell.addNewP(); - bodyElements = new ArrayList(); - paragraphs = new ArrayList(); - tables = new ArrayList(); - - XmlCursor cursor = ctTc.newCursor(); - cursor.selectPath("./*"); - while (cursor.toNextSelection()) { - XmlObject o = cursor.getObject(); - if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP) o, this); - paragraphs.add(p); - bodyElements.add(p); - } - if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl) o, this); - tables.add(t); - bodyElements.add(t); - } - if (o instanceof CTSdtBlock) { - XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); - bodyElements.add(c); - } - if (o instanceof CTSdtRun) { - XWPFSDT c = new XWPFSDT((CTSdtRun) o, this); - System.out.println(c.getContent().getText()); - bodyElements.add(c); - } - } - cursor.dispose(); - } - - @Internal - public CTTc getCTTc() { - return ctTc; - } - - /** - * returns an Iterator with paragraphs and tables - * - * @see org.apache.poi.xwpf.usermodel.IBody#getBodyElements() - */ - public List getBodyElements() { - return Collections.unmodifiableList(bodyElements); - } - - public void setParagraph(XWPFParagraph p) { - if (ctTc.sizeOfPArray() == 0) { - ctTc.addNewP(); - } - ctTc.setPArray(0, p.getCTP()); - } - - /** - * returns a list of paragraphs - */ - public List getParagraphs() { - return paragraphs; - } - - /** - * Add a Paragraph to this Table Cell - * - * @return The paragraph which was added - */ - public XWPFParagraph addParagraph() { - XWPFParagraph p = new XWPFParagraph(ctTc.addNewP(), this); - addParagraph(p); - return p; - } - - /** - * add a Paragraph to this TableCell - * - * @param p the paragaph which has to be added - */ - public void addParagraph(XWPFParagraph p) { - paragraphs.add(p); - } - - /** - * removes a paragraph of this tablecell - * - * @param pos The position in the list of paragraphs, 0-based - */ - public void removeParagraph(int pos) { - paragraphs.remove(pos); - ctTc.removeP(pos); - } - - /** - * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this table - * the method will return this paragraph - * if there is no corresponding {@link XWPFParagraph} the method will return null - * - * @param p is instance of CTP and is searching for an XWPFParagraph - * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this table - * XWPFParagraph with the correspondig CTP p - */ - public XWPFParagraph getParagraph(CTP p) { - for (XWPFParagraph paragraph : paragraphs) { - if (p.equals(paragraph.getCTP())) { - return paragraph; - } - } - return null; - } - - public XWPFTableRow getTableRow() { - return tableRow; - } - - /** - * Get cell color. Note that this method only returns the "fill" value. - * - * @return RGB string of cell color - */ - public String getColor() { - String color = null; - CTTcPr tcpr = ctTc.getTcPr(); - if (tcpr != null) { - CTShd ctshd = tcpr.getShd(); - if (ctshd != null) { - color = ctshd.xgetFill().getStringValue(); - } - } - return color; - } - - /** - * Set cell color. This sets some associated values; for finer control - * you may want to access these elements individually. - * - * @param rgbStr - the desired cell color, in the hex form "RRGGBB". - */ - public void setColor(String rgbStr) { - CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); - CTShd ctshd = tcpr.isSetShd() ? tcpr.getShd() : tcpr.addNewShd(); - ctshd.setColor("auto"); - ctshd.setVal(STShd.CLEAR); - ctshd.setFill(rgbStr); - } - - /** - * Get the vertical alignment of the cell. - * - * @return the cell alignment enum value or null - * if no vertical alignment is set. - */ - public XWPFVertAlign getVerticalAlignment() { - XWPFVertAlign vAlign = null; - CTTcPr tcpr = ctTc.getTcPr(); - if (tcpr != null) { - CTVerticalJc va = tcpr.getVAlign(); - if(va != null) { - vAlign = stVertAlignTypeMap.get(va.getVal().intValue()); - } else { - vAlign = XWPFVertAlign.TOP; - } - if (va != null && va.getVal() != null) { - vAlign = stVertAlignTypeMap.get(va.getVal().intValue()); - } - } - return vAlign; - } - - /** - * Set the vertical alignment of the cell. - * - * @param vAlign - the desired alignment enum value - */ - public void setVerticalAlignment(XWPFVertAlign vAlign) { - CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); - CTVerticalJc va = tcpr.addNewVAlign(); - va.setVal(alignMap.get(vAlign)); - } - - /** - * add a new paragraph at position of the cursor - * - * @param cursor The XmlCursor structure created with XmlBeans - * @return the inserted paragraph - */ - public XWPFParagraph insertNewParagraph(final XmlCursor cursor) { - if (!isCursorInTableCell(cursor)) { - return null; - } - - String uri = CTP.type.getName().getNamespaceURI(); - String localPart = "p"; - cursor.beginElement(localPart, uri); - cursor.toParent(); - CTP p = (CTP) cursor.getObject(); - XWPFParagraph newP = new XWPFParagraph(p, this); - XmlObject o = null; - while (!(o instanceof CTP) && (cursor.toPrevSibling())) { - o = cursor.getObject(); - } - if ((!(o instanceof CTP)) || (CTP) o == p) { - paragraphs.add(0, newP); - } else { - int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1; - paragraphs.add(pos, newP); - } - int i = 0; - XmlCursor p2 = p.newCursor(); - cursor.toCursor(p2); - p2.dispose(); - while (cursor.toPrevSibling()) { - o = cursor.getObject(); - if (o instanceof CTP || o instanceof CTTbl) - i++; - } - bodyElements.add(i, newP); - p2 = p.newCursor(); - cursor.toCursor(p2); - p2.dispose(); - cursor.toEndToken(); - return newP; - } - - public XWPFTable insertNewTbl(final XmlCursor cursor) { - if (isCursorInTableCell(cursor)) { - String uri = CTTbl.type.getName().getNamespaceURI(); - String localPart = "tbl"; - cursor.beginElement(localPart, uri); - cursor.toParent(); - CTTbl t = (CTTbl) cursor.getObject(); - XWPFTable newT = new XWPFTable(t, this); - cursor.removeXmlContents(); - XmlObject o = null; - while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) { - o = cursor.getObject(); - } - if (!(o instanceof CTTbl)) { - tables.add(0, newT); - } else { - int pos = tables.indexOf(getTable((CTTbl) o)) + 1; - tables.add(pos, newT); - } - int i = 0; - XmlCursor cursor2 = t.newCursor(); - while (cursor2.toPrevSibling()) { - o = cursor2.getObject(); - if (o instanceof CTP || o instanceof CTTbl) - i++; - } - cursor2.dispose(); - bodyElements.add(i, newT); - cursor2 = t.newCursor(); - cursor.toCursor(cursor2); - cursor.toEndToken(); - cursor2.dispose(); - return newT; - } - return null; - } - - /** - * verifies that cursor is on the right position - */ - private boolean isCursorInTableCell(XmlCursor cursor) { - XmlCursor verify = cursor.newCursor(); - verify.toParent(); - boolean result = (verify.getObject() == this.ctTc); - verify.dispose(); - return result; - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int) - */ - public XWPFParagraph getParagraphArray(int pos) { - if (pos >= 0 && pos < paragraphs.size()) { - return paragraphs.get(pos); - } - return null; - } - - /** - * get the to which the TableCell belongs - * - * @see org.apache.poi.xwpf.usermodel.IBody#getPart() - */ - public POIXMLDocumentPart getPart() { - return tableRow.getTable().getPart(); - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() - */ - public BodyType getPartType() { - return BodyType.TABLECELL; - } - - /** - * get a table by its CTTbl-Object - * - * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) - */ - public XWPFTable getTable(CTTbl ctTable) { - for (int i = 0; i < tables.size(); i++) { - if (getTables().get(i).getCTTbl() == ctTable) return getTables().get(i); - } - return null; - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) - */ - public XWPFTable getTableArray(int pos) { - if(pos >= 0 && pos < tables.size()) { - return tables.get(pos); - } - return null; - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getTables() - */ - public List getTables() { - return Collections.unmodifiableList(tables); - } - - /** - * inserts an existing XWPFTable to the arrays bodyElements and tables - * - * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int, org.apache.poi.xwpf.usermodel.XWPFTable) - */ - public void insertTable(int pos, XWPFTable table) { - bodyElements.add(pos, table); - int i = 0; - for (CTTbl tbl : ctTc.getTblArray()) { - if (tbl == table.getCTTbl()) { - break; - } - i++; - } - tables.add(i, table); - } - - public String getText() { - StringBuilder text = new StringBuilder(); - for (XWPFParagraph p : paragraphs) { - text.append(p.getText()); - } - return text.toString(); - } - - public void setText(String text) { - CTP ctP = (ctTc.sizeOfPArray() == 0) ? ctTc.addNewP() : ctTc.getPArray(0); - XWPFParagraph par = new XWPFParagraph(ctP, this); - par.createRun().setText(text); - } - - /** - * extracts all text recursively through embedded tables and embedded SDTs - */ - public String getTextRecursively() { - - StringBuffer text = new StringBuffer(); - for (int i = 0; i < bodyElements.size(); i++) { - boolean isLast = (i == bodyElements.size() - 1); - appendBodyElementText(text, bodyElements.get(i), isLast); - } - - return text.toString(); - } - - private void appendBodyElementText(StringBuffer text, IBodyElement e, boolean isLast) { - if (e instanceof XWPFParagraph) { - text.append(((XWPFParagraph) e).getText()); - if (!isLast) { - text.append('\t'); - } - } else if (e instanceof XWPFTable) { - XWPFTable eTable = (XWPFTable) e; - for (XWPFTableRow row : eTable.getRows()) { - for (XWPFTableCell cell : row.getTableCells()) { - List localBodyElements = cell.getBodyElements(); - for (int i = 0; i < localBodyElements.size(); i++) { - boolean localIsLast = (i == localBodyElements.size() - 1); - appendBodyElementText(text, localBodyElements.get(i), localIsLast); - } - } - } - - if (!isLast) { - text.append('\n'); - } - } else if (e instanceof XWPFSDT) { - text.append(((XWPFSDT) e).getContent().getText()); - if (!isLast) { - text.append('\t'); - } - } - } - - /** - * get the TableCell which belongs to the TableCell - */ - public XWPFTableCell getTableCell(CTTc cell) { - XmlCursor cursor = cell.newCursor(); - cursor.toParent(); - XmlObject o = cursor.getObject(); - if (!(o instanceof CTRow)) { - return null; - } - CTRow row = (CTRow) o; - cursor.toParent(); - o = cursor.getObject(); - cursor.dispose(); - if (!(o instanceof CTTbl)) { - return null; - } - CTTbl tbl = (CTTbl) o; - XWPFTable table = getTable(tbl); - if (table == null) { - return null; - } - XWPFTableRow tr = table.getRow(row); - if (tr == null) { - return null; - } - return tr.getTableCell(cell); - } - - public XWPFDocument getXWPFDocument() { - return part.getXWPFDocument(); - } - - // Create a map from this XWPF-level enum to the STVerticalJc.Enum values - public enum XWPFVertAlign { - TOP, CENTER, BOTH, BOTTOM - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xwpf.usermodel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.util.Internal; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtRun; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STShd; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; + +/** + * Represents a Cell within a {@link XWPFTable}. The + * Cell is the thing that holds the actual content (paragraphs etc) + */ +public class XWPFTableCell implements IBody, ICell { + private static EnumMap alignMap; + // Create a map from the STVerticalJc.Enum values to the XWPF-level enums + private static HashMap stVertAlignTypeMap; + + static { + // populate enum maps + alignMap = new EnumMap(XWPFVertAlign.class); + alignMap.put(XWPFVertAlign.TOP, STVerticalJc.Enum.forInt(STVerticalJc.INT_TOP)); + alignMap.put(XWPFVertAlign.CENTER, STVerticalJc.Enum.forInt(STVerticalJc.INT_CENTER)); + alignMap.put(XWPFVertAlign.BOTH, STVerticalJc.Enum.forInt(STVerticalJc.INT_BOTH)); + alignMap.put(XWPFVertAlign.BOTTOM, STVerticalJc.Enum.forInt(STVerticalJc.INT_BOTTOM)); + + stVertAlignTypeMap = new HashMap(); + stVertAlignTypeMap.put(STVerticalJc.INT_TOP, XWPFVertAlign.TOP); + stVertAlignTypeMap.put(STVerticalJc.INT_CENTER, XWPFVertAlign.CENTER); + stVertAlignTypeMap.put(STVerticalJc.INT_BOTH, XWPFVertAlign.BOTH); + stVertAlignTypeMap.put(STVerticalJc.INT_BOTTOM, XWPFVertAlign.BOTTOM); + + } + + private final CTTc ctTc; + protected List paragraphs = null; + protected List tables = null; + protected List bodyElements = null; + + protected IBody part; + private XWPFTableRow tableRow = null; + + /** + * If a table cell does not include at least one block-level element, then this document shall be considered corrupt + */ + public XWPFTableCell(CTTc cell, XWPFTableRow tableRow, IBody part) { + this.ctTc = cell; + this.part = part; + this.tableRow = tableRow; + // NB: If a table cell does not include at least one block-level element, then this document shall be considered corrupt. + if (cell.sizeOfPArray() < 1) + cell.addNewP(); + bodyElements = new ArrayList(); + paragraphs = new ArrayList(); + tables = new ArrayList(); + + XmlCursor cursor = ctTc.newCursor(); + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { + XmlObject o = cursor.getObject(); + if (o instanceof CTP) { + XWPFParagraph p = new XWPFParagraph((CTP) o, this); + paragraphs.add(p); + bodyElements.add(p); + } + if (o instanceof CTTbl) { + XWPFTable t = new XWPFTable((CTTbl) o, this); + tables.add(t); + bodyElements.add(t); + } + if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); + bodyElements.add(c); + } + if (o instanceof CTSdtRun) { + XWPFSDT c = new XWPFSDT((CTSdtRun) o, this); + System.out.println(c.getContent().getText()); + bodyElements.add(c); + } + } + cursor.dispose(); + } + + @Internal + public CTTc getCTTc() { + return ctTc; + } + + /** + * returns an Iterator with paragraphs and tables + * + * @see org.apache.poi.xwpf.usermodel.IBody#getBodyElements() + */ + public List getBodyElements() { + return Collections.unmodifiableList(bodyElements); + } + + public void setParagraph(XWPFParagraph p) { + if (ctTc.sizeOfPArray() == 0) { + ctTc.addNewP(); + } + ctTc.setPArray(0, p.getCTP()); + } + + /** + * returns a list of paragraphs + */ + public List getParagraphs() { + return paragraphs; + } + + /** + * Add a Paragraph to this Table Cell + * + * @return The paragraph which was added + */ + public XWPFParagraph addParagraph() { + XWPFParagraph p = new XWPFParagraph(ctTc.addNewP(), this); + addParagraph(p); + return p; + } + + /** + * add a Paragraph to this TableCell + * + * @param p the paragaph which has to be added + */ + public void addParagraph(XWPFParagraph p) { + paragraphs.add(p); + } + + /** + * removes a paragraph of this tablecell + * + * @param pos The position in the list of paragraphs, 0-based + */ + public void removeParagraph(int pos) { + paragraphs.remove(pos); + ctTc.removeP(pos); + } + + /** + * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this table + * the method will return this paragraph + * if there is no corresponding {@link XWPFParagraph} the method will return null + * + * @param p is instance of CTP and is searching for an XWPFParagraph + * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this table + * XWPFParagraph with the correspondig CTP p + */ + public XWPFParagraph getParagraph(CTP p) { + for (XWPFParagraph paragraph : paragraphs) { + if (p.equals(paragraph.getCTP())) { + return paragraph; + } + } + return null; + } + + public XWPFTableRow getTableRow() { + return tableRow; + } + + /** + * Get cell color. Note that this method only returns the "fill" value. + * + * @return RGB string of cell color + */ + public String getColor() { + String color = null; + CTTcPr tcpr = ctTc.getTcPr(); + if (tcpr != null) { + CTShd ctshd = tcpr.getShd(); + if (ctshd != null) { + color = ctshd.xgetFill().getStringValue(); + } + } + return color; + } + + /** + * Set cell color. This sets some associated values; for finer control + * you may want to access these elements individually. + * + * @param rgbStr - the desired cell color, in the hex form "RRGGBB". + */ + public void setColor(String rgbStr) { + CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); + CTShd ctshd = tcpr.isSetShd() ? tcpr.getShd() : tcpr.addNewShd(); + ctshd.setColor("auto"); + ctshd.setVal(STShd.CLEAR); + ctshd.setFill(rgbStr); + } + + /** + * Get the vertical alignment of the cell. + * + * @return the cell alignment enum value or null + * if no vertical alignment is set. + */ + public XWPFVertAlign getVerticalAlignment() { + XWPFVertAlign vAlign = null; + CTTcPr tcpr = ctTc.getTcPr(); + if (tcpr != null) { + CTVerticalJc va = tcpr.getVAlign(); + if(va != null) { + vAlign = stVertAlignTypeMap.get(va.getVal().intValue()); + } else { + vAlign = XWPFVertAlign.TOP; + } + if (va != null && va.getVal() != null) { + vAlign = stVertAlignTypeMap.get(va.getVal().intValue()); + } + } + return vAlign; + } + + /** + * Set the vertical alignment of the cell. + * + * @param vAlign - the desired alignment enum value + */ + public void setVerticalAlignment(XWPFVertAlign vAlign) { + CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); + CTVerticalJc va = tcpr.addNewVAlign(); + va.setVal(alignMap.get(vAlign)); + } + + /** + * add a new paragraph at position of the cursor + * + * @param cursor The XmlCursor structure created with XmlBeans + * @return the inserted paragraph + */ + public XWPFParagraph insertNewParagraph(final XmlCursor cursor) { + if (!isCursorInTableCell(cursor)) { + return null; + } + + String uri = CTP.type.getName().getNamespaceURI(); + String localPart = "p"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTP p = (CTP) cursor.getObject(); + XWPFParagraph newP = new XWPFParagraph(p, this); + XmlObject o = null; + while (!(o instanceof CTP) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if ((!(o instanceof CTP)) || (CTP) o == p) { + paragraphs.add(0, newP); + } else { + int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1; + paragraphs.add(pos, newP); + } + int i = 0; + XmlCursor p2 = p.newCursor(); + cursor.toCursor(p2); + p2.dispose(); + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + bodyElements.add(i, newP); + p2 = p.newCursor(); + cursor.toCursor(p2); + p2.dispose(); + cursor.toEndToken(); + return newP; + } + + public XWPFTable insertNewTbl(final XmlCursor cursor) { + if (isCursorInTableCell(cursor)) { + String uri = CTTbl.type.getName().getNamespaceURI(); + String localPart = "tbl"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTTbl t = (CTTbl) cursor.getObject(); + XWPFTable newT = new XWPFTable(t, this); + cursor.removeXmlContents(); + XmlObject o = null; + while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if (!(o instanceof CTTbl)) { + tables.add(0, newT); + } else { + int pos = tables.indexOf(getTable((CTTbl) o)) + 1; + tables.add(pos, newT); + } + int i = 0; + XmlCursor cursor2 = t.newCursor(); + while (cursor2.toPrevSibling()) { + o = cursor2.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + cursor2.dispose(); + bodyElements.add(i, newT); + cursor2 = t.newCursor(); + cursor.toCursor(cursor2); + cursor.toEndToken(); + cursor2.dispose(); + return newT; + } + return null; + } + + /** + * verifies that cursor is on the right position + */ + private boolean isCursorInTableCell(XmlCursor cursor) { + XmlCursor verify = cursor.newCursor(); + verify.toParent(); + boolean result = (verify.getObject() == this.ctTc); + verify.dispose(); + return result; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int) + */ + public XWPFParagraph getParagraphArray(int pos) { + if (pos >= 0 && pos < paragraphs.size()) { + return paragraphs.get(pos); + } + return null; + } + + /** + * get the to which the TableCell belongs + * + * @see org.apache.poi.xwpf.usermodel.IBody#getPart() + */ + public POIXMLDocumentPart getPart() { + return tableRow.getTable().getPart(); + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() + */ + public BodyType getPartType() { + return BodyType.TABLECELL; + } + + /** + * get a table by its CTTbl-Object + * + * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) + */ + public XWPFTable getTable(CTTbl ctTable) { + for (int i = 0; i < tables.size(); i++) { + if (getTables().get(i).getCTTbl() == ctTable) return getTables().get(i); + } + return null; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) + */ + public XWPFTable getTableArray(int pos) { + if(pos >= 0 && pos < tables.size()) { + return tables.get(pos); + } + return null; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getTables() + */ + public List getTables() { + return Collections.unmodifiableList(tables); + } + + /** + * inserts an existing XWPFTable to the arrays bodyElements and tables + * + * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int, org.apache.poi.xwpf.usermodel.XWPFTable) + */ + public void insertTable(int pos, XWPFTable table) { + bodyElements.add(pos, table); + int i = 0; + for (CTTbl tbl : ctTc.getTblArray()) { + if (tbl == table.getCTTbl()) { + break; + } + i++; + } + tables.add(i, table); + } + + public String getText() { + StringBuilder text = new StringBuilder(); + for (XWPFParagraph p : paragraphs) { + text.append(p.getText()); + } + return text.toString(); + } + + public void setText(String text) { + CTP ctP = (ctTc.sizeOfPArray() == 0) ? ctTc.addNewP() : ctTc.getPArray(0); + XWPFParagraph par = new XWPFParagraph(ctP, this); + par.createRun().setText(text); + } + + /** + * extracts all text recursively through embedded tables and embedded SDTs + */ + public String getTextRecursively() { + + StringBuffer text = new StringBuffer(); + for (int i = 0; i < bodyElements.size(); i++) { + boolean isLast = (i == bodyElements.size() - 1); + appendBodyElementText(text, bodyElements.get(i), isLast); + } + + return text.toString(); + } + + private void appendBodyElementText(StringBuffer text, IBodyElement e, boolean isLast) { + if (e instanceof XWPFParagraph) { + text.append(((XWPFParagraph) e).getText()); + if (!isLast) { + text.append('\t'); + } + } else if (e instanceof XWPFTable) { + XWPFTable eTable = (XWPFTable) e; + for (XWPFTableRow row : eTable.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + List localBodyElements = cell.getBodyElements(); + for (int i = 0; i < localBodyElements.size(); i++) { + boolean localIsLast = (i == localBodyElements.size() - 1); + appendBodyElementText(text, localBodyElements.get(i), localIsLast); + } + } + } + + if (!isLast) { + text.append('\n'); + } + } else if (e instanceof XWPFSDT) { + text.append(((XWPFSDT) e).getContent().getText()); + if (!isLast) { + text.append('\t'); + } + } + } + + /** + * get the TableCell which belongs to the TableCell + */ + public XWPFTableCell getTableCell(CTTc cell) { + XmlCursor cursor = cell.newCursor(); + cursor.toParent(); + XmlObject o = cursor.getObject(); + if (!(o instanceof CTRow)) { + return null; + } + CTRow row = (CTRow) o; + cursor.toParent(); + o = cursor.getObject(); + cursor.dispose(); + if (!(o instanceof CTTbl)) { + return null; + } + CTTbl tbl = (CTTbl) o; + XWPFTable table = getTable(tbl); + if (table == null) { + return null; + } + XWPFTableRow tr = table.getRow(row); + if (tr == null) { + return null; + } + return tr.getTableCell(cell); + } + + public XWPFDocument getXWPFDocument() { + return part.getXWPFDocument(); + } + + // Create a map from this XWPF-level enum to the STVerticalJc.Enum values + public enum XWPFVertAlign { + TOP, CENTER, BOTH, BOTTOM + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java index 454a4c3f22..4755a82096 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java @@ -31,14 +31,14 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtCell; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr; - -/** - * A row within an {@link XWPFTable}. Rows mostly just have - * sizings and stylings, the interesting content lives inside - * the child {@link XWPFTableCell}s - */ -public class XWPFTableRow { - private CTRow ctRow; + +/** + * A row within an {@link XWPFTable}. Rows mostly just have + * sizings and stylings, the interesting content lives inside + * the child {@link XWPFTableCell}s + */ +public class XWPFTableRow { + private CTRow ctRow; private XWPFTable table; private List tableCells; @@ -52,144 +52,144 @@ public class XWPFTableRow { public CTRow getCtRow() { return ctRow; } - - /** - * create a new XWPFTableCell and add it to the tableCell-list of this tableRow - * - * @return the newly created XWPFTableCell - */ - public XWPFTableCell createCell() { - XWPFTableCell tableCell = new XWPFTableCell(ctRow.addNewTc(), this, table.getBody()); - tableCells.add(tableCell); - return tableCell; - } - - public XWPFTableCell getCell(int pos) { - if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { - return getTableCells().get(pos); - } - return null; - } - - public void removeCell(int pos) { - if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { - tableCells.remove(pos); - } - } - - /** - * adds a new TableCell at the end of this tableRow - */ - public XWPFTableCell addNewTableCell() { - CTTc cell = ctRow.addNewTc(); - XWPFTableCell tableCell = new XWPFTableCell(cell, this, table.getBody()); - tableCells.add(tableCell); - return tableCell; - } - - /** + + /** + * create a new XWPFTableCell and add it to the tableCell-list of this tableRow + * + * @return the newly created XWPFTableCell + */ + public XWPFTableCell createCell() { + XWPFTableCell tableCell = new XWPFTableCell(ctRow.addNewTc(), this, table.getBody()); + tableCells.add(tableCell); + return tableCell; + } + + public XWPFTableCell getCell(int pos) { + if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { + return getTableCells().get(pos); + } + return null; + } + + public void removeCell(int pos) { + if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { + tableCells.remove(pos); + } + } + + /** + * adds a new TableCell at the end of this tableRow + */ + public XWPFTableCell addNewTableCell() { + CTTc cell = ctRow.addNewTc(); + XWPFTableCell tableCell = new XWPFTableCell(cell, this, table.getBody()); + tableCells.add(tableCell); + return tableCell; + } + + /** * This element specifies the height of the current table row within the * current table. This height shall be used to determine the resulting * height of the table row, which may be absolute or relative (depending on * its attribute values). If omitted, then the table row shall automatically - * resize its height to the height required by its contents (the equivalent - * of an hRule value of auto). - * - * @return height - */ - public int getHeight() { - CTTrPr properties = getTrPr(); - return properties.sizeOfTrHeightArray() == 0 ? 0 : properties.getTrHeightArray(0).getVal().intValue(); - } - - /** + * resize its height to the height required by its contents (the equivalent + * of an hRule value of auto). + * + * @return height + */ + public int getHeight() { + CTTrPr properties = getTrPr(); + return properties.sizeOfTrHeightArray() == 0 ? 0 : properties.getTrHeightArray(0).getVal().intValue(); + } + + /** * This element specifies the height of the current table row within the * current table. This height shall be used to determine the resulting * height of the table row, which may be absolute or relative (depending on * its attribute values). If omitted, then the table row shall automatically - * resize its height to the height required by its contents (the equivalent - * of an hRule value of auto). - * - * @param height - */ - public void setHeight(int height) { - CTTrPr properties = getTrPr(); - CTHeight h = properties.sizeOfTrHeightArray() == 0 ? properties.addNewTrHeight() : properties.getTrHeightArray(0); - h.setVal(new BigInteger("" + height)); - } - - private CTTrPr getTrPr() { - return (ctRow.isSetTrPr()) ? ctRow.getTrPr() : ctRow.addNewTrPr(); - } - - public XWPFTable getTable() { - return table; - } - - /** - * create and return a list of all XWPFTableCell - * who belongs to this row - * - * @return a list of {@link XWPFTableCell} - */ - public List getTableICells() { - - List cells = new ArrayList(); - //Can't use ctRow.getTcList because that only gets table cells - //Can't use ctRow.getSdtList because that only gets sdts that are at cell level + * resize its height to the height required by its contents (the equivalent + * of an hRule value of auto). + * + * @param height + */ + public void setHeight(int height) { + CTTrPr properties = getTrPr(); + CTHeight h = properties.sizeOfTrHeightArray() == 0 ? properties.addNewTrHeight() : properties.getTrHeightArray(0); + h.setVal(new BigInteger("" + height)); + } + + private CTTrPr getTrPr() { + return (ctRow.isSetTrPr()) ? ctRow.getTrPr() : ctRow.addNewTrPr(); + } + + public XWPFTable getTable() { + return table; + } + + /** + * create and return a list of all XWPFTableCell + * who belongs to this row + * + * @return a list of {@link XWPFTableCell} + */ + public List getTableICells() { + + List cells = new ArrayList(); + //Can't use ctRow.getTcList because that only gets table cells + //Can't use ctRow.getSdtList because that only gets sdts that are at cell level XmlCursor cursor = ctRow.newCursor(); - cursor.selectPath("./*"); - while (cursor.toNextSelection()) { - XmlObject o = cursor.getObject(); - if (o instanceof CTTc) { - cells.add(new XWPFTableCell((CTTc) o, this, table.getBody())); - } else if (o instanceof CTSdtCell) { - cells.add(new XWPFSDTCell((CTSdtCell) o, this, table.getBody())); - } + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { + XmlObject o = cursor.getObject(); + if (o instanceof CTTc) { + cells.add(new XWPFTableCell((CTTc) o, this, table.getBody())); + } else if (o instanceof CTSdtCell) { + cells.add(new XWPFSDTCell((CTSdtCell) o, this, table.getBody())); + } + } + cursor.dispose(); + return cells; + } + + /** + * create and return a list of all XWPFTableCell + * who belongs to this row + * + * @return a list of {@link XWPFTableCell} + */ + public List getTableCells() { + if (tableCells == null) { + List cells = new ArrayList(); + for (CTTc tableCell : ctRow.getTcArray()) { + cells.add(new XWPFTableCell(tableCell, this, table.getBody())); + } + //TODO: it is possible to have an SDT that contains a cell in within a row + //need to modify this code so that it pulls out SDT wrappers around cells, too. + + this.tableCells = cells; } - cursor.dispose(); - return cells; + return tableCells; } - /** - * create and return a list of all XWPFTableCell - * who belongs to this row - * - * @return a list of {@link XWPFTableCell} - */ - public List getTableCells() { - if (tableCells == null) { - List cells = new ArrayList(); - for (CTTc tableCell : ctRow.getTcArray()) { - cells.add(new XWPFTableCell(tableCell, this, table.getBody())); - } - //TODO: it is possible to have an SDT that contains a cell in within a row - //need to modify this code so that it pulls out SDT wrappers around cells, too. - - this.tableCells = cells; - } - return tableCells; - } - - /** + /** * returns the XWPFTableCell which belongs to the CTTC cell - * if there is no XWPFTableCell which belongs to the parameter CTTc cell null will be returned - */ - public XWPFTableCell getTableCell(CTTc cell) { - for (int i = 0; i < tableCells.size(); i++) { - if (tableCells.get(i).getCTTc() == cell) - return tableCells.get(i); - } - return null; - } - - /** - * Return true if the "can't split row" value is true. The logic for this - * attribute is a little unusual: a TRUE value means DON'T allow rows to - * split, FALSE means allow rows to split. - * - * @return true if rows can't be split, false otherwise. - */ + * if there is no XWPFTableCell which belongs to the parameter CTTc cell null will be returned + */ + public XWPFTableCell getTableCell(CTTc cell) { + for (int i = 0; i < tableCells.size(); i++) { + if (tableCells.get(i).getCTTc() == cell) + return tableCells.get(i); + } + return null; + } + + /** + * Return true if the "can't split row" value is true. The logic for this + * attribute is a little unusual: a TRUE value means DON'T allow rows to + * split, FALSE means allow rows to split. + * + * @return true if rows can't be split, false otherwise. + */ public boolean isCantSplitRow() { boolean isCant = false; if (ctRow.isSetTrPr()) { @@ -200,41 +200,41 @@ public class XWPFTableRow { } } return isCant; - } - - /** - * Controls whether to allow this table row to split across pages. - * The logic for this attribute is a little unusual: a true value means - * DON'T allow rows to split, false means allow rows to split. - * - * @param split - if true, don't allow row to be split. If false, allow - * row to be split. - */ - public void setCantSplitRow(boolean split) { - CTTrPr trpr = getTrPr(); - CTOnOff onoff = (trpr.sizeOfCantSplitArray() > 0 ? trpr.getCantSplitArray(0) : trpr.addNewCantSplit()); - onoff.setVal(WMLHelper.convertBooleanToSTOnOff(split)); - } - - /** - * Return true if a table's header row should be repeated at the top of a + } + + /** + * Controls whether to allow this table row to split across pages. + * The logic for this attribute is a little unusual: a true value means + * DON'T allow rows to split, false means allow rows to split. + * + * @param split - if true, don't allow row to be split. If false, allow + * row to be split. + */ + public void setCantSplitRow(boolean split) { + CTTrPr trpr = getTrPr(); + CTOnOff onoff = (trpr.sizeOfCantSplitArray() > 0 ? trpr.getCantSplitArray(0) : trpr.addNewCantSplit()); + onoff.setVal(WMLHelper.convertBooleanToSTOnOff(split)); + } + + /** + * Return true if a table's header row should be repeated at the top of a * table split across pages. NOTE - Word will not repeat a table row unless * all preceding rows of the table are also repeated. This function returns * false if the row will not be repeated even if the repeat tag is present - * for this row. - * - * @return true if table's header row should be repeated at the top of each - * page of table, false otherwise. - */ - public boolean isRepeatHeader() { + * for this row. + * + * @return true if table's header row should be repeated at the top of each + * page of table, false otherwise. + */ + public boolean isRepeatHeader() { boolean repeat = false; for (XWPFTableRow row : table.getRows()) { repeat = row.getRepeat(); if (row == this || !repeat) { break; } - } - return repeat; + } + return repeat; } private boolean getRepeat() { @@ -247,19 +247,19 @@ public class XWPFTableRow { } } return repeat; - } - - /** - * This attribute controls whether to repeat a table's header row at the top + } + + /** + * This attribute controls whether to repeat a table's header row at the top * of a table split across pages. NOTE - for a row to be repeated, all preceding - * rows in the table must also be repeated. - * - * @param repeat - if TRUE, repeat header row at the top of each page of table; - * if FALSE, don't repeat header row. - */ - public void setRepeatHeader(boolean repeat) { - CTTrPr trpr = getTrPr(); - CTOnOff onoff = (trpr.sizeOfTblHeaderArray() > 0 ? trpr.getTblHeaderArray(0) : trpr.addNewTblHeader()); - onoff.setVal(WMLHelper.convertBooleanToSTOnOff(repeat)); - } -} + * rows in the table must also be repeated. + * + * @param repeat - if TRUE, repeat header row at the top of each page of table; + * if FALSE, don't repeat header row. + */ + public void setRepeatHeader(boolean repeat) { + CTTrPr trpr = getTrPr(); + CTOnOff onoff = (trpr.sizeOfTblHeaderArray() > 0 ? trpr.getTblHeaderArray(0) : trpr.addNewTblHeader()); + onoff.setVal(WMLHelper.convertBooleanToSTOnOff(repeat)); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java index a910acc0e6..a19e52b97a 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java @@ -1,139 +1,139 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Set; -import java.util.TreeMap; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import org.junit.Assert; - -import junit.framework.AssertionFailedError; - -/** - * Compare the contents of 2 zip files. - */ -public class ZipFileAssert { - private ZipFileAssert() { - } - - static final int BUFFER_SIZE = 2048; - - protected static void equals( - TreeMap file1, - TreeMap file2) { - Set listFile1 = file1.keySet(); - Assert.assertEquals("not the same number of files in zip:", listFile1.size(), file2.keySet().size()); - - for (String fileName : listFile1) { - // extract the contents for both - ByteArrayOutputStream contain2 = file2.get(fileName); - ByteArrayOutputStream contain1 = file1.get(fileName); - - assertNotNull(fileName + " not found in 2nd zip", contain2); - // no need to check for contain1. The key come from it - - if ((fileName.endsWith(".xml")) || fileName.endsWith(".rels")) { - // we have a xml file - // TODO - // YK: the original OpenXML4J version attempted to compare xml using xmlunit (http://xmlunit.sourceforge.net), - // but POI does not depend on this library - } else { - // not xml, may be an image or other binary format - Assert.assertEquals(fileName + " does not have the same size in both zip:", contain2.size(), contain1.size()); - assertArrayEquals("contents differ", contain1.toByteArray(), contain2.toByteArray()); - } - } - } - - protected static TreeMap decompress( - File filename) throws IOException { - // store the zip content in memory - // let s assume it is not Go ;-) - TreeMap zipContent = new TreeMap(); - - byte data[] = new byte[BUFFER_SIZE]; - /* Open file to decompress */ - FileInputStream file_decompress = new FileInputStream(filename); - - /* Create a buffer for the decompressed files */ - BufferedInputStream buffi = new BufferedInputStream(file_decompress); - - /* Open the file with the buffer */ - ZipInputStream zis = new ZipInputStream(buffi); - - /* Processing entries of the zip file */ - ZipEntry entree; - int count; - while ((entree = zis.getNextEntry()) != null) { - - /* Create a array for the current entry */ - ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); - zipContent.put(entree.getName(), byteArray); - - /* copy in memory */ - while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) { - byteArray.write(data, 0, count); - } - /* Flush the buffer */ - byteArray.flush(); - byteArray.close(); - } - - zis.close(); - - return zipContent; - } - - /** - * Asserts that two files are equal. Throws an AssertionFailedError - * if they are not. - *

    - * - */ - public static void assertEquals(File expected, File actual) { - assertNotNull(expected); - assertNotNull(actual); - - assertTrue("File does not exist [" + expected.getAbsolutePath() - + "]", expected.exists()); - assertTrue("File does not exist [" + actual.getAbsolutePath() - + "]", actual.exists()); - - assertTrue("Expected file not readable", expected.canRead()); - assertTrue("Actual file not readable", actual.canRead()); - - try { - TreeMap file1 = decompress(expected); - TreeMap file2 = decompress(actual); - equals(file1, file2); - } catch (IOException e) { - throw new AssertionFailedError(e.toString()); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Set; +import java.util.TreeMap; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.junit.Assert; + +import junit.framework.AssertionFailedError; + +/** + * Compare the contents of 2 zip files. + */ +public class ZipFileAssert { + private ZipFileAssert() { + } + + static final int BUFFER_SIZE = 2048; + + protected static void equals( + TreeMap file1, + TreeMap file2) { + Set listFile1 = file1.keySet(); + Assert.assertEquals("not the same number of files in zip:", listFile1.size(), file2.keySet().size()); + + for (String fileName : listFile1) { + // extract the contents for both + ByteArrayOutputStream contain2 = file2.get(fileName); + ByteArrayOutputStream contain1 = file1.get(fileName); + + assertNotNull(fileName + " not found in 2nd zip", contain2); + // no need to check for contain1. The key come from it + + if ((fileName.endsWith(".xml")) || fileName.endsWith(".rels")) { + // we have a xml file + // TODO + // YK: the original OpenXML4J version attempted to compare xml using xmlunit (http://xmlunit.sourceforge.net), + // but POI does not depend on this library + } else { + // not xml, may be an image or other binary format + Assert.assertEquals(fileName + " does not have the same size in both zip:", contain2.size(), contain1.size()); + assertArrayEquals("contents differ", contain1.toByteArray(), contain2.toByteArray()); + } + } + } + + protected static TreeMap decompress( + File filename) throws IOException { + // store the zip content in memory + // let s assume it is not Go ;-) + TreeMap zipContent = new TreeMap(); + + byte data[] = new byte[BUFFER_SIZE]; + /* Open file to decompress */ + FileInputStream file_decompress = new FileInputStream(filename); + + /* Create a buffer for the decompressed files */ + BufferedInputStream buffi = new BufferedInputStream(file_decompress); + + /* Open the file with the buffer */ + ZipInputStream zis = new ZipInputStream(buffi); + + /* Processing entries of the zip file */ + ZipEntry entree; + int count; + while ((entree = zis.getNextEntry()) != null) { + + /* Create a array for the current entry */ + ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); + zipContent.put(entree.getName(), byteArray); + + /* copy in memory */ + while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) { + byteArray.write(data, 0, count); + } + /* Flush the buffer */ + byteArray.flush(); + byteArray.close(); + } + + zis.close(); + + return zipContent; + } + + /** + * Asserts that two files are equal. Throws an AssertionFailedError + * if they are not. + *

    + * + */ + public static void assertEquals(File expected, File actual) { + assertNotNull(expected); + assertNotNull(actual); + + assertTrue("File does not exist [" + expected.getAbsolutePath() + + "]", expected.exists()); + assertTrue("File does not exist [" + actual.getAbsolutePath() + + "]", actual.exists()); + + assertTrue("Expected file not readable", expected.canRead()); + assertTrue("Actual file not readable", actual.canRead()); + + try { + TreeMap file1 = decompress(expected); + TreeMap file2 = decompress(actual); + equals(file1, file2); + } catch (IOException e) { + throw new AssertionFailedError(e.toString()); + } + } +} diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java index fd8e56a745..90bc4ceb36 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java @@ -1,36 +1,36 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - - -/** - * Tests for org.apache.poi.poifs.crypt - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - TestEncryptionInfo.class - , TestDecryptor.class - , TestEncryptor.class - , TestAgileEncryptionParameters.class - , TestCertificateEncryption.class -}) -public final class AllPOIFSCryptoTests { +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + + +/** + * Tests for org.apache.poi.poifs.crypt + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestEncryptionInfo.class + , TestDecryptor.class + , TestEncryptor.class + , TestAgileEncryptionParameters.class + , TestCertificateEncryption.class +}) +public final class AllPOIFSCryptoTests { } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/PkiTestUtils.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/PkiTestUtils.java index afd70f08e5..2b6ab98380 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/PkiTestUtils.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/PkiTestUtils.java @@ -1,317 +1,317 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.cert.CRLException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.RSAKeyGenParameterSpec; -import java.util.Date; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Result; -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.bouncycastle.asn1.DERIA5String; -import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.AuthorityInformationAccess; -import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; -import org.bouncycastle.asn1.x509.BasicConstraints; -import org.bouncycastle.asn1.x509.CRLNumber; -import org.bouncycastle.asn1.x509.CRLReason; -import org.bouncycastle.asn1.x509.DistributionPoint; -import org.bouncycastle.asn1.x509.DistributionPointName; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.Extensions; -import org.bouncycastle.asn1.x509.GeneralName; -import org.bouncycastle.asn1.x509.GeneralNames; -import org.bouncycastle.asn1.x509.KeyUsage; -import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; -import org.bouncycastle.cert.X509CRLHolder; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.X509ExtensionUtils; -import org.bouncycastle.cert.X509v2CRLBuilder; -import org.bouncycastle.cert.X509v3CertificateBuilder; -import org.bouncycastle.cert.jcajce.JcaX509CRLConverter; -import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; -import org.bouncycastle.cert.ocsp.BasicOCSPResp; -import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder; -import org.bouncycastle.cert.ocsp.CertificateID; -import org.bouncycastle.cert.ocsp.CertificateStatus; -import org.bouncycastle.cert.ocsp.OCSPReq; -import org.bouncycastle.cert.ocsp.OCSPReqBuilder; -import org.bouncycastle.cert.ocsp.OCSPResp; -import org.bouncycastle.cert.ocsp.OCSPRespBuilder; -import org.bouncycastle.cert.ocsp.Req; -import org.bouncycastle.cert.ocsp.RevokedStatus; -import org.bouncycastle.crypto.params.RSAKeyParameters; -import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.DigestCalculator; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class PkiTestUtils { - - private PkiTestUtils() { - super(); - } - - static KeyPair generateKeyPair() throws Exception { - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - SecureRandom random = new SecureRandom(); - keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024, - RSAKeyGenParameterSpec.F4), random); - KeyPair keyPair = keyPairGenerator.generateKeyPair(); - return keyPair; - } - - static X509Certificate generateCertificate(PublicKey subjectPublicKey, - String subjectDn, Date notBefore, Date notAfter, - X509Certificate issuerCertificate, PrivateKey issuerPrivateKey, - boolean caFlag, int pathLength, String crlUri, String ocspUri, - KeyUsage keyUsage) - throws IOException, OperatorCreationException, CertificateException - { - String signatureAlgorithm = "SHA1withRSA"; - X500Name issuerName; - if (issuerCertificate != null) { - issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer(); - } else { - issuerName = new X500Name(subjectDn); - } - - RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey; - RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent()); - - SubjectPublicKeyInfo subjectPublicKeyInfo = - SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec); - - DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder() - .setProvider("BC").build().get(CertificateID.HASH_SHA1); - - X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder( - issuerName - , new BigInteger(128, new SecureRandom()) - , notBefore - , notAfter - , new X500Name(subjectDn) - , subjectPublicKeyInfo - ); - - X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc); - SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo); - AuthorityKeyIdentifier autKeyId = (issuerCertificate != null) - ? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded())) - : exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo); - - certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId); - certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId); - - if (caFlag) { - BasicConstraints bc; - - if (-1 == pathLength) { - bc = new BasicConstraints(true); - } else { - bc = new BasicConstraints(pathLength); - } - certificateGenerator.addExtension(Extension.basicConstraints, false, bc); - } - - if (null != crlUri) { - int uri = GeneralName.uniformResourceIdentifier; - DERIA5String crlUriDer = new DERIA5String(crlUri); - GeneralName gn = new GeneralName(uri, crlUriDer); - - DERSequence gnDer = new DERSequence(gn); - GeneralNames gns = GeneralNames.getInstance(gnDer); - - DistributionPointName dpn = new DistributionPointName(0, gns); - DistributionPoint distp = new DistributionPoint(dpn, null, null); - DERSequence distpDer = new DERSequence(distp); - certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer); - } - - if (null != ocspUri) { - int uri = GeneralName.uniformResourceIdentifier; - GeneralName ocspName = new GeneralName(uri, ocspUri); - - AuthorityInformationAccess authorityInformationAccess = - new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName); - - certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess); - } - - if (null != keyUsage) { - certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage); - } - - JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm); - signerBuilder.setProvider("BC"); - - X509CertificateHolder certHolder = - certificateGenerator.build(signerBuilder.build(issuerPrivateKey)); - - /* - * Next certificate factory trick is needed to make sure that the - * certificate delivered to the caller is provided by the default - * security provider instead of BouncyCastle. If we don't do this trick - * we might run into trouble when trying to use the CertPath validator. - */ -// CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); -// certificate = (X509Certificate) certificateFactory -// .generateCertificate(new ByteArrayInputStream(certificate -// .getEncoded())); - return new JcaX509CertificateConverter().getCertificate(certHolder); - } - - static Document loadDocument(InputStream documentInputStream) - throws ParserConfigurationException, SAXException, IOException { - InputSource inputSource = new InputSource(documentInputStream); - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory - .newInstance(); - documentBuilderFactory.setNamespaceAware(true); - DocumentBuilder documentBuilder = documentBuilderFactory - .newDocumentBuilder(); - Document document = documentBuilder.parse(inputSource); - return document; - } - - static String toString(Node dom) throws TransformerException { - Source source = new DOMSource(dom); - StringWriter stringWriter = new StringWriter(); - Result result = new StreamResult(stringWriter); - TransformerFactory transformerFactory = TransformerFactory - .newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - /* - * We have to omit the ?xml declaration if we want to embed the - * document. - */ - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - transformer.transform(source, result); - return stringWriter.getBuffer().toString(); - } - - public static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey) - throws CertificateEncodingException, IOException, CRLException, OperatorCreationException { - - X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded()); - X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date()); - crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000)); - JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC"); - - CRLNumber crlNumber = new CRLNumber(new BigInteger("1234")); - - crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber); - X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey)); - return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl); - } - - public static OCSPResp createOcspResp(X509Certificate certificate, - boolean revoked, X509Certificate issuerCertificate, - X509Certificate ocspResponderCertificate, - PrivateKey ocspResponderPrivateKey, String signatureAlgorithm, - long nonceTimeinMillis) - throws Exception { - DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder() - .setProvider("BC").build().get(CertificateID.HASH_SHA1); - X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded()); - CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber()); - - // request - //create a nonce to avoid replay attack - BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis); - DEROctetString nonceDer = new DEROctetString(nonce.toByteArray()); - Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer); - Extensions exts = new Extensions(ext); - - OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder(); - ocspReqBuilder.addRequest(certId); - ocspReqBuilder.setRequestExtensions(exts); - OCSPReq ocspReq = ocspReqBuilder.build(); - - - SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo - (CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded()); - - BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc); - basicOCSPRespBuilder.setResponseExtensions(exts); - - // request processing - Req[] requestList = ocspReq.getRequestList(); - for (Req ocspRequest : requestList) { - CertificateID certificateID = ocspRequest.getCertID(); - CertificateStatus certificateStatus = CertificateStatus.GOOD; - if (revoked) { - certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn); - } - basicOCSPRespBuilder.addResponse(certificateID, certificateStatus); - } - - // basic response generation - X509CertificateHolder[] chain = null; - if (!ocspResponderCertificate.equals(issuerCertificate)) { - // TODO: HorribleProxy can't convert array input params yet - chain = new X509CertificateHolder[] { - new X509CertificateHolder(ocspResponderCertificate.getEncoded()), - issuerHolder - }; - } - - ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA") - .setProvider("BC").build(ocspResponderPrivateKey); - BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis)); - - - OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder(); - OCSPResp ocspResp = ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp); - - return ocspResp; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.CRLException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.RSAKeyGenParameterSpec; +import java.util.Date; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.bouncycastle.asn1.DERIA5String; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.AuthorityInformationAccess; +import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.CRLNumber; +import org.bouncycastle.asn1.x509.CRLReason; +import org.bouncycastle.asn1.x509.DistributionPoint; +import org.bouncycastle.asn1.x509.DistributionPointName; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.Extensions; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.asn1.x509.KeyUsage; +import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; +import org.bouncycastle.cert.X509CRLHolder; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509ExtensionUtils; +import org.bouncycastle.cert.X509v2CRLBuilder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CRLConverter; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.ocsp.BasicOCSPResp; +import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder; +import org.bouncycastle.cert.ocsp.CertificateID; +import org.bouncycastle.cert.ocsp.CertificateStatus; +import org.bouncycastle.cert.ocsp.OCSPReq; +import org.bouncycastle.cert.ocsp.OCSPReqBuilder; +import org.bouncycastle.cert.ocsp.OCSPResp; +import org.bouncycastle.cert.ocsp.OCSPRespBuilder; +import org.bouncycastle.cert.ocsp.Req; +import org.bouncycastle.cert.ocsp.RevokedStatus; +import org.bouncycastle.crypto.params.RSAKeyParameters; +import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.DigestCalculator; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class PkiTestUtils { + + private PkiTestUtils() { + super(); + } + + static KeyPair generateKeyPair() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + SecureRandom random = new SecureRandom(); + keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024, + RSAKeyGenParameterSpec.F4), random); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + return keyPair; + } + + static X509Certificate generateCertificate(PublicKey subjectPublicKey, + String subjectDn, Date notBefore, Date notAfter, + X509Certificate issuerCertificate, PrivateKey issuerPrivateKey, + boolean caFlag, int pathLength, String crlUri, String ocspUri, + KeyUsage keyUsage) + throws IOException, OperatorCreationException, CertificateException + { + String signatureAlgorithm = "SHA1withRSA"; + X500Name issuerName; + if (issuerCertificate != null) { + issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer(); + } else { + issuerName = new X500Name(subjectDn); + } + + RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey; + RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent()); + + SubjectPublicKeyInfo subjectPublicKeyInfo = + SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec); + + DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder() + .setProvider("BC").build().get(CertificateID.HASH_SHA1); + + X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder( + issuerName + , new BigInteger(128, new SecureRandom()) + , notBefore + , notAfter + , new X500Name(subjectDn) + , subjectPublicKeyInfo + ); + + X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc); + SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo); + AuthorityKeyIdentifier autKeyId = (issuerCertificate != null) + ? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded())) + : exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo); + + certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId); + certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId); + + if (caFlag) { + BasicConstraints bc; + + if (-1 == pathLength) { + bc = new BasicConstraints(true); + } else { + bc = new BasicConstraints(pathLength); + } + certificateGenerator.addExtension(Extension.basicConstraints, false, bc); + } + + if (null != crlUri) { + int uri = GeneralName.uniformResourceIdentifier; + DERIA5String crlUriDer = new DERIA5String(crlUri); + GeneralName gn = new GeneralName(uri, crlUriDer); + + DERSequence gnDer = new DERSequence(gn); + GeneralNames gns = GeneralNames.getInstance(gnDer); + + DistributionPointName dpn = new DistributionPointName(0, gns); + DistributionPoint distp = new DistributionPoint(dpn, null, null); + DERSequence distpDer = new DERSequence(distp); + certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer); + } + + if (null != ocspUri) { + int uri = GeneralName.uniformResourceIdentifier; + GeneralName ocspName = new GeneralName(uri, ocspUri); + + AuthorityInformationAccess authorityInformationAccess = + new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName); + + certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess); + } + + if (null != keyUsage) { + certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage); + } + + JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm); + signerBuilder.setProvider("BC"); + + X509CertificateHolder certHolder = + certificateGenerator.build(signerBuilder.build(issuerPrivateKey)); + + /* + * Next certificate factory trick is needed to make sure that the + * certificate delivered to the caller is provided by the default + * security provider instead of BouncyCastle. If we don't do this trick + * we might run into trouble when trying to use the CertPath validator. + */ +// CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); +// certificate = (X509Certificate) certificateFactory +// .generateCertificate(new ByteArrayInputStream(certificate +// .getEncoded())); + return new JcaX509CertificateConverter().getCertificate(certHolder); + } + + static Document loadDocument(InputStream documentInputStream) + throws ParserConfigurationException, SAXException, IOException { + InputSource inputSource = new InputSource(documentInputStream); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory + .newInstance(); + documentBuilderFactory.setNamespaceAware(true); + DocumentBuilder documentBuilder = documentBuilderFactory + .newDocumentBuilder(); + Document document = documentBuilder.parse(inputSource); + return document; + } + + static String toString(Node dom) throws TransformerException { + Source source = new DOMSource(dom); + StringWriter stringWriter = new StringWriter(); + Result result = new StreamResult(stringWriter); + TransformerFactory transformerFactory = TransformerFactory + .newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + /* + * We have to omit the ?xml declaration if we want to embed the + * document. + */ + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + transformer.transform(source, result); + return stringWriter.getBuffer().toString(); + } + + public static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey) + throws CertificateEncodingException, IOException, CRLException, OperatorCreationException { + + X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded()); + X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date()); + crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000)); + JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC"); + + CRLNumber crlNumber = new CRLNumber(new BigInteger("1234")); + + crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber); + X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey)); + return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl); + } + + public static OCSPResp createOcspResp(X509Certificate certificate, + boolean revoked, X509Certificate issuerCertificate, + X509Certificate ocspResponderCertificate, + PrivateKey ocspResponderPrivateKey, String signatureAlgorithm, + long nonceTimeinMillis) + throws Exception { + DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder() + .setProvider("BC").build().get(CertificateID.HASH_SHA1); + X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded()); + CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber()); + + // request + //create a nonce to avoid replay attack + BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis); + DEROctetString nonceDer = new DEROctetString(nonce.toByteArray()); + Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer); + Extensions exts = new Extensions(ext); + + OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder(); + ocspReqBuilder.addRequest(certId); + ocspReqBuilder.setRequestExtensions(exts); + OCSPReq ocspReq = ocspReqBuilder.build(); + + + SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo + (CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded()); + + BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc); + basicOCSPRespBuilder.setResponseExtensions(exts); + + // request processing + Req[] requestList = ocspReq.getRequestList(); + for (Req ocspRequest : requestList) { + CertificateID certificateID = ocspRequest.getCertID(); + CertificateStatus certificateStatus = CertificateStatus.GOOD; + if (revoked) { + certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn); + } + basicOCSPRespBuilder.addResponse(certificateID, certificateStatus); + } + + // basic response generation + X509CertificateHolder[] chain = null; + if (!ocspResponderCertificate.equals(issuerCertificate)) { + // TODO: HorribleProxy can't convert array input params yet + chain = new X509CertificateHolder[] { + new X509CertificateHolder(ocspResponderCertificate.getEncoded()), + issuerHolder + }; + } + + ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA") + .setProvider("BC").build(ocspResponderPrivateKey); + BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis)); + + + OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder(); + OCSPResp ocspResp = ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp); + + return ocspResp; + } +} diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java index 2cefa95cf5..0786ed51d2 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java @@ -1,109 +1,109 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.crypto.Cipher; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.IOUtils; -import org.junit.Assume; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) -public class TestAgileEncryptionParameters { - - static byte testData[]; - - @Parameter(value = 0) - public CipherAlgorithm ca; - @Parameter(value = 1) - public HashAlgorithm ha; - @Parameter(value = 2) - public ChainingMode cm; - - @Parameters(name="{0} {1} {2}") - public static Collection data() { - CipherAlgorithm caList[] = { CipherAlgorithm.aes128, CipherAlgorithm.aes192, CipherAlgorithm.aes256, CipherAlgorithm.rc2, CipherAlgorithm.des, CipherAlgorithm.des3 }; - HashAlgorithm haList[] = { HashAlgorithm.sha1, HashAlgorithm.sha256, HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.md5 }; - ChainingMode cmList[] = { ChainingMode.cbc, ChainingMode.cfb }; - - List data = new ArrayList(); - for (CipherAlgorithm ca : caList) { - for (HashAlgorithm ha : haList) { - for (ChainingMode cm : cmList) { - data.add(new Object[]{ca,ha,cm}); - } - } - } - - return data; - } - - @BeforeClass - public static void initTestData() throws Exception { - InputStream testFile = POIDataSamples.getDocumentInstance().openResourceAsStream("SampleDoc.docx"); - testData = IOUtils.toByteArray(testFile); - testFile.close(); - } - - @Test - public void testAgileEncryptionModes() throws Exception { - int maxKeyLen = Cipher.getMaxAllowedKeyLength(ca.jceId); - Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files", maxKeyLen >= ca.defaultKeySize); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - - POIFSFileSystem fsEnc = new POIFSFileSystem(); - EncryptionInfo infoEnc = new EncryptionInfo(EncryptionMode.agile, ca, ha, -1, -1, cm); - Encryptor enc = infoEnc.getEncryptor(); - enc.confirmPassword("foobaa"); - OutputStream os = enc.getDataStream(fsEnc); - os.write(testData); - os.close(); - bos.reset(); - fsEnc.writeFilesystem(bos); - fsEnc.close(); - - POIFSFileSystem fsDec = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - EncryptionInfo infoDec = new EncryptionInfo(fsDec); - Decryptor dec = infoDec.getDecryptor(); - boolean passed = dec.verifyPassword("foobaa"); - assertTrue(passed); - InputStream is = dec.getDataStream(fsDec); - byte actualData[] = IOUtils.toByteArray(is); - is.close(); - fsDec.close(); - assertArrayEquals("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, actualData); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.crypto.Cipher; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class TestAgileEncryptionParameters { + + static byte testData[]; + + @Parameter(value = 0) + public CipherAlgorithm ca; + @Parameter(value = 1) + public HashAlgorithm ha; + @Parameter(value = 2) + public ChainingMode cm; + + @Parameters(name="{0} {1} {2}") + public static Collection data() { + CipherAlgorithm caList[] = { CipherAlgorithm.aes128, CipherAlgorithm.aes192, CipherAlgorithm.aes256, CipherAlgorithm.rc2, CipherAlgorithm.des, CipherAlgorithm.des3 }; + HashAlgorithm haList[] = { HashAlgorithm.sha1, HashAlgorithm.sha256, HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.md5 }; + ChainingMode cmList[] = { ChainingMode.cbc, ChainingMode.cfb }; + + List data = new ArrayList(); + for (CipherAlgorithm ca : caList) { + for (HashAlgorithm ha : haList) { + for (ChainingMode cm : cmList) { + data.add(new Object[]{ca,ha,cm}); + } + } + } + + return data; + } + + @BeforeClass + public static void initTestData() throws Exception { + InputStream testFile = POIDataSamples.getDocumentInstance().openResourceAsStream("SampleDoc.docx"); + testData = IOUtils.toByteArray(testFile); + testFile.close(); + } + + @Test + public void testAgileEncryptionModes() throws Exception { + int maxKeyLen = Cipher.getMaxAllowedKeyLength(ca.jceId); + Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files", maxKeyLen >= ca.defaultKeySize); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + POIFSFileSystem fsEnc = new POIFSFileSystem(); + EncryptionInfo infoEnc = new EncryptionInfo(EncryptionMode.agile, ca, ha, -1, -1, cm); + Encryptor enc = infoEnc.getEncryptor(); + enc.confirmPassword("foobaa"); + OutputStream os = enc.getDataStream(fsEnc); + os.write(testData); + os.close(); + bos.reset(); + fsEnc.writeFilesystem(bos); + fsEnc.close(); + + POIFSFileSystem fsDec = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); + EncryptionInfo infoDec = new EncryptionInfo(fsDec); + Decryptor dec = infoDec.getDecryptor(); + boolean passed = dec.verifyPassword("foobaa"); + assertTrue(passed); + InputStream is = dec.getDataStream(fsDec); + byte actualData[] = IOUtils.toByteArray(is); + is.close(); + fsDec.close(); + assertArrayEquals("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, actualData); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java index d48fb0da38..5495d7a80a 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java @@ -1,197 +1,197 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.cert.X509Certificate; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.poifs.crypt.agile.AgileDecryptor; -import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.IOUtils; -import org.junit.Test; - -/* -import org.junit.BeforeClass; -import java.util.Date; -import java.math.BigInteger; -import java.security.KeyPairGenerator; -import java.security.SecureRandom; -import java.security.cert.Certificate; -import sun.security.x509.AlgorithmId; -import sun.security.x509.CertificateAlgorithmId; -import sun.security.x509.CertificateIssuerName; -import sun.security.x509.CertificateSerialNumber; -import sun.security.x509.CertificateSubjectName; -import sun.security.x509.CertificateValidity; -import sun.security.x509.CertificateVersion; -import sun.security.x509.CertificateX509Key; -import sun.security.x509.X500Name; -import sun.security.x509.X509CertImpl; -import sun.security.x509.X509CertInfo; -*/ - -/** - * @see creating a self-signed certificate - */ -public class TestCertificateEncryption { - /** - * how many days from now the Certificate is valid for - */ - static final int days = 1000; - /** - * the signing algorithm, eg "SHA1withRSA" - */ - static final String algorithm = "SHA1withRSA"; - static final String password = "foobaa"; - static final String certAlias = "poitest"; - /** - * the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB" - */ - static final String certDN = "CN=poitest"; - // static final File pfxFile = TempFile.createTempFile("poitest", ".pfx"); - static byte pfxFileBytes[]; - - static class CertData { - KeyPair keypair; - X509Certificate x509; - } - - /** - * Create a self-signed X.509 Certificate - * - * The keystore generation / loading is split, because normally the keystore would - * already exist. - */ - /* @BeforeClass - public static void initKeystore() throws GeneralSecurityException, IOException { - CertData certData = new CertData(); - - KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - keyGen.initialize(1024); - certData.keypair = keyGen.generateKeyPair(); - PrivateKey privkey = certData.keypair.getPrivate(); - PublicKey publkey = certData.keypair.getPublic(); - - X509CertInfo info = new X509CertInfo(); - Date from = new Date(); - Date to = new Date(from.getTime() + days * 86400000l); - CertificateValidity interval = new CertificateValidity(from, to); - BigInteger sn = new BigInteger(64, new SecureRandom()); - X500Name owner = new X500Name(certDN); - - info.set(X509CertInfo.VALIDITY, interval); - info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn)); - info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner)); - info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner)); - info.set(X509CertInfo.KEY, new CertificateX509Key(publkey)); - info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); - AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid); - info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo)); - - // Sign the cert to identify the algorithm that's used. - X509CertImpl cert = new X509CertImpl(info); - cert.sign(privkey, algorithm); - - // Update the algorith, and resign. - algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG); - info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo); - cert = new X509CertImpl(info); - cert.sign(privkey, algorithm); - certData.x509 = cert; - - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, password.toCharArray()); - keystore.setKeyEntry(certAlias, certData.keypair.getPrivate(), password.toCharArray(), new Certificate[]{certData.x509}); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - keystore.store(bos, password.toCharArray()); - pfxFileBytes = bos.toByteArray(); - } */ - - public CertData loadKeystore() - throws GeneralSecurityException, IOException { - KeyStore keystore = KeyStore.getInstance("PKCS12"); - - // InputStream fis = new ByteArrayInputStream(pfxFileBytes); - InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("poitest.pfx"); - keystore.load(fis, password.toCharArray()); - fis.close(); - - X509Certificate x509 = (X509Certificate)keystore.getCertificate(certAlias); - PrivateKey privateKey = (PrivateKey)keystore.getKey(certAlias, password.toCharArray()); - PublicKey publicKey = x509.getPublicKey(); - - CertData certData = new CertData(); - certData.keypair = new KeyPair(publicKey, privateKey); - certData.x509 = x509; - - return certData; - } - - @Test - public void testCertificateEncryption() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(); - EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile, CipherAlgorithm.aes128, HashAlgorithm.sha1, -1, -1, ChainingMode.cbc); - AgileEncryptionVerifier aev = (AgileEncryptionVerifier)info.getVerifier(); - CertData certData = loadKeystore(); - aev.addCertificate(certData.x509); - - Encryptor enc = info.getEncryptor(); - enc.confirmPassword("foobaa"); - - File file = POIDataSamples.getDocumentInstance().getFile("VariousPictures.docx"); - InputStream fis = new FileInputStream(file); - byte byteExpected[] = IOUtils.toByteArray(fis); - fis.close(); - - OutputStream os = enc.getDataStream(fs); - IOUtils.copy(new ByteArrayInputStream(byteExpected), os); - os.close(); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - fs.writeFilesystem(bos); - bos.close(); - - fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - info = new EncryptionInfo(fs); - AgileDecryptor agDec = (AgileDecryptor)info.getDecryptor(); - boolean passed = agDec.verifyPassword(certData.keypair, certData.x509); - assertTrue("certificate verification failed", passed); - - fis = agDec.getDataStream(fs); - byte byteActual[] = IOUtils.toByteArray(fis); - fis.close(); - - assertThat(byteExpected, equalTo(byteActual)); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.X509Certificate; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.poifs.crypt.agile.AgileDecryptor; +import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; +import org.junit.Test; + +/* +import org.junit.BeforeClass; +import java.util.Date; +import java.math.BigInteger; +import java.security.KeyPairGenerator; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import sun.security.x509.AlgorithmId; +import sun.security.x509.CertificateAlgorithmId; +import sun.security.x509.CertificateIssuerName; +import sun.security.x509.CertificateSerialNumber; +import sun.security.x509.CertificateSubjectName; +import sun.security.x509.CertificateValidity; +import sun.security.x509.CertificateVersion; +import sun.security.x509.CertificateX509Key; +import sun.security.x509.X500Name; +import sun.security.x509.X509CertImpl; +import sun.security.x509.X509CertInfo; +*/ + +/** + * @see creating a self-signed certificate + */ +public class TestCertificateEncryption { + /** + * how many days from now the Certificate is valid for + */ + static final int days = 1000; + /** + * the signing algorithm, eg "SHA1withRSA" + */ + static final String algorithm = "SHA1withRSA"; + static final String password = "foobaa"; + static final String certAlias = "poitest"; + /** + * the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB" + */ + static final String certDN = "CN=poitest"; + // static final File pfxFile = TempFile.createTempFile("poitest", ".pfx"); + static byte pfxFileBytes[]; + + static class CertData { + KeyPair keypair; + X509Certificate x509; + } + + /** + * Create a self-signed X.509 Certificate + * + * The keystore generation / loading is split, because normally the keystore would + * already exist. + */ + /* @BeforeClass + public static void initKeystore() throws GeneralSecurityException, IOException { + CertData certData = new CertData(); + + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(1024); + certData.keypair = keyGen.generateKeyPair(); + PrivateKey privkey = certData.keypair.getPrivate(); + PublicKey publkey = certData.keypair.getPublic(); + + X509CertInfo info = new X509CertInfo(); + Date from = new Date(); + Date to = new Date(from.getTime() + days * 86400000l); + CertificateValidity interval = new CertificateValidity(from, to); + BigInteger sn = new BigInteger(64, new SecureRandom()); + X500Name owner = new X500Name(certDN); + + info.set(X509CertInfo.VALIDITY, interval); + info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn)); + info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner)); + info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner)); + info.set(X509CertInfo.KEY, new CertificateX509Key(publkey)); + info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); + AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid); + info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo)); + + // Sign the cert to identify the algorithm that's used. + X509CertImpl cert = new X509CertImpl(info); + cert.sign(privkey, algorithm); + + // Update the algorith, and resign. + algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG); + info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo); + cert = new X509CertImpl(info); + cert.sign(privkey, algorithm); + certData.x509 = cert; + + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, password.toCharArray()); + keystore.setKeyEntry(certAlias, certData.keypair.getPrivate(), password.toCharArray(), new Certificate[]{certData.x509}); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + keystore.store(bos, password.toCharArray()); + pfxFileBytes = bos.toByteArray(); + } */ + + public CertData loadKeystore() + throws GeneralSecurityException, IOException { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + + // InputStream fis = new ByteArrayInputStream(pfxFileBytes); + InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("poitest.pfx"); + keystore.load(fis, password.toCharArray()); + fis.close(); + + X509Certificate x509 = (X509Certificate)keystore.getCertificate(certAlias); + PrivateKey privateKey = (PrivateKey)keystore.getKey(certAlias, password.toCharArray()); + PublicKey publicKey = x509.getPublicKey(); + + CertData certData = new CertData(); + certData.keypair = new KeyPair(publicKey, privateKey); + certData.x509 = x509; + + return certData; + } + + @Test + public void testCertificateEncryption() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(); + EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile, CipherAlgorithm.aes128, HashAlgorithm.sha1, -1, -1, ChainingMode.cbc); + AgileEncryptionVerifier aev = (AgileEncryptionVerifier)info.getVerifier(); + CertData certData = loadKeystore(); + aev.addCertificate(certData.x509); + + Encryptor enc = info.getEncryptor(); + enc.confirmPassword("foobaa"); + + File file = POIDataSamples.getDocumentInstance().getFile("VariousPictures.docx"); + InputStream fis = new FileInputStream(file); + byte byteExpected[] = IOUtils.toByteArray(fis); + fis.close(); + + OutputStream os = enc.getDataStream(fs); + IOUtils.copy(new ByteArrayInputStream(byteExpected), os); + os.close(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + fs.writeFilesystem(bos); + bos.close(); + + fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); + info = new EncryptionInfo(fs); + AgileDecryptor agDec = (AgileDecryptor)info.getDecryptor(); + boolean passed = agDec.verifyPassword(certData.keypair, certData.x509); + assertTrue("certificate verification failed", passed); + + fis = agDec.getDataStream(fs); + byte byteActual[] = IOUtils.toByteArray(fis); + fis.close(); + + assertThat(byteExpected, equalTo(byteActual)); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java index e17e2dcb81..2dcbcf0e94 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java @@ -1,185 +1,185 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import javax.crypto.Cipher; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.IOUtils; -import org.apache.poi.xssf.XSSFTestDataSamples; -import org.junit.Assume; -import org.junit.Test; - -public class TestDecryptor { - @Test - public void passwordVerification() throws IOException, GeneralSecurityException { - POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); - - EncryptionInfo info = new EncryptionInfo(fs); - - Decryptor d = Decryptor.getInstance(info); - - assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD)); - } - - @Test - public void decrypt() throws IOException, GeneralSecurityException { - POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); - - EncryptionInfo info = new EncryptionInfo(fs); - - Decryptor d = Decryptor.getInstance(info); - - d.verifyPassword(Decryptor.DEFAULT_PASSWORD); - - zipOk(fs.getRoot(), d); - } - - @Test - public void agile() throws IOException, GeneralSecurityException { - POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx")); - - EncryptionInfo info = new EncryptionInfo(fs); - - assertTrue(info.getVersionMajor() == 4 && info.getVersionMinor() == 4); - - Decryptor d = Decryptor.getInstance(info); - - assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD)); - - zipOk(fs.getRoot(), d); - } - - private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException { - ZipInputStream zin = new ZipInputStream(d.getDataStream(root)); - - while (true) { - ZipEntry entry = zin.getNextEntry(); - if (entry==null) break; - // crc32 is checked within zip-stream - if (entry.isDirectory()) continue; - zin.skip(entry.getSize()); - byte buf[] = new byte[10]; - int readBytes = zin.read(buf); - // zin.available() doesn't work for entries - assertEquals("size failed for "+entry.getName(), -1, readBytes); - } - - zin.close(); - } - - @Test - public void dataLength() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx")); - - EncryptionInfo info = new EncryptionInfo(fs); - - Decryptor d = Decryptor.getInstance(info); - - d.verifyPassword(Decryptor.DEFAULT_PASSWORD); - - InputStream is = d.getDataStream(fs); - - long len = d.getLength(); - assertEquals(12810, len); - - byte[] buf = new byte[(int)len]; - - is.read(buf); - - ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(buf)); - - while (true) { - ZipEntry entry = zin.getNextEntry(); - if (entry==null) { - break; - } - - while (zin.available()>0) { - zin.skip(zin.available()); - } - } - } - - @Test - public void bug57080() throws Exception { - // the test file contains a wrong ole entry size, produced by extenxls - // the fix limits the available size and tries to read all entries - File f = POIDataSamples.getPOIFSInstance().getFile("extenxls_pwd123.xlsx"); - NPOIFSFileSystem fs = new NPOIFSFileSystem(f, true); - EncryptionInfo info = new EncryptionInfo(fs); - Decryptor d = Decryptor.getInstance(info); - d.verifyPassword("pwd123"); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ZipInputStream zis = new ZipInputStream(d.getDataStream(fs)); - ZipEntry ze; - while ((ze = zis.getNextEntry()) != null) { - bos.reset(); - IOUtils.copy(zis, bos); - assertEquals(ze.getSize(), bos.size()); - } - - zis.close(); - fs.close(); - } - - @Test - public void test58616() throws IOException, GeneralSecurityException { - POIFSFileSystem pfs = new POIFSFileSystem(new FileInputStream(XSSFTestDataSamples.getSampleFile("58616.xlsx"))); - EncryptionInfo info = new EncryptionInfo(pfs); - Decryptor dec = Decryptor.getInstance(info); - //dec.verifyPassword(null); - dec.getDataStream(pfs); - } - - @Test - public void bug60320() throws IOException, GeneralSecurityException { - int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); - Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); - - InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx"); - POIFSFileSystem fs = new POIFSFileSystem(is); - is.close(); - - EncryptionInfo info = new EncryptionInfo(fs); - - Decryptor d = Decryptor.getInstance(info); - - boolean b = d.verifyPassword("Test001!!"); - assertTrue(b); - - zipOk(fs.getRoot(), d); - - fs.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import javax.crypto.Cipher; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.XSSFTestDataSamples; +import org.junit.Assume; +import org.junit.Test; + +public class TestDecryptor { + @Test + public void passwordVerification() throws IOException, GeneralSecurityException { + POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); + + EncryptionInfo info = new EncryptionInfo(fs); + + Decryptor d = Decryptor.getInstance(info); + + assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD)); + } + + @Test + public void decrypt() throws IOException, GeneralSecurityException { + POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); + + EncryptionInfo info = new EncryptionInfo(fs); + + Decryptor d = Decryptor.getInstance(info); + + d.verifyPassword(Decryptor.DEFAULT_PASSWORD); + + zipOk(fs.getRoot(), d); + } + + @Test + public void agile() throws IOException, GeneralSecurityException { + POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx")); + + EncryptionInfo info = new EncryptionInfo(fs); + + assertTrue(info.getVersionMajor() == 4 && info.getVersionMinor() == 4); + + Decryptor d = Decryptor.getInstance(info); + + assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD)); + + zipOk(fs.getRoot(), d); + } + + private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException { + ZipInputStream zin = new ZipInputStream(d.getDataStream(root)); + + while (true) { + ZipEntry entry = zin.getNextEntry(); + if (entry==null) break; + // crc32 is checked within zip-stream + if (entry.isDirectory()) continue; + zin.skip(entry.getSize()); + byte buf[] = new byte[10]; + int readBytes = zin.read(buf); + // zin.available() doesn't work for entries + assertEquals("size failed for "+entry.getName(), -1, readBytes); + } + + zin.close(); + } + + @Test + public void dataLength() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx")); + + EncryptionInfo info = new EncryptionInfo(fs); + + Decryptor d = Decryptor.getInstance(info); + + d.verifyPassword(Decryptor.DEFAULT_PASSWORD); + + InputStream is = d.getDataStream(fs); + + long len = d.getLength(); + assertEquals(12810, len); + + byte[] buf = new byte[(int)len]; + + is.read(buf); + + ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(buf)); + + while (true) { + ZipEntry entry = zin.getNextEntry(); + if (entry==null) { + break; + } + + while (zin.available()>0) { + zin.skip(zin.available()); + } + } + } + + @Test + public void bug57080() throws Exception { + // the test file contains a wrong ole entry size, produced by extenxls + // the fix limits the available size and tries to read all entries + File f = POIDataSamples.getPOIFSInstance().getFile("extenxls_pwd123.xlsx"); + NPOIFSFileSystem fs = new NPOIFSFileSystem(f, true); + EncryptionInfo info = new EncryptionInfo(fs); + Decryptor d = Decryptor.getInstance(info); + d.verifyPassword("pwd123"); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ZipInputStream zis = new ZipInputStream(d.getDataStream(fs)); + ZipEntry ze; + while ((ze = zis.getNextEntry()) != null) { + bos.reset(); + IOUtils.copy(zis, bos); + assertEquals(ze.getSize(), bos.size()); + } + + zis.close(); + fs.close(); + } + + @Test + public void test58616() throws IOException, GeneralSecurityException { + POIFSFileSystem pfs = new POIFSFileSystem(new FileInputStream(XSSFTestDataSamples.getSampleFile("58616.xlsx"))); + EncryptionInfo info = new EncryptionInfo(pfs); + Decryptor dec = Decryptor.getInstance(info); + //dec.verifyPassword(null); + dec.getDataStream(pfs); + } + + @Test + public void bug60320() throws IOException, GeneralSecurityException { + int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); + Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); + + InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx"); + POIFSFileSystem fs = new POIFSFileSystem(is); + is.close(); + + EncryptionInfo info = new EncryptionInfo(fs); + + Decryptor d = Decryptor.getInstance(info); + + boolean b = d.verifyPassword("Test001!!"); + assertTrue(b); + + zipOk(fs.getRoot(), d); + + fs.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptionInfo.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptionInfo.java index 204c2ed621..0b4e3d2702 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptionInfo.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptionInfo.java @@ -1,65 +1,65 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import static org.junit.Assert.assertEquals; - -import java.io.IOException; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.junit.Test; - -public class TestEncryptionInfo { - @Test - public void testEncryptionInfo() throws IOException { - POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); - - EncryptionInfo info = new EncryptionInfo(fs); - - assertEquals(3, info.getVersionMajor()); - assertEquals(2, info.getVersionMinor()); - - assertEquals(CipherAlgorithm.aes128, info.getHeader().getCipherAlgorithm()); - assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithm()); - assertEquals(128, info.getHeader().getKeySize()); - assertEquals(32, info.getVerifier().getEncryptedVerifierHash().length); - assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider()); - assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName()); - - fs.close(); - } - - @Test - public void testEncryptionInfoSHA512() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_sha512.xlsx")); - - EncryptionInfo info = new EncryptionInfo(fs); - - assertEquals(4, info.getVersionMajor()); - assertEquals(4, info.getVersionMinor()); - - assertEquals(CipherAlgorithm.aes256, info.getHeader().getCipherAlgorithm()); - assertEquals(HashAlgorithm.sha512, info.getHeader().getHashAlgorithm()); - assertEquals(256, info.getHeader().getKeySize()); - assertEquals(64, info.getVerifier().getEncryptedVerifierHash().length); - assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider()); -// assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName()); - - fs.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.junit.Test; + +public class TestEncryptionInfo { + @Test + public void testEncryptionInfo() throws IOException { + POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); + + EncryptionInfo info = new EncryptionInfo(fs); + + assertEquals(3, info.getVersionMajor()); + assertEquals(2, info.getVersionMinor()); + + assertEquals(CipherAlgorithm.aes128, info.getHeader().getCipherAlgorithm()); + assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithm()); + assertEquals(128, info.getHeader().getKeySize()); + assertEquals(32, info.getVerifier().getEncryptedVerifierHash().length); + assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider()); + assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName()); + + fs.close(); + } + + @Test + public void testEncryptionInfoSHA512() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_sha512.xlsx")); + + EncryptionInfo info = new EncryptionInfo(fs); + + assertEquals(4, info.getVersionMajor()); + assertEquals(4, info.getVersionMinor()); + + assertEquals(CipherAlgorithm.aes256, info.getHeader().getCipherAlgorithm()); + assertEquals(HashAlgorithm.sha512, info.getHeader().getHashAlgorithm()); + assertEquals(256, info.getHeader().getKeySize()); + assertEquals(64, info.getVerifier().getEncryptedVerifierHash().length); + assertEquals(CipherProvider.aes, info.getHeader().getCipherProvider()); +// assertEquals("Microsoft Enhanced RSA and AES Cryptographic Provider", info.getHeader().getCspName()); + + fs.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java index cd2d532e34..d31a58a334 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java @@ -1,526 +1,526 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Iterator; - -import javax.crypto.Cipher; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.openxml4j.opc.ContentTypes; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.poifs.crypt.agile.AgileDecryptor; -import org.apache.poi.poifs.crypt.agile.AgileEncryptionHeader; -import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.DocumentNode; -import org.apache.poi.poifs.filesystem.Entry; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.BoundedInputStream; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.TempFile; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.junit.Assume; -import org.junit.Ignore; -import org.junit.Test; - -public class TestEncryptor { - @Test - public void binaryRC4Encryption() throws Exception { - // please contribute a real sample file, which is binary rc4 encrypted - // ... at least the output can be opened in Excel Viewer - String password = "pass"; - - InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx"); - ByteArrayOutputStream payloadExpected = new ByteArrayOutputStream(); - IOUtils.copy(is, payloadExpected); - is.close(); - - POIFSFileSystem fs = new POIFSFileSystem(); - EncryptionInfo ei = new EncryptionInfo(EncryptionMode.binaryRC4); - Encryptor enc = ei.getEncryptor(); - enc.confirmPassword(password); - - OutputStream os = enc.getDataStream(fs.getRoot()); - payloadExpected.writeTo(os); - os.close(); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - fs.writeFilesystem(bos); - - fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - ei = new EncryptionInfo(fs); - Decryptor dec = ei.getDecryptor(); - boolean b = dec.verifyPassword(password); - assertTrue(b); - - ByteArrayOutputStream payloadActual = new ByteArrayOutputStream(); - is = dec.getDataStream(fs.getRoot()); - IOUtils.copy(is,payloadActual); - is.close(); - - assertArrayEquals(payloadExpected.toByteArray(), payloadActual.toByteArray()); - } - - @Test - public void agileEncryption() throws Exception { - int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); - Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); - - File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx"); - String pass = "pass"; - NPOIFSFileSystem nfs = new NPOIFSFileSystem(file); - - // Check the encryption details - EncryptionInfo infoExpected = new EncryptionInfo(nfs); - Decryptor decExpected = Decryptor.getInstance(infoExpected); - boolean passed = decExpected.verifyPassword(pass); - assertTrue("Unable to process: document is encrypted", passed); - - // extract the payload - InputStream is = decExpected.getDataStream(nfs); - byte payloadExpected[] = IOUtils.toByteArray(is); - is.close(); - - long decPackLenExpected = decExpected.getLength(); - assertEquals(decPackLenExpected, payloadExpected.length); - - is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY); - is = new BoundedInputStream(is, is.available()-16); // ignore padding block - byte encPackExpected[] = IOUtils.toByteArray(is); - is.close(); - - // listDir(nfs.getRoot(), "orig", ""); - - nfs.close(); - - // check that same verifier/salt lead to same hashes - byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt(); - byte verifierExpected[] = decExpected.getVerifier(); - byte keySalt[] = infoExpected.getHeader().getKeySalt(); - byte keySpec[] = decExpected.getSecretKey().getEncoded(); - byte integritySalt[] = decExpected.getIntegrityHmacKey(); - // the hmacs of the file always differ, as we use PKCS5-padding to pad the bytes - // whereas office just uses random bytes - // byte integrityHash[] = d.getIntegrityHmacValue(); - - POIFSFileSystem fs = new POIFSFileSystem(); - EncryptionInfo infoActual = new EncryptionInfo( - EncryptionMode.agile - , infoExpected.getVerifier().getCipherAlgorithm() - , infoExpected.getVerifier().getHashAlgorithm() - , infoExpected.getHeader().getKeySize() - , infoExpected.getHeader().getBlockSize() - , infoExpected.getVerifier().getChainingMode() - ); - - Encryptor e = Encryptor.getInstance(infoActual); - e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, integritySalt); - - OutputStream os = e.getDataStream(fs); - IOUtils.copy(new ByteArrayInputStream(payloadExpected), os); - os.close(); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - fs.writeFilesystem(bos); - - nfs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - infoActual = new EncryptionInfo(nfs.getRoot()); - Decryptor decActual = Decryptor.getInstance(infoActual); - passed = decActual.verifyPassword(pass); - assertTrue("Unable to process: document is encrypted", passed); - - // extract the payload - is = decActual.getDataStream(nfs); - byte payloadActual[] = IOUtils.toByteArray(is); - is.close(); - - long decPackLenActual = decActual.getLength(); - - is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY); - is = new BoundedInputStream(is, is.available()-16); // ignore padding block - byte encPackActual[] = IOUtils.toByteArray(is); - is.close(); - - // listDir(nfs.getRoot(), "copy", ""); - - nfs.close(); - - AgileEncryptionHeader aehExpected = (AgileEncryptionHeader)infoExpected.getHeader(); - AgileEncryptionHeader aehActual = (AgileEncryptionHeader)infoActual.getHeader(); - assertArrayEquals(aehExpected.getEncryptedHmacKey(), aehActual.getEncryptedHmacKey()); - assertEquals(decPackLenExpected, decPackLenActual); - assertArrayEquals(payloadExpected, payloadActual); - assertArrayEquals(encPackExpected, encPackActual); - } - - @Test - public void standardEncryption() throws Exception { - File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx"); - String pass = "solrcell"; - - NPOIFSFileSystem nfs = new NPOIFSFileSystem(file); - - // Check the encryption details - EncryptionInfo infoExpected = new EncryptionInfo(nfs); - Decryptor d = Decryptor.getInstance(infoExpected); - boolean passed = d.verifyPassword(pass); - assertTrue("Unable to process: document is encrypted", passed); - - // extract the payload - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - InputStream is = d.getDataStream(nfs); - IOUtils.copy(is, bos); - is.close(); - nfs.close(); - byte payloadExpected[] = bos.toByteArray(); - - // check that same verifier/salt lead to same hashes - byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt(); - byte verifierExpected[] = d.getVerifier(); - byte keySpec[] = d.getSecretKey().getEncoded(); - byte keySalt[] = infoExpected.getHeader().getKeySalt(); - - - EncryptionInfo infoActual = new EncryptionInfo( - EncryptionMode.standard - , infoExpected.getVerifier().getCipherAlgorithm() - , infoExpected.getVerifier().getHashAlgorithm() - , infoExpected.getHeader().getKeySize() - , infoExpected.getHeader().getBlockSize() - , infoExpected.getVerifier().getChainingMode() - ); - - Encryptor e = Encryptor.getInstance(infoActual); - e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, null); - - assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifier(), infoActual.getVerifier().getEncryptedVerifier()); - assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifierHash(), infoActual.getVerifier().getEncryptedVerifierHash()); - - // now we use a newly generated salt/verifier and check - // if the file content is still the same - - infoActual = new EncryptionInfo( - EncryptionMode.standard - , infoExpected.getVerifier().getCipherAlgorithm() - , infoExpected.getVerifier().getHashAlgorithm() - , infoExpected.getHeader().getKeySize() - , infoExpected.getHeader().getBlockSize() - , infoExpected.getVerifier().getChainingMode() - ); - - e = Encryptor.getInstance(infoActual); - e.confirmPassword(pass); - - POIFSFileSystem fs = new POIFSFileSystem(); - OutputStream os = e.getDataStream(fs); - IOUtils.copy(new ByteArrayInputStream(payloadExpected), os); - os.close(); - - bos.reset(); - fs.writeFilesystem(bos); - - ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); - - // FileOutputStream fos = new FileOutputStream("encrypted.docx"); - // IOUtils.copy(bis, fos); - // fos.close(); - // bis.reset(); - - nfs = new NPOIFSFileSystem(bis); - infoExpected = new EncryptionInfo(nfs); - d = Decryptor.getInstance(infoExpected); - passed = d.verifyPassword(pass); - assertTrue("Unable to process: document is encrypted", passed); - - bos.reset(); - is = d.getDataStream(nfs); - IOUtils.copy(is, bos); - is.close(); - nfs.close(); - byte payloadActual[] = bos.toByteArray(); - - assertArrayEquals(payloadExpected, payloadActual); - } - - /** - * Ensure we can encrypt a package that is missing the Core - * Properties, eg one from dodgy versions of Jasper Reports - * See https://github.com/nestoru/xlsxenc/ and - * http://stackoverflow.com/questions/28593223 - */ - @Test - public void encryptPackageWithoutCoreProperties() throws Exception { - // Open our file without core properties - File inp = POIDataSamples.getOpenXML4JInstance().getFile("OPCCompliance_NoCoreProperties.xlsx"); - OPCPackage pkg = OPCPackage.open(inp.getPath()); - - // It doesn't have any core properties yet - assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); - assertNotNull(pkg.getPackageProperties()); - assertNotNull(pkg.getPackageProperties().getLanguageProperty()); - assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); - - // Encrypt it - EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile); - NPOIFSFileSystem fs = new NPOIFSFileSystem(); - - Encryptor enc = info.getEncryptor(); - enc.confirmPassword("password"); - OutputStream os = enc.getDataStream(fs); - pkg.save(os); - pkg.revert(); - - // Save the resulting OLE2 document, and re-open it - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - fs.writeFilesystem(baos); - - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - NPOIFSFileSystem inpFS = new NPOIFSFileSystem(bais); - - // Check we can decrypt it - info = new EncryptionInfo(inpFS); - Decryptor d = Decryptor.getInstance(info); - assertEquals(true, d.verifyPassword("password")); - - OPCPackage inpPkg = OPCPackage.open(d.getDataStream(inpFS)); - - // Check it now has empty core properties - assertEquals(1, inpPkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); - assertNotNull(inpPkg.getPackageProperties()); - assertNotNull(inpPkg.getPackageProperties().getLanguageProperty()); - assertNull(inpPkg.getPackageProperties().getLanguageProperty().getValue()); - } - - @Test - @Ignore - public void inPlaceRewrite() throws Exception { - File f = TempFile.createTempFile("protected_agile", ".docx"); - // File f = new File("protected_agile.docx"); - FileOutputStream fos = new FileOutputStream(f); - InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx"); - IOUtils.copy(fis, fos); - fis.close(); - fos.close(); - - NPOIFSFileSystem fs = new NPOIFSFileSystem(f, false); - - // decrypt the protected file - in this case it was encrypted with the default password - EncryptionInfo encInfo = new EncryptionInfo(fs); - Decryptor d = encInfo.getDecryptor(); - boolean b = d.verifyPassword(Decryptor.DEFAULT_PASSWORD); - assertTrue(b); - - // do some strange things with it ;) - XWPFDocument docx = new XWPFDocument(d.getDataStream(fs)); - docx.getParagraphArray(0).insertNewRun(0).setText("POI was here! All your base are belong to us!"); - docx.getParagraphArray(0).insertNewRun(1).addBreak(); - - // and encrypt it again - Encryptor e = encInfo.getEncryptor(); - e.confirmPassword("AYBABTU"); - docx.write(e.getDataStream(fs)); - - docx.close(); - fs.close(); - } - - - private void listEntry(DocumentNode de, String ext, String path) throws IOException { - path += "\\" + de.getName().replaceAll("[\\p{Cntrl}]", "_"); - System.out.println(ext+": "+path+" ("+de.getSize()+" bytes)"); - - String name = de.getName().replaceAll("[\\p{Cntrl}]", "_"); - - InputStream is = ((DirectoryNode)de.getParent()).createDocumentInputStream(de); - FileOutputStream fos = new FileOutputStream("solr."+name+"."+ext); - IOUtils.copy(is, fos); - fos.close(); - is.close(); - } - - @SuppressWarnings("unused") - private void listDir(DirectoryNode dn, String ext, String path) throws IOException { - path += "\\" + dn.getName().replace('\u0006', '_'); - System.out.println(ext+": "+path+" ("+dn.getStorageClsid()+")"); - - Iterator iter = dn.getEntries(); - while (iter.hasNext()) { - Entry ent = iter.next(); - if (ent instanceof DirectoryNode) { - listDir((DirectoryNode)ent, ext, path); - } else { - listEntry((DocumentNode)ent, ext, path); - } - } - } - - /* - * this test simulates the generation of bugs 60320 sample file - * as the padding bytes of the EncryptedPackage stream are random or in POIs case PKCS5-padded - * one would need to mock those bytes to get the same hmacValues - see diff below - * - * this use-case is experimental - for the time being the setters of the encryption classes - * are spreaded between two packages and are protected - so you would need to violate - * the packages rules and provide a helper class in the *poifs.crypt package-namespace. - * the default way of defining the encryption settings is via the EncryptionInfo class - */ - @Test - public void bug60320CustomEncrypt() throws Exception { - int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); - Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); - - // --- src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (revision 1766745) - // +++ src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (working copy) - // @@ -208,6 +208,13 @@ - // protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException { - // byte plain[] = (_plainByteFlags.isEmpty()) ? null : _chunk.clone(); - // - // + if (posInChunk < 4096) { - // + _cipher.update(_chunk, 0, posInChunk, _chunk); - // + byte bla[] = { (byte)0x7A,(byte)0x0F,(byte)0x27,(byte)0xF0,(byte)0x17,(byte)0x6E,(byte)0x77,(byte)0x05,(byte)0xB9,(byte)0xDA,(byte)0x49,(byte)0xF9,(byte)0xD7,(byte)0x8E,(byte)0x03,(byte)0x1D }; - // + System.arraycopy(bla, 0, _chunk, posInChunk-2, bla.length); - // + return posInChunk-2+bla.length; - // + } - // + - // int ciLen = (doFinal) - // ? _cipher.doFinal(_chunk, 0, posInChunk, _chunk) - // : _cipher.update(_chunk, 0, posInChunk, _chunk); - // - // --- src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (revision 1766745) - // +++ src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (working copy) - // - // @@ -300,7 +297,7 @@ - // protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode) - // throws GeneralSecurityException { - // EncryptionHeader header = encryptionInfo.getHeader(); - // - String padding = (lastChunk ? "PKCS5Padding" : "NoPadding"); - // + String padding = "NoPadding"; // (lastChunk ? "PKCS5Padding" : "NoPadding"); - // if (existing == null || !existing.getAlgorithm().endsWith(padding)) { - // existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding); - // } - - InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx"); - POIFSFileSystem fsOrig = new POIFSFileSystem(is); - is.close(); - EncryptionInfo infoOrig = new EncryptionInfo(fsOrig); - Decryptor decOrig = infoOrig.getDecryptor(); - boolean b = decOrig.verifyPassword("Test001!!"); - assertTrue(b); - InputStream decIn = decOrig.getDataStream(fsOrig); - byte[] zipInput = IOUtils.toByteArray(decIn); - decIn.close(); - - InputStream epOrig = fsOrig.getRoot().createDocumentInputStream("EncryptedPackage"); - // ignore the 16 padding bytes - byte[] epOrigBytes = IOUtils.toByteArray(epOrig, 9400); - epOrig.close(); - - EncryptionInfo eiNew = new EncryptionInfo(EncryptionMode.agile); - AgileEncryptionHeader aehHeader = (AgileEncryptionHeader)eiNew.getHeader(); - aehHeader.setCipherAlgorithm(CipherAlgorithm.aes128); - aehHeader.setHashAlgorithm(HashAlgorithm.sha1); - AgileEncryptionVerifier aehVerifier = (AgileEncryptionVerifier)eiNew.getVerifier(); - - // this cast might look strange - if the setters would be public, it will become obsolete - // see http://stackoverflow.com/questions/5637650/overriding-protected-methods-in-java - ((EncryptionVerifier)aehVerifier).setCipherAlgorithm(CipherAlgorithm.aes256); - aehVerifier.setHashAlgorithm(HashAlgorithm.sha512); - - Encryptor enc = eiNew.getEncryptor(); - enc.confirmPassword("Test001!!", - infoOrig.getDecryptor().getSecretKey().getEncoded(), - infoOrig.getHeader().getKeySalt(), - infoOrig.getDecryptor().getVerifier(), - infoOrig.getVerifier().getSalt(), - infoOrig.getDecryptor().getIntegrityHmacKey() - ); - NPOIFSFileSystem fsNew = new NPOIFSFileSystem(); - OutputStream os = enc.getDataStream(fsNew); - os.write(zipInput); - os.close(); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - fsNew.writeFilesystem(bos); - fsNew.close(); - - NPOIFSFileSystem fsReload = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - InputStream epReload = fsReload.getRoot().createDocumentInputStream("EncryptedPackage"); - byte[] epNewBytes = IOUtils.toByteArray(epReload, 9400); - epReload.close(); - - assertArrayEquals(epOrigBytes, epNewBytes); - - EncryptionInfo infoReload = new EncryptionInfo(fsOrig); - Decryptor decReload = infoReload.getDecryptor(); - b = decReload.verifyPassword("Test001!!"); - assertTrue(b); - - AgileEncryptionHeader aehOrig = (AgileEncryptionHeader)infoOrig.getHeader(); - AgileEncryptionHeader aehReload = (AgileEncryptionHeader)infoReload.getHeader(); - assertEquals(aehOrig.getBlockSize(), aehReload.getBlockSize()); - assertEquals(aehOrig.getChainingMode(), aehReload.getChainingMode()); - assertEquals(aehOrig.getCipherAlgorithm(), aehReload.getCipherAlgorithm()); - assertEquals(aehOrig.getCipherProvider(), aehReload.getCipherProvider()); - assertEquals(aehOrig.getCspName(), aehReload.getCspName()); - assertArrayEquals(aehOrig.getEncryptedHmacKey(), aehReload.getEncryptedHmacKey()); - // this only works, when the paddings are mocked to be the same ... - // assertArrayEquals(aehOrig.getEncryptedHmacValue(), aehReload.getEncryptedHmacValue()); - assertEquals(aehOrig.getFlags(), aehReload.getFlags()); - assertEquals(aehOrig.getHashAlgorithm(), aehReload.getHashAlgorithm()); - assertArrayEquals(aehOrig.getKeySalt(), aehReload.getKeySalt()); - assertEquals(aehOrig.getKeySize(), aehReload.getKeySize()); - - AgileEncryptionVerifier aevOrig = (AgileEncryptionVerifier)infoOrig.getVerifier(); - AgileEncryptionVerifier aevReload = (AgileEncryptionVerifier)infoReload.getVerifier(); - assertEquals(aevOrig.getBlockSize(), aevReload.getBlockSize()); - assertEquals(aevOrig.getChainingMode(), aevReload.getChainingMode()); - assertEquals(aevOrig.getCipherAlgorithm(), aevReload.getCipherAlgorithm()); - assertArrayEquals(aevOrig.getEncryptedKey(), aevReload.getEncryptedKey()); - assertArrayEquals(aevOrig.getEncryptedVerifier(), aevReload.getEncryptedVerifier()); - assertArrayEquals(aevOrig.getEncryptedVerifierHash(), aevReload.getEncryptedVerifierHash()); - assertEquals(aevOrig.getHashAlgorithm(), aevReload.getHashAlgorithm()); - assertEquals(aevOrig.getKeySize(), aevReload.getKeySize()); - assertArrayEquals(aevOrig.getSalt(), aevReload.getSalt()); - assertEquals(aevOrig.getSpinCount(), aevReload.getSpinCount()); - - AgileDecryptor adOrig = (AgileDecryptor)infoOrig.getDecryptor(); - AgileDecryptor adReload = (AgileDecryptor)infoReload.getDecryptor(); - - assertArrayEquals(adOrig.getIntegrityHmacKey(), adReload.getIntegrityHmacKey()); - // doesn't work without mocking ... see above - // assertArrayEquals(adOrig.getIntegrityHmacValue(), adReload.getIntegrityHmacValue()); - assertArrayEquals(adOrig.getSecretKey().getEncoded(), adReload.getSecretKey().getEncoded()); - assertArrayEquals(adOrig.getVerifier(), adReload.getVerifier()); - - fsReload.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.poifs.crypt; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Iterator; + +import javax.crypto.Cipher; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.poifs.crypt.agile.AgileDecryptor; +import org.apache.poi.poifs.crypt.agile.AgileEncryptionHeader; +import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentNode; +import org.apache.poi.poifs.filesystem.Entry; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.BoundedInputStream; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.TempFile; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.junit.Assume; +import org.junit.Ignore; +import org.junit.Test; + +public class TestEncryptor { + @Test + public void binaryRC4Encryption() throws Exception { + // please contribute a real sample file, which is binary rc4 encrypted + // ... at least the output can be opened in Excel Viewer + String password = "pass"; + + InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx"); + ByteArrayOutputStream payloadExpected = new ByteArrayOutputStream(); + IOUtils.copy(is, payloadExpected); + is.close(); + + POIFSFileSystem fs = new POIFSFileSystem(); + EncryptionInfo ei = new EncryptionInfo(EncryptionMode.binaryRC4); + Encryptor enc = ei.getEncryptor(); + enc.confirmPassword(password); + + OutputStream os = enc.getDataStream(fs.getRoot()); + payloadExpected.writeTo(os); + os.close(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + fs.writeFilesystem(bos); + + fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); + ei = new EncryptionInfo(fs); + Decryptor dec = ei.getDecryptor(); + boolean b = dec.verifyPassword(password); + assertTrue(b); + + ByteArrayOutputStream payloadActual = new ByteArrayOutputStream(); + is = dec.getDataStream(fs.getRoot()); + IOUtils.copy(is,payloadActual); + is.close(); + + assertArrayEquals(payloadExpected.toByteArray(), payloadActual.toByteArray()); + } + + @Test + public void agileEncryption() throws Exception { + int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); + Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); + + File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx"); + String pass = "pass"; + NPOIFSFileSystem nfs = new NPOIFSFileSystem(file); + + // Check the encryption details + EncryptionInfo infoExpected = new EncryptionInfo(nfs); + Decryptor decExpected = Decryptor.getInstance(infoExpected); + boolean passed = decExpected.verifyPassword(pass); + assertTrue("Unable to process: document is encrypted", passed); + + // extract the payload + InputStream is = decExpected.getDataStream(nfs); + byte payloadExpected[] = IOUtils.toByteArray(is); + is.close(); + + long decPackLenExpected = decExpected.getLength(); + assertEquals(decPackLenExpected, payloadExpected.length); + + is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY); + is = new BoundedInputStream(is, is.available()-16); // ignore padding block + byte encPackExpected[] = IOUtils.toByteArray(is); + is.close(); + + // listDir(nfs.getRoot(), "orig", ""); + + nfs.close(); + + // check that same verifier/salt lead to same hashes + byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt(); + byte verifierExpected[] = decExpected.getVerifier(); + byte keySalt[] = infoExpected.getHeader().getKeySalt(); + byte keySpec[] = decExpected.getSecretKey().getEncoded(); + byte integritySalt[] = decExpected.getIntegrityHmacKey(); + // the hmacs of the file always differ, as we use PKCS5-padding to pad the bytes + // whereas office just uses random bytes + // byte integrityHash[] = d.getIntegrityHmacValue(); + + POIFSFileSystem fs = new POIFSFileSystem(); + EncryptionInfo infoActual = new EncryptionInfo( + EncryptionMode.agile + , infoExpected.getVerifier().getCipherAlgorithm() + , infoExpected.getVerifier().getHashAlgorithm() + , infoExpected.getHeader().getKeySize() + , infoExpected.getHeader().getBlockSize() + , infoExpected.getVerifier().getChainingMode() + ); + + Encryptor e = Encryptor.getInstance(infoActual); + e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, integritySalt); + + OutputStream os = e.getDataStream(fs); + IOUtils.copy(new ByteArrayInputStream(payloadExpected), os); + os.close(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + fs.writeFilesystem(bos); + + nfs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); + infoActual = new EncryptionInfo(nfs.getRoot()); + Decryptor decActual = Decryptor.getInstance(infoActual); + passed = decActual.verifyPassword(pass); + assertTrue("Unable to process: document is encrypted", passed); + + // extract the payload + is = decActual.getDataStream(nfs); + byte payloadActual[] = IOUtils.toByteArray(is); + is.close(); + + long decPackLenActual = decActual.getLength(); + + is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY); + is = new BoundedInputStream(is, is.available()-16); // ignore padding block + byte encPackActual[] = IOUtils.toByteArray(is); + is.close(); + + // listDir(nfs.getRoot(), "copy", ""); + + nfs.close(); + + AgileEncryptionHeader aehExpected = (AgileEncryptionHeader)infoExpected.getHeader(); + AgileEncryptionHeader aehActual = (AgileEncryptionHeader)infoActual.getHeader(); + assertArrayEquals(aehExpected.getEncryptedHmacKey(), aehActual.getEncryptedHmacKey()); + assertEquals(decPackLenExpected, decPackLenActual); + assertArrayEquals(payloadExpected, payloadActual); + assertArrayEquals(encPackExpected, encPackActual); + } + + @Test + public void standardEncryption() throws Exception { + File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx"); + String pass = "solrcell"; + + NPOIFSFileSystem nfs = new NPOIFSFileSystem(file); + + // Check the encryption details + EncryptionInfo infoExpected = new EncryptionInfo(nfs); + Decryptor d = Decryptor.getInstance(infoExpected); + boolean passed = d.verifyPassword(pass); + assertTrue("Unable to process: document is encrypted", passed); + + // extract the payload + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + InputStream is = d.getDataStream(nfs); + IOUtils.copy(is, bos); + is.close(); + nfs.close(); + byte payloadExpected[] = bos.toByteArray(); + + // check that same verifier/salt lead to same hashes + byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt(); + byte verifierExpected[] = d.getVerifier(); + byte keySpec[] = d.getSecretKey().getEncoded(); + byte keySalt[] = infoExpected.getHeader().getKeySalt(); + + + EncryptionInfo infoActual = new EncryptionInfo( + EncryptionMode.standard + , infoExpected.getVerifier().getCipherAlgorithm() + , infoExpected.getVerifier().getHashAlgorithm() + , infoExpected.getHeader().getKeySize() + , infoExpected.getHeader().getBlockSize() + , infoExpected.getVerifier().getChainingMode() + ); + + Encryptor e = Encryptor.getInstance(infoActual); + e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, null); + + assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifier(), infoActual.getVerifier().getEncryptedVerifier()); + assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifierHash(), infoActual.getVerifier().getEncryptedVerifierHash()); + + // now we use a newly generated salt/verifier and check + // if the file content is still the same + + infoActual = new EncryptionInfo( + EncryptionMode.standard + , infoExpected.getVerifier().getCipherAlgorithm() + , infoExpected.getVerifier().getHashAlgorithm() + , infoExpected.getHeader().getKeySize() + , infoExpected.getHeader().getBlockSize() + , infoExpected.getVerifier().getChainingMode() + ); + + e = Encryptor.getInstance(infoActual); + e.confirmPassword(pass); + + POIFSFileSystem fs = new POIFSFileSystem(); + OutputStream os = e.getDataStream(fs); + IOUtils.copy(new ByteArrayInputStream(payloadExpected), os); + os.close(); + + bos.reset(); + fs.writeFilesystem(bos); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + + // FileOutputStream fos = new FileOutputStream("encrypted.docx"); + // IOUtils.copy(bis, fos); + // fos.close(); + // bis.reset(); + + nfs = new NPOIFSFileSystem(bis); + infoExpected = new EncryptionInfo(nfs); + d = Decryptor.getInstance(infoExpected); + passed = d.verifyPassword(pass); + assertTrue("Unable to process: document is encrypted", passed); + + bos.reset(); + is = d.getDataStream(nfs); + IOUtils.copy(is, bos); + is.close(); + nfs.close(); + byte payloadActual[] = bos.toByteArray(); + + assertArrayEquals(payloadExpected, payloadActual); + } + + /** + * Ensure we can encrypt a package that is missing the Core + * Properties, eg one from dodgy versions of Jasper Reports + * See https://github.com/nestoru/xlsxenc/ and + * http://stackoverflow.com/questions/28593223 + */ + @Test + public void encryptPackageWithoutCoreProperties() throws Exception { + // Open our file without core properties + File inp = POIDataSamples.getOpenXML4JInstance().getFile("OPCCompliance_NoCoreProperties.xlsx"); + OPCPackage pkg = OPCPackage.open(inp.getPath()); + + // It doesn't have any core properties yet + assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(pkg.getPackageProperties()); + assertNotNull(pkg.getPackageProperties().getLanguageProperty()); + assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); + + // Encrypt it + EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile); + NPOIFSFileSystem fs = new NPOIFSFileSystem(); + + Encryptor enc = info.getEncryptor(); + enc.confirmPassword("password"); + OutputStream os = enc.getDataStream(fs); + pkg.save(os); + pkg.revert(); + + // Save the resulting OLE2 document, and re-open it + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + fs.writeFilesystem(baos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + NPOIFSFileSystem inpFS = new NPOIFSFileSystem(bais); + + // Check we can decrypt it + info = new EncryptionInfo(inpFS); + Decryptor d = Decryptor.getInstance(info); + assertEquals(true, d.verifyPassword("password")); + + OPCPackage inpPkg = OPCPackage.open(d.getDataStream(inpFS)); + + // Check it now has empty core properties + assertEquals(1, inpPkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(inpPkg.getPackageProperties()); + assertNotNull(inpPkg.getPackageProperties().getLanguageProperty()); + assertNull(inpPkg.getPackageProperties().getLanguageProperty().getValue()); + } + + @Test + @Ignore + public void inPlaceRewrite() throws Exception { + File f = TempFile.createTempFile("protected_agile", ".docx"); + // File f = new File("protected_agile.docx"); + FileOutputStream fos = new FileOutputStream(f); + InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx"); + IOUtils.copy(fis, fos); + fis.close(); + fos.close(); + + NPOIFSFileSystem fs = new NPOIFSFileSystem(f, false); + + // decrypt the protected file - in this case it was encrypted with the default password + EncryptionInfo encInfo = new EncryptionInfo(fs); + Decryptor d = encInfo.getDecryptor(); + boolean b = d.verifyPassword(Decryptor.DEFAULT_PASSWORD); + assertTrue(b); + + // do some strange things with it ;) + XWPFDocument docx = new XWPFDocument(d.getDataStream(fs)); + docx.getParagraphArray(0).insertNewRun(0).setText("POI was here! All your base are belong to us!"); + docx.getParagraphArray(0).insertNewRun(1).addBreak(); + + // and encrypt it again + Encryptor e = encInfo.getEncryptor(); + e.confirmPassword("AYBABTU"); + docx.write(e.getDataStream(fs)); + + docx.close(); + fs.close(); + } + + + private void listEntry(DocumentNode de, String ext, String path) throws IOException { + path += "\\" + de.getName().replaceAll("[\\p{Cntrl}]", "_"); + System.out.println(ext+": "+path+" ("+de.getSize()+" bytes)"); + + String name = de.getName().replaceAll("[\\p{Cntrl}]", "_"); + + InputStream is = ((DirectoryNode)de.getParent()).createDocumentInputStream(de); + FileOutputStream fos = new FileOutputStream("solr."+name+"."+ext); + IOUtils.copy(is, fos); + fos.close(); + is.close(); + } + + @SuppressWarnings("unused") + private void listDir(DirectoryNode dn, String ext, String path) throws IOException { + path += "\\" + dn.getName().replace('\u0006', '_'); + System.out.println(ext+": "+path+" ("+dn.getStorageClsid()+")"); + + Iterator iter = dn.getEntries(); + while (iter.hasNext()) { + Entry ent = iter.next(); + if (ent instanceof DirectoryNode) { + listDir((DirectoryNode)ent, ext, path); + } else { + listEntry((DocumentNode)ent, ext, path); + } + } + } + + /* + * this test simulates the generation of bugs 60320 sample file + * as the padding bytes of the EncryptedPackage stream are random or in POIs case PKCS5-padded + * one would need to mock those bytes to get the same hmacValues - see diff below + * + * this use-case is experimental - for the time being the setters of the encryption classes + * are spreaded between two packages and are protected - so you would need to violate + * the packages rules and provide a helper class in the *poifs.crypt package-namespace. + * the default way of defining the encryption settings is via the EncryptionInfo class + */ + @Test + public void bug60320CustomEncrypt() throws Exception { + int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); + Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); + + // --- src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (revision 1766745) + // +++ src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (working copy) + // @@ -208,6 +208,13 @@ + // protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException { + // byte plain[] = (_plainByteFlags.isEmpty()) ? null : _chunk.clone(); + // + // + if (posInChunk < 4096) { + // + _cipher.update(_chunk, 0, posInChunk, _chunk); + // + byte bla[] = { (byte)0x7A,(byte)0x0F,(byte)0x27,(byte)0xF0,(byte)0x17,(byte)0x6E,(byte)0x77,(byte)0x05,(byte)0xB9,(byte)0xDA,(byte)0x49,(byte)0xF9,(byte)0xD7,(byte)0x8E,(byte)0x03,(byte)0x1D }; + // + System.arraycopy(bla, 0, _chunk, posInChunk-2, bla.length); + // + return posInChunk-2+bla.length; + // + } + // + + // int ciLen = (doFinal) + // ? _cipher.doFinal(_chunk, 0, posInChunk, _chunk) + // : _cipher.update(_chunk, 0, posInChunk, _chunk); + // + // --- src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (revision 1766745) + // +++ src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (working copy) + // + // @@ -300,7 +297,7 @@ + // protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode) + // throws GeneralSecurityException { + // EncryptionHeader header = encryptionInfo.getHeader(); + // - String padding = (lastChunk ? "PKCS5Padding" : "NoPadding"); + // + String padding = "NoPadding"; // (lastChunk ? "PKCS5Padding" : "NoPadding"); + // if (existing == null || !existing.getAlgorithm().endsWith(padding)) { + // existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding); + // } + + InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx"); + POIFSFileSystem fsOrig = new POIFSFileSystem(is); + is.close(); + EncryptionInfo infoOrig = new EncryptionInfo(fsOrig); + Decryptor decOrig = infoOrig.getDecryptor(); + boolean b = decOrig.verifyPassword("Test001!!"); + assertTrue(b); + InputStream decIn = decOrig.getDataStream(fsOrig); + byte[] zipInput = IOUtils.toByteArray(decIn); + decIn.close(); + + InputStream epOrig = fsOrig.getRoot().createDocumentInputStream("EncryptedPackage"); + // ignore the 16 padding bytes + byte[] epOrigBytes = IOUtils.toByteArray(epOrig, 9400); + epOrig.close(); + + EncryptionInfo eiNew = new EncryptionInfo(EncryptionMode.agile); + AgileEncryptionHeader aehHeader = (AgileEncryptionHeader)eiNew.getHeader(); + aehHeader.setCipherAlgorithm(CipherAlgorithm.aes128); + aehHeader.setHashAlgorithm(HashAlgorithm.sha1); + AgileEncryptionVerifier aehVerifier = (AgileEncryptionVerifier)eiNew.getVerifier(); + + // this cast might look strange - if the setters would be public, it will become obsolete + // see http://stackoverflow.com/questions/5637650/overriding-protected-methods-in-java + ((EncryptionVerifier)aehVerifier).setCipherAlgorithm(CipherAlgorithm.aes256); + aehVerifier.setHashAlgorithm(HashAlgorithm.sha512); + + Encryptor enc = eiNew.getEncryptor(); + enc.confirmPassword("Test001!!", + infoOrig.getDecryptor().getSecretKey().getEncoded(), + infoOrig.getHeader().getKeySalt(), + infoOrig.getDecryptor().getVerifier(), + infoOrig.getVerifier().getSalt(), + infoOrig.getDecryptor().getIntegrityHmacKey() + ); + NPOIFSFileSystem fsNew = new NPOIFSFileSystem(); + OutputStream os = enc.getDataStream(fsNew); + os.write(zipInput); + os.close(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + fsNew.writeFilesystem(bos); + fsNew.close(); + + NPOIFSFileSystem fsReload = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); + InputStream epReload = fsReload.getRoot().createDocumentInputStream("EncryptedPackage"); + byte[] epNewBytes = IOUtils.toByteArray(epReload, 9400); + epReload.close(); + + assertArrayEquals(epOrigBytes, epNewBytes); + + EncryptionInfo infoReload = new EncryptionInfo(fsOrig); + Decryptor decReload = infoReload.getDecryptor(); + b = decReload.verifyPassword("Test001!!"); + assertTrue(b); + + AgileEncryptionHeader aehOrig = (AgileEncryptionHeader)infoOrig.getHeader(); + AgileEncryptionHeader aehReload = (AgileEncryptionHeader)infoReload.getHeader(); + assertEquals(aehOrig.getBlockSize(), aehReload.getBlockSize()); + assertEquals(aehOrig.getChainingMode(), aehReload.getChainingMode()); + assertEquals(aehOrig.getCipherAlgorithm(), aehReload.getCipherAlgorithm()); + assertEquals(aehOrig.getCipherProvider(), aehReload.getCipherProvider()); + assertEquals(aehOrig.getCspName(), aehReload.getCspName()); + assertArrayEquals(aehOrig.getEncryptedHmacKey(), aehReload.getEncryptedHmacKey()); + // this only works, when the paddings are mocked to be the same ... + // assertArrayEquals(aehOrig.getEncryptedHmacValue(), aehReload.getEncryptedHmacValue()); + assertEquals(aehOrig.getFlags(), aehReload.getFlags()); + assertEquals(aehOrig.getHashAlgorithm(), aehReload.getHashAlgorithm()); + assertArrayEquals(aehOrig.getKeySalt(), aehReload.getKeySalt()); + assertEquals(aehOrig.getKeySize(), aehReload.getKeySize()); + + AgileEncryptionVerifier aevOrig = (AgileEncryptionVerifier)infoOrig.getVerifier(); + AgileEncryptionVerifier aevReload = (AgileEncryptionVerifier)infoReload.getVerifier(); + assertEquals(aevOrig.getBlockSize(), aevReload.getBlockSize()); + assertEquals(aevOrig.getChainingMode(), aevReload.getChainingMode()); + assertEquals(aevOrig.getCipherAlgorithm(), aevReload.getCipherAlgorithm()); + assertArrayEquals(aevOrig.getEncryptedKey(), aevReload.getEncryptedKey()); + assertArrayEquals(aevOrig.getEncryptedVerifier(), aevReload.getEncryptedVerifier()); + assertArrayEquals(aevOrig.getEncryptedVerifierHash(), aevReload.getEncryptedVerifierHash()); + assertEquals(aevOrig.getHashAlgorithm(), aevReload.getHashAlgorithm()); + assertEquals(aevOrig.getKeySize(), aevReload.getKeySize()); + assertArrayEquals(aevOrig.getSalt(), aevReload.getSalt()); + assertEquals(aevOrig.getSpinCount(), aevReload.getSpinCount()); + + AgileDecryptor adOrig = (AgileDecryptor)infoOrig.getDecryptor(); + AgileDecryptor adReload = (AgileDecryptor)infoReload.getDecryptor(); + + assertArrayEquals(adOrig.getIntegrityHmacKey(), adReload.getIntegrityHmacKey()); + // doesn't work without mocking ... see above + // assertArrayEquals(adOrig.getIntegrityHmacValue(), adReload.getIntegrityHmacValue()); + assertArrayEquals(adOrig.getSecretKey().getEncoded(), adReload.getSecretKey().getEncoded()); + assertArrayEquals(adOrig.getVerifier(), adReload.getVerifier()); + + fsReload.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java index bd13e13c03..3c172f385d 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java @@ -1,724 +1,724 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -/* ==================================================================== - This product contains an ASLv2 licensed version of the OOXML signer - package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt - Copyright (C) 2008-2014 FedICT. - ================================================================= */ -package org.apache.poi.poifs.crypt; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.ConnectException; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.security.Key; -import java.security.KeyPair; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.POITestCase; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackageAccess; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.poifs.crypt.dsig.DigestInfo; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig; -import org.apache.poi.poifs.crypt.dsig.SignatureInfo; -import org.apache.poi.poifs.crypt.dsig.SignatureInfo.SignaturePart; -import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet; -import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet; -import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet; -import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet; -import org.apache.poi.poifs.crypt.dsig.services.RevocationData; -import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService; -import org.apache.poi.poifs.crypt.dsig.services.TimeStampService; -import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator; -import org.apache.poi.ss.usermodel.WorkbookFactory; -import org.apache.poi.util.DocumentHelper; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LocaleUtil; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.xmlbeans.XmlObject; -import org.bouncycastle.asn1.x509.KeyUsage; -import org.bouncycastle.cert.ocsp.OCSPResp; -import org.etsi.uri.x01903.v13.DigestAlgAndValueType; -import org.etsi.uri.x01903.v13.QualifyingPropertiesType; -import org.junit.Assume; -import org.junit.BeforeClass; -import org.junit.Test; -import org.w3.x2000.x09.xmldsig.ReferenceType; -import org.w3.x2000.x09.xmldsig.SignatureDocument; -import org.w3c.dom.Document; - -public class TestSignatureInfo { - private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class); - private static final POIDataSamples testdata = POIDataSamples.getXmlDSignInstance(); - - private static Calendar cal; - private KeyPair keyPair = null; - private X509Certificate x509 = null; - - @BeforeClass - public static void initBouncy() throws IOException { - CryptoFunctions.registerBouncyCastle(); - - // Set cal to now ... only set to fixed date for debugging ... - cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC); - assertNotNull(cal); -// cal.set(2014, 7, 6, 21, 42, 12); -// cal.clear(Calendar.MILLISECOND); - - // don't run this test when we are using older Xerces as it triggers an XML Parser backwards compatibility issue - // in the xmlsec jar file - String additionalJar = System.getProperty("additionaljar"); - //System.out.println("Having: " + additionalJar); - Assume.assumeTrue("Not running TestSignatureInfo because we are testing with additionaljar set to " + additionalJar, - additionalJar == null || additionalJar.trim().length() == 0); - } - - @Test - public void office2007prettyPrintedRels() throws Exception { - OPCPackage pkg = OPCPackage.open(testdata.getFile("office2007prettyPrintedRels.docx"), PackageAccess.READ); - try { - SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(sic); - boolean isValid = si.verifySignature(); - assertTrue(isValid); - } finally { - pkg.close(); - } - } - - @Test - public void getSignerUnsigned() throws Exception { - String testFiles[] = { - "hello-world-unsigned.docx", - "hello-world-unsigned.pptx", - "hello-world-unsigned.xlsx", - "hello-world-office-2010-technical-preview-unsigned.docx" - }; - - for (String testFile : testFiles) { - OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); - SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(sic); - List result = new ArrayList(); - for (SignaturePart sp : si.getSignatureParts()) { - if (sp.validate()) { - result.add(sp.getSigner()); - } - } - pkg.revert(); - pkg.close(); - assertNotNull(result); - assertTrue(result.isEmpty()); - } - } - - @Test - public void getSigner() throws Exception { - String testFiles[] = { - "hyperlink-example-signed.docx", - "hello-world-signed.docx", - "hello-world-signed.pptx", - "hello-world-signed.xlsx", - "hello-world-office-2010-technical-preview.docx", - "ms-office-2010-signed.docx", - "ms-office-2010-signed.pptx", - "ms-office-2010-signed.xlsx", - "Office2010-SP1-XAdES-X-L.docx", - "signed.docx", - }; - - for (String testFile : testFiles) { - OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); - try { - SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(sic); - List result = new ArrayList(); - for (SignaturePart sp : si.getSignatureParts()) { - if (sp.validate()) { - result.add(sp.getSigner()); - } - } - - assertNotNull(result); - assertEquals("test-file: "+testFile, 1, result.size()); - X509Certificate signer = result.get(0); - LOG.log(POILogger.DEBUG, "signer: " + signer.getSubjectX500Principal()); - - boolean b = si.verifySignature(); - assertTrue("test-file: "+testFile, b); - pkg.revert(); - } finally { - pkg.close(); - } - } - } - - @Test - public void getMultiSigners() throws Exception { - String testFile = "hello-world-signed-twice.docx"; - OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); - try { - SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(sic); - List result = new ArrayList(); - for (SignaturePart sp : si.getSignatureParts()) { - if (sp.validate()) { - result.add(sp.getSigner()); - } - } - - assertNotNull(result); - assertEquals("test-file: "+testFile, 2, result.size()); - X509Certificate signer1 = result.get(0); - X509Certificate signer2 = result.get(1); - LOG.log(POILogger.DEBUG, "signer 1: " + signer1.getSubjectX500Principal()); - LOG.log(POILogger.DEBUG, "signer 2: " + signer2.getSubjectX500Principal()); - - boolean b = si.verifySignature(); - assertTrue("test-file: "+testFile, b); - pkg.revert(); - } finally { - pkg.close(); - } - } - - @Test - public void testSignSpreadsheet() throws Exception { - String testFile = "hello-world-unsigned.xlsx"; - OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - sign(pkg, "Test", "CN=Test", 1); - pkg.close(); - } - - @Test - public void testManipulation() throws Exception { - // sign & validate - String testFile = "hello-world-unsigned.xlsx"; - @SuppressWarnings("resource") - OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - sign(pkg, "Test", "CN=Test", 1); - - // manipulate - XSSFWorkbook wb = new XSSFWorkbook(pkg); - wb.setSheetName(0, "manipulated"); - // ... I don't know, why commit is protected ... - POITestCase.callMethod(XSSFWorkbook.class, wb, Void.class, "commit", new Class[0], new Object[0]); - - // todo: test a manipulation on a package part, which is not signed - // ... maybe in combination with #56164 - - // validate - SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(sic); - boolean b = si.verifySignature(); - assertFalse("signature should be broken", b); - - wb.close(); - } - - @Test - public void testSignSpreadsheetWithSignatureInfo() throws Exception { - initKeyPair("Test", "CN=Test"); - String testFile = "hello-world-unsigned.xlsx"; - OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - SignatureConfig sic = new SignatureConfig(); - sic.setOpcPackage(pkg); - sic.setKey(keyPair.getPrivate()); - sic.setSigningCertificateChain(Collections.singletonList(x509)); - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(sic); - // hash > sha1 doesn't work in excel viewer ... - si.confirmSignature(); - List result = new ArrayList(); - for (SignaturePart sp : si.getSignatureParts()) { - if (sp.validate()) { - result.add(sp.getSigner()); - } - } - assertEquals(1, result.size()); - pkg.close(); - } - - @Test - public void testSignEnvelopingDocument() throws Exception { - String testFile = "hello-world-unsigned.xlsx"; - OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - - initKeyPair("Test", "CN=Test"); - final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate()); - - // setup - SignatureConfig signatureConfig = new SignatureConfig(); - signatureConfig.setOpcPackage(pkg); - signatureConfig.setKey(keyPair.getPrivate()); - - /* - * We need at least 2 certificates for the XAdES-C complete certificate - * refs construction. - */ - List certificateChain = new ArrayList(); - certificateChain.add(x509); - certificateChain.add(x509); - signatureConfig.setSigningCertificateChain(certificateChain); - - signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet()); - signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet()); - signatureConfig.addSignatureFacet(new XAdESSignatureFacet()); - signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet()); - - // check for internet, no error means it works - boolean mockTsp = (getAccessError("http://timestamp.comodoca.com/rfc3161", true, 10000) != null); - - // http://timestamping.edelweb.fr/service/tsp - // http://tsa.belgium.be/connect - // http://timestamp.comodoca.com/authenticode - // http://timestamp.comodoca.com/rfc3161 - // http://services.globaltrustfinder.com/adss/tsa - signatureConfig.setTspUrl("http://timestamp.comodoca.com/rfc3161"); - signatureConfig.setTspRequestPolicy(null); // comodoca request fails, if default policy is set ... - signatureConfig.setTspOldProtocol(false); - - //set proxy info if any - String proxy = System.getProperty("http_proxy"); - if (proxy != null && proxy.trim().length() > 0) { - signatureConfig.setProxyUrl(proxy); - } - - if (mockTsp) { - TimeStampService tspService = new TimeStampService(){ - @Override - public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception { - revocationData.addCRL(crl); - return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252); - } - @Override - public void setSignatureConfig(SignatureConfig config) { - // empty on purpose - } - }; - signatureConfig.setTspService(tspService); - } else { - TimeStampServiceValidator tspValidator = new TimeStampServiceValidator() { - @Override - public void validate(List validateChain, - RevocationData revocationData) throws Exception { - for (X509Certificate certificate : validateChain) { - LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal()); - LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter()); - } - } - }; - signatureConfig.setTspValidator(tspValidator); - signatureConfig.setTspOldProtocol(signatureConfig.getTspUrl().contains("edelweb")); - } - - final RevocationData revocationData = new RevocationData(); - revocationData.addCRL(crl); - OCSPResp ocspResp = PkiTestUtils.createOcspResp(x509, false, - x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis()); - revocationData.addOCSP(ocspResp.getEncoded()); - - RevocationDataService revocationDataService = new RevocationDataService(){ - @Override - public RevocationData getRevocationData(List revocationChain) { - return revocationData; - } - }; - signatureConfig.setRevocationDataService(revocationDataService); - - // operate - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(signatureConfig); - try { - si.confirmSignature(); - } catch (RuntimeException e) { - pkg.close(); - // only allow a ConnectException because of timeout, we see this in Jenkins from time to time... - if(e.getCause() == null) { - throw e; - } - if((e.getCause() instanceof ConnectException) || (e.getCause() instanceof SocketTimeoutException)) { - Assume.assumeFalse("Only allowing ConnectException with 'timed out' as message here, but had: " + e, - e.getCause().getMessage().contains("timed out")); - } else if (e.getCause() instanceof IOException) { - Assume.assumeFalse("Only allowing IOException with 'Error contacting TSP server' as message here, but had: " + e, - e.getCause().getMessage().contains("Error contacting TSP server")); - } else if (e.getCause() instanceof RuntimeException) { - Assume.assumeFalse("Only allowing RuntimeException with 'This site is cur' as message here, but had: " + e, - e.getCause().getMessage().contains("This site is cur")); - } - throw e; - } - - // verify - Iterator spIter = si.getSignatureParts().iterator(); - assertTrue("Had: " + si.getSignatureConfig().getOpcPackage(). - getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), - spIter.hasNext()); - SignaturePart sp = spIter.next(); - boolean valid = sp.validate(); - assertTrue(valid); - - SignatureDocument sigDoc = sp.getSignatureDocument(); - String declareNS = - "declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; " - + "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "; - - String digestValXQuery = declareNS + - "$this/ds:Signature/ds:SignedInfo/ds:Reference"; - for (ReferenceType rt : (ReferenceType[])sigDoc.selectPath(digestValXQuery)) { - assertNotNull(rt.getDigestValue()); - assertEquals(signatureConfig.getDigestMethodUri(), rt.getDigestMethod().getAlgorithm()); - } - - String certDigestXQuery = declareNS + - "$this//xades:SigningCertificate/xades:Cert/xades:CertDigest"; - XmlObject xoList[] = sigDoc.selectPath(certDigestXQuery); - assertEquals(xoList.length, 1); - DigestAlgAndValueType certDigest = (DigestAlgAndValueType)xoList[0]; - assertNotNull(certDigest.getDigestValue()); - - String qualPropXQuery = declareNS + - "$this/ds:Signature/ds:Object/xades:QualifyingProperties"; - xoList = sigDoc.selectPath(qualPropXQuery); - assertEquals(xoList.length, 1); - QualifyingPropertiesType qualProp = (QualifyingPropertiesType)xoList[0]; - boolean qualPropXsdOk = qualProp.validate(); - assertTrue(qualPropXsdOk); - - pkg.close(); - } - - public static String getAccessError(String destinationUrl, boolean fireRequest, int timeout) { - URL url; - try { - url = new URL(destinationUrl); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Invalid destination URL", e); - } - - HttpURLConnection conn = null; - try { - conn = (HttpURLConnection) url.openConnection(); - - // set specified timeout if non-zero - if(timeout != 0) { - conn.setConnectTimeout(timeout); - conn.setReadTimeout(timeout); - } - - conn.setDoOutput(false); - conn.setDoInput(true); - - /* if connecting is not possible this will throw a connection refused exception */ - conn.connect(); - - if (fireRequest) { - InputStream is = null; - try { - is = conn.getInputStream(); - } finally { - IOUtils.closeQuietly(is); - } - - } - /* if connecting is possible we return true here */ - return null; - - } catch (IOException e) { - /* exception is thrown -> server not available */ - return e.getClass().getName() + ": " + e.getMessage(); - } finally { - if (conn != null) { - conn.disconnect(); - } - } - } - - @Test - public void testCertChain() throws Exception { - KeyStore keystore = KeyStore.getInstance("PKCS12"); - String password = "test"; - InputStream is = testdata.openResourceAsStream("chaintest.pfx"); - keystore.load(is, password.toCharArray()); - is.close(); - - Key key = keystore.getKey("poitest", password.toCharArray()); - Certificate chainList[] = keystore.getCertificateChain("poitest"); - List certChain = new ArrayList(); - for (Certificate c : chainList) { - certChain.add((X509Certificate)c); - } - x509 = certChain.get(0); - keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key); - - String testFile = "hello-world-unsigned.xlsx"; - OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - - SignatureConfig signatureConfig = new SignatureConfig(); - signatureConfig.setKey(keyPair.getPrivate()); - signatureConfig.setSigningCertificateChain(certChain); - Calendar oldCal = LocaleUtil.getLocaleCalendar(2007, 7, 1); - signatureConfig.setExecutionTime(oldCal.getTime()); - signatureConfig.setDigestAlgo(HashAlgorithm.sha1); - signatureConfig.setOpcPackage(pkg); - - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(signatureConfig); - - si.confirmSignature(); - - for (SignaturePart sp : si.getSignatureParts()){ - assertTrue("Could not validate", sp.validate()); - X509Certificate signer = sp.getSigner(); - assertNotNull("signer undefined?!", signer); - List certChainRes = sp.getCertChain(); - assertEquals(3, certChainRes.size()); - } - - pkg.close(); - } - - @Test - public void testNonSha1() throws Exception { - String testFile = "hello-world-unsigned.xlsx"; - initKeyPair("Test", "CN=Test"); - - SignatureConfig signatureConfig = new SignatureConfig(); - signatureConfig.setKey(keyPair.getPrivate()); - signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); - - HashAlgorithm testAlgo[] = { HashAlgorithm.sha224, HashAlgorithm.sha256 - , HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.ripemd160 }; - - for (HashAlgorithm ha : testAlgo) { - OPCPackage pkg = null; - try { - signatureConfig.setDigestAlgo(ha); - pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); - signatureConfig.setOpcPackage(pkg); - - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(signatureConfig); - - si.confirmSignature(); - boolean b = si.verifySignature(); - assertTrue("Signature not correctly calculated for " + ha, b); - } finally { - if (pkg != null) { - pkg.close(); - } - } - } - } - - @Test - public void bug58630() throws Exception { - // test deletion of sheet 0 and signing - File tpl = copy(testdata.getFile("bug58630.xlsx")); - SXSSFWorkbook wb1 = new SXSSFWorkbook((XSSFWorkbook)WorkbookFactory.create(tpl), 10); - wb1.setCompressTempFiles(true); - wb1.removeSheetAt(0); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - wb1.write(os); - wb1.close(); - OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray())); - - initKeyPair("Test", "CN=Test"); - SignatureConfig signatureConfig = new SignatureConfig(); - signatureConfig.setKey(keyPair.getPrivate()); - signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); - signatureConfig.setOpcPackage(pkg); - - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(signatureConfig); - si.confirmSignature(); - assertTrue("invalid signature", si.verifySignature()); - - pkg.close(); - } - - @Test - public void testMultiSign() throws Exception { - initKeyPair("KeyA", "CN=KeyA"); - //KeyPair keyPairA = keyPair; - //X509Certificate x509A = x509; - initKeyPair("KeyB", "CN=KeyB"); - //KeyPair keyPairB = keyPair; - //X509Certificate x509B = x509; - - File tpl = copy(testdata.getFile("bug58630.xlsx")); - OPCPackage pkg = OPCPackage.open(tpl); - try { - //SignatureConfig signatureConfig = new SignatureConfig(); - assertNotNull(pkg); - } finally { - pkg.close(); - } - } - - private void sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception { - initKeyPair(alias, signerDn); - - SignatureConfig signatureConfig = new SignatureConfig(); - signatureConfig.setKey(keyPair.getPrivate()); - signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); - signatureConfig.setExecutionTime(cal.getTime()); - signatureConfig.setDigestAlgo(HashAlgorithm.sha1); - signatureConfig.setOpcPackage(pkgCopy); - - SignatureInfo si = new SignatureInfo(); - si.setSignatureConfig(signatureConfig); - - Document document = DocumentHelper.createDocument(); - - // operate - DigestInfo digestInfo = si.preSign(document, null); - - // verify - assertNotNull(digestInfo); - LOG.log(POILogger.DEBUG, "digest algo: " + digestInfo.hashAlgo); - LOG.log(POILogger.DEBUG, "digest description: " + digestInfo.description); - assertEquals("Office OpenXML Document", digestInfo.description); - assertNotNull(digestInfo.hashAlgo); - assertNotNull(digestInfo.digestValue); - - // setup: key material, signature value - byte[] signatureValue = si.signDigest(digestInfo.digestValue); - - // operate: postSign - si.postSign(document, signatureValue); - - // verify: signature - si.getSignatureConfig().setOpcPackage(pkgCopy); - List result = new ArrayList(); - for (SignaturePart sp : si.getSignatureParts()) { - if (sp.validate()) { - result.add(sp.getSigner()); - } - } - assertEquals(signerCount, result.size()); - } - - private void initKeyPair(String alias, String subjectDN) throws Exception { - final char password[] = "test".toCharArray(); - File file = new File("build/test.pfx"); - - KeyStore keystore = KeyStore.getInstance("PKCS12"); - - if (file.exists()) { - FileInputStream fis = new FileInputStream(file); - keystore.load(fis, password); - fis.close(); - } else { - keystore.load(null, password); - } - - if (keystore.isKeyEntry(alias)) { - Key key = keystore.getKey(alias, password); - x509 = (X509Certificate)keystore.getCertificate(alias); - keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key); - } else { - keyPair = PkiTestUtils.generateKeyPair(); - Date notBefore = cal.getTime(); - Calendar cal2 = (Calendar)cal.clone(); - cal2.add(Calendar.YEAR, 1); - Date notAfter = cal2.getTime(); - KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature); - - x509 = PkiTestUtils.generateCertificate(keyPair.getPublic(), subjectDN - , notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage); - - keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509}); - FileOutputStream fos = new FileOutputStream(file); - keystore.store(fos, password); - fos.close(); - } - } - - private static File copy(File input) throws IOException { - String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1"); - if (extension == null || "".equals(extension)) { - extension = ".zip"; - } - - // ensure that we create the "build" directory as it might not be existing - // in the Sonar Maven runs where we are at a different source directory - File buildDir = new File("build"); - if(!buildDir.exists()) { - assertTrue("Failed to create " + buildDir.getAbsolutePath(), - buildDir.mkdirs()); - } - File tmpFile = new File(buildDir, "sigtest"+extension); - - OutputStream fos = new FileOutputStream(tmpFile); - try { - InputStream fis = new FileInputStream(input); - try { - IOUtils.copy(fis, fos); - } finally { - fis.close(); - } - } finally { - fos.close(); - } - - return tmpFile; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ +package org.apache.poi.poifs.crypt; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.security.Key; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.POITestCase; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; +import org.apache.poi.poifs.crypt.dsig.DigestInfo; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo.SignaturePart; +import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet; +import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet; +import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet; +import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet; +import org.apache.poi.poifs.crypt.dsig.services.RevocationData; +import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService; +import org.apache.poi.poifs.crypt.dsig.services.TimeStampService; +import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.util.DocumentHelper; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LocaleUtil; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.xmlbeans.XmlObject; +import org.bouncycastle.asn1.x509.KeyUsage; +import org.bouncycastle.cert.ocsp.OCSPResp; +import org.etsi.uri.x01903.v13.DigestAlgAndValueType; +import org.etsi.uri.x01903.v13.QualifyingPropertiesType; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3.x2000.x09.xmldsig.ReferenceType; +import org.w3.x2000.x09.xmldsig.SignatureDocument; +import org.w3c.dom.Document; + +public class TestSignatureInfo { + private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class); + private static final POIDataSamples testdata = POIDataSamples.getXmlDSignInstance(); + + private static Calendar cal; + private KeyPair keyPair = null; + private X509Certificate x509 = null; + + @BeforeClass + public static void initBouncy() throws IOException { + CryptoFunctions.registerBouncyCastle(); + + // Set cal to now ... only set to fixed date for debugging ... + cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC); + assertNotNull(cal); +// cal.set(2014, 7, 6, 21, 42, 12); +// cal.clear(Calendar.MILLISECOND); + + // don't run this test when we are using older Xerces as it triggers an XML Parser backwards compatibility issue + // in the xmlsec jar file + String additionalJar = System.getProperty("additionaljar"); + //System.out.println("Having: " + additionalJar); + Assume.assumeTrue("Not running TestSignatureInfo because we are testing with additionaljar set to " + additionalJar, + additionalJar == null || additionalJar.trim().length() == 0); + } + + @Test + public void office2007prettyPrintedRels() throws Exception { + OPCPackage pkg = OPCPackage.open(testdata.getFile("office2007prettyPrintedRels.docx"), PackageAccess.READ); + try { + SignatureConfig sic = new SignatureConfig(); + sic.setOpcPackage(pkg); + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(sic); + boolean isValid = si.verifySignature(); + assertTrue(isValid); + } finally { + pkg.close(); + } + } + + @Test + public void getSignerUnsigned() throws Exception { + String testFiles[] = { + "hello-world-unsigned.docx", + "hello-world-unsigned.pptx", + "hello-world-unsigned.xlsx", + "hello-world-office-2010-technical-preview-unsigned.docx" + }; + + for (String testFile : testFiles) { + OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); + SignatureConfig sic = new SignatureConfig(); + sic.setOpcPackage(pkg); + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(sic); + List result = new ArrayList(); + for (SignaturePart sp : si.getSignatureParts()) { + if (sp.validate()) { + result.add(sp.getSigner()); + } + } + pkg.revert(); + pkg.close(); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + } + + @Test + public void getSigner() throws Exception { + String testFiles[] = { + "hyperlink-example-signed.docx", + "hello-world-signed.docx", + "hello-world-signed.pptx", + "hello-world-signed.xlsx", + "hello-world-office-2010-technical-preview.docx", + "ms-office-2010-signed.docx", + "ms-office-2010-signed.pptx", + "ms-office-2010-signed.xlsx", + "Office2010-SP1-XAdES-X-L.docx", + "signed.docx", + }; + + for (String testFile : testFiles) { + OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); + try { + SignatureConfig sic = new SignatureConfig(); + sic.setOpcPackage(pkg); + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(sic); + List result = new ArrayList(); + for (SignaturePart sp : si.getSignatureParts()) { + if (sp.validate()) { + result.add(sp.getSigner()); + } + } + + assertNotNull(result); + assertEquals("test-file: "+testFile, 1, result.size()); + X509Certificate signer = result.get(0); + LOG.log(POILogger.DEBUG, "signer: " + signer.getSubjectX500Principal()); + + boolean b = si.verifySignature(); + assertTrue("test-file: "+testFile, b); + pkg.revert(); + } finally { + pkg.close(); + } + } + } + + @Test + public void getMultiSigners() throws Exception { + String testFile = "hello-world-signed-twice.docx"; + OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ); + try { + SignatureConfig sic = new SignatureConfig(); + sic.setOpcPackage(pkg); + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(sic); + List result = new ArrayList(); + for (SignaturePart sp : si.getSignatureParts()) { + if (sp.validate()) { + result.add(sp.getSigner()); + } + } + + assertNotNull(result); + assertEquals("test-file: "+testFile, 2, result.size()); + X509Certificate signer1 = result.get(0); + X509Certificate signer2 = result.get(1); + LOG.log(POILogger.DEBUG, "signer 1: " + signer1.getSubjectX500Principal()); + LOG.log(POILogger.DEBUG, "signer 2: " + signer2.getSubjectX500Principal()); + + boolean b = si.verifySignature(); + assertTrue("test-file: "+testFile, b); + pkg.revert(); + } finally { + pkg.close(); + } + } + + @Test + public void testSignSpreadsheet() throws Exception { + String testFile = "hello-world-unsigned.xlsx"; + OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); + sign(pkg, "Test", "CN=Test", 1); + pkg.close(); + } + + @Test + public void testManipulation() throws Exception { + // sign & validate + String testFile = "hello-world-unsigned.xlsx"; + @SuppressWarnings("resource") + OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); + sign(pkg, "Test", "CN=Test", 1); + + // manipulate + XSSFWorkbook wb = new XSSFWorkbook(pkg); + wb.setSheetName(0, "manipulated"); + // ... I don't know, why commit is protected ... + POITestCase.callMethod(XSSFWorkbook.class, wb, Void.class, "commit", new Class[0], new Object[0]); + + // todo: test a manipulation on a package part, which is not signed + // ... maybe in combination with #56164 + + // validate + SignatureConfig sic = new SignatureConfig(); + sic.setOpcPackage(pkg); + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(sic); + boolean b = si.verifySignature(); + assertFalse("signature should be broken", b); + + wb.close(); + } + + @Test + public void testSignSpreadsheetWithSignatureInfo() throws Exception { + initKeyPair("Test", "CN=Test"); + String testFile = "hello-world-unsigned.xlsx"; + OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); + SignatureConfig sic = new SignatureConfig(); + sic.setOpcPackage(pkg); + sic.setKey(keyPair.getPrivate()); + sic.setSigningCertificateChain(Collections.singletonList(x509)); + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(sic); + // hash > sha1 doesn't work in excel viewer ... + si.confirmSignature(); + List result = new ArrayList(); + for (SignaturePart sp : si.getSignatureParts()) { + if (sp.validate()) { + result.add(sp.getSigner()); + } + } + assertEquals(1, result.size()); + pkg.close(); + } + + @Test + public void testSignEnvelopingDocument() throws Exception { + String testFile = "hello-world-unsigned.xlsx"; + OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); + + initKeyPair("Test", "CN=Test"); + final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate()); + + // setup + SignatureConfig signatureConfig = new SignatureConfig(); + signatureConfig.setOpcPackage(pkg); + signatureConfig.setKey(keyPair.getPrivate()); + + /* + * We need at least 2 certificates for the XAdES-C complete certificate + * refs construction. + */ + List certificateChain = new ArrayList(); + certificateChain.add(x509); + certificateChain.add(x509); + signatureConfig.setSigningCertificateChain(certificateChain); + + signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet()); + signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet()); + signatureConfig.addSignatureFacet(new XAdESSignatureFacet()); + signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet()); + + // check for internet, no error means it works + boolean mockTsp = (getAccessError("http://timestamp.comodoca.com/rfc3161", true, 10000) != null); + + // http://timestamping.edelweb.fr/service/tsp + // http://tsa.belgium.be/connect + // http://timestamp.comodoca.com/authenticode + // http://timestamp.comodoca.com/rfc3161 + // http://services.globaltrustfinder.com/adss/tsa + signatureConfig.setTspUrl("http://timestamp.comodoca.com/rfc3161"); + signatureConfig.setTspRequestPolicy(null); // comodoca request fails, if default policy is set ... + signatureConfig.setTspOldProtocol(false); + + //set proxy info if any + String proxy = System.getProperty("http_proxy"); + if (proxy != null && proxy.trim().length() > 0) { + signatureConfig.setProxyUrl(proxy); + } + + if (mockTsp) { + TimeStampService tspService = new TimeStampService(){ + @Override + public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception { + revocationData.addCRL(crl); + return "time-stamp-token".getBytes(LocaleUtil.CHARSET_1252); + } + @Override + public void setSignatureConfig(SignatureConfig config) { + // empty on purpose + } + }; + signatureConfig.setTspService(tspService); + } else { + TimeStampServiceValidator tspValidator = new TimeStampServiceValidator() { + @Override + public void validate(List validateChain, + RevocationData revocationData) throws Exception { + for (X509Certificate certificate : validateChain) { + LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal()); + LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter()); + } + } + }; + signatureConfig.setTspValidator(tspValidator); + signatureConfig.setTspOldProtocol(signatureConfig.getTspUrl().contains("edelweb")); + } + + final RevocationData revocationData = new RevocationData(); + revocationData.addCRL(crl); + OCSPResp ocspResp = PkiTestUtils.createOcspResp(x509, false, + x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis()); + revocationData.addOCSP(ocspResp.getEncoded()); + + RevocationDataService revocationDataService = new RevocationDataService(){ + @Override + public RevocationData getRevocationData(List revocationChain) { + return revocationData; + } + }; + signatureConfig.setRevocationDataService(revocationDataService); + + // operate + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(signatureConfig); + try { + si.confirmSignature(); + } catch (RuntimeException e) { + pkg.close(); + // only allow a ConnectException because of timeout, we see this in Jenkins from time to time... + if(e.getCause() == null) { + throw e; + } + if((e.getCause() instanceof ConnectException) || (e.getCause() instanceof SocketTimeoutException)) { + Assume.assumeFalse("Only allowing ConnectException with 'timed out' as message here, but had: " + e, + e.getCause().getMessage().contains("timed out")); + } else if (e.getCause() instanceof IOException) { + Assume.assumeFalse("Only allowing IOException with 'Error contacting TSP server' as message here, but had: " + e, + e.getCause().getMessage().contains("Error contacting TSP server")); + } else if (e.getCause() instanceof RuntimeException) { + Assume.assumeFalse("Only allowing RuntimeException with 'This site is cur' as message here, but had: " + e, + e.getCause().getMessage().contains("This site is cur")); + } + throw e; + } + + // verify + Iterator spIter = si.getSignatureParts().iterator(); + assertTrue("Had: " + si.getSignatureConfig().getOpcPackage(). + getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), + spIter.hasNext()); + SignaturePart sp = spIter.next(); + boolean valid = sp.validate(); + assertTrue(valid); + + SignatureDocument sigDoc = sp.getSignatureDocument(); + String declareNS = + "declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; " + + "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "; + + String digestValXQuery = declareNS + + "$this/ds:Signature/ds:SignedInfo/ds:Reference"; + for (ReferenceType rt : (ReferenceType[])sigDoc.selectPath(digestValXQuery)) { + assertNotNull(rt.getDigestValue()); + assertEquals(signatureConfig.getDigestMethodUri(), rt.getDigestMethod().getAlgorithm()); + } + + String certDigestXQuery = declareNS + + "$this//xades:SigningCertificate/xades:Cert/xades:CertDigest"; + XmlObject xoList[] = sigDoc.selectPath(certDigestXQuery); + assertEquals(xoList.length, 1); + DigestAlgAndValueType certDigest = (DigestAlgAndValueType)xoList[0]; + assertNotNull(certDigest.getDigestValue()); + + String qualPropXQuery = declareNS + + "$this/ds:Signature/ds:Object/xades:QualifyingProperties"; + xoList = sigDoc.selectPath(qualPropXQuery); + assertEquals(xoList.length, 1); + QualifyingPropertiesType qualProp = (QualifyingPropertiesType)xoList[0]; + boolean qualPropXsdOk = qualProp.validate(); + assertTrue(qualPropXsdOk); + + pkg.close(); + } + + public static String getAccessError(String destinationUrl, boolean fireRequest, int timeout) { + URL url; + try { + url = new URL(destinationUrl); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Invalid destination URL", e); + } + + HttpURLConnection conn = null; + try { + conn = (HttpURLConnection) url.openConnection(); + + // set specified timeout if non-zero + if(timeout != 0) { + conn.setConnectTimeout(timeout); + conn.setReadTimeout(timeout); + } + + conn.setDoOutput(false); + conn.setDoInput(true); + + /* if connecting is not possible this will throw a connection refused exception */ + conn.connect(); + + if (fireRequest) { + InputStream is = null; + try { + is = conn.getInputStream(); + } finally { + IOUtils.closeQuietly(is); + } + + } + /* if connecting is possible we return true here */ + return null; + + } catch (IOException e) { + /* exception is thrown -> server not available */ + return e.getClass().getName() + ": " + e.getMessage(); + } finally { + if (conn != null) { + conn.disconnect(); + } + } + } + + @Test + public void testCertChain() throws Exception { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + String password = "test"; + InputStream is = testdata.openResourceAsStream("chaintest.pfx"); + keystore.load(is, password.toCharArray()); + is.close(); + + Key key = keystore.getKey("poitest", password.toCharArray()); + Certificate chainList[] = keystore.getCertificateChain("poitest"); + List certChain = new ArrayList(); + for (Certificate c : chainList) { + certChain.add((X509Certificate)c); + } + x509 = certChain.get(0); + keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key); + + String testFile = "hello-world-unsigned.xlsx"; + OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); + + SignatureConfig signatureConfig = new SignatureConfig(); + signatureConfig.setKey(keyPair.getPrivate()); + signatureConfig.setSigningCertificateChain(certChain); + Calendar oldCal = LocaleUtil.getLocaleCalendar(2007, 7, 1); + signatureConfig.setExecutionTime(oldCal.getTime()); + signatureConfig.setDigestAlgo(HashAlgorithm.sha1); + signatureConfig.setOpcPackage(pkg); + + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(signatureConfig); + + si.confirmSignature(); + + for (SignaturePart sp : si.getSignatureParts()){ + assertTrue("Could not validate", sp.validate()); + X509Certificate signer = sp.getSigner(); + assertNotNull("signer undefined?!", signer); + List certChainRes = sp.getCertChain(); + assertEquals(3, certChainRes.size()); + } + + pkg.close(); + } + + @Test + public void testNonSha1() throws Exception { + String testFile = "hello-world-unsigned.xlsx"; + initKeyPair("Test", "CN=Test"); + + SignatureConfig signatureConfig = new SignatureConfig(); + signatureConfig.setKey(keyPair.getPrivate()); + signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); + + HashAlgorithm testAlgo[] = { HashAlgorithm.sha224, HashAlgorithm.sha256 + , HashAlgorithm.sha384, HashAlgorithm.sha512, HashAlgorithm.ripemd160 }; + + for (HashAlgorithm ha : testAlgo) { + OPCPackage pkg = null; + try { + signatureConfig.setDigestAlgo(ha); + pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE); + signatureConfig.setOpcPackage(pkg); + + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(signatureConfig); + + si.confirmSignature(); + boolean b = si.verifySignature(); + assertTrue("Signature not correctly calculated for " + ha, b); + } finally { + if (pkg != null) { + pkg.close(); + } + } + } + } + + @Test + public void bug58630() throws Exception { + // test deletion of sheet 0 and signing + File tpl = copy(testdata.getFile("bug58630.xlsx")); + SXSSFWorkbook wb1 = new SXSSFWorkbook((XSSFWorkbook)WorkbookFactory.create(tpl), 10); + wb1.setCompressTempFiles(true); + wb1.removeSheetAt(0); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + wb1.write(os); + wb1.close(); + OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(os.toByteArray())); + + initKeyPair("Test", "CN=Test"); + SignatureConfig signatureConfig = new SignatureConfig(); + signatureConfig.setKey(keyPair.getPrivate()); + signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); + signatureConfig.setOpcPackage(pkg); + + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(signatureConfig); + si.confirmSignature(); + assertTrue("invalid signature", si.verifySignature()); + + pkg.close(); + } + + @Test + public void testMultiSign() throws Exception { + initKeyPair("KeyA", "CN=KeyA"); + //KeyPair keyPairA = keyPair; + //X509Certificate x509A = x509; + initKeyPair("KeyB", "CN=KeyB"); + //KeyPair keyPairB = keyPair; + //X509Certificate x509B = x509; + + File tpl = copy(testdata.getFile("bug58630.xlsx")); + OPCPackage pkg = OPCPackage.open(tpl); + try { + //SignatureConfig signatureConfig = new SignatureConfig(); + assertNotNull(pkg); + } finally { + pkg.close(); + } + } + + private void sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception { + initKeyPair(alias, signerDn); + + SignatureConfig signatureConfig = new SignatureConfig(); + signatureConfig.setKey(keyPair.getPrivate()); + signatureConfig.setSigningCertificateChain(Collections.singletonList(x509)); + signatureConfig.setExecutionTime(cal.getTime()); + signatureConfig.setDigestAlgo(HashAlgorithm.sha1); + signatureConfig.setOpcPackage(pkgCopy); + + SignatureInfo si = new SignatureInfo(); + si.setSignatureConfig(signatureConfig); + + Document document = DocumentHelper.createDocument(); + + // operate + DigestInfo digestInfo = si.preSign(document, null); + + // verify + assertNotNull(digestInfo); + LOG.log(POILogger.DEBUG, "digest algo: " + digestInfo.hashAlgo); + LOG.log(POILogger.DEBUG, "digest description: " + digestInfo.description); + assertEquals("Office OpenXML Document", digestInfo.description); + assertNotNull(digestInfo.hashAlgo); + assertNotNull(digestInfo.digestValue); + + // setup: key material, signature value + byte[] signatureValue = si.signDigest(digestInfo.digestValue); + + // operate: postSign + si.postSign(document, signatureValue); + + // verify: signature + si.getSignatureConfig().setOpcPackage(pkgCopy); + List result = new ArrayList(); + for (SignaturePart sp : si.getSignatureParts()) { + if (sp.validate()) { + result.add(sp.getSigner()); + } + } + assertEquals(signerCount, result.size()); + } + + private void initKeyPair(String alias, String subjectDN) throws Exception { + final char password[] = "test".toCharArray(); + File file = new File("build/test.pfx"); + + KeyStore keystore = KeyStore.getInstance("PKCS12"); + + if (file.exists()) { + FileInputStream fis = new FileInputStream(file); + keystore.load(fis, password); + fis.close(); + } else { + keystore.load(null, password); + } + + if (keystore.isKeyEntry(alias)) { + Key key = keystore.getKey(alias, password); + x509 = (X509Certificate)keystore.getCertificate(alias); + keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key); + } else { + keyPair = PkiTestUtils.generateKeyPair(); + Date notBefore = cal.getTime(); + Calendar cal2 = (Calendar)cal.clone(); + cal2.add(Calendar.YEAR, 1); + Date notAfter = cal2.getTime(); + KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature); + + x509 = PkiTestUtils.generateCertificate(keyPair.getPublic(), subjectDN + , notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage); + + keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509}); + FileOutputStream fos = new FileOutputStream(file); + keystore.store(fos, password); + fos.close(); + } + } + + private static File copy(File input) throws IOException { + String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1"); + if (extension == null || "".equals(extension)) { + extension = ".zip"; + } + + // ensure that we create the "build" directory as it might not be existing + // in the Sonar Maven runs where we are at a different source directory + File buildDir = new File("build"); + if(!buildDir.exists()) { + assertTrue("Failed to create " + buildDir.getAbsolutePath(), + buildDir.mkdirs()); + } + File tmpFile = new File(buildDir, "sigtest"+extension); + + OutputStream fos = new FileOutputStream(tmpFile); + try { + InputStream fis = new FileInputStream(input); + try { + IOUtils.copy(fis, fos); + } finally { + fis.close(); + } + } finally { + fos.close(); + } + + return tmpFile; + } + +} diff --git a/src/ooxml/testcases/org/apache/poi/sl/TestHeadersFooters.java b/src/ooxml/testcases/org/apache/poi/sl/TestHeadersFooters.java index 684311f719..c51652ff5e 100644 --- a/src/ooxml/testcases/org/apache/poi/sl/TestHeadersFooters.java +++ b/src/ooxml/testcases/org/apache/poi/sl/TestHeadersFooters.java @@ -1,103 +1,103 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.sl; - -import static org.apache.poi.sl.TestTable.openSampleSlideshow; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeFalse; - -import java.io.IOException; -import java.util.List; - -import org.apache.poi.hslf.model.HeadersFooters; -import org.apache.poi.hslf.usermodel.HSLFSlide; -import org.apache.poi.hslf.usermodel.HSLFTextParagraph; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.TextParagraph; -import org.apache.poi.sl.usermodel.TextShape; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestHeadersFooters { - private static boolean xslfOnly = false; - - @BeforeClass - public static void checkHslf() { - try { - Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); - } catch (Exception e) { - xslfOnly = true; - } - } - - - @Test - public void bug58144a() throws IOException { - assumeFalse(xslfOnly); - SlideShow ppt = openSampleSlideshow("bug58144-headers-footers-2003.ppt"); - HSLFSlide sl = (HSLFSlide)ppt.getSlides().get(0); - HeadersFooters hfs = sl.getHeadersFooters(); - assertNull(hfs.getHeaderText()); - assertEquals("Confidential", hfs.getFooterText()); - List> llp = sl.getTextParagraphs(); - assertEquals("Test", HSLFTextParagraph.getText(llp.get(0))); - assertFalse(llp.get(0).get(0).isHeaderOrFooter()); - ppt.close(); - } - - @Test - public void bug58144b() throws IOException { - assumeFalse(xslfOnly); - SlideShow ppt = openSampleSlideshow("bug58144-headers-footers-2007.ppt"); - Slide sl = ppt.getSlides().get(0); - HeadersFooters hfs2 = ((HSLFSlide)sl).getHeadersFooters(); - assertNull(hfs2.getHeaderText()); - assertEquals("Slide footer", hfs2.getFooterText()); - - testSlideShow(ppt); - ppt.close(); - } - - @Test - public void bug58144c() throws IOException { - SlideShow ppt = openSampleSlideshow("bug58144-headers-footers-2007.pptx"); - testSlideShow(ppt); - ppt.close(); - } - - private void testSlideShow(SlideShow ppt) { - Slide sl = ppt.getSlides().get(0); - - List> shapes = sl.getShapes(); - TextShape ts0 = (TextShape)shapes.get(0); - assertEquals("Test file", ts0.getText()); - TextShape ts1 = (TextShape)shapes.get(1); - assertEquals("Has some text in the headers and footers", ts1.getText()); - TextShape ts2 = (TextShape)shapes.get(2); - assertEquals("Slide footer", ts2.getText()); - List> ltp = ts2.getTextParagraphs(); - assertTrue(ltp.get(0).isHeaderOrFooter()); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.sl; + +import static org.apache.poi.sl.TestTable.openSampleSlideshow; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; + +import java.io.IOException; +import java.util.List; + +import org.apache.poi.hslf.model.HeadersFooters; +import org.apache.poi.hslf.usermodel.HSLFSlide; +import org.apache.poi.hslf.usermodel.HSLFTextParagraph; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.TextParagraph; +import org.apache.poi.sl.usermodel.TextShape; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestHeadersFooters { + private static boolean xslfOnly = false; + + @BeforeClass + public static void checkHslf() { + try { + Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); + } catch (Exception e) { + xslfOnly = true; + } + } + + + @Test + public void bug58144a() throws IOException { + assumeFalse(xslfOnly); + SlideShow ppt = openSampleSlideshow("bug58144-headers-footers-2003.ppt"); + HSLFSlide sl = (HSLFSlide)ppt.getSlides().get(0); + HeadersFooters hfs = sl.getHeadersFooters(); + assertNull(hfs.getHeaderText()); + assertEquals("Confidential", hfs.getFooterText()); + List> llp = sl.getTextParagraphs(); + assertEquals("Test", HSLFTextParagraph.getText(llp.get(0))); + assertFalse(llp.get(0).get(0).isHeaderOrFooter()); + ppt.close(); + } + + @Test + public void bug58144b() throws IOException { + assumeFalse(xslfOnly); + SlideShow ppt = openSampleSlideshow("bug58144-headers-footers-2007.ppt"); + Slide sl = ppt.getSlides().get(0); + HeadersFooters hfs2 = ((HSLFSlide)sl).getHeadersFooters(); + assertNull(hfs2.getHeaderText()); + assertEquals("Slide footer", hfs2.getFooterText()); + + testSlideShow(ppt); + ppt.close(); + } + + @Test + public void bug58144c() throws IOException { + SlideShow ppt = openSampleSlideshow("bug58144-headers-footers-2007.pptx"); + testSlideShow(ppt); + ppt.close(); + } + + private void testSlideShow(SlideShow ppt) { + Slide sl = ppt.getSlides().get(0); + + List> shapes = sl.getShapes(); + TextShape ts0 = (TextShape)shapes.get(0); + assertEquals("Test file", ts0.getText()); + TextShape ts1 = (TextShape)shapes.get(1); + assertEquals("Has some text in the headers and footers", ts1.getText()); + TextShape ts2 = (TextShape)shapes.get(2); + assertEquals("Slide footer", ts2.getText()); + List> ltp = ts2.getTextParagraphs(); + assertTrue(ltp.get(0).isHeaderOrFooter()); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/sl/TestTable.java b/src/ooxml/testcases/org/apache/poi/sl/TestTable.java index 2eaeee3951..0b02b74783 100644 --- a/src/ooxml/testcases/org/apache/poi/sl/TestTable.java +++ b/src/ooxml/testcases/org/apache/poi/sl/TestTable.java @@ -1,163 +1,163 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.sl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assume.assumeFalse; - -import java.awt.geom.Rectangle2D; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.hslf.usermodel.HSLFSlideShow; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.SlideShowFactory; -import org.apache.poi.sl.usermodel.TableCell; -import org.apache.poi.sl.usermodel.TableShape; -import org.apache.poi.sl.usermodel.TextShape.TextDirection; -import org.apache.poi.xslf.usermodel.XMLSlideShow; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestTable { - private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); - private static boolean xslfOnly = false; - - @BeforeClass - public static void checkHslf() { - try { - Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); - } catch (Exception e) { - xslfOnly = true; - } - } - - - /** a generic way to open a sample slideshow document **/ - public static SlideShow openSampleSlideshow(String sampleName) throws IOException { - InputStream is = _slTests.openResourceAsStream(sampleName); - try { - return SlideShowFactory.create(is); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - is.close(); - } - } - - @Test - public void testColWidthRowHeight() throws IOException { - assumeFalse(xslfOnly); - - // Test of table dimensions of same slideshow saved as ppt/x - // to check if both return similar (points) value - SlideShow ppt = openSampleSlideshow("table_test.ppt"); - TableShape ts = (TableShape)ppt.getSlides().get(0).getShapes().get(0); - - SlideShow pptx = openSampleSlideshow("table_test.pptx"); - TableShape tsx = (TableShape)pptx.getSlides().get(0).getShapes().get(0); - - // assume table shape should be equal to itself - confirmTableShapeEqual(ts, ts); - confirmTableShapeEqual(tsx, tsx); - - // assert ppt and pptx versions of the same table have the same shape - confirmTableShapeEqual(ts, tsx); - - pptx.close(); - ppt.close(); - } - - private void confirmTableShapeEqual(TableShape tableA, TableShape tableB) { - int cols = tableA.getNumberOfColumns(); - int rows = tableA.getNumberOfRows(); - - int colsx = tableB.getNumberOfColumns(); - int rowsx = tableB.getNumberOfRows(); - - assertEquals("tables should have same number of columns", cols, colsx); - assertEquals("tables should have same number of rows", rows, rowsx); - - for (int i=0; i ppt1 = new HSLFSlideShow(); - testTextDirection(ppt1); - ppt1.close(); - } - - @Test - public void testTextDirectionXSLF() throws IOException { - SlideShow ppt1 = new XMLSlideShow(); - testTextDirection(ppt1); - ppt1.close(); - } - - private void testTextDirection(SlideShow ppt1) throws IOException { - - TextDirection tds[] = { - TextDirection.HORIZONTAL, - TextDirection.VERTICAL, - TextDirection.VERTICAL_270, - // TextDirection.STACKED is not supported on HSLF - }; - - TableShape tbl1 = ppt1.createSlide().createTable(1, 3); - tbl1.setAnchor(new Rectangle2D.Double(50, 50, 200, 200)); - - int col = 0; - for (TextDirection td : tds) { - TableCell c = tbl1.getCell(0, col++); - if (c != null) { - c.setTextDirection(td); - c.setText("bla"); - } - } - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ppt1.write(bos); - ppt1.close(); - - InputStream is = new ByteArrayInputStream(bos.toByteArray()); - SlideShow ppt2 = SlideShowFactory.create(is); - TableShape tbl2 = (TableShape)ppt2.getSlides().get(0).getShapes().get(0); - - col = 0; - for (TextDirection td : tds) { - TableCell c = tbl2.getCell(0, col++); - assertEquals(td, c.getTextDirection()); - } - ppt2.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.sl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assume.assumeFalse; + +import java.awt.geom.Rectangle2D; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.sl.usermodel.TableCell; +import org.apache.poi.sl.usermodel.TableShape; +import org.apache.poi.sl.usermodel.TextShape.TextDirection; +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestTable { + private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); + private static boolean xslfOnly = false; + + @BeforeClass + public static void checkHslf() { + try { + Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); + } catch (Exception e) { + xslfOnly = true; + } + } + + + /** a generic way to open a sample slideshow document **/ + public static SlideShow openSampleSlideshow(String sampleName) throws IOException { + InputStream is = _slTests.openResourceAsStream(sampleName); + try { + return SlideShowFactory.create(is); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + is.close(); + } + } + + @Test + public void testColWidthRowHeight() throws IOException { + assumeFalse(xslfOnly); + + // Test of table dimensions of same slideshow saved as ppt/x + // to check if both return similar (points) value + SlideShow ppt = openSampleSlideshow("table_test.ppt"); + TableShape ts = (TableShape)ppt.getSlides().get(0).getShapes().get(0); + + SlideShow pptx = openSampleSlideshow("table_test.pptx"); + TableShape tsx = (TableShape)pptx.getSlides().get(0).getShapes().get(0); + + // assume table shape should be equal to itself + confirmTableShapeEqual(ts, ts); + confirmTableShapeEqual(tsx, tsx); + + // assert ppt and pptx versions of the same table have the same shape + confirmTableShapeEqual(ts, tsx); + + pptx.close(); + ppt.close(); + } + + private void confirmTableShapeEqual(TableShape tableA, TableShape tableB) { + int cols = tableA.getNumberOfColumns(); + int rows = tableA.getNumberOfRows(); + + int colsx = tableB.getNumberOfColumns(); + int rowsx = tableB.getNumberOfRows(); + + assertEquals("tables should have same number of columns", cols, colsx); + assertEquals("tables should have same number of rows", rows, rowsx); + + for (int i=0; i ppt1 = new HSLFSlideShow(); + testTextDirection(ppt1); + ppt1.close(); + } + + @Test + public void testTextDirectionXSLF() throws IOException { + SlideShow ppt1 = new XMLSlideShow(); + testTextDirection(ppt1); + ppt1.close(); + } + + private void testTextDirection(SlideShow ppt1) throws IOException { + + TextDirection tds[] = { + TextDirection.HORIZONTAL, + TextDirection.VERTICAL, + TextDirection.VERTICAL_270, + // TextDirection.STACKED is not supported on HSLF + }; + + TableShape tbl1 = ppt1.createSlide().createTable(1, 3); + tbl1.setAnchor(new Rectangle2D.Double(50, 50, 200, 200)); + + int col = 0; + for (TextDirection td : tds) { + TableCell c = tbl1.getCell(0, col++); + if (c != null) { + c.setTextDirection(td); + c.setText("bla"); + } + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ppt1.write(bos); + ppt1.close(); + + InputStream is = new ByteArrayInputStream(bos.toByteArray()); + SlideShow ppt2 = SlideShowFactory.create(is); + TableShape tbl2 = (TableShape)ppt2.getSlides().get(0).getShapes().get(0); + + col = 0; + for (TextDirection td : tds) { + TableCell c = tbl2.getCell(0, col++); + assertEquals(td, c.getTextDirection()); + } + ppt2.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/util/TestIdentifierManager.java b/src/ooxml/testcases/org/apache/poi/util/TestIdentifierManager.java index db062f4112..383545176d 100644 --- a/src/ooxml/testcases/org/apache/poi/util/TestIdentifierManager.java +++ b/src/ooxml/testcases/org/apache/poi/util/TestIdentifierManager.java @@ -1,129 +1,129 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.util; - -import junit.framework.TestCase; - -public class TestIdentifierManager extends TestCase -{ - public void testBasic() - { - IdentifierManager manager = new IdentifierManager(0L,100L); - assertEquals(101L,manager.getRemainingIdentifiers()); - assertEquals(0L,manager.reserveNew()); - assertEquals(100L,manager.getRemainingIdentifiers()); - assertEquals(1L,manager.reserve(0L)); - assertEquals(99L,manager.getRemainingIdentifiers()); - } - - public void testLongLimits() - { - long min = IdentifierManager.MIN_ID; - long max = IdentifierManager.MAX_ID; - IdentifierManager manager = new IdentifierManager(min,max); - assertTrue("Limits lead to a long variable overflow", max - min + 1 > 0); - assertTrue("Limits lead to a long variable overflow", manager.getRemainingIdentifiers() > 0); - assertEquals(min,manager.reserveNew()); - assertEquals(max,manager.reserve(max)); - assertEquals(max - min -1, manager.getRemainingIdentifiers()); - manager.release(max); - manager.release(min); - } - - public void testReserve() - { - IdentifierManager manager = new IdentifierManager(10L,30L); - assertEquals(12L,manager.reserve(12L)); - long reserve = manager.reserve(12L); - assertFalse("Same id must be reserved twice!",reserve == 12L); - assertTrue(manager.release(12L)); - assertTrue(manager.release(reserve)); - assertFalse(manager.release(12L)); - assertFalse(manager.release(reserve)); - - manager = new IdentifierManager(0L,2L); - assertEquals(0L,manager.reserve(0L)); - assertEquals(1L,manager.reserve(1L)); - assertEquals(2L,manager.reserve(2L)); - try - { - manager.reserve(0L); - fail("Exception expected"); - } - catch(IllegalStateException e) - { - // expected - } - try - { - manager.reserve(1L); - fail("Exception expected"); - } - catch(IllegalStateException e) - { - // expected - } - try - { - manager.reserve(2L); - fail("Exception expected"); - } - catch(IllegalStateException e) - { - // expected - } - } - - public void testReserveNew() - { - IdentifierManager manager = new IdentifierManager(10L,12L); - assertSame(10L,manager.reserveNew()); - assertSame(11L,manager.reserveNew()); - assertSame(12L,manager.reserveNew()); - try { - manager.reserveNew(); - fail("IllegalStateException expected"); - } - catch (IllegalStateException e) - { - // expected - } - } - - public void testRelease() { - IdentifierManager manager = new IdentifierManager(10L,20L); - assertEquals(10L,manager.reserve(10L)); - assertEquals(11L,manager.reserve(11L)); - assertEquals(12L,manager.reserve(12L)); - assertEquals(13L,manager.reserve(13L)); - assertEquals(14L,manager.reserve(14L)); - - assertTrue(manager.release(10L)); - assertEquals(10L,manager.reserve(10L)); - assertTrue(manager.release(10L)); - - assertTrue(manager.release(11L)); - assertEquals(11L,manager.reserve(11L)); - assertTrue(manager.release(11L)); - assertFalse(manager.release(11L)); - assertFalse(manager.release(10L)); - - assertEquals(10L,manager.reserve(10L)); - assertEquals(11L,manager.reserve(11L)); - assertTrue(manager.release(12L)); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.util; + +import junit.framework.TestCase; + +public class TestIdentifierManager extends TestCase +{ + public void testBasic() + { + IdentifierManager manager = new IdentifierManager(0L,100L); + assertEquals(101L,manager.getRemainingIdentifiers()); + assertEquals(0L,manager.reserveNew()); + assertEquals(100L,manager.getRemainingIdentifiers()); + assertEquals(1L,manager.reserve(0L)); + assertEquals(99L,manager.getRemainingIdentifiers()); + } + + public void testLongLimits() + { + long min = IdentifierManager.MIN_ID; + long max = IdentifierManager.MAX_ID; + IdentifierManager manager = new IdentifierManager(min,max); + assertTrue("Limits lead to a long variable overflow", max - min + 1 > 0); + assertTrue("Limits lead to a long variable overflow", manager.getRemainingIdentifiers() > 0); + assertEquals(min,manager.reserveNew()); + assertEquals(max,manager.reserve(max)); + assertEquals(max - min -1, manager.getRemainingIdentifiers()); + manager.release(max); + manager.release(min); + } + + public void testReserve() + { + IdentifierManager manager = new IdentifierManager(10L,30L); + assertEquals(12L,manager.reserve(12L)); + long reserve = manager.reserve(12L); + assertFalse("Same id must be reserved twice!",reserve == 12L); + assertTrue(manager.release(12L)); + assertTrue(manager.release(reserve)); + assertFalse(manager.release(12L)); + assertFalse(manager.release(reserve)); + + manager = new IdentifierManager(0L,2L); + assertEquals(0L,manager.reserve(0L)); + assertEquals(1L,manager.reserve(1L)); + assertEquals(2L,manager.reserve(2L)); + try + { + manager.reserve(0L); + fail("Exception expected"); + } + catch(IllegalStateException e) + { + // expected + } + try + { + manager.reserve(1L); + fail("Exception expected"); + } + catch(IllegalStateException e) + { + // expected + } + try + { + manager.reserve(2L); + fail("Exception expected"); + } + catch(IllegalStateException e) + { + // expected + } + } + + public void testReserveNew() + { + IdentifierManager manager = new IdentifierManager(10L,12L); + assertSame(10L,manager.reserveNew()); + assertSame(11L,manager.reserveNew()); + assertSame(12L,manager.reserveNew()); + try { + manager.reserveNew(); + fail("IllegalStateException expected"); + } + catch (IllegalStateException e) + { + // expected + } + } + + public void testRelease() { + IdentifierManager manager = new IdentifierManager(10L,20L); + assertEquals(10L,manager.reserve(10L)); + assertEquals(11L,manager.reserve(11L)); + assertEquals(12L,manager.reserve(12L)); + assertEquals(13L,manager.reserve(13L)); + assertEquals(14L,manager.reserve(14L)); + + assertTrue(manager.release(10L)); + assertEquals(10L,manager.reserve(10L)); + assertTrue(manager.release(10L)); + + assertTrue(manager.release(11L)); + assertEquals(11L,manager.reserve(11L)); + assertTrue(manager.release(11L)); + assertFalse(manager.release(11L)); + assertFalse(manager.release(10L)); + + assertEquals(10L,manager.reserve(10L)); + assertEquals(11L,manager.reserve(11L)); + assertTrue(manager.release(12L)); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java b/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java index 550c4d8b95..72ed16f94b 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/XSLFTestDataSamples.java @@ -1,72 +1,72 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.xslf.usermodel.XMLSlideShow; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author Yegor Kozlov - */ -public class XSLFTestDataSamples { - - public static XMLSlideShow openSampleDocument(String sampleName) { - InputStream is = POIDataSamples.getSlideShowInstance().openResourceAsStream(sampleName); - try { - return new XMLSlideShow(OPCPackage.open(is)); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - try { - is.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - public static XMLSlideShow writeOutAndReadBack(XMLSlideShow doc) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); - try { - doc.write(baos); - } catch (IOException e) { - throw new RuntimeException(e); - } - - InputStream bais; - bais = new ByteArrayInputStream(baos.toByteArray()); - try { - return new XMLSlideShow(OPCPackage.open(bais)); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - try { - baos.close(); - bais.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.xslf.usermodel.XMLSlideShow; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Yegor Kozlov + */ +public class XSLFTestDataSamples { + + public static XMLSlideShow openSampleDocument(String sampleName) { + InputStream is = POIDataSamples.getSlideShowInstance().openResourceAsStream(sampleName); + try { + return new XMLSlideShow(OPCPackage.open(is)); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + try { + is.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + public static XMLSlideShow writeOutAndReadBack(XMLSlideShow doc) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + try { + doc.write(baos); + } catch (IOException e) { + throw new RuntimeException(e); + } + + InputStream bais; + bais = new ByteArrayInputStream(baos.toByteArray()); + try { + return new XMLSlideShow(OPCPackage.open(bais)); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + try { + baos.close(); + bais.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java index 2929496d36..0ae8463f6a 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java @@ -1,103 +1,103 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assume.assumeFalse; - -import java.io.File; -import java.io.FileFilter; -import java.util.Collection; -import java.util.Locale; -import java.util.Set; -import java.util.TreeSet; -import java.util.regex.Pattern; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.xslf.util.PPTX2PNG; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - -/** - * Test class for testing PPTX2PNG utility which renderes .ppt and .pptx slideshows - */ -@RunWith(Parameterized.class) -public class TestPPTX2PNG { - private static boolean xslfOnly = false; - private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance(); - private static final File basedir = null; - private static final String files = - "53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx"; - - - - @BeforeClass - public static void checkHslf() { - try { - Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); - } catch (Exception e) { - xslfOnly = true; - } - } - - // use filename instead of File object to omit full pathname in test name - @Parameter(value = 0) - public String pptFile; - - @Parameters(name="{0}") - public static Collection data() { - final Set data = new TreeSet(); - for (String f : files.split(", ?")) { - if (basedir == null) { - data.add(f); - } else { - final Pattern p = Pattern.compile(f); - basedir.listFiles(new FileFilter(){ - public boolean accept(File pathname) { - String name = pathname.getName(); - if (p.matcher(name).matches()) { - data.add(name); - } - return false; - } - }); - } - } - - return data; - } - - @Test - public void render() throws Exception { - assumeFalse("ignore HSLF / .ppt files in no-scratchpad run", xslfOnly && pptFile.toLowerCase(Locale.ROOT).endsWith("ppt")); - - String[] args = { - "-format", "null", // png,gif,jpg or null for test - "-slide", "-1", // -1 for all - "-outdir", new File("build/tmp/").getCanonicalPath(), - "-quiet", - (basedir == null ? samples.getFile(pptFile) : new File(basedir, pptFile)).getAbsolutePath() - }; - PPTX2PNG.main(args); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assume.assumeFalse; + +import java.io.File; +import java.io.FileFilter; +import java.util.Collection; +import java.util.Locale; +import java.util.Set; +import java.util.TreeSet; +import java.util.regex.Pattern; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.xslf.util.PPTX2PNG; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +/** + * Test class for testing PPTX2PNG utility which renderes .ppt and .pptx slideshows + */ +@RunWith(Parameterized.class) +public class TestPPTX2PNG { + private static boolean xslfOnly = false; + private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance(); + private static final File basedir = null; + private static final String files = + "53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx"; + + + + @BeforeClass + public static void checkHslf() { + try { + Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); + } catch (Exception e) { + xslfOnly = true; + } + } + + // use filename instead of File object to omit full pathname in test name + @Parameter(value = 0) + public String pptFile; + + @Parameters(name="{0}") + public static Collection data() { + final Set data = new TreeSet(); + for (String f : files.split(", ?")) { + if (basedir == null) { + data.add(f); + } else { + final Pattern p = Pattern.compile(f); + basedir.listFiles(new FileFilter(){ + public boolean accept(File pathname) { + String name = pathname.getName(); + if (p.matcher(name).matches()) { + data.add(name); + } + return false; + } + }); + } + } + + return data; + } + + @Test + public void render() throws Exception { + assumeFalse("ignore HSLF / .ppt files in no-scratchpad run", xslfOnly && pptFile.toLowerCase(Locale.ROOT).endsWith("ppt")); + + String[] args = { + "-format", "null", // png,gif,jpg or null for test + "-slide", "-1", // -1 for all + "-outdir", new File("build/tmp/").getCanonicalPath(), + "-quiet", + (basedir == null ? samples.getFile(pptFile) : new File(basedir, pptFile)).getAbsolutePath() + }; + PPTX2PNG.main(args); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java index 3104cbb677..d7869d722b 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java @@ -1,311 +1,311 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; - -import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; -import org.apache.poi.sl.usermodel.TextShape.TextAutofit; -import org.apache.poi.sl.usermodel.TextShape.TextDirection; -import org.apache.poi.sl.usermodel.VerticalAlignment; -import org.apache.poi.util.Units; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; - -public class TestXSLFAutoShape { - @Test - public void testTextBodyProperies() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFAutoShape shape = slide.createAutoShape(); - shape.addNewTextParagraph().addNewTextRun().setText("POI"); - - // default margins from slide master - assertEquals(3.6, shape.getBottomInset(), 0); - assertEquals(3.6, shape.getTopInset(), 0); - assertEquals(7.2, shape.getLeftInset(), 0); - assertEquals(7.2, shape.getRightInset(), 0); - - shape.setBottomInset(1.0); - assertEquals(1.0, shape.getBottomInset(), 0); - shape.setTopInset(2.0); - assertEquals(2.0, shape.getTopInset(), 0); - shape.setLeftInset(3.0); - assertEquals(3.0, shape.getLeftInset(), 0); - shape.setRightInset(4.0); - assertEquals(4.0, shape.getRightInset(), 0); - - shape.setBottomInset(0.0); - assertEquals(0.0, shape.getBottomInset(), 0); - shape.setTopInset(0.0); - assertEquals(0.0, shape.getTopInset(), 0); - shape.setLeftInset(0.0); - assertEquals(0.0, shape.getLeftInset(), 0); - shape.setRightInset(0.0); - assertEquals(0.0, shape.getRightInset(), 0); - - // unset to defauls - shape.setBottomInset(-1); - assertEquals(3.6, shape.getBottomInset(), 0); - shape.setTopInset(-1); - assertEquals(3.6, shape.getTopInset(), 0); - shape.setLeftInset(-1); - assertEquals(7.2, shape.getLeftInset(), 0); - shape.setRightInset(-1); - assertEquals(7.2, shape.getRightInset(), 0); - - // shape - assertTrue(shape.getWordWrap()); - shape.setWordWrap(false); - assertFalse(shape.getWordWrap()); - shape.setWordWrap(true); - assertTrue(shape.getWordWrap()); - - // shape - assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); - shape.setTextAutofit(TextAutofit.NONE); - assertEquals(TextAutofit.NONE, shape.getTextAutofit()); - shape.setTextAutofit(TextAutofit.SHAPE); - assertEquals(TextAutofit.SHAPE, shape.getTextAutofit()); - shape.setTextAutofit(TextAutofit.NORMAL); - assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); - - assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment()); - shape.setVerticalAlignment(VerticalAlignment.BOTTOM); - assertEquals(VerticalAlignment.BOTTOM, shape.getVerticalAlignment()); - shape.setVerticalAlignment(VerticalAlignment.MIDDLE); - assertEquals(VerticalAlignment.MIDDLE, shape.getVerticalAlignment()); - shape.setVerticalAlignment(null); - assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment()); - - assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection()); - shape.setTextDirection(TextDirection.VERTICAL); - assertEquals(TextDirection.VERTICAL, shape.getTextDirection()); - shape.setTextDirection(null); - assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection()); - - ppt.close(); - } - - @Test - public void testTextParagraph() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - assertTrue(slide.getShapes().isEmpty()); - - XSLFAutoShape shape = slide.createAutoShape(); - assertEquals(0, shape.getTextParagraphs().size()); - XSLFTextParagraph p = shape.addNewTextParagraph(); - assertEquals(1, shape.getTextParagraphs().size()); - - assertNull(p.getIndent()); - assertEquals(0, p.getLeftMargin(), 0); - assertNull(p.getLineSpacing()); - assertNull(p.getSpaceAfter()); - assertNull(p.getSpaceBefore()); - assertEquals(0, p.getIndentLevel()); - - p.setIndent(2.0); - assertEquals(2.0, p.getIndent(), 0); - assertTrue(p.getXmlObject().getPPr().isSetIndent()); - p.setIndent(null); - assertNull(p.getIndent()); - assertFalse(p.getXmlObject().getPPr().isSetIndent()); - p.setIndent(10.0); - assertEquals(10., p.getIndent(), 0); - assertTrue(p.getXmlObject().getPPr().isSetIndent()); - - - assertFalse(p.getXmlObject().getPPr().isSetLvl()); - p.setIndentLevel(1); - assertEquals(1, p.getIndentLevel()); - assertTrue(p.getXmlObject().getPPr().isSetLvl()); - p.setIndentLevel(2); - assertEquals(2, p.getIndentLevel()); - - p.setLeftMargin(2.0); - assertEquals(2.0, p.getLeftMargin(), 0); - assertTrue(p.getXmlObject().getPPr().isSetMarL()); - p.setLeftMargin(10.0); - assertEquals(10., p.getLeftMargin(), 0); - assertEquals(Units.toEMU(10), p.getXmlObject().getPPr().getMarL()); - - - assertFalse(p.getXmlObject().getPPr().isSetSpcAft()); - p.setSpaceAfter(200d); - assertEquals(200000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); - p.setSpaceAfter(100d); - assertEquals(100000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); - p.setSpaceAfter(-20d); - assertEquals(2000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); - p.setSpaceAfter(-10d); - assertEquals(1000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); - - assertFalse(p.getXmlObject().getPPr().isSetSpcBef()); - p.setSpaceBefore(200d); - assertEquals(200000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); - p.setSpaceBefore(100d); - assertEquals(100000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); - p.setSpaceBefore(-20d); - assertEquals(2000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); - p.setSpaceBefore(-10d); - assertEquals(1000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); - assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); - - assertFalse(p.getXmlObject().getPPr().isSetLnSpc()); - p.setLineSpacing(200d); - assertEquals(200000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); - assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); - p.setLineSpacing(100d); - assertEquals(100000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); - assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); - p.setLineSpacing(-20d); - assertEquals(2000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); - assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); - p.setLineSpacing(-10d); - assertEquals(1000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); - assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); - - // align is set in autoshape prototype - assertTrue(p.getXmlObject().getPPr().isSetAlgn()); - assertEquals(TextAlign.LEFT, p.getTextAlign()); - p.setTextAlign(TextAlign.LEFT); - assertTrue(p.getXmlObject().getPPr().isSetAlgn()); - assertEquals(TextAlign.LEFT, p.getTextAlign()); - p.setTextAlign(TextAlign.RIGHT); - assertEquals(TextAlign.RIGHT, p.getTextAlign()); - p.setTextAlign(TextAlign.JUSTIFY); - assertEquals(TextAlign.JUSTIFY, p.getTextAlign()); - p.setTextAlign(null); - assertEquals(TextAlign.LEFT, p.getTextAlign()); - assertFalse(p.getXmlObject().getPPr().isSetAlgn()); - - ppt.close(); - } - - @Test - public void testTextRun() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFAutoShape shape = slide.createAutoShape(); - assertEquals(0, shape.getTextParagraphs().size()); - XSLFTextParagraph p = shape.addNewTextParagraph(); - assertEquals(1, shape.getTextParagraphs().size()); - assertEquals(0, p.getTextRuns().size()); - XSLFTextRun r = p.addNewTextRun(); - CTTextCharacterProperties rPr = r.getRPr(false); - assertNotNull(rPr); - assertEquals(1, p.getTextRuns().size()); - assertSame(r, p.getTextRuns().get(0)); - - - assertEquals(18.0, r.getFontSize(), 0); // default font size for text boxes - assertFalse(rPr.isSetSz()); - r.setFontSize(10.0); - assertEquals(1000, rPr.getSz()); - r.setFontSize(12.5); - assertEquals(1250, rPr.getSz()); - r.setFontSize(null); - assertFalse(rPr.isSetSz()); - - assertFalse(rPr.isSetLatin()); - assertEquals("Calibri", r.getFontFamily()); // comes from the slide master - r.setFontFamily(null); - assertEquals("Calibri", r.getFontFamily()); // comes from the slide master - r.setFontFamily("Arial"); - assertEquals("Arial", r.getFontFamily()); - assertEquals("Arial", rPr.getLatin().getTypeface()); - r.setFontFamily("Symbol"); - assertEquals("Symbol", r.getFontFamily()); - assertEquals("Symbol", rPr.getLatin().getTypeface()); - r.setFontFamily(null); - assertEquals("Calibri", r.getFontFamily()); // comes from the slide master - assertFalse(rPr.isSetLatin()); - - assertFalse(r.isStrikethrough()); - assertFalse(rPr.isSetStrike()); - r.setStrikethrough(true); - assertTrue(r.isStrikethrough()); - assertEquals(STTextStrikeType.SNG_STRIKE, rPr.getStrike()); - - assertFalse(r.isBold()); - assertFalse(rPr.isSetB()); - r.setBold(true); - assertTrue(r.isBold()); - assertEquals(true, rPr.getB()); - - assertFalse(r.isItalic()); - assertFalse(rPr.isSetI()); - r.setItalic(true); - assertTrue(r.isItalic()); - assertEquals(true, rPr.getI()); - - assertFalse(r.isUnderlined()); - assertFalse(rPr.isSetU()); - r.setUnderlined(true); - assertTrue(r.isUnderlined()); - assertEquals(STTextUnderlineType.SNG, rPr.getU()); - - r.setText("Apache"); - assertEquals("Apache", r.getRawText()); - r.setText("POI"); - assertEquals("POI", r.getRawText()); - r.setText(null); - assertNull(r.getRawText()); - - ppt.close(); - } - - @Test - public void testShapeType() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFAutoShape shape = slide.createAutoShape(); - assertEquals(ShapeType.RECT, shape.getShapeType()); - - shape.setShapeType(ShapeType.TRIANGLE); - assertEquals(ShapeType.TRIANGLE, shape.getShapeType()); - - for(ShapeType tp : ShapeType.values()) { - if (tp.ooxmlId == -1 || tp == ShapeType.SEAL) continue; - shape.setShapeType(tp); - assertEquals(tp, shape.getShapeType()); - } - - ppt.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; +import org.apache.poi.sl.usermodel.TextShape.TextAutofit; +import org.apache.poi.sl.usermodel.TextShape.TextDirection; +import org.apache.poi.sl.usermodel.VerticalAlignment; +import org.apache.poi.util.Units; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; + +public class TestXSLFAutoShape { + @Test + public void testTextBodyProperies() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFAutoShape shape = slide.createAutoShape(); + shape.addNewTextParagraph().addNewTextRun().setText("POI"); + + // default margins from slide master + assertEquals(3.6, shape.getBottomInset(), 0); + assertEquals(3.6, shape.getTopInset(), 0); + assertEquals(7.2, shape.getLeftInset(), 0); + assertEquals(7.2, shape.getRightInset(), 0); + + shape.setBottomInset(1.0); + assertEquals(1.0, shape.getBottomInset(), 0); + shape.setTopInset(2.0); + assertEquals(2.0, shape.getTopInset(), 0); + shape.setLeftInset(3.0); + assertEquals(3.0, shape.getLeftInset(), 0); + shape.setRightInset(4.0); + assertEquals(4.0, shape.getRightInset(), 0); + + shape.setBottomInset(0.0); + assertEquals(0.0, shape.getBottomInset(), 0); + shape.setTopInset(0.0); + assertEquals(0.0, shape.getTopInset(), 0); + shape.setLeftInset(0.0); + assertEquals(0.0, shape.getLeftInset(), 0); + shape.setRightInset(0.0); + assertEquals(0.0, shape.getRightInset(), 0); + + // unset to defauls + shape.setBottomInset(-1); + assertEquals(3.6, shape.getBottomInset(), 0); + shape.setTopInset(-1); + assertEquals(3.6, shape.getTopInset(), 0); + shape.setLeftInset(-1); + assertEquals(7.2, shape.getLeftInset(), 0); + shape.setRightInset(-1); + assertEquals(7.2, shape.getRightInset(), 0); + + // shape + assertTrue(shape.getWordWrap()); + shape.setWordWrap(false); + assertFalse(shape.getWordWrap()); + shape.setWordWrap(true); + assertTrue(shape.getWordWrap()); + + // shape + assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); + shape.setTextAutofit(TextAutofit.NONE); + assertEquals(TextAutofit.NONE, shape.getTextAutofit()); + shape.setTextAutofit(TextAutofit.SHAPE); + assertEquals(TextAutofit.SHAPE, shape.getTextAutofit()); + shape.setTextAutofit(TextAutofit.NORMAL); + assertEquals(TextAutofit.NORMAL, shape.getTextAutofit()); + + assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment()); + shape.setVerticalAlignment(VerticalAlignment.BOTTOM); + assertEquals(VerticalAlignment.BOTTOM, shape.getVerticalAlignment()); + shape.setVerticalAlignment(VerticalAlignment.MIDDLE); + assertEquals(VerticalAlignment.MIDDLE, shape.getVerticalAlignment()); + shape.setVerticalAlignment(null); + assertEquals(VerticalAlignment.TOP, shape.getVerticalAlignment()); + + assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection()); + shape.setTextDirection(TextDirection.VERTICAL); + assertEquals(TextDirection.VERTICAL, shape.getTextDirection()); + shape.setTextDirection(null); + assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection()); + + ppt.close(); + } + + @Test + public void testTextParagraph() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + assertTrue(slide.getShapes().isEmpty()); + + XSLFAutoShape shape = slide.createAutoShape(); + assertEquals(0, shape.getTextParagraphs().size()); + XSLFTextParagraph p = shape.addNewTextParagraph(); + assertEquals(1, shape.getTextParagraphs().size()); + + assertNull(p.getIndent()); + assertEquals(0, p.getLeftMargin(), 0); + assertNull(p.getLineSpacing()); + assertNull(p.getSpaceAfter()); + assertNull(p.getSpaceBefore()); + assertEquals(0, p.getIndentLevel()); + + p.setIndent(2.0); + assertEquals(2.0, p.getIndent(), 0); + assertTrue(p.getXmlObject().getPPr().isSetIndent()); + p.setIndent(null); + assertNull(p.getIndent()); + assertFalse(p.getXmlObject().getPPr().isSetIndent()); + p.setIndent(10.0); + assertEquals(10., p.getIndent(), 0); + assertTrue(p.getXmlObject().getPPr().isSetIndent()); + + + assertFalse(p.getXmlObject().getPPr().isSetLvl()); + p.setIndentLevel(1); + assertEquals(1, p.getIndentLevel()); + assertTrue(p.getXmlObject().getPPr().isSetLvl()); + p.setIndentLevel(2); + assertEquals(2, p.getIndentLevel()); + + p.setLeftMargin(2.0); + assertEquals(2.0, p.getLeftMargin(), 0); + assertTrue(p.getXmlObject().getPPr().isSetMarL()); + p.setLeftMargin(10.0); + assertEquals(10., p.getLeftMargin(), 0); + assertEquals(Units.toEMU(10), p.getXmlObject().getPPr().getMarL()); + + + assertFalse(p.getXmlObject().getPPr().isSetSpcAft()); + p.setSpaceAfter(200d); + assertEquals(200000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); + p.setSpaceAfter(100d); + assertEquals(100000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); + p.setSpaceAfter(-20d); + assertEquals(2000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); + p.setSpaceAfter(-10d); + assertEquals(1000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); + + assertFalse(p.getXmlObject().getPPr().isSetSpcBef()); + p.setSpaceBefore(200d); + assertEquals(200000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); + p.setSpaceBefore(100d); + assertEquals(100000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); + p.setSpaceBefore(-20d); + assertEquals(2000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); + p.setSpaceBefore(-10d); + assertEquals(1000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); + + assertFalse(p.getXmlObject().getPPr().isSetLnSpc()); + p.setLineSpacing(200d); + assertEquals(200000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); + p.setLineSpacing(100d); + assertEquals(100000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); + p.setLineSpacing(-20d); + assertEquals(2000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); + p.setLineSpacing(-10d); + assertEquals(1000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); + assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); + + // align is set in autoshape prototype + assertTrue(p.getXmlObject().getPPr().isSetAlgn()); + assertEquals(TextAlign.LEFT, p.getTextAlign()); + p.setTextAlign(TextAlign.LEFT); + assertTrue(p.getXmlObject().getPPr().isSetAlgn()); + assertEquals(TextAlign.LEFT, p.getTextAlign()); + p.setTextAlign(TextAlign.RIGHT); + assertEquals(TextAlign.RIGHT, p.getTextAlign()); + p.setTextAlign(TextAlign.JUSTIFY); + assertEquals(TextAlign.JUSTIFY, p.getTextAlign()); + p.setTextAlign(null); + assertEquals(TextAlign.LEFT, p.getTextAlign()); + assertFalse(p.getXmlObject().getPPr().isSetAlgn()); + + ppt.close(); + } + + @Test + public void testTextRun() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFAutoShape shape = slide.createAutoShape(); + assertEquals(0, shape.getTextParagraphs().size()); + XSLFTextParagraph p = shape.addNewTextParagraph(); + assertEquals(1, shape.getTextParagraphs().size()); + assertEquals(0, p.getTextRuns().size()); + XSLFTextRun r = p.addNewTextRun(); + CTTextCharacterProperties rPr = r.getRPr(false); + assertNotNull(rPr); + assertEquals(1, p.getTextRuns().size()); + assertSame(r, p.getTextRuns().get(0)); + + + assertEquals(18.0, r.getFontSize(), 0); // default font size for text boxes + assertFalse(rPr.isSetSz()); + r.setFontSize(10.0); + assertEquals(1000, rPr.getSz()); + r.setFontSize(12.5); + assertEquals(1250, rPr.getSz()); + r.setFontSize(null); + assertFalse(rPr.isSetSz()); + + assertFalse(rPr.isSetLatin()); + assertEquals("Calibri", r.getFontFamily()); // comes from the slide master + r.setFontFamily(null); + assertEquals("Calibri", r.getFontFamily()); // comes from the slide master + r.setFontFamily("Arial"); + assertEquals("Arial", r.getFontFamily()); + assertEquals("Arial", rPr.getLatin().getTypeface()); + r.setFontFamily("Symbol"); + assertEquals("Symbol", r.getFontFamily()); + assertEquals("Symbol", rPr.getLatin().getTypeface()); + r.setFontFamily(null); + assertEquals("Calibri", r.getFontFamily()); // comes from the slide master + assertFalse(rPr.isSetLatin()); + + assertFalse(r.isStrikethrough()); + assertFalse(rPr.isSetStrike()); + r.setStrikethrough(true); + assertTrue(r.isStrikethrough()); + assertEquals(STTextStrikeType.SNG_STRIKE, rPr.getStrike()); + + assertFalse(r.isBold()); + assertFalse(rPr.isSetB()); + r.setBold(true); + assertTrue(r.isBold()); + assertEquals(true, rPr.getB()); + + assertFalse(r.isItalic()); + assertFalse(rPr.isSetI()); + r.setItalic(true); + assertTrue(r.isItalic()); + assertEquals(true, rPr.getI()); + + assertFalse(r.isUnderlined()); + assertFalse(rPr.isSetU()); + r.setUnderlined(true); + assertTrue(r.isUnderlined()); + assertEquals(STTextUnderlineType.SNG, rPr.getU()); + + r.setText("Apache"); + assertEquals("Apache", r.getRawText()); + r.setText("POI"); + assertEquals("POI", r.getRawText()); + r.setText(null); + assertNull(r.getRawText()); + + ppt.close(); + } + + @Test + public void testShapeType() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFAutoShape shape = slide.createAutoShape(); + assertEquals(ShapeType.RECT, shape.getShapeType()); + + shape.setShapeType(ShapeType.TRIANGLE); + assertEquals(ShapeType.TRIANGLE, shape.getShapeType()); + + for(ShapeType tp : ShapeType.values()) { + if (tp.ooxmlId == -1 || tp == ShapeType.SEAL) continue; + shape.setShapeType(tp); + assertEquals(tp, shape.getShapeType()); + } + + ppt.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFChart.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFChart.java index 02fa668ef8..c6d1efca96 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFChart.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFChart.java @@ -1,132 +1,132 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xslf.usermodel; - -import java.io.OutputStream; -import java.util.LinkedHashMap; -import java.util.Map; - -import junit.framework.TestCase; - -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.openxmlformats.schemas.drawingml.x2006.chart.*; - -/** - * @author Yegor Kozlov - */ -public class TestXSLFChart extends TestCase { - - /** - * a modified version from POI-examples - */ - public void testFillChartTemplate() throws Exception { - - String chartTitle = "Apache POI"; // first line is chart title - - XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("pie-chart.pptx"); - XSLFSlide slide = pptx.getSlides().get(0); - - // find chart in the slide - XSLFChart chart = null; - for(POIXMLDocumentPart part : slide.getRelations()){ - if(part instanceof XSLFChart){ - chart = (XSLFChart) part; - break; - } - } - - if(chart == null) throw new IllegalStateException("chart not found in the template"); - - // embedded Excel workbook that holds the chart data - POIXMLDocumentPart xlsPart = chart.getRelations().get(0); - XSSFWorkbook wb = new XSSFWorkbook(); - XSSFSheet sheet = wb.createSheet(); - - CTChart ctChart = chart.getCTChart(); - CTPlotArea plotArea = ctChart.getPlotArea(); - - CTPieChart pieChart = plotArea.getPieChartArray(0); - //Pie Chart Series - CTPieSer ser = pieChart.getSerArray(0); - - // Series Text - CTSerTx tx = ser.getTx(); - tx.getStrRef().getStrCache().getPtArray(0).setV(chartTitle); - sheet.createRow(0).createCell(1).setCellValue(chartTitle); - String titleRef = new CellReference(sheet.getSheetName(), 0, 1, true, true).formatAsString(); - tx.getStrRef().setF(titleRef); - - - // Category Axis Data - CTAxDataSource cat = ser.getCat(); - CTStrData strData = cat.getStrRef().getStrCache(); - - // Values - CTNumDataSource valSrc = ser.getVal(); - CTNumData numData = valSrc.getNumRef().getNumCache(); - - strData.setPtArray(null); // unset old axis text - numData.setPtArray(null); // unset old values - - Map pieModel = new LinkedHashMap(); - pieModel.put("First", 1.0); - pieModel.put("Second", 3.0); - pieModel.put("Third", 4.0); - - // set model - int idx = 0; - int rownum = 1; - for(String key : pieModel.keySet()){ - double val = pieModel.get(key); - - CTNumVal numVal = numData.addNewPt(); - numVal.setIdx(idx); - numVal.setV("" + val); - - CTStrVal sVal = strData.addNewPt(); - sVal.setIdx(idx); - sVal.setV(key); - - idx++; - XSSFRow row = sheet.createRow(rownum++); - row.createCell(0).setCellValue(key); - row.createCell(1).setCellValue(val); - } - numData.getPtCount().setVal(idx); - strData.getPtCount().setVal(idx); - - String numDataRange = new CellRangeAddress(1, rownum-1, 1, 1).formatAsString(sheet.getSheetName(), true); - valSrc.getNumRef().setF(numDataRange); - String axisDataRange = new CellRangeAddress(1, rownum-1, 0, 0).formatAsString(sheet.getSheetName(), true); - cat.getStrRef().setF(axisDataRange); - - // updated the embedded workbook with the data - OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream(); - wb.write(xlsOut); - xlsOut.close(); - - } - +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xslf.usermodel; + +import java.io.OutputStream; +import java.util.LinkedHashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openxmlformats.schemas.drawingml.x2006.chart.*; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFChart extends TestCase { + + /** + * a modified version from POI-examples + */ + public void testFillChartTemplate() throws Exception { + + String chartTitle = "Apache POI"; // first line is chart title + + XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("pie-chart.pptx"); + XSLFSlide slide = pptx.getSlides().get(0); + + // find chart in the slide + XSLFChart chart = null; + for(POIXMLDocumentPart part : slide.getRelations()){ + if(part instanceof XSLFChart){ + chart = (XSLFChart) part; + break; + } + } + + if(chart == null) throw new IllegalStateException("chart not found in the template"); + + // embedded Excel workbook that holds the chart data + POIXMLDocumentPart xlsPart = chart.getRelations().get(0); + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + + CTChart ctChart = chart.getCTChart(); + CTPlotArea plotArea = ctChart.getPlotArea(); + + CTPieChart pieChart = plotArea.getPieChartArray(0); + //Pie Chart Series + CTPieSer ser = pieChart.getSerArray(0); + + // Series Text + CTSerTx tx = ser.getTx(); + tx.getStrRef().getStrCache().getPtArray(0).setV(chartTitle); + sheet.createRow(0).createCell(1).setCellValue(chartTitle); + String titleRef = new CellReference(sheet.getSheetName(), 0, 1, true, true).formatAsString(); + tx.getStrRef().setF(titleRef); + + + // Category Axis Data + CTAxDataSource cat = ser.getCat(); + CTStrData strData = cat.getStrRef().getStrCache(); + + // Values + CTNumDataSource valSrc = ser.getVal(); + CTNumData numData = valSrc.getNumRef().getNumCache(); + + strData.setPtArray(null); // unset old axis text + numData.setPtArray(null); // unset old values + + Map pieModel = new LinkedHashMap(); + pieModel.put("First", 1.0); + pieModel.put("Second", 3.0); + pieModel.put("Third", 4.0); + + // set model + int idx = 0; + int rownum = 1; + for(String key : pieModel.keySet()){ + double val = pieModel.get(key); + + CTNumVal numVal = numData.addNewPt(); + numVal.setIdx(idx); + numVal.setV("" + val); + + CTStrVal sVal = strData.addNewPt(); + sVal.setIdx(idx); + sVal.setV(key); + + idx++; + XSSFRow row = sheet.createRow(rownum++); + row.createCell(0).setCellValue(key); + row.createCell(1).setCellValue(val); + } + numData.getPtCount().setVal(idx); + strData.getPtCount().setVal(idx); + + String numDataRange = new CellRangeAddress(1, rownum-1, 1, 1).formatAsString(sheet.getSheetName(), true); + valSrc.getNumRef().setF(numDataRange); + String axisDataRange = new CellRangeAddress(1, rownum-1, 0, 0).formatAsString(sheet.getSheetName(), true); + cat.getStrRef().setF(axisDataRange); + + // updated the embedded workbook with the data + OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream(); + wb.write(xlsOut); + xlsOut.close(); + + } + } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java index 659f4beae7..a862c16b44 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java @@ -1,184 +1,184 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.awt.Color; -import java.io.IOException; - -import org.apache.poi.sl.usermodel.PresetColor; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSystemColor; -import org.openxmlformats.schemas.drawingml.x2006.main.STPresetColorVal; -import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; -import org.openxmlformats.schemas.drawingml.x2006.main.STSystemColorVal; - -public class TestXSLFColor { - - @Test - public void testGetters() { - CTColor xml = CTColor.Factory.newInstance(); - CTSRgbColor c = xml.addNewSrgbClr(); - c.setVal(new byte[]{(byte)0xFF, 0, 0}); - - XSLFColor color = new XSLFColor(xml, null, null); - - assertEquals(-1, color.getAlpha()); - c.addNewAlpha().setVal(50000); - assertEquals(50, color.getAlpha()); - - assertEquals(-1, color.getAlphaMod()); - c.addNewAlphaMod().setVal(50000); - assertEquals(50, color.getAlphaMod()); - - assertEquals(-1, color.getAlphaOff()); - c.addNewAlphaOff().setVal(50000); - assertEquals(50, color.getAlphaOff()); - - assertEquals(-1, color.getLumMod()); - c.addNewLumMod().setVal(50000); - assertEquals(50, color.getLumMod()); - - assertEquals(-1, color.getLumOff()); - c.addNewLumOff().setVal(50000); - assertEquals(50, color.getLumOff()); - - assertEquals(-1, color.getSat()); - c.addNewSat().setVal(50000); - assertEquals(50, color.getSat()); - - assertEquals(-1, color.getSatMod()); - c.addNewSatMod().setVal(50000); - assertEquals(50, color.getSatMod()); - - assertEquals(-1, color.getSatOff()); - c.addNewSatOff().setVal(50000); - assertEquals(50, color.getSatOff()); - - assertEquals(-1, color.getRed()); - c.addNewRed().setVal(50000); - assertEquals(50, color.getRed()); - - assertEquals(-1, color.getGreen()); - c.addNewGreen().setVal(50000); - assertEquals(50, color.getGreen()); - - assertEquals(-1, color.getBlue()); - c.addNewBlue().setVal(50000); - assertEquals(50, color.getRed()); - - assertEquals(-1, color.getShade()); - c.addNewShade().setVal(50000); - assertEquals(50, color.getShade()); - - assertEquals(-1, color.getTint()); - c.addNewTint().setVal(50000); - assertEquals(50, color.getTint()); - } - - @Test - public void testHSL() { - CTColor xml = CTColor.Factory.newInstance(); - CTHslColor c = xml.addNewHslClr(); - c.setHue2(14400000); - c.setSat2(100000); - c.setLum2(50000); - - XSLFColor color = new XSLFColor(xml, null, null); - assertEquals(Color.BLUE, color.getColor()); - } - - @Test - public void testSRgb() { - CTColor xml = CTColor.Factory.newInstance(); - xml.addNewSrgbClr().setVal(new byte[]{ (byte)0xFF, (byte)0xFF, 0}); - - XSLFColor color = new XSLFColor(xml, null, null); - assertEquals(new Color(0xFF, 0xFF, 0), color.getColor()); - } - - @Test - public void testSchemeColor() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFTheme theme = ppt.createSlide().getTheme(); - - CTColor xml = CTColor.Factory.newInstance(); - xml.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_2); - - XSLFColor color = new XSLFColor(xml, theme, null); - // accent2 is theme1.xml is - assertEquals(Color.decode("0xC0504D"), color.getColor()); - - xml = CTColor.Factory.newInstance(); - xml.addNewSchemeClr().setVal(STSchemeColorVal.LT_1); - color = new XSLFColor(xml, theme, null); - // - assertEquals(Color.decode("0xFFFFFF"), color.getColor()); - - xml = CTColor.Factory.newInstance(); - xml.addNewSchemeClr().setVal(STSchemeColorVal.DK_1); - color = new XSLFColor(xml, theme, null); - // - assertEquals(Color.decode("0x000000"), color.getColor()); - - ppt.close(); - } - - @Test - public void testPresetColor() { - CTColor xml = CTColor.Factory.newInstance(); - xml.addNewPrstClr().setVal(STPresetColorVal.AQUAMARINE); - XSLFColor color = new XSLFColor(xml, null, null); - assertEquals(new Color(127, 255, 212), color.getColor()); - - - for(PresetColor pc : PresetColor.values()) { - if (pc.ooxmlId == null) continue; - xml = CTColor.Factory.newInstance(); - STPresetColorVal.Enum preVal = STPresetColorVal.Enum.forString(pc.ooxmlId); - STSystemColorVal.Enum sysVal = STSystemColorVal.Enum.forString(pc.ooxmlId); - assertTrue(pc.ooxmlId, preVal != null || sysVal != null); - if (preVal != null) { - xml.addNewPrstClr().setVal(preVal); - } else { - xml.addNewSysClr().setVal(sysVal); - } - color = new XSLFColor(xml, null, null); - assertEquals(pc.color, color.getColor()); - } - } - - @Test - public void testSys() { - CTColor xml = CTColor.Factory.newInstance(); - CTSystemColor sys = xml.addNewSysClr(); - sys.setVal(STSystemColorVal.CAPTION_TEXT); - XSLFColor color = new XSLFColor(xml, null, null); - assertEquals(Color.black, color.getColor()); - - xml = CTColor.Factory.newInstance(); - sys = xml.addNewSysClr(); - sys.setLastClr(new byte[]{(byte)0xFF, 0, 0}); - color = new XSLFColor(xml, null, null); - assertEquals(Color.red, color.getColor()); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.awt.Color; +import java.io.IOException; + +import org.apache.poi.sl.usermodel.PresetColor; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSystemColor; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetColorVal; +import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; +import org.openxmlformats.schemas.drawingml.x2006.main.STSystemColorVal; + +public class TestXSLFColor { + + @Test + public void testGetters() { + CTColor xml = CTColor.Factory.newInstance(); + CTSRgbColor c = xml.addNewSrgbClr(); + c.setVal(new byte[]{(byte)0xFF, 0, 0}); + + XSLFColor color = new XSLFColor(xml, null, null); + + assertEquals(-1, color.getAlpha()); + c.addNewAlpha().setVal(50000); + assertEquals(50, color.getAlpha()); + + assertEquals(-1, color.getAlphaMod()); + c.addNewAlphaMod().setVal(50000); + assertEquals(50, color.getAlphaMod()); + + assertEquals(-1, color.getAlphaOff()); + c.addNewAlphaOff().setVal(50000); + assertEquals(50, color.getAlphaOff()); + + assertEquals(-1, color.getLumMod()); + c.addNewLumMod().setVal(50000); + assertEquals(50, color.getLumMod()); + + assertEquals(-1, color.getLumOff()); + c.addNewLumOff().setVal(50000); + assertEquals(50, color.getLumOff()); + + assertEquals(-1, color.getSat()); + c.addNewSat().setVal(50000); + assertEquals(50, color.getSat()); + + assertEquals(-1, color.getSatMod()); + c.addNewSatMod().setVal(50000); + assertEquals(50, color.getSatMod()); + + assertEquals(-1, color.getSatOff()); + c.addNewSatOff().setVal(50000); + assertEquals(50, color.getSatOff()); + + assertEquals(-1, color.getRed()); + c.addNewRed().setVal(50000); + assertEquals(50, color.getRed()); + + assertEquals(-1, color.getGreen()); + c.addNewGreen().setVal(50000); + assertEquals(50, color.getGreen()); + + assertEquals(-1, color.getBlue()); + c.addNewBlue().setVal(50000); + assertEquals(50, color.getRed()); + + assertEquals(-1, color.getShade()); + c.addNewShade().setVal(50000); + assertEquals(50, color.getShade()); + + assertEquals(-1, color.getTint()); + c.addNewTint().setVal(50000); + assertEquals(50, color.getTint()); + } + + @Test + public void testHSL() { + CTColor xml = CTColor.Factory.newInstance(); + CTHslColor c = xml.addNewHslClr(); + c.setHue2(14400000); + c.setSat2(100000); + c.setLum2(50000); + + XSLFColor color = new XSLFColor(xml, null, null); + assertEquals(Color.BLUE, color.getColor()); + } + + @Test + public void testSRgb() { + CTColor xml = CTColor.Factory.newInstance(); + xml.addNewSrgbClr().setVal(new byte[]{ (byte)0xFF, (byte)0xFF, 0}); + + XSLFColor color = new XSLFColor(xml, null, null); + assertEquals(new Color(0xFF, 0xFF, 0), color.getColor()); + } + + @Test + public void testSchemeColor() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFTheme theme = ppt.createSlide().getTheme(); + + CTColor xml = CTColor.Factory.newInstance(); + xml.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_2); + + XSLFColor color = new XSLFColor(xml, theme, null); + // accent2 is theme1.xml is + assertEquals(Color.decode("0xC0504D"), color.getColor()); + + xml = CTColor.Factory.newInstance(); + xml.addNewSchemeClr().setVal(STSchemeColorVal.LT_1); + color = new XSLFColor(xml, theme, null); + // + assertEquals(Color.decode("0xFFFFFF"), color.getColor()); + + xml = CTColor.Factory.newInstance(); + xml.addNewSchemeClr().setVal(STSchemeColorVal.DK_1); + color = new XSLFColor(xml, theme, null); + // + assertEquals(Color.decode("0x000000"), color.getColor()); + + ppt.close(); + } + + @Test + public void testPresetColor() { + CTColor xml = CTColor.Factory.newInstance(); + xml.addNewPrstClr().setVal(STPresetColorVal.AQUAMARINE); + XSLFColor color = new XSLFColor(xml, null, null); + assertEquals(new Color(127, 255, 212), color.getColor()); + + + for(PresetColor pc : PresetColor.values()) { + if (pc.ooxmlId == null) continue; + xml = CTColor.Factory.newInstance(); + STPresetColorVal.Enum preVal = STPresetColorVal.Enum.forString(pc.ooxmlId); + STSystemColorVal.Enum sysVal = STSystemColorVal.Enum.forString(pc.ooxmlId); + assertTrue(pc.ooxmlId, preVal != null || sysVal != null); + if (preVal != null) { + xml.addNewPrstClr().setVal(preVal); + } else { + xml.addNewSysClr().setVal(sysVal); + } + color = new XSLFColor(xml, null, null); + assertEquals(pc.color, color.getColor()); + } + } + + @Test + public void testSys() { + CTColor xml = CTColor.Factory.newInstance(); + CTSystemColor sys = xml.addNewSysClr(); + sys.setVal(STSystemColorVal.CAPTION_TEXT); + XSLFColor color = new XSLFColor(xml, null, null); + assertEquals(Color.black, color.getColor()); + + xml = CTColor.Factory.newInstance(); + sys = xml.addNewSysClr(); + sys.setLastClr(new byte[]{(byte)0xFF, 0, 0}); + color = new XSLFColor(xml, null, null); + assertEquals(Color.red, color.getColor()); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java index 059856242c..03f29859a9 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java @@ -1,159 +1,159 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr; - -import java.awt.Color; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; -import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; -import org.apache.poi.sl.usermodel.ShapeType; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.CTConnection; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualConnectorProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; -import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; -import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; - -public class TestXSLFConnectorShape { - - @Test - public void testLineDecorations() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFConnectorShape shape = slide.createConnector(); - assertEquals(1, slide.getShapes().size()); - - assertFalse(getSpPr(shape).getLn().isSetHeadEnd()); - assertFalse(getSpPr(shape).getLn().isSetTailEnd()); - - // line decorations - assertEquals(DecorationShape.NONE, shape.getLineHeadDecoration()); - assertEquals(DecorationShape.NONE, shape.getLineTailDecoration()); - shape.setLineHeadDecoration(null); - shape.setLineTailDecoration(null); - assertEquals(DecorationShape.NONE, shape.getLineHeadDecoration()); - assertEquals(DecorationShape.NONE, shape.getLineTailDecoration()); - assertFalse(getSpPr(shape).getLn().getHeadEnd().isSetType()); - assertFalse(getSpPr(shape).getLn().getTailEnd().isSetType()); - - shape.setLineHeadDecoration(DecorationShape.ARROW); - shape.setLineTailDecoration(DecorationShape.DIAMOND); - assertEquals(DecorationShape.ARROW, shape.getLineHeadDecoration()); - assertEquals(DecorationShape.DIAMOND, shape.getLineTailDecoration()); - assertEquals(STLineEndType.ARROW, getSpPr(shape).getLn().getHeadEnd().getType()); - assertEquals(STLineEndType.DIAMOND, getSpPr(shape).getLn().getTailEnd().getType()); - - shape.setLineHeadDecoration(DecorationShape.DIAMOND); - shape.setLineTailDecoration(DecorationShape.ARROW); - assertEquals(DecorationShape.DIAMOND, shape.getLineHeadDecoration()); - assertEquals(DecorationShape.ARROW, shape.getLineTailDecoration()); - assertEquals(STLineEndType.DIAMOND, getSpPr(shape).getLn().getHeadEnd().getType()); - assertEquals(STLineEndType.ARROW, getSpPr(shape).getLn().getTailEnd().getType()); - - // line end width - assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); - assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); - shape.setLineHeadWidth(null); - shape.setLineHeadWidth(null); - assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); - assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); - assertFalse(getSpPr(shape).getLn().getHeadEnd().isSetW()); - assertFalse(getSpPr(shape).getLn().getTailEnd().isSetW()); - shape.setLineHeadWidth(DecorationSize.LARGE); - shape.setLineTailWidth(DecorationSize.MEDIUM); - assertEquals(DecorationSize.LARGE, shape.getLineHeadWidth()); - assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); - assertEquals(STLineEndWidth.LG, getSpPr(shape).getLn().getHeadEnd().getW()); - assertEquals(STLineEndWidth.MED, getSpPr(shape).getLn().getTailEnd().getW()); - shape.setLineHeadWidth(DecorationSize.MEDIUM); - shape.setLineTailWidth(DecorationSize.LARGE); - assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); - assertEquals(DecorationSize.LARGE, shape.getLineTailWidth()); - assertEquals(STLineEndWidth.MED, getSpPr(shape).getLn().getHeadEnd().getW()); - assertEquals(STLineEndWidth.LG, getSpPr(shape).getLn().getTailEnd().getW()); - - // line end length - assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); - assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); - shape.setLineHeadLength(null); - shape.setLineTailLength(null); - assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); - assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); - assertFalse(getSpPr(shape).getLn().getHeadEnd().isSetLen()); - assertFalse(getSpPr(shape).getLn().getTailEnd().isSetLen()); - shape.setLineHeadLength(DecorationSize.LARGE); - shape.setLineTailLength(DecorationSize.MEDIUM); - assertEquals(DecorationSize.LARGE, shape.getLineHeadLength()); - assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); - assertEquals(STLineEndLength.LG, getSpPr(shape).getLn().getHeadEnd().getLen()); - assertEquals(STLineEndLength.MED, getSpPr(shape).getLn().getTailEnd().getLen()); - shape.setLineHeadLength(DecorationSize.MEDIUM); - shape.setLineTailLength(DecorationSize.LARGE); - assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); - assertEquals(DecorationSize.LARGE, shape.getLineTailLength()); - assertEquals(STLineEndLength.MED, getSpPr(shape).getLn().getHeadEnd().getLen()); - assertEquals(STLineEndLength.LG, getSpPr(shape).getLn().getTailEnd().getLen()); - - ppt.close(); - } - - @Test - public void testAddConnector() throws IOException { - XMLSlideShow pptx = new XMLSlideShow(); - XSLFSlide slide = pptx.createSlide(); - - XSLFAutoShape rect1 = slide.createAutoShape(); - rect1.setShapeType(ShapeType.RECT); - rect1.setAnchor(new Rectangle2D.Double(100, 100, 100, 100)); - rect1.setFillColor(Color.blue); - - XSLFAutoShape rect2 = slide.createAutoShape(); - rect2.setShapeType(ShapeType.RECT); - rect2.setAnchor(new Rectangle2D.Double(300, 300, 100, 100)); - rect2.setFillColor(Color.red); - - - XSLFConnectorShape connector1 = slide.createConnector(); - connector1.setAnchor(new Rectangle2D.Double(200, 150, 100, 200)); - - CTConnector ctConnector = (CTConnector)connector1.getXmlObject(); - ctConnector.getSpPr().getPrstGeom().setPrst(STShapeType.BENT_CONNECTOR_3); - CTNonVisualConnectorProperties cx = ctConnector.getNvCxnSpPr().getCNvCxnSpPr(); - // connection start - CTConnection stCxn = cx.addNewStCxn(); - stCxn.setId(rect1.getShapeId()); - // side of the rectangle to attach the connector: left=1, bottom=2,right=3, top=4 - stCxn.setIdx(2); - - CTConnection end = cx.addNewEndCxn(); - end.setId(rect2.getShapeId()); - // side of the rectangle to attach the connector: left=1, bottom=2,right=3, top=4 - end.setIdx(3); - - pptx.close(); - } - +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr; + +import java.awt.Color; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; +import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; +import org.apache.poi.sl.usermodel.ShapeType; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTConnection; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualConnectorProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; + +public class TestXSLFConnectorShape { + + @Test + public void testLineDecorations() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFConnectorShape shape = slide.createConnector(); + assertEquals(1, slide.getShapes().size()); + + assertFalse(getSpPr(shape).getLn().isSetHeadEnd()); + assertFalse(getSpPr(shape).getLn().isSetTailEnd()); + + // line decorations + assertEquals(DecorationShape.NONE, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.NONE, shape.getLineTailDecoration()); + shape.setLineHeadDecoration(null); + shape.setLineTailDecoration(null); + assertEquals(DecorationShape.NONE, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.NONE, shape.getLineTailDecoration()); + assertFalse(getSpPr(shape).getLn().getHeadEnd().isSetType()); + assertFalse(getSpPr(shape).getLn().getTailEnd().isSetType()); + + shape.setLineHeadDecoration(DecorationShape.ARROW); + shape.setLineTailDecoration(DecorationShape.DIAMOND); + assertEquals(DecorationShape.ARROW, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.DIAMOND, shape.getLineTailDecoration()); + assertEquals(STLineEndType.ARROW, getSpPr(shape).getLn().getHeadEnd().getType()); + assertEquals(STLineEndType.DIAMOND, getSpPr(shape).getLn().getTailEnd().getType()); + + shape.setLineHeadDecoration(DecorationShape.DIAMOND); + shape.setLineTailDecoration(DecorationShape.ARROW); + assertEquals(DecorationShape.DIAMOND, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.ARROW, shape.getLineTailDecoration()); + assertEquals(STLineEndType.DIAMOND, getSpPr(shape).getLn().getHeadEnd().getType()); + assertEquals(STLineEndType.ARROW, getSpPr(shape).getLn().getTailEnd().getType()); + + // line end width + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); + shape.setLineHeadWidth(null); + shape.setLineHeadWidth(null); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); + assertFalse(getSpPr(shape).getLn().getHeadEnd().isSetW()); + assertFalse(getSpPr(shape).getLn().getTailEnd().isSetW()); + shape.setLineHeadWidth(DecorationSize.LARGE); + shape.setLineTailWidth(DecorationSize.MEDIUM); + assertEquals(DecorationSize.LARGE, shape.getLineHeadWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); + assertEquals(STLineEndWidth.LG, getSpPr(shape).getLn().getHeadEnd().getW()); + assertEquals(STLineEndWidth.MED, getSpPr(shape).getLn().getTailEnd().getW()); + shape.setLineHeadWidth(DecorationSize.MEDIUM); + shape.setLineTailWidth(DecorationSize.LARGE); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); + assertEquals(DecorationSize.LARGE, shape.getLineTailWidth()); + assertEquals(STLineEndWidth.MED, getSpPr(shape).getLn().getHeadEnd().getW()); + assertEquals(STLineEndWidth.LG, getSpPr(shape).getLn().getTailEnd().getW()); + + // line end length + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); + shape.setLineHeadLength(null); + shape.setLineTailLength(null); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); + assertFalse(getSpPr(shape).getLn().getHeadEnd().isSetLen()); + assertFalse(getSpPr(shape).getLn().getTailEnd().isSetLen()); + shape.setLineHeadLength(DecorationSize.LARGE); + shape.setLineTailLength(DecorationSize.MEDIUM); + assertEquals(DecorationSize.LARGE, shape.getLineHeadLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); + assertEquals(STLineEndLength.LG, getSpPr(shape).getLn().getHeadEnd().getLen()); + assertEquals(STLineEndLength.MED, getSpPr(shape).getLn().getTailEnd().getLen()); + shape.setLineHeadLength(DecorationSize.MEDIUM); + shape.setLineTailLength(DecorationSize.LARGE); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); + assertEquals(DecorationSize.LARGE, shape.getLineTailLength()); + assertEquals(STLineEndLength.MED, getSpPr(shape).getLn().getHeadEnd().getLen()); + assertEquals(STLineEndLength.LG, getSpPr(shape).getLn().getTailEnd().getLen()); + + ppt.close(); + } + + @Test + public void testAddConnector() throws IOException { + XMLSlideShow pptx = new XMLSlideShow(); + XSLFSlide slide = pptx.createSlide(); + + XSLFAutoShape rect1 = slide.createAutoShape(); + rect1.setShapeType(ShapeType.RECT); + rect1.setAnchor(new Rectangle2D.Double(100, 100, 100, 100)); + rect1.setFillColor(Color.blue); + + XSLFAutoShape rect2 = slide.createAutoShape(); + rect2.setShapeType(ShapeType.RECT); + rect2.setAnchor(new Rectangle2D.Double(300, 300, 100, 100)); + rect2.setFillColor(Color.red); + + + XSLFConnectorShape connector1 = slide.createConnector(); + connector1.setAnchor(new Rectangle2D.Double(200, 150, 100, 200)); + + CTConnector ctConnector = (CTConnector)connector1.getXmlObject(); + ctConnector.getSpPr().getPrstGeom().setPrst(STShapeType.BENT_CONNECTOR_3); + CTNonVisualConnectorProperties cx = ctConnector.getNvCxnSpPr().getCNvCxnSpPr(); + // connection start + CTConnection stCxn = cx.addNewStCxn(); + stCxn.setId(rect1.getShapeId()); + // side of the rectangle to attach the connector: left=1, bottom=2,right=3, top=4 + stCxn.setIdx(2); + + CTConnection end = cx.addNewEndCxn(); + end.setId(rect2.getShapeId()); + // side of the rectangle to attach the connector: left=1, bottom=2,right=3, top=4 + end.setIdx(3); + + pptx.close(); + } + } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java index 5a4e100e62..c45244ee5d 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFFreeformShape.java @@ -1,55 +1,55 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - - -import static org.junit.Assert.assertEquals; -import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr; - -import java.awt.geom.Ellipse2D; -import java.awt.geom.Path2D; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import org.junit.Test; - -public class TestXSLFFreeformShape { - - @Test - public void testSetPath() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - XSLFFreeformShape shape1 = slide.createFreeform(); - // comples path consisting of a rectangle and an ellipse inside it - Path2D.Double path1 = new Path2D.Double(new Rectangle2D.Double(150, 150, 300, 300)); - path1.append(new Ellipse2D.Double(200, 200, 100, 50), false); - shape1.setPath(path1); - - Path2D.Double path2 = shape1.getPath(); - - // YK: how to compare the original path1 and the value returned by XSLFFreeformShape.getPath() ? - // one way is to create another XSLFFreeformShape from path2 and compare the resulting xml - assertEquals(path1.getBounds2D(), path2.getBounds2D()); - - XSLFFreeformShape shape2 = slide.createFreeform(); - shape2.setPath(path2); - - assertEquals(getSpPr(shape1).getCustGeom().toString(), getSpPr(shape2).getCustGeom().toString()); - - ppt.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + + +import static org.junit.Assert.assertEquals; +import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr; + +import java.awt.geom.Ellipse2D; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.junit.Test; + +public class TestXSLFFreeformShape { + + @Test + public void testSetPath() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFFreeformShape shape1 = slide.createFreeform(); + // comples path consisting of a rectangle and an ellipse inside it + Path2D.Double path1 = new Path2D.Double(new Rectangle2D.Double(150, 150, 300, 300)); + path1.append(new Ellipse2D.Double(200, 200, 100, 50), false); + shape1.setPath(path1); + + Path2D.Double path2 = shape1.getPath(); + + // YK: how to compare the original path1 and the value returned by XSLFFreeformShape.getPath() ? + // one way is to create another XSLFFreeformShape from path2 and compare the resulting xml + assertEquals(path1.getBounds2D(), path2.getBounds2D()); + + XSLFFreeformShape shape2 = slide.createFreeform(); + shape2.setPath(path2); + + assertEquals(getSpPr(shape1).getCustGeom().toString(), getSpPr(shape2).getCustGeom().toString()); + + ppt.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java index ff06d51079..6363177215 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java @@ -1,108 +1,108 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.awt.Dimension; -import java.awt.geom.Rectangle2D; - -import org.junit.Test; - -/** - * @author Yegor Kozlov - */ -public class TestXSLFGroupShape { - - @Test - public void testCreateShapes() throws Exception { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - ppt.setPageSize(new Dimension(792, 612)); - - XSLFGroupShape group = slide.createGroup(); - assertEquals(1, slide.getShapes().size()); - - Rectangle2D interior = new Rectangle2D.Double(-10, -10, 20, 20); - group.setInteriorAnchor(interior); - assertEquals(interior, group.getInteriorAnchor()); - - Rectangle2D anchor = new Rectangle2D.Double(0, 0, 792, 612); - group.setAnchor(anchor); - assertEquals(anchor, group.getAnchor()); - - assertTrue(group.getShapes().isEmpty()); - - XSLFTextBox shape1 = group.createTextBox(); - assertEquals(1, group.getShapes().size()); - assertSame(shape1, group.getShapes().get(0)); - assertEquals(3, shape1.getShapeId()); - - XSLFAutoShape shape2 = group.createAutoShape(); - assertEquals(2, group.getShapes().size()); - assertSame(shape1, group.getShapes().get(0)); - assertSame(shape2, group.getShapes().get(1)); - assertEquals(4, shape2.getShapeId()); - - XSLFConnectorShape shape3 = group.createConnector(); - assertEquals(3, group.getShapes().size()); - assertSame(shape3, group.getShapes().get(2)); - assertEquals(5, shape3.getShapeId()); - - XSLFGroupShape shape4 = group.createGroup(); - assertEquals(4, group.getShapes().size()); - assertSame(shape4, group.getShapes().get(3)); - assertEquals(6, shape4.getShapeId()); - - group.removeShape(shape2); - assertEquals(3, group.getShapes().size()); - assertSame(shape1, group.getShapes().get(0)); - assertSame(shape3, group.getShapes().get(1)); - assertSame(shape4, group.getShapes().get(2)); - - group.removeShape(shape3); - assertEquals(2, group.getShapes().size()); - assertSame(shape1, group.getShapes().get(0)); - assertSame(shape4, group.getShapes().get(1)); - - group.removeShape(shape1); - group.removeShape(shape4); - assertTrue(group.getShapes().isEmpty()); - - ppt.close(); - } - - @Test - public void testRemoveShapes() throws Exception { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFGroupShape group1 = slide.createGroup(); - group1.createTextBox(); - XSLFGroupShape group2 = slide.createGroup(); - group2.createTextBox(); - XSLFGroupShape group3 = slide.createGroup(); - slide.removeShape(group1); - slide.removeShape(group2); - slide.removeShape(group3); - - ppt.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.awt.Dimension; +import java.awt.geom.Rectangle2D; + +import org.junit.Test; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFGroupShape { + + @Test + public void testCreateShapes() throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + ppt.setPageSize(new Dimension(792, 612)); + + XSLFGroupShape group = slide.createGroup(); + assertEquals(1, slide.getShapes().size()); + + Rectangle2D interior = new Rectangle2D.Double(-10, -10, 20, 20); + group.setInteriorAnchor(interior); + assertEquals(interior, group.getInteriorAnchor()); + + Rectangle2D anchor = new Rectangle2D.Double(0, 0, 792, 612); + group.setAnchor(anchor); + assertEquals(anchor, group.getAnchor()); + + assertTrue(group.getShapes().isEmpty()); + + XSLFTextBox shape1 = group.createTextBox(); + assertEquals(1, group.getShapes().size()); + assertSame(shape1, group.getShapes().get(0)); + assertEquals(3, shape1.getShapeId()); + + XSLFAutoShape shape2 = group.createAutoShape(); + assertEquals(2, group.getShapes().size()); + assertSame(shape1, group.getShapes().get(0)); + assertSame(shape2, group.getShapes().get(1)); + assertEquals(4, shape2.getShapeId()); + + XSLFConnectorShape shape3 = group.createConnector(); + assertEquals(3, group.getShapes().size()); + assertSame(shape3, group.getShapes().get(2)); + assertEquals(5, shape3.getShapeId()); + + XSLFGroupShape shape4 = group.createGroup(); + assertEquals(4, group.getShapes().size()); + assertSame(shape4, group.getShapes().get(3)); + assertEquals(6, shape4.getShapeId()); + + group.removeShape(shape2); + assertEquals(3, group.getShapes().size()); + assertSame(shape1, group.getShapes().get(0)); + assertSame(shape3, group.getShapes().get(1)); + assertSame(shape4, group.getShapes().get(2)); + + group.removeShape(shape3); + assertEquals(2, group.getShapes().size()); + assertSame(shape1, group.getShapes().get(0)); + assertSame(shape4, group.getShapes().get(1)); + + group.removeShape(shape1); + group.removeShape(shape4); + assertTrue(group.getShapes().isEmpty()); + + ppt.close(); + } + + @Test + public void testRemoveShapes() throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFGroupShape group1 = slide.createGroup(); + group1.createTextBox(); + XSLFGroupShape group2 = slide.createGroup(); + group2.createTextBox(); + XSLFGroupShape group3 = slide.createGroup(); + slide.removeShape(group1); + slide.removeShape(group2); + slide.removeShape(group3); + + ppt.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java index a705bfbbe2..746c1bb124 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFHyperlink.java @@ -1,180 +1,180 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.awt.geom.Rectangle2D; -import java.io.IOException; -import java.util.List; - -import org.apache.poi.common.usermodel.HyperlinkType; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; - -public class TestXSLFHyperlink { - - @Test - public void testRead() throws IOException{ - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); - - XSLFSlide slide = ppt.getSlides().get(4); - List shapes = slide.getShapes(); - XSLFTable tbl = (XSLFTable)shapes.get(0); - XSLFTableCell cell1 = tbl.getRows().get(1).getCells().get(0); - assertEquals("Web Page", cell1.getText()); - XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); - assertNotNull(link1); - assertEquals("http://poi.apache.org/", link1.getAddress()); - - XSLFTableCell cell2 = tbl.getRows().get(2).getCells().get(0); - assertEquals("Place in this document", cell2.getText()); - XSLFHyperlink link2 = cell2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); - assertNotNull(link2); - assertEquals("/ppt/slides/slide2.xml", link2.getAddress()); - - XSLFTableCell cell3 = tbl.getRows().get(3).getCells().get(0); - assertEquals("Email", cell3.getText()); - XSLFHyperlink link3 = cell3.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); - assertNotNull(link3); - assertEquals("mailto:dev@poi.apache.org?subject=Hi%20There", link3.getAddress()); - - ppt.close(); - } - - @Test - public void testCreate() throws IOException, InvalidFormatException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide1 = ppt.createSlide(); - XSLFSlide slide2 = ppt.createSlide(); - - int numRel = slide1.getPackagePart().getRelationships().size(); - assertEquals(1, numRel); - XSLFTextBox sh1 = slide1.createTextBox(); - XSLFTextRun r1 = sh1.addNewTextParagraph().addNewTextRun(); - r1.setText("Web Page"); - XSLFHyperlink link1 = r1.createHyperlink(); - link1.setAddress("http://poi.apache.org/"); - assertEquals("http://poi.apache.org/", link1.getAddress()); - assertEquals(numRel + 1, slide1.getPackagePart().getRelationships().size()); - - String id1 = link1.getXmlObject().getId(); - assertNotNull(id1); - PackageRelationship rel1 = slide1.getPackagePart().getRelationship(id1); - assertNotNull(rel1); - assertEquals(id1, rel1.getId()); - assertEquals(TargetMode.EXTERNAL, rel1.getTargetMode()); - assertEquals(XSLFRelation.HYPERLINK.getRelation(), rel1.getRelationshipType()); - - XSLFTextBox sh2 = slide1.createTextBox(); - XSLFTextRun r2 = sh2.addNewTextParagraph().addNewTextRun(); - r2.setText("Place in this document"); - XSLFHyperlink link2 = r2.createHyperlink(); - link2.linkToSlide(slide2); - assertEquals("/ppt/slides/slide2.xml", link2.getAddress()); - assertEquals(numRel + 2, slide1.getPackagePart().getRelationships().size()); - - String id2 = link2.getXmlObject().getId(); - assertNotNull(id2); - PackageRelationship rel2 = slide1.getPackagePart().getRelationship(id2); - assertNotNull(rel2); - assertEquals(id2, rel2.getId()); - assertEquals(TargetMode.INTERNAL, rel2.getTargetMode()); - assertEquals(XSLFRelation.SLIDE.getRelation(), rel2.getRelationshipType()); - - ppt.close(); - } - - - @Test - public void bug47291() throws IOException { - Rectangle2D anchor = new Rectangle2D.Double(100,100,100,100); - XMLSlideShow ppt1 = new XMLSlideShow(); - XSLFSlide slide1 = ppt1.createSlide(); - XSLFTextBox tb1 = slide1.createTextBox(); - tb1.setAnchor(anchor); - XSLFTextRun r1 = tb1.setText("page1"); - XSLFHyperlink hl1 = r1.createHyperlink(); - hl1.linkToEmail("dev@poi.apache.org"); - XSLFTextBox tb2 = ppt1.createSlide().createTextBox(); - tb2.setAnchor(anchor); - XSLFTextRun r2 = tb2.setText("page2"); - XSLFHyperlink hl2 = r2.createHyperlink(); - hl2.linkToLastSlide(); - XSLFSlide sl3 = ppt1.createSlide(); - XSLFTextBox tb3 = sl3.createTextBox(); - tb3.setAnchor(anchor); - tb3.setText("text1 "); - tb3.appendText("lin\u000bk", false); - tb3.appendText(" text2", false); - List tb3runs = tb3.getTextParagraphs().get(0).getTextRuns(); - tb3runs.get(1).createHyperlink().linkToSlide(slide1); // "lin" - tb3runs.get(3).createHyperlink().linkToSlide(slide1); // "k" - XSLFTextBox tb4 = ppt1.createSlide().createTextBox(); - tb4.setAnchor(anchor); - XSLFTextRun r4 = tb4.setText("page4"); - XSLFHyperlink hl4 = r4.createHyperlink(); - hl4.linkToUrl("http://poi.apache.org"); - XSLFTextBox tb5 = ppt1.createSlide().createTextBox(); - tb5.setAnchor(anchor); - tb5.setText("page5"); - XSLFHyperlink hl5 = tb5.createHyperlink(); - hl5.linkToFirstSlide(); - - XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); - ppt1.close(); - - List slides = ppt2.getSlides(); - tb1 = (XSLFTextBox)slides.get(0).getShapes().get(0); - hl1 = tb1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); - assertNotNull(hl1); - assertEquals("dev@poi.apache.org", hl1.getLabel()); - assertEquals(HyperlinkType.EMAIL, hl1.getTypeEnum()); - - tb2 = (XSLFTextBox)slides.get(1).getShapes().get(0); - hl2 = tb2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); - assertNotNull(hl2); - assertEquals("lastslide", hl2.getXmlObject().getAction().split("=")[1]); - assertEquals(HyperlinkType.DOCUMENT, hl2.getTypeEnum()); - - tb3 = (XSLFTextBox)slides.get(2).getShapes().get(0); - XSLFHyperlink hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(1).getHyperlink(); - assertNotNull(hl3); - hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(3).getHyperlink(); - assertNotNull(hl3); - assertEquals("/ppt/slides/slide1.xml", hl3.getAddress()); - assertEquals(HyperlinkType.DOCUMENT, hl3.getTypeEnum()); - - tb4 = (XSLFTextBox)slides.get(3).getShapes().get(0); - hl4 = tb4.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); - assertNotNull(hl4); - assertEquals("http://poi.apache.org", hl4.getLabel()); - assertEquals(HyperlinkType.URL, hl4.getTypeEnum()); - - tb5 = (XSLFTextBox)slides.get(4).getShapes().get(0); - hl5 = tb5.getHyperlink(); - assertNotNull(hl5); - assertEquals("firstslide", hl5.getXmlObject().getAction().split("=")[1]); - assertEquals(HyperlinkType.DOCUMENT, hl5.getTypeEnum()); - - ppt2.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.util.List; + +import org.apache.poi.common.usermodel.HyperlinkType; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; + +public class TestXSLFHyperlink { + + @Test + public void testRead() throws IOException{ + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + + XSLFSlide slide = ppt.getSlides().get(4); + List shapes = slide.getShapes(); + XSLFTable tbl = (XSLFTable)shapes.get(0); + XSLFTableCell cell1 = tbl.getRows().get(1).getCells().get(0); + assertEquals("Web Page", cell1.getText()); + XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(link1); + assertEquals("http://poi.apache.org/", link1.getAddress()); + + XSLFTableCell cell2 = tbl.getRows().get(2).getCells().get(0); + assertEquals("Place in this document", cell2.getText()); + XSLFHyperlink link2 = cell2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(link2); + assertEquals("/ppt/slides/slide2.xml", link2.getAddress()); + + XSLFTableCell cell3 = tbl.getRows().get(3).getCells().get(0); + assertEquals("Email", cell3.getText()); + XSLFHyperlink link3 = cell3.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(link3); + assertEquals("mailto:dev@poi.apache.org?subject=Hi%20There", link3.getAddress()); + + ppt.close(); + } + + @Test + public void testCreate() throws IOException, InvalidFormatException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide1 = ppt.createSlide(); + XSLFSlide slide2 = ppt.createSlide(); + + int numRel = slide1.getPackagePart().getRelationships().size(); + assertEquals(1, numRel); + XSLFTextBox sh1 = slide1.createTextBox(); + XSLFTextRun r1 = sh1.addNewTextParagraph().addNewTextRun(); + r1.setText("Web Page"); + XSLFHyperlink link1 = r1.createHyperlink(); + link1.setAddress("http://poi.apache.org/"); + assertEquals("http://poi.apache.org/", link1.getAddress()); + assertEquals(numRel + 1, slide1.getPackagePart().getRelationships().size()); + + String id1 = link1.getXmlObject().getId(); + assertNotNull(id1); + PackageRelationship rel1 = slide1.getPackagePart().getRelationship(id1); + assertNotNull(rel1); + assertEquals(id1, rel1.getId()); + assertEquals(TargetMode.EXTERNAL, rel1.getTargetMode()); + assertEquals(XSLFRelation.HYPERLINK.getRelation(), rel1.getRelationshipType()); + + XSLFTextBox sh2 = slide1.createTextBox(); + XSLFTextRun r2 = sh2.addNewTextParagraph().addNewTextRun(); + r2.setText("Place in this document"); + XSLFHyperlink link2 = r2.createHyperlink(); + link2.linkToSlide(slide2); + assertEquals("/ppt/slides/slide2.xml", link2.getAddress()); + assertEquals(numRel + 2, slide1.getPackagePart().getRelationships().size()); + + String id2 = link2.getXmlObject().getId(); + assertNotNull(id2); + PackageRelationship rel2 = slide1.getPackagePart().getRelationship(id2); + assertNotNull(rel2); + assertEquals(id2, rel2.getId()); + assertEquals(TargetMode.INTERNAL, rel2.getTargetMode()); + assertEquals(XSLFRelation.SLIDE.getRelation(), rel2.getRelationshipType()); + + ppt.close(); + } + + + @Test + public void bug47291() throws IOException { + Rectangle2D anchor = new Rectangle2D.Double(100,100,100,100); + XMLSlideShow ppt1 = new XMLSlideShow(); + XSLFSlide slide1 = ppt1.createSlide(); + XSLFTextBox tb1 = slide1.createTextBox(); + tb1.setAnchor(anchor); + XSLFTextRun r1 = tb1.setText("page1"); + XSLFHyperlink hl1 = r1.createHyperlink(); + hl1.linkToEmail("dev@poi.apache.org"); + XSLFTextBox tb2 = ppt1.createSlide().createTextBox(); + tb2.setAnchor(anchor); + XSLFTextRun r2 = tb2.setText("page2"); + XSLFHyperlink hl2 = r2.createHyperlink(); + hl2.linkToLastSlide(); + XSLFSlide sl3 = ppt1.createSlide(); + XSLFTextBox tb3 = sl3.createTextBox(); + tb3.setAnchor(anchor); + tb3.setText("text1 "); + tb3.appendText("lin\u000bk", false); + tb3.appendText(" text2", false); + List tb3runs = tb3.getTextParagraphs().get(0).getTextRuns(); + tb3runs.get(1).createHyperlink().linkToSlide(slide1); // "lin" + tb3runs.get(3).createHyperlink().linkToSlide(slide1); // "k" + XSLFTextBox tb4 = ppt1.createSlide().createTextBox(); + tb4.setAnchor(anchor); + XSLFTextRun r4 = tb4.setText("page4"); + XSLFHyperlink hl4 = r4.createHyperlink(); + hl4.linkToUrl("http://poi.apache.org"); + XSLFTextBox tb5 = ppt1.createSlide().createTextBox(); + tb5.setAnchor(anchor); + tb5.setText("page5"); + XSLFHyperlink hl5 = tb5.createHyperlink(); + hl5.linkToFirstSlide(); + + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt1.close(); + + List slides = ppt2.getSlides(); + tb1 = (XSLFTextBox)slides.get(0).getShapes().get(0); + hl1 = tb1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(hl1); + assertEquals("dev@poi.apache.org", hl1.getLabel()); + assertEquals(HyperlinkType.EMAIL, hl1.getTypeEnum()); + + tb2 = (XSLFTextBox)slides.get(1).getShapes().get(0); + hl2 = tb2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(hl2); + assertEquals("lastslide", hl2.getXmlObject().getAction().split("=")[1]); + assertEquals(HyperlinkType.DOCUMENT, hl2.getTypeEnum()); + + tb3 = (XSLFTextBox)slides.get(2).getShapes().get(0); + XSLFHyperlink hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(1).getHyperlink(); + assertNotNull(hl3); + hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(3).getHyperlink(); + assertNotNull(hl3); + assertEquals("/ppt/slides/slide1.xml", hl3.getAddress()); + assertEquals(HyperlinkType.DOCUMENT, hl3.getTypeEnum()); + + tb4 = (XSLFTextBox)slides.get(3).getShapes().get(0); + hl4 = tb4.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink(); + assertNotNull(hl4); + assertEquals("http://poi.apache.org", hl4.getLabel()); + assertEquals(HyperlinkType.URL, hl4.getTypeEnum()); + + tb5 = (XSLFTextBox)slides.get(4).getShapes().get(0); + hl5 = tb5.getHyperlink(); + assertNotNull(hl5); + assertEquals("firstslide", hl5.getXmlObject().getAction().split("=")[1]); + assertEquals(HyperlinkType.DOCUMENT, hl5.getTypeEnum()); + + ppt2.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java index ae18fc70c2..6ce747be72 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java @@ -1,106 +1,106 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.io.IOException; - -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; - -public class TestXSLFNotes { - - @Test - public void createNewNote() throws IOException { - - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide1 = ppt.createSlide(); - - assertNull(ppt.getNotesMaster()); - assertNull(slide1.getNotes()); - - XSLFNotes notesSlide = ppt.getNotesSlide(slide1); - assertNotNull(ppt.getNotesMaster()); - assertNotNull(notesSlide); - - String note = null; - for (XSLFTextShape shape : notesSlide.getPlaceholders()) { - if (shape.getTextType() == Placeholder.BODY) { - shape.setText("New Note"); - note = shape.getText(); - break; - } - } - assertNotNull(note); - assertEquals("New Note", note); - - ppt.close(); - } - - @Test - public void addNote() throws IOException { - - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx"); - - XSLFSlide slide = ppt.createSlide(); - XSLFNotes notesSlide = ppt.getNotesSlide(slide); - assertNotNull(notesSlide); - - String note = null; - for (XSLFTextShape shape : notesSlide.getPlaceholders()) { - if (shape.getTextType() == Placeholder.BODY) { - shape.setText("New Note"); - note = shape.getText(); - break; - } - } - assertNotNull(note); - assertEquals("New Note", note); - - ppt.close(); - } - - @Test - public void replaceNotes() throws IOException { - - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx"); - - for (XSLFSlide slide : ppt.getSlides()) { - assertNotNull(slide.getNotes()); - - XSLFNotes notesSlide = ppt.getNotesSlide(slide); - assertNotNull(notesSlide); - - String note = null; - for (XSLFTextShape shape : notesSlide.getPlaceholders()) { - if (shape.getTextType() == Placeholder.BODY) { - shape.setText("New Note"); - note = shape.getText(); - break; - } - } - assertNotNull(note); - assertEquals("New Note", note); - } - - ppt.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.IOException; + +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; + +public class TestXSLFNotes { + + @Test + public void createNewNote() throws IOException { + + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide1 = ppt.createSlide(); + + assertNull(ppt.getNotesMaster()); + assertNull(slide1.getNotes()); + + XSLFNotes notesSlide = ppt.getNotesSlide(slide1); + assertNotNull(ppt.getNotesMaster()); + assertNotNull(notesSlide); + + String note = null; + for (XSLFTextShape shape : notesSlide.getPlaceholders()) { + if (shape.getTextType() == Placeholder.BODY) { + shape.setText("New Note"); + note = shape.getText(); + break; + } + } + assertNotNull(note); + assertEquals("New Note", note); + + ppt.close(); + } + + @Test + public void addNote() throws IOException { + + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx"); + + XSLFSlide slide = ppt.createSlide(); + XSLFNotes notesSlide = ppt.getNotesSlide(slide); + assertNotNull(notesSlide); + + String note = null; + for (XSLFTextShape shape : notesSlide.getPlaceholders()) { + if (shape.getTextType() == Placeholder.BODY) { + shape.setText("New Note"); + note = shape.getText(); + break; + } + } + assertNotNull(note); + assertEquals("New Note", note); + + ppt.close(); + } + + @Test + public void replaceNotes() throws IOException { + + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx"); + + for (XSLFSlide slide : ppt.getSlides()) { + assertNotNull(slide.getNotes()); + + XSLFNotes notesSlide = ppt.getNotesSlide(slide); + assertNotNull(notesSlide); + + String note = null; + for (XSLFTextShape shape : notesSlide.getPlaceholders()) { + if (shape.getTextType() == Placeholder.BODY) { + shape.setText("New Note"); + note = shape.getText(); + break; + } + } + assertNotNull(note); + assertEquals("New Note", note); + } + + ppt.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java index 95d407a02f..3ca01733ef 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java @@ -1,211 +1,211 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.sl.usermodel.PictureData.PictureType; -import org.apache.poi.util.IOUtils; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; - -public class TestXSLFPictureShape { - private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); - - @Test - public void testCreate() throws Exception { - XMLSlideShow ppt1 = new XMLSlideShow(); - assertEquals(0, ppt1.getPictureData().size()); - byte[] data1 = new byte[100]; - for(int i = 0;i < 100;i++) { data1[i] = (byte)i; } - XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG); - assertEquals(0, pdata1.getIndex()); - assertEquals(1, ppt1.getPictureData().size()); - - XSLFSlide slide = ppt1.createSlide(); - XSLFPictureShape shape1 = slide.createPicture(pdata1); - assertNotNull(shape1.getPictureData()); - assertArrayEquals(data1, shape1.getPictureData().getData()); - - byte[] data2 = new byte[200]; - for(int i = 0;i < 200;i++) { data2[i] = (byte)i; } - XSLFPictureData pdata2 = ppt1.addPicture(data2, PictureType.PNG); - XSLFPictureShape shape2 = slide.createPicture(pdata2); - assertNotNull(shape2.getPictureData()); - assertEquals(1, pdata2.getIndex()); - assertEquals(2, ppt1.getPictureData().size()); - assertArrayEquals(data2, shape2.getPictureData().getData()); - - XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); - ppt1.close(); - List pics = ppt2.getPictureData(); - assertEquals(2, pics.size()); - assertArrayEquals(data1, pics.get(0).getData()); - assertArrayEquals(data2, pics.get(1).getData()); - - List shapes = ppt2.getSlides().get(0).getShapes(); - assertArrayEquals(data1, ((XSLFPictureShape) shapes.get(0)).getPictureData().getData()); - assertArrayEquals(data2, ((XSLFPictureShape) shapes.get(1)).getPictureData().getData()); - ppt2.close(); - } - - @Test - public void testCreateMultiplePictures() throws Exception { - XMLSlideShow ppt1 = new XMLSlideShow(); - XSLFSlide slide1 = ppt1.createSlide(); - XSLFGroupShape group1 = slide1.createGroup(); - - - int pictureIndex = 0; - // first add 20 images to the slide - for (int i = 0; i < 20; i++, pictureIndex++) { - byte[] data = new byte[]{(byte)pictureIndex}; - XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG); - assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19 - XSLFPictureShape picture = slide1.createPicture(elementData); - // POI saves images as image1.png, image2.png, etc. - String fileName = "image" + (elementData.getIndex()+1) + ".png"; - assertEquals(fileName, picture.getPictureData().getFileName()); - assertArrayEquals(data, picture.getPictureData().getData()); - } - - // and then add next 20 images to a group - for (int i = 0; i < 20; i++, pictureIndex++) { - byte[] data = new byte[]{(byte)pictureIndex}; - XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG); - XSLFPictureShape picture = group1.createPicture(elementData); - // POI saves images as image1.png, image2.png, etc. - assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19 - String fileName = "image" + (pictureIndex + 1) + ".png"; - assertEquals(fileName, picture.getPictureData().getFileName()); - assertArrayEquals(data, picture.getPictureData().getData()); - } - - // serialize, read back and check that all images are there - - XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); - ppt1.close(); - // pictures keyed by file name - Map pics = new HashMap(); - for(XSLFPictureData p : ppt2.getPictureData()){ - pics.put(p.getFileName(), p); - } - assertEquals(40, pics.size()); - for (int i = 0; i < 40; i++) { - byte[] data1 = new byte[]{(byte)i}; - String fileName = "image" + (i + 1) + ".png"; - XSLFPictureData data = pics.get(fileName); - assertNotNull(data); - assertEquals(fileName, data.getFileName()); - assertArrayEquals(data1, data.getData()); - } - ppt2.close(); - } - - @Test - public void testImageCaching() throws Exception { - XMLSlideShow ppt = new XMLSlideShow(); - byte[] img1 = new byte[]{1,2,3}; - byte[] img2 = new byte[]{3,4,5}; - XSLFPictureData pdata1 = ppt.addPicture(img1, PictureType.PNG); - assertEquals(0, pdata1.getIndex()); - assertEquals(0, ppt.addPicture(img1, PictureType.PNG).getIndex()); - - XSLFPictureData idx2 = ppt.addPicture(img2, PictureType.PNG); - assertEquals(1, idx2.getIndex()); - assertEquals(1, ppt.addPicture(img2, PictureType.PNG).getIndex()); - - XSLFSlide slide1 = ppt.createSlide(); - assertNotNull(slide1); - XSLFSlide slide2 = ppt.createSlide(); - assertNotNull(slide2); - - ppt.close(); - } - - @Test - public void testMerge() throws Exception { - XMLSlideShow ppt1 = new XMLSlideShow(); - byte[] data1 = new byte[100]; - XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG); - - XSLFSlide slide1 = ppt1.createSlide(); - XSLFPictureShape shape1 = slide1.createPicture(pdata1); - CTPicture ctPic1 = (CTPicture)shape1.getXmlObject(); - ctPic1.getNvPicPr().getNvPr().addNewCustDataLst().addNewTags().setId("rId99"); - - XMLSlideShow ppt2 = new XMLSlideShow(); - - XSLFSlide slide2 = ppt2.createSlide().importContent(slide1); - XSLFPictureShape shape2 = (XSLFPictureShape)slide2.getShapes().get(0); - - assertArrayEquals(data1, shape2.getPictureData().getData()); - - CTPicture ctPic2 = (CTPicture)shape2.getXmlObject(); - assertFalse(ctPic2.getNvPicPr().getNvPr().isSetCustDataLst()); - - ppt1.close(); - ppt2.close(); - } - - @Test - public void bug58663() throws IOException { - InputStream is = _slTests.openResourceAsStream("shapes.pptx"); - XMLSlideShow ppt = new XMLSlideShow(is); - is.close(); - - XSLFSlide slide = ppt.getSlides().get(0); - XSLFPictureShape ps = (XSLFPictureShape)slide.getShapes().get(3); - slide.removeShape(ps); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ppt.write(bos); - ppt.close(); - - XMLSlideShow ppt2 = new XMLSlideShow(new ByteArrayInputStream(bos.toByteArray())); - assertTrue(ppt2.getPictureData().isEmpty()); - ppt2.close(); - } - - @Test - public void testTiffImageBug59742() throws Exception { - XMLSlideShow slideShow = new XMLSlideShow(); - final InputStream tiffStream = _slTests.openResourceAsStream("testtiff.tif"); - final byte[] pictureData = IOUtils.toByteArray(tiffStream); - IOUtils.closeQuietly(tiffStream); - - XSLFPictureData pic = slideShow.addPicture(pictureData, PictureType.TIFF); - assertEquals("image/tiff", pic.getContentType()); - assertEquals("image1.tiff", pic.getFileName()); - - slideShow.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.sl.usermodel.PictureData.PictureType; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; + +public class TestXSLFPictureShape { + private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); + + @Test + public void testCreate() throws Exception { + XMLSlideShow ppt1 = new XMLSlideShow(); + assertEquals(0, ppt1.getPictureData().size()); + byte[] data1 = new byte[100]; + for(int i = 0;i < 100;i++) { data1[i] = (byte)i; } + XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG); + assertEquals(0, pdata1.getIndex()); + assertEquals(1, ppt1.getPictureData().size()); + + XSLFSlide slide = ppt1.createSlide(); + XSLFPictureShape shape1 = slide.createPicture(pdata1); + assertNotNull(shape1.getPictureData()); + assertArrayEquals(data1, shape1.getPictureData().getData()); + + byte[] data2 = new byte[200]; + for(int i = 0;i < 200;i++) { data2[i] = (byte)i; } + XSLFPictureData pdata2 = ppt1.addPicture(data2, PictureType.PNG); + XSLFPictureShape shape2 = slide.createPicture(pdata2); + assertNotNull(shape2.getPictureData()); + assertEquals(1, pdata2.getIndex()); + assertEquals(2, ppt1.getPictureData().size()); + assertArrayEquals(data2, shape2.getPictureData().getData()); + + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt1.close(); + List pics = ppt2.getPictureData(); + assertEquals(2, pics.size()); + assertArrayEquals(data1, pics.get(0).getData()); + assertArrayEquals(data2, pics.get(1).getData()); + + List shapes = ppt2.getSlides().get(0).getShapes(); + assertArrayEquals(data1, ((XSLFPictureShape) shapes.get(0)).getPictureData().getData()); + assertArrayEquals(data2, ((XSLFPictureShape) shapes.get(1)).getPictureData().getData()); + ppt2.close(); + } + + @Test + public void testCreateMultiplePictures() throws Exception { + XMLSlideShow ppt1 = new XMLSlideShow(); + XSLFSlide slide1 = ppt1.createSlide(); + XSLFGroupShape group1 = slide1.createGroup(); + + + int pictureIndex = 0; + // first add 20 images to the slide + for (int i = 0; i < 20; i++, pictureIndex++) { + byte[] data = new byte[]{(byte)pictureIndex}; + XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG); + assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19 + XSLFPictureShape picture = slide1.createPicture(elementData); + // POI saves images as image1.png, image2.png, etc. + String fileName = "image" + (elementData.getIndex()+1) + ".png"; + assertEquals(fileName, picture.getPictureData().getFileName()); + assertArrayEquals(data, picture.getPictureData().getData()); + } + + // and then add next 20 images to a group + for (int i = 0; i < 20; i++, pictureIndex++) { + byte[] data = new byte[]{(byte)pictureIndex}; + XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG); + XSLFPictureShape picture = group1.createPicture(elementData); + // POI saves images as image1.png, image2.png, etc. + assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19 + String fileName = "image" + (pictureIndex + 1) + ".png"; + assertEquals(fileName, picture.getPictureData().getFileName()); + assertArrayEquals(data, picture.getPictureData().getData()); + } + + // serialize, read back and check that all images are there + + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt1.close(); + // pictures keyed by file name + Map pics = new HashMap(); + for(XSLFPictureData p : ppt2.getPictureData()){ + pics.put(p.getFileName(), p); + } + assertEquals(40, pics.size()); + for (int i = 0; i < 40; i++) { + byte[] data1 = new byte[]{(byte)i}; + String fileName = "image" + (i + 1) + ".png"; + XSLFPictureData data = pics.get(fileName); + assertNotNull(data); + assertEquals(fileName, data.getFileName()); + assertArrayEquals(data1, data.getData()); + } + ppt2.close(); + } + + @Test + public void testImageCaching() throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + byte[] img1 = new byte[]{1,2,3}; + byte[] img2 = new byte[]{3,4,5}; + XSLFPictureData pdata1 = ppt.addPicture(img1, PictureType.PNG); + assertEquals(0, pdata1.getIndex()); + assertEquals(0, ppt.addPicture(img1, PictureType.PNG).getIndex()); + + XSLFPictureData idx2 = ppt.addPicture(img2, PictureType.PNG); + assertEquals(1, idx2.getIndex()); + assertEquals(1, ppt.addPicture(img2, PictureType.PNG).getIndex()); + + XSLFSlide slide1 = ppt.createSlide(); + assertNotNull(slide1); + XSLFSlide slide2 = ppt.createSlide(); + assertNotNull(slide2); + + ppt.close(); + } + + @Test + public void testMerge() throws Exception { + XMLSlideShow ppt1 = new XMLSlideShow(); + byte[] data1 = new byte[100]; + XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG); + + XSLFSlide slide1 = ppt1.createSlide(); + XSLFPictureShape shape1 = slide1.createPicture(pdata1); + CTPicture ctPic1 = (CTPicture)shape1.getXmlObject(); + ctPic1.getNvPicPr().getNvPr().addNewCustDataLst().addNewTags().setId("rId99"); + + XMLSlideShow ppt2 = new XMLSlideShow(); + + XSLFSlide slide2 = ppt2.createSlide().importContent(slide1); + XSLFPictureShape shape2 = (XSLFPictureShape)slide2.getShapes().get(0); + + assertArrayEquals(data1, shape2.getPictureData().getData()); + + CTPicture ctPic2 = (CTPicture)shape2.getXmlObject(); + assertFalse(ctPic2.getNvPicPr().getNvPr().isSetCustDataLst()); + + ppt1.close(); + ppt2.close(); + } + + @Test + public void bug58663() throws IOException { + InputStream is = _slTests.openResourceAsStream("shapes.pptx"); + XMLSlideShow ppt = new XMLSlideShow(is); + is.close(); + + XSLFSlide slide = ppt.getSlides().get(0); + XSLFPictureShape ps = (XSLFPictureShape)slide.getShapes().get(3); + slide.removeShape(ps); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ppt.write(bos); + ppt.close(); + + XMLSlideShow ppt2 = new XMLSlideShow(new ByteArrayInputStream(bos.toByteArray())); + assertTrue(ppt2.getPictureData().isEmpty()); + ppt2.close(); + } + + @Test + public void testTiffImageBug59742() throws Exception { + XMLSlideShow slideShow = new XMLSlideShow(); + final InputStream tiffStream = _slTests.openResourceAsStream("testtiff.tif"); + final byte[] pictureData = IOUtils.toByteArray(tiffStream); + IOUtils.closeQuietly(tiffStream); + + XSLFPictureData pic = slideShow.addPicture(pictureData, PictureType.TIFF); + assertEquals("image/tiff", pic.getContentType()); + assertEquals("image1.tiff", pic.getFileName()); + + slideShow.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java index 403ccb6790..346e98922b 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShape.java @@ -1,108 +1,108 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.List; - -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; - -public class TestXSLFShape { - - @Test - public void testReadTextShapes() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); - List slides = ppt.getSlides(); - - XSLFSlide slide1 = slides.get(0); - List shapes1 = slide1.getShapes(); - assertEquals(7, shapes1.size()); - assertEquals("TextBox 3", shapes1.get(0).getShapeName()); - XSLFAutoShape sh0 = (XSLFAutoShape) shapes1.get(0); - assertEquals("Learning PPTX", sh0.getText()); - List paragraphs0 = sh0.getTextParagraphs(); - assertEquals(1, paragraphs0.size()); - XSLFTextParagraph p0 = paragraphs0.get(0); - assertEquals("Learning PPTX", p0.getText()); - assertEquals(1, p0.getTextRuns().size()); - XSLFTextRun r0 = p0.getTextRuns().get(0); - assertEquals("Learning PPTX", r0.getRawText()); - - XSLFSlide slide2 = slides.get(1); - List shapes2 = slide2.getShapes(); - assertTrue(shapes2.get(0) instanceof XSLFAutoShape); - assertEquals("PPTX Title", ((XSLFAutoShape) shapes2.get(0)).getText()); - XSLFAutoShape sh1 = (XSLFAutoShape) shapes2.get(0); - List paragraphs1 = sh1.getTextParagraphs(); - assertEquals(1, paragraphs1.size()); - XSLFTextParagraph p1 = paragraphs1.get(0); - assertEquals("PPTX Title", p1.getText()); - List r2 = paragraphs1.get(0).getTextRuns(); - assertEquals(2, r2.size()); - assertEquals("PPTX ", r2.get(0).getRawText()); - assertEquals("Title", r2.get(1).getRawText()); - // Title is underlined - assertEquals(STTextUnderlineType.SNG, r2.get(1).getRPr(false).getU()); - - - assertTrue(shapes2.get(1) instanceof XSLFAutoShape); - assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape) shapes2.get(1)).getText()); - XSLFAutoShape sh2 = (XSLFAutoShape) shapes2.get(1); - List paragraphs2 = sh2.getTextParagraphs(); - assertEquals(2, paragraphs2.size()); - assertEquals("Subtitle", paragraphs2.get(0).getText()); - assertEquals("And second line", paragraphs2.get(1).getText()); - - assertEquals(1, paragraphs2.get(0).getTextRuns().size()); - assertEquals(1, paragraphs2.get(1).getTextRuns().size()); - - assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getRawText()); - assertTrue(paragraphs2.get(0).getTextRuns().get(0).getRPr(false).getB()); - assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getRawText()); - - ppt.close(); - } - - @Test - public void testCreateShapes() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - assertTrue(slide.getShapes().isEmpty()); - - XSLFTextBox textBox = slide.createTextBox(); - - assertEquals(1, slide.getShapes().size()); - assertSame(textBox, slide.getShapes().get(0)); - - assertEquals("", textBox.getText()); - // FIXME: is this correct? Should it be starting out with 0 or 1 text paragraphs? - assertEquals(1, textBox.getTextParagraphs().size()); - textBox.addNewTextParagraph().addNewTextRun().setText("Apache"); - textBox.addNewTextParagraph().addNewTextRun().setText("POI"); - assertEquals("Apache\nPOI", textBox.getText()); - assertEquals(3, textBox.getTextParagraphs().size()); - - ppt.close(); - } - +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.List; + +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; + +public class TestXSLFShape { + + @Test + public void testReadTextShapes() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + List slides = ppt.getSlides(); + + XSLFSlide slide1 = slides.get(0); + List shapes1 = slide1.getShapes(); + assertEquals(7, shapes1.size()); + assertEquals("TextBox 3", shapes1.get(0).getShapeName()); + XSLFAutoShape sh0 = (XSLFAutoShape) shapes1.get(0); + assertEquals("Learning PPTX", sh0.getText()); + List paragraphs0 = sh0.getTextParagraphs(); + assertEquals(1, paragraphs0.size()); + XSLFTextParagraph p0 = paragraphs0.get(0); + assertEquals("Learning PPTX", p0.getText()); + assertEquals(1, p0.getTextRuns().size()); + XSLFTextRun r0 = p0.getTextRuns().get(0); + assertEquals("Learning PPTX", r0.getRawText()); + + XSLFSlide slide2 = slides.get(1); + List shapes2 = slide2.getShapes(); + assertTrue(shapes2.get(0) instanceof XSLFAutoShape); + assertEquals("PPTX Title", ((XSLFAutoShape) shapes2.get(0)).getText()); + XSLFAutoShape sh1 = (XSLFAutoShape) shapes2.get(0); + List paragraphs1 = sh1.getTextParagraphs(); + assertEquals(1, paragraphs1.size()); + XSLFTextParagraph p1 = paragraphs1.get(0); + assertEquals("PPTX Title", p1.getText()); + List r2 = paragraphs1.get(0).getTextRuns(); + assertEquals(2, r2.size()); + assertEquals("PPTX ", r2.get(0).getRawText()); + assertEquals("Title", r2.get(1).getRawText()); + // Title is underlined + assertEquals(STTextUnderlineType.SNG, r2.get(1).getRPr(false).getU()); + + + assertTrue(shapes2.get(1) instanceof XSLFAutoShape); + assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape) shapes2.get(1)).getText()); + XSLFAutoShape sh2 = (XSLFAutoShape) shapes2.get(1); + List paragraphs2 = sh2.getTextParagraphs(); + assertEquals(2, paragraphs2.size()); + assertEquals("Subtitle", paragraphs2.get(0).getText()); + assertEquals("And second line", paragraphs2.get(1).getText()); + + assertEquals(1, paragraphs2.get(0).getTextRuns().size()); + assertEquals(1, paragraphs2.get(1).getTextRuns().size()); + + assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getRawText()); + assertTrue(paragraphs2.get(0).getTextRuns().get(0).getRPr(false).getB()); + assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getRawText()); + + ppt.close(); + } + + @Test + public void testCreateShapes() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + assertTrue(slide.getShapes().isEmpty()); + + XSLFTextBox textBox = slide.createTextBox(); + + assertEquals(1, slide.getShapes().size()); + assertSame(textBox, slide.getShapes().get(0)); + + assertEquals("", textBox.getText()); + // FIXME: is this correct? Should it be starting out with 0 or 1 text paragraphs? + assertEquals(1, textBox.getTextParagraphs().size()); + textBox.addNewTextParagraph().addNewTextRun().setText("Apache"); + textBox.addNewTextParagraph().addNewTextRun().setText("POI"); + assertEquals("Apache\nPOI", textBox.getText()); + assertEquals(3, textBox.getTextParagraphs().size()); + + ppt.close(); + } + } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShapeContainer.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShapeContainer.java index 22bab7c5de..217976def6 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShapeContainer.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFShapeContainer.java @@ -1,64 +1,64 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.*; - -import org.junit.Test; - -/** - * test common operations on containers of shapes (sheets and groups of shapes) - * - * @author Yegor Kozlov - */ -public class TestXSLFShapeContainer { - - @SuppressWarnings("unused") - public void verifyContainer(XSLFShapeContainer container) { - container.clear(); - assertEquals(0, container.getShapes().size()); - - XSLFGroupShape shape1 = container.createGroup(); - assertEquals(1, container.getShapes().size()); - - XSLFTextBox shape2 = container.createTextBox(); - assertEquals(2, container.getShapes().size()); - - XSLFAutoShape shape3 = container.createAutoShape(); - assertEquals(3, container.getShapes().size()); - - XSLFConnectorShape shape4 = container.createConnector(); - assertEquals(4, container.getShapes().size()); - - container.clear(); - assertEquals(0, container.getShapes().size()); - } - - @Test - public void testSheet() { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSheet sheet = ppt.createSlide(); - verifyContainer(sheet); - - - XSLFGroupShape group = sheet.createGroup(); - verifyContainer(group); - - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * test common operations on containers of shapes (sheets and groups of shapes) + * + * @author Yegor Kozlov + */ +public class TestXSLFShapeContainer { + + @SuppressWarnings("unused") + public void verifyContainer(XSLFShapeContainer container) { + container.clear(); + assertEquals(0, container.getShapes().size()); + + XSLFGroupShape shape1 = container.createGroup(); + assertEquals(1, container.getShapes().size()); + + XSLFTextBox shape2 = container.createTextBox(); + assertEquals(2, container.getShapes().size()); + + XSLFAutoShape shape3 = container.createAutoShape(); + assertEquals(3, container.getShapes().size()); + + XSLFConnectorShape shape4 = container.createConnector(); + assertEquals(4, container.getShapes().size()); + + container.clear(); + assertEquals(0, container.getShapes().size()); + } + + @Test + public void testSheet() { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSheet sheet = ppt.createSlide(); + verifyContainer(sheet); + + + XSLFGroupShape group = sheet.createGroup(); + verifyContainer(group); + + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java index a307eaab7f..b68577acac 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSheet.java @@ -1,75 +1,75 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.*; - -import java.io.IOException; -import java.util.List; - -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; - -/** - * test common properties for sheets (slides, masters, layouts, etc.) - * - * @author Yegor Kozlov - */ -public class TestXSLFSheet { - - @Test - public void testCreateShapes() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - assertTrue(slide.getShapes().isEmpty()); - - XSLFSimpleShape shape1 = slide.createAutoShape(); - assertEquals(1, slide.getShapes().size()); - assertSame(shape1, slide.getShapes().get(0)); - - XSLFTextBox shape2 = slide.createTextBox(); - assertEquals(2, slide.getShapes().size()); - assertSame(shape1, slide.getShapes().get(0)); - assertSame(shape2, slide.getShapes().get(1)); - - XSLFConnectorShape shape3 = slide.createConnector(); - assertEquals(3, slide.getShapes().size()); - assertSame(shape1, slide.getShapes().get(0)); - assertSame(shape2, slide.getShapes().get(1)); - assertSame(shape3, slide.getShapes().get(2)); - - XSLFGroupShape shape4 = slide.createGroup(); - assertEquals(4, slide.getShapes().size()); - assertSame(shape1, slide.getShapes().get(0)); - assertSame(shape2, slide.getShapes().get(1)); - assertSame(shape3, slide.getShapes().get(2)); - assertSame(shape4, slide.getShapes().get(3)); - - XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt); - slide = ppt2.getSlides().get(0); - List shapes = slide.getShapes(); - assertEquals(4, shapes.size()); - - assertTrue(shapes.get(0) instanceof XSLFAutoShape); - assertTrue(shapes.get(1) instanceof XSLFTextBox); - assertTrue(shapes.get(2) instanceof XSLFConnectorShape); - assertTrue(shapes.get(3) instanceof XSLFGroupShape); - - ppt.close(); - ppt2.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.List; + +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; + +/** + * test common properties for sheets (slides, masters, layouts, etc.) + * + * @author Yegor Kozlov + */ +public class TestXSLFSheet { + + @Test + public void testCreateShapes() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + assertTrue(slide.getShapes().isEmpty()); + + XSLFSimpleShape shape1 = slide.createAutoShape(); + assertEquals(1, slide.getShapes().size()); + assertSame(shape1, slide.getShapes().get(0)); + + XSLFTextBox shape2 = slide.createTextBox(); + assertEquals(2, slide.getShapes().size()); + assertSame(shape1, slide.getShapes().get(0)); + assertSame(shape2, slide.getShapes().get(1)); + + XSLFConnectorShape shape3 = slide.createConnector(); + assertEquals(3, slide.getShapes().size()); + assertSame(shape1, slide.getShapes().get(0)); + assertSame(shape2, slide.getShapes().get(1)); + assertSame(shape3, slide.getShapes().get(2)); + + XSLFGroupShape shape4 = slide.createGroup(); + assertEquals(4, slide.getShapes().size()); + assertSame(shape1, slide.getShapes().get(0)); + assertSame(shape2, slide.getShapes().get(1)); + assertSame(shape3, slide.getShapes().get(2)); + assertSame(shape4, slide.getShapes().get(3)); + + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt); + slide = ppt2.getSlides().get(0); + List shapes = slide.getShapes(); + assertEquals(4, shapes.size()); + + assertTrue(shapes.get(0) instanceof XSLFAutoShape); + assertTrue(shapes.get(1) instanceof XSLFTextBox); + assertTrue(shapes.get(2) instanceof XSLFConnectorShape); + assertTrue(shapes.get(3) instanceof XSLFGroupShape); + + ppt.close(); + ppt2.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java index c000da8a49..4531ddd85b 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java @@ -1,386 +1,386 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.List; - -import org.apache.poi.sl.draw.DrawFactory; -import org.apache.poi.sl.draw.geom.TestPresetGeometries; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; -import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; -import org.apache.poi.util.Units; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.apache.xmlbeans.XmlObject; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem; -import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleList; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; -import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; -import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; - -public class TestXSLFSimpleShape { - - @Test - public void testLineStyles() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFSimpleShape shape = slide.createAutoShape(); - assertEquals(1, slide.getShapes().size()); - // line properties are not set by default - assertFalse(getSpPr(shape).isSetLn()); - - assertEquals(0., shape.getLineWidth(), 0); - assertEquals(null, shape.getLineColor()); - assertEquals(null, shape.getLineDash()); - assertEquals(null, shape.getLineCap()); - - shape.setLineWidth(0); - shape.setLineColor(null); - shape.setLineDash(null); - shape.setLineCap(null); - - assertTrue(getSpPr(shape).isSetLn()); - assertTrue(getSpPr(shape).getLn().isSetNoFill()); - - // line width - shape.setLineWidth(1.0); - assertEquals(1.0, shape.getLineWidth(), 0); - assertEquals(Units.EMU_PER_POINT, getSpPr(shape).getLn().getW()); - shape.setLineWidth(5.5); - assertEquals(5.5, shape.getLineWidth(), 0); - assertEquals(Units.toEMU(5.5), getSpPr(shape).getLn().getW()); - shape.setLineWidth(0.0); - // setting line width to zero unsets the W attribute - assertFalse(getSpPr(shape).getLn().isSetW()); - - // line cap - shape.setLineCap(LineCap.FLAT); - assertEquals(LineCap.FLAT, shape.getLineCap()); - assertEquals(STLineCap.FLAT, getSpPr(shape).getLn().getCap()); - shape.setLineCap(LineCap.SQUARE); - assertEquals(LineCap.SQUARE, shape.getLineCap()); - assertEquals(STLineCap.SQ, getSpPr(shape).getLn().getCap()); - shape.setLineCap(LineCap.ROUND); - assertEquals(LineCap.ROUND, shape.getLineCap()); - assertEquals(STLineCap.RND, getSpPr(shape).getLn().getCap()); - shape.setLineCap(null); - // setting cap to null unsets the Cap attribute - assertFalse(getSpPr(shape).getLn().isSetCap()); - - // line dash - shape.setLineDash(LineDash.SOLID); - assertEquals(LineDash.SOLID, shape.getLineDash()); - assertEquals(STPresetLineDashVal.SOLID, getSpPr(shape).getLn().getPrstDash().getVal()); - shape.setLineDash(LineDash.DASH_DOT); - assertEquals(LineDash.DASH_DOT, shape.getLineDash()); - assertEquals(STPresetLineDashVal.DASH_DOT, getSpPr(shape).getLn().getPrstDash().getVal()); - shape.setLineDash(LineDash.LG_DASH_DOT); - assertEquals(LineDash.LG_DASH_DOT, shape.getLineDash()); - assertEquals(STPresetLineDashVal.LG_DASH_DOT, getSpPr(shape).getLn().getPrstDash().getVal()); - shape.setLineDash(null); - // setting dash width to null unsets the Dash element - assertFalse(getSpPr(shape).getLn().isSetPrstDash()); - - // line color - assertFalse(getSpPr(shape).getLn().isSetSolidFill()); - shape.setLineColor(Color.RED); - assertEquals(Color.RED, shape.getLineColor()); - assertTrue(getSpPr(shape).getLn().isSetSolidFill()); - shape.setLineColor(Color.BLUE); - assertEquals(Color.BLUE, shape.getLineColor()); - assertTrue(getSpPr(shape).getLn().isSetSolidFill()); - shape.setLineColor(null); - assertEquals(null, shape.getLineColor()); - // setting dash width to null unsets the SolidFill element - assertFalse(getSpPr(shape).getLn().isSetSolidFill()); - - XSLFSimpleShape ln2 = slide.createAutoShape(); - ln2.setLineDash(LineDash.DOT); - assertEquals(LineDash.DOT, ln2.getLineDash()); - ln2.setLineWidth(0.); - assertEquals(0., ln2.getLineWidth(), 0); - - XSLFSimpleShape ln3 = slide.createAutoShape(); - ln3.setLineWidth(1.); - assertEquals(1., ln3.getLineWidth(), 0); - ln3.setLineDash(null); - assertEquals(null, ln3.getLineDash()); - ln3.setLineCap(null); - assertEquals(null, ln3.getLineDash()); - - ppt.close(); - } - - @Test - public void testFill() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFAutoShape shape = slide.createAutoShape(); - // line properties are not set by default - assertFalse(getSpPr(shape).isSetSolidFill()); - - assertNull(shape.getFillColor()); - shape.setFillColor(null); - assertNull(shape.getFillColor()); - assertFalse(getSpPr(shape).isSetSolidFill()); - - shape.setFillColor(Color.RED); - assertEquals(Color.RED, shape.getFillColor()); - shape.setFillColor(Color.DARK_GRAY); - assertEquals(Color.DARK_GRAY, shape.getFillColor()); - assertTrue(getSpPr(shape).isSetSolidFill()); - - shape.setFillColor(null); - assertNull(shape.getFillColor()); - assertFalse(getSpPr(shape).isSetSolidFill()); - ppt.close(); - } - - @Test - public void testDefaultProperties() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); - - XSLFSlide slide6 = ppt.getSlides().get(5); - List shapes = slide6.getShapes(); - for(XSLFShape xs : shapes){ - XSLFSimpleShape s = (XSLFSimpleShape)xs; - // all shapes have a theme color="accent1" - assertEquals("accent1", s.getSpStyle().getFillRef().getSchemeClr().getVal().toString()); - assertEquals(2.0, s.getLineWidth(), 0); - assertEquals(LineCap.FLAT, s.getLineCap()); - assertEquals(new Color(79,129,189), s.getLineColor()); - } - - XSLFSimpleShape s0 = (XSLFSimpleShape) shapes.get(0); - // fill is not set - assertNull(getSpPr(s0).getSolidFill()); - //assertEquals(slide6.getTheme().getColor("accent1").getColor(), s0.getFillColor()); - assertEquals(new Color(79, 129, 189), s0.getFillColor()); - - // lighter 80% - XSLFSimpleShape s1 = (XSLFSimpleShape)shapes.get(1); - CTSchemeColor ref1 = getSpPr(s1).getSolidFill().getSchemeClr(); - assertEquals(1, ref1.sizeOfLumModArray()); - assertEquals(1, ref1.sizeOfLumOffArray()); - assertEquals(20000, ref1.getLumModArray(0).getVal()); - assertEquals(80000, ref1.getLumOffArray(0).getVal()); - assertEquals("accent1", ref1.getVal().toString()); - assertEquals(new Color(220, 230, 242), s1.getFillColor()); - - // lighter 60% - XSLFSimpleShape s2 = (XSLFSimpleShape)shapes.get(2); - CTSchemeColor ref2 = getSpPr(s2).getSolidFill().getSchemeClr(); - assertEquals(1, ref2.sizeOfLumModArray()); - assertEquals(1, ref2.sizeOfLumOffArray()); - assertEquals(40000, ref2.getLumModArray(0).getVal()); - assertEquals(60000, ref2.getLumOffArray(0).getVal()); - assertEquals("accent1", ref2.getVal().toString()); - assertEquals(new Color(185, 205, 229), s2.getFillColor()); - - // lighter 40% - XSLFSimpleShape s3 = (XSLFSimpleShape)shapes.get(3); - CTSchemeColor ref3 = getSpPr(s3).getSolidFill().getSchemeClr(); - assertEquals(1, ref3.sizeOfLumModArray()); - assertEquals(1, ref3.sizeOfLumOffArray()); - assertEquals(60000, ref3.getLumModArray(0).getVal()); - assertEquals(40000, ref3.getLumOffArray(0).getVal()); - assertEquals("accent1", ref3.getVal().toString()); - assertEquals(new Color(149, 179, 215), s3.getFillColor()); - - // darker 25% - XSLFSimpleShape s4 = (XSLFSimpleShape)shapes.get(4); - CTSchemeColor ref4 = getSpPr(s4).getSolidFill().getSchemeClr(); - assertEquals(1, ref4.sizeOfLumModArray()); - assertEquals(0, ref4.sizeOfLumOffArray()); - assertEquals(75000, ref4.getLumModArray(0).getVal()); - assertEquals("accent1", ref3.getVal().toString()); - assertEquals(new Color(55, 96, 146), s4.getFillColor()); - - XSLFSimpleShape s5 = (XSLFSimpleShape)shapes.get(5); - CTSchemeColor ref5 = getSpPr(s5).getSolidFill().getSchemeClr(); - assertEquals(1, ref5.sizeOfLumModArray()); - assertEquals(0, ref5.sizeOfLumOffArray()); - assertEquals(50000, ref5.getLumModArray(0).getVal()); - assertEquals("accent1", ref5.getVal().toString()); - assertEquals(new Color(37, 64, 97), s5.getFillColor()); - - ppt.close(); - } - - @Test - public void testAnchor() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); - List slide = ppt.getSlides(); - - XSLFSlide slide2 = slide.get(1); - XSLFSlideLayout layout2 = slide2.getSlideLayout(); - List shapes2 = slide2.getShapes(); - XSLFTextShape sh1 = (XSLFTextShape)shapes2.get(0); - assertEquals(Placeholder.CENTERED_TITLE, sh1.getTextType()); - assertEquals("PPTX Title", sh1.getText()); - assertFalse(getSpPr(sh1).isSetXfrm()); // xfrm is not set, the query is delegated to the slide layout - assertEquals(sh1.getAnchor(), layout2.getTextShapeByType(Placeholder.CENTERED_TITLE).getAnchor()); - - XSLFTextShape sh2 = (XSLFTextShape)shapes2.get(1); - assertEquals("Subtitle\nAnd second line", sh2.getText()); - assertEquals(Placeholder.SUBTITLE, sh2.getTextType()); - assertFalse(getSpPr(sh2).isSetXfrm()); // xfrm is not set, the query is delegated to the slide layout - assertEquals(sh2.getAnchor(), layout2.getTextShapeByType(Placeholder.SUBTITLE).getAnchor()); - - XSLFSlide slide5 = slide.get(4); - XSLFSlideLayout layout5 = slide5.getSlideLayout(); - XSLFTextShape shTitle = slide5.getTextShapeByType(Placeholder.TITLE); - assertEquals("Hyperlinks", shTitle.getText()); - // xfrm is not set, the query is delegated to the slide layout - assertFalse(getSpPr(shTitle).isSetXfrm()); - // xfrm is not set, the query is delegated to the slide master - assertFalse(getSpPr(layout5.getTextShapeByType(Placeholder.TITLE)).isSetXfrm()); - assertTrue(getSpPr(layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE)).isSetXfrm()); - assertEquals(shTitle.getAnchor(), layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getAnchor()); - - ppt.close(); - } - - @SuppressWarnings("unused") - @Test - public void testShadowEffects() throws IOException{ - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - CTStyleMatrix styleMatrix = slide.getTheme().getXmlObject().getThemeElements().getFmtScheme(); - CTEffectStyleList lst = styleMatrix.getEffectStyleLst(); - assertNotNull(lst); - for(CTEffectStyleItem ef : lst.getEffectStyleArray()){ - CTOuterShadowEffect obj = ef.getEffectLst().getOuterShdw(); - } - ppt.close(); - } - - @Test - public void testValidGeometry() throws Exception { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFSimpleShape shape = slide.createAutoShape(); - CTShapeProperties spPr = getSpPr(shape); - - CTPresetGeometry2D prstGeom = CTPresetGeometry2D.Factory.newInstance(); - prstGeom.setPrst(STShapeType.Enum.forInt(1)); - - assertNotNull(prstGeom.getPrst()); - assertNotNull(prstGeom.getPrst().toString()); - assertNotNull(spPr.getPrstGeom()); - spPr.setPrstGeom(prstGeom); - assertNotNull(spPr.getPrstGeom().getPrst()); - assertNotNull(spPr.getPrstGeom().getPrst().toString()); - - assertNotNull(shape.getGeometry()); - - ppt.close(); - } - - - @Test - public void testInvalidGeometry() throws Exception { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFSimpleShape shape = slide.createAutoShape(); - CTShapeProperties spPr = getSpPr(shape); - - CTPresetGeometry2D prstGeom = CTPresetGeometry2D.Factory.newInstance(); - prstGeom.setPrst(STShapeType.Enum.forInt(1)); - - assertNotNull(prstGeom.getPrst()); - assertNotNull(prstGeom.getPrst().toString()); - assertNotNull(spPr.getPrstGeom()); - spPr.setPrstGeom(prstGeom); - assertNotNull(spPr.getPrstGeom().getPrst()); - assertNotNull(spPr.getPrstGeom().getPrst().toString()); - - try { - // cause the geometries to be not found - TestPresetGeometries.clearPreset(); - try { - shape.getGeometry(); - fail("Should fail without the geometry"); - } catch (IllegalStateException e) { - assertTrue(e.getMessage(), e.getMessage().contains("line")); - } - } finally { - // reset to not affect other tests - TestPresetGeometries.resetPreset(); - } - - ppt.close(); - } - - @SuppressWarnings("Duplicates") - @Test - public void testArrayStoreException() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("aascu.org_workarea_downloadasset.aspx_id=5864.pptx"); - Dimension pgsize = ppt.getPageSize(); - - for (Slide s : ppt.getSlides()) { - //System.out.println("Slide: " + s); - - BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = img.createGraphics(); - DrawFactory.getInstance(graphics).fixFonts(graphics); - - // default rendering options - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - - // draw stuff - s.draw(graphics); - - graphics.dispose(); - img.flush(); - } - ppt.close(); - } - - static CTShapeProperties getSpPr(XSLFShape shape) { - XmlObject xo = shape.getShapeProperties(); - assertTrue(xo instanceof CTShapeProperties); - return (CTShapeProperties)xo; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; + +import org.apache.poi.sl.draw.DrawFactory; +import org.apache.poi.sl.draw.geom.TestPresetGeometries; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; +import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; +import org.apache.poi.util.Units; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.apache.xmlbeans.XmlObject; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem; +import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleList; +import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; + +public class TestXSLFSimpleShape { + + @Test + public void testLineStyles() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFSimpleShape shape = slide.createAutoShape(); + assertEquals(1, slide.getShapes().size()); + // line properties are not set by default + assertFalse(getSpPr(shape).isSetLn()); + + assertEquals(0., shape.getLineWidth(), 0); + assertEquals(null, shape.getLineColor()); + assertEquals(null, shape.getLineDash()); + assertEquals(null, shape.getLineCap()); + + shape.setLineWidth(0); + shape.setLineColor(null); + shape.setLineDash(null); + shape.setLineCap(null); + + assertTrue(getSpPr(shape).isSetLn()); + assertTrue(getSpPr(shape).getLn().isSetNoFill()); + + // line width + shape.setLineWidth(1.0); + assertEquals(1.0, shape.getLineWidth(), 0); + assertEquals(Units.EMU_PER_POINT, getSpPr(shape).getLn().getW()); + shape.setLineWidth(5.5); + assertEquals(5.5, shape.getLineWidth(), 0); + assertEquals(Units.toEMU(5.5), getSpPr(shape).getLn().getW()); + shape.setLineWidth(0.0); + // setting line width to zero unsets the W attribute + assertFalse(getSpPr(shape).getLn().isSetW()); + + // line cap + shape.setLineCap(LineCap.FLAT); + assertEquals(LineCap.FLAT, shape.getLineCap()); + assertEquals(STLineCap.FLAT, getSpPr(shape).getLn().getCap()); + shape.setLineCap(LineCap.SQUARE); + assertEquals(LineCap.SQUARE, shape.getLineCap()); + assertEquals(STLineCap.SQ, getSpPr(shape).getLn().getCap()); + shape.setLineCap(LineCap.ROUND); + assertEquals(LineCap.ROUND, shape.getLineCap()); + assertEquals(STLineCap.RND, getSpPr(shape).getLn().getCap()); + shape.setLineCap(null); + // setting cap to null unsets the Cap attribute + assertFalse(getSpPr(shape).getLn().isSetCap()); + + // line dash + shape.setLineDash(LineDash.SOLID); + assertEquals(LineDash.SOLID, shape.getLineDash()); + assertEquals(STPresetLineDashVal.SOLID, getSpPr(shape).getLn().getPrstDash().getVal()); + shape.setLineDash(LineDash.DASH_DOT); + assertEquals(LineDash.DASH_DOT, shape.getLineDash()); + assertEquals(STPresetLineDashVal.DASH_DOT, getSpPr(shape).getLn().getPrstDash().getVal()); + shape.setLineDash(LineDash.LG_DASH_DOT); + assertEquals(LineDash.LG_DASH_DOT, shape.getLineDash()); + assertEquals(STPresetLineDashVal.LG_DASH_DOT, getSpPr(shape).getLn().getPrstDash().getVal()); + shape.setLineDash(null); + // setting dash width to null unsets the Dash element + assertFalse(getSpPr(shape).getLn().isSetPrstDash()); + + // line color + assertFalse(getSpPr(shape).getLn().isSetSolidFill()); + shape.setLineColor(Color.RED); + assertEquals(Color.RED, shape.getLineColor()); + assertTrue(getSpPr(shape).getLn().isSetSolidFill()); + shape.setLineColor(Color.BLUE); + assertEquals(Color.BLUE, shape.getLineColor()); + assertTrue(getSpPr(shape).getLn().isSetSolidFill()); + shape.setLineColor(null); + assertEquals(null, shape.getLineColor()); + // setting dash width to null unsets the SolidFill element + assertFalse(getSpPr(shape).getLn().isSetSolidFill()); + + XSLFSimpleShape ln2 = slide.createAutoShape(); + ln2.setLineDash(LineDash.DOT); + assertEquals(LineDash.DOT, ln2.getLineDash()); + ln2.setLineWidth(0.); + assertEquals(0., ln2.getLineWidth(), 0); + + XSLFSimpleShape ln3 = slide.createAutoShape(); + ln3.setLineWidth(1.); + assertEquals(1., ln3.getLineWidth(), 0); + ln3.setLineDash(null); + assertEquals(null, ln3.getLineDash()); + ln3.setLineCap(null); + assertEquals(null, ln3.getLineDash()); + + ppt.close(); + } + + @Test + public void testFill() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFAutoShape shape = slide.createAutoShape(); + // line properties are not set by default + assertFalse(getSpPr(shape).isSetSolidFill()); + + assertNull(shape.getFillColor()); + shape.setFillColor(null); + assertNull(shape.getFillColor()); + assertFalse(getSpPr(shape).isSetSolidFill()); + + shape.setFillColor(Color.RED); + assertEquals(Color.RED, shape.getFillColor()); + shape.setFillColor(Color.DARK_GRAY); + assertEquals(Color.DARK_GRAY, shape.getFillColor()); + assertTrue(getSpPr(shape).isSetSolidFill()); + + shape.setFillColor(null); + assertNull(shape.getFillColor()); + assertFalse(getSpPr(shape).isSetSolidFill()); + ppt.close(); + } + + @Test + public void testDefaultProperties() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + + XSLFSlide slide6 = ppt.getSlides().get(5); + List shapes = slide6.getShapes(); + for(XSLFShape xs : shapes){ + XSLFSimpleShape s = (XSLFSimpleShape)xs; + // all shapes have a theme color="accent1" + assertEquals("accent1", s.getSpStyle().getFillRef().getSchemeClr().getVal().toString()); + assertEquals(2.0, s.getLineWidth(), 0); + assertEquals(LineCap.FLAT, s.getLineCap()); + assertEquals(new Color(79,129,189), s.getLineColor()); + } + + XSLFSimpleShape s0 = (XSLFSimpleShape) shapes.get(0); + // fill is not set + assertNull(getSpPr(s0).getSolidFill()); + //assertEquals(slide6.getTheme().getColor("accent1").getColor(), s0.getFillColor()); + assertEquals(new Color(79, 129, 189), s0.getFillColor()); + + // lighter 80% + XSLFSimpleShape s1 = (XSLFSimpleShape)shapes.get(1); + CTSchemeColor ref1 = getSpPr(s1).getSolidFill().getSchemeClr(); + assertEquals(1, ref1.sizeOfLumModArray()); + assertEquals(1, ref1.sizeOfLumOffArray()); + assertEquals(20000, ref1.getLumModArray(0).getVal()); + assertEquals(80000, ref1.getLumOffArray(0).getVal()); + assertEquals("accent1", ref1.getVal().toString()); + assertEquals(new Color(220, 230, 242), s1.getFillColor()); + + // lighter 60% + XSLFSimpleShape s2 = (XSLFSimpleShape)shapes.get(2); + CTSchemeColor ref2 = getSpPr(s2).getSolidFill().getSchemeClr(); + assertEquals(1, ref2.sizeOfLumModArray()); + assertEquals(1, ref2.sizeOfLumOffArray()); + assertEquals(40000, ref2.getLumModArray(0).getVal()); + assertEquals(60000, ref2.getLumOffArray(0).getVal()); + assertEquals("accent1", ref2.getVal().toString()); + assertEquals(new Color(185, 205, 229), s2.getFillColor()); + + // lighter 40% + XSLFSimpleShape s3 = (XSLFSimpleShape)shapes.get(3); + CTSchemeColor ref3 = getSpPr(s3).getSolidFill().getSchemeClr(); + assertEquals(1, ref3.sizeOfLumModArray()); + assertEquals(1, ref3.sizeOfLumOffArray()); + assertEquals(60000, ref3.getLumModArray(0).getVal()); + assertEquals(40000, ref3.getLumOffArray(0).getVal()); + assertEquals("accent1", ref3.getVal().toString()); + assertEquals(new Color(149, 179, 215), s3.getFillColor()); + + // darker 25% + XSLFSimpleShape s4 = (XSLFSimpleShape)shapes.get(4); + CTSchemeColor ref4 = getSpPr(s4).getSolidFill().getSchemeClr(); + assertEquals(1, ref4.sizeOfLumModArray()); + assertEquals(0, ref4.sizeOfLumOffArray()); + assertEquals(75000, ref4.getLumModArray(0).getVal()); + assertEquals("accent1", ref3.getVal().toString()); + assertEquals(new Color(55, 96, 146), s4.getFillColor()); + + XSLFSimpleShape s5 = (XSLFSimpleShape)shapes.get(5); + CTSchemeColor ref5 = getSpPr(s5).getSolidFill().getSchemeClr(); + assertEquals(1, ref5.sizeOfLumModArray()); + assertEquals(0, ref5.sizeOfLumOffArray()); + assertEquals(50000, ref5.getLumModArray(0).getVal()); + assertEquals("accent1", ref5.getVal().toString()); + assertEquals(new Color(37, 64, 97), s5.getFillColor()); + + ppt.close(); + } + + @Test + public void testAnchor() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + List slide = ppt.getSlides(); + + XSLFSlide slide2 = slide.get(1); + XSLFSlideLayout layout2 = slide2.getSlideLayout(); + List shapes2 = slide2.getShapes(); + XSLFTextShape sh1 = (XSLFTextShape)shapes2.get(0); + assertEquals(Placeholder.CENTERED_TITLE, sh1.getTextType()); + assertEquals("PPTX Title", sh1.getText()); + assertFalse(getSpPr(sh1).isSetXfrm()); // xfrm is not set, the query is delegated to the slide layout + assertEquals(sh1.getAnchor(), layout2.getTextShapeByType(Placeholder.CENTERED_TITLE).getAnchor()); + + XSLFTextShape sh2 = (XSLFTextShape)shapes2.get(1); + assertEquals("Subtitle\nAnd second line", sh2.getText()); + assertEquals(Placeholder.SUBTITLE, sh2.getTextType()); + assertFalse(getSpPr(sh2).isSetXfrm()); // xfrm is not set, the query is delegated to the slide layout + assertEquals(sh2.getAnchor(), layout2.getTextShapeByType(Placeholder.SUBTITLE).getAnchor()); + + XSLFSlide slide5 = slide.get(4); + XSLFSlideLayout layout5 = slide5.getSlideLayout(); + XSLFTextShape shTitle = slide5.getTextShapeByType(Placeholder.TITLE); + assertEquals("Hyperlinks", shTitle.getText()); + // xfrm is not set, the query is delegated to the slide layout + assertFalse(getSpPr(shTitle).isSetXfrm()); + // xfrm is not set, the query is delegated to the slide master + assertFalse(getSpPr(layout5.getTextShapeByType(Placeholder.TITLE)).isSetXfrm()); + assertTrue(getSpPr(layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE)).isSetXfrm()); + assertEquals(shTitle.getAnchor(), layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getAnchor()); + + ppt.close(); + } + + @SuppressWarnings("unused") + @Test + public void testShadowEffects() throws IOException{ + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + CTStyleMatrix styleMatrix = slide.getTheme().getXmlObject().getThemeElements().getFmtScheme(); + CTEffectStyleList lst = styleMatrix.getEffectStyleLst(); + assertNotNull(lst); + for(CTEffectStyleItem ef : lst.getEffectStyleArray()){ + CTOuterShadowEffect obj = ef.getEffectLst().getOuterShdw(); + } + ppt.close(); + } + + @Test + public void testValidGeometry() throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFSimpleShape shape = slide.createAutoShape(); + CTShapeProperties spPr = getSpPr(shape); + + CTPresetGeometry2D prstGeom = CTPresetGeometry2D.Factory.newInstance(); + prstGeom.setPrst(STShapeType.Enum.forInt(1)); + + assertNotNull(prstGeom.getPrst()); + assertNotNull(prstGeom.getPrst().toString()); + assertNotNull(spPr.getPrstGeom()); + spPr.setPrstGeom(prstGeom); + assertNotNull(spPr.getPrstGeom().getPrst()); + assertNotNull(spPr.getPrstGeom().getPrst().toString()); + + assertNotNull(shape.getGeometry()); + + ppt.close(); + } + + + @Test + public void testInvalidGeometry() throws Exception { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFSimpleShape shape = slide.createAutoShape(); + CTShapeProperties spPr = getSpPr(shape); + + CTPresetGeometry2D prstGeom = CTPresetGeometry2D.Factory.newInstance(); + prstGeom.setPrst(STShapeType.Enum.forInt(1)); + + assertNotNull(prstGeom.getPrst()); + assertNotNull(prstGeom.getPrst().toString()); + assertNotNull(spPr.getPrstGeom()); + spPr.setPrstGeom(prstGeom); + assertNotNull(spPr.getPrstGeom().getPrst()); + assertNotNull(spPr.getPrstGeom().getPrst().toString()); + + try { + // cause the geometries to be not found + TestPresetGeometries.clearPreset(); + try { + shape.getGeometry(); + fail("Should fail without the geometry"); + } catch (IllegalStateException e) { + assertTrue(e.getMessage(), e.getMessage().contains("line")); + } + } finally { + // reset to not affect other tests + TestPresetGeometries.resetPreset(); + } + + ppt.close(); + } + + @SuppressWarnings("Duplicates") + @Test + public void testArrayStoreException() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("aascu.org_workarea_downloadasset.aspx_id=5864.pptx"); + Dimension pgsize = ppt.getPageSize(); + + for (Slide s : ppt.getSlides()) { + //System.out.println("Slide: " + s); + + BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = img.createGraphics(); + DrawFactory.getInstance(graphics).fixFonts(graphics); + + // default rendering options + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + // draw stuff + s.draw(graphics); + + graphics.dispose(); + img.flush(); + } + ppt.close(); + } + + static CTShapeProperties getSpPr(XSLFShape shape) { + XmlObject xo = shape.getShapeProperties(); + assertTrue(xo instanceof CTShapeProperties); + return (CTShapeProperties)xo; + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java index fad3f82a00..fbf4589765 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java @@ -1,197 +1,197 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.apache.poi.sl.TestCommonSL.sameColor; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.awt.Color; -import java.io.IOException; -import java.util.List; - -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; - -/** - * @author Yegor Kozlov - */ -public class TestXSLFSlide { - - @Test - public void testReadShapes() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); - List slides = ppt.getSlides(); - - XSLFSlide slide1 = slides.get(0); - List shapes1 = slide1.getShapes(); - assertEquals(7, shapes1.size()); - assertEquals("TextBox 3", shapes1.get(0).getShapeName()); - assertTrue(shapes1.get(0) instanceof XSLFTextBox); - XSLFAutoShape sh0 = (XSLFAutoShape)shapes1.get(0); - assertEquals("Learning PPTX", sh0.getText()); - - - assertEquals("Straight Connector 5", shapes1.get(1).getShapeName()); - assertTrue(shapes1.get(1) instanceof XSLFConnectorShape); - - assertEquals("Freeform 6", shapes1.get(2).getShapeName()); - assertTrue(shapes1.get(2) instanceof XSLFFreeformShape); - XSLFAutoShape sh2 = (XSLFAutoShape)shapes1.get(2); - assertEquals("Cloud", sh2.getText()); - - assertEquals("Picture 1", shapes1.get(3).getShapeName()); - assertTrue(shapes1.get(3) instanceof XSLFPictureShape); - - assertEquals("Table 2", shapes1.get(4).getShapeName()); - assertTrue(shapes1.get(4) instanceof XSLFGraphicFrame); - - assertEquals("Straight Arrow Connector 7", shapes1.get(5).getShapeName()); - assertTrue(shapes1.get(5) instanceof XSLFConnectorShape); - - assertEquals("Elbow Connector 9", shapes1.get(6).getShapeName()); - assertTrue(shapes1.get(6) instanceof XSLFConnectorShape); - - // titles on slide2 - XSLFSlide slide2 = slides.get(1); - List shapes2 = slide2.getShapes(); - assertEquals(2, shapes2.size()); - assertTrue(shapes2.get(0) instanceof XSLFAutoShape); - assertEquals("PPTX Title", ((XSLFAutoShape)shapes2.get(0)).getText()); - assertTrue(shapes2.get(1) instanceof XSLFAutoShape); - assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape)shapes2.get(1)).getText()); - - // group shape on slide3 - XSLFSlide slide3 = slides.get(2); - List shapes3 = slide3.getShapes(); - assertEquals(1, shapes3.size()); - assertTrue(shapes3.get(0) instanceof XSLFGroupShape); - List groupShapes = ((XSLFGroupShape)shapes3.get(0)).getShapes(); - assertEquals(3, groupShapes.size()); - assertTrue(groupShapes.get(0) instanceof XSLFAutoShape); - assertEquals("Rectangle 1", groupShapes.get(0).getShapeName()); - - assertTrue(groupShapes.get(1) instanceof XSLFAutoShape); - assertEquals("Oval 2", groupShapes.get(1).getShapeName()); - - assertTrue(groupShapes.get(2) instanceof XSLFAutoShape); - assertEquals("Right Arrow 3", groupShapes.get(2).getShapeName()); - - XSLFSlide slide4 = slides.get(3); - List shapes4 = slide4.getShapes(); - assertEquals(1, shapes4.size()); - assertTrue(shapes4.get(0) instanceof XSLFTable); - XSLFTable tbl = (XSLFTable)shapes4.get(0); - assertEquals(3, tbl.getNumberOfColumns()); - assertEquals(6, tbl.getNumberOfRows()); - - ppt.close(); - } - - @Test - public void testCreateSlide() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - assertEquals(0, ppt.getSlides().size()); - - XSLFSlide slide = ppt.createSlide(); - assertTrue(slide.getFollowMasterGraphics()); - slide.setFollowMasterGraphics(false); - assertFalse(slide.getFollowMasterGraphics()); - slide.setFollowMasterGraphics(true); - assertTrue(slide.getFollowMasterGraphics()); - - ppt.close(); - } - - @Test - public void testImportContent() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - - XMLSlideShow src = XSLFTestDataSamples.openSampleDocument("themes.pptx"); - - // create a blank slide and import content from the 4th slide of themes.pptx - XSLFSlide slide1 = ppt.createSlide().importContent(src.getSlides().get(3)); - List shapes1 = slide1.getShapes(); - assertEquals(2, shapes1.size()); - - XSLFTextShape sh1 = (XSLFTextShape)shapes1.get(0); - assertEquals("Austin Theme", sh1.getText()); - XSLFTextRun r1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals("Century Gothic", r1.getFontFamily()); - assertEquals(40.0, r1.getFontSize(), 0); - assertTrue(r1.isBold()); - assertTrue(r1.isItalic()); - assertTrue(sameColor(new Color(148, 198, 0), r1.getFontColor())); - assertNull(sh1.getFillColor()); - assertNull(sh1.getLineColor()); - - XSLFTextShape sh2 = (XSLFTextShape)shapes1.get(1); - assertEquals( - "Text in a autoshape is white\n" + - "Fill: RGB(148, 198,0)", sh2.getText()); - XSLFTextRun r2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals("Century Gothic", r2.getFontFamily()); - assertEquals(18.0, r2.getFontSize(), 0); - assertFalse(r2.isBold()); - assertFalse(r2.isItalic()); - assertTrue(sameColor(Color.white, r2.getFontColor())); - assertEquals(new Color(148, 198, 0), sh2.getFillColor()); - assertEquals(new Color(148, 198, 0), sh2.getLineColor()); // slightly different from PowerPoint! - - // the 5th slide has a picture and a texture fill - XSLFSlide slide2 = ppt.createSlide().importContent(src.getSlides().get(4)); - List shapes2 = slide2.getShapes(); - assertEquals(2, shapes2.size()); - - XSLFTextShape sh3 = (XSLFTextShape)shapes2.get(0); - assertEquals("This slide overrides master background with a texture fill", sh3.getText()); - XSLFTextRun r3 = sh3.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals("Century Gothic", r3.getFontFamily()); - //assertEquals(32.4.0, r3.getFontSize()); - assertTrue(r3.isBold()); - assertTrue(r3.isItalic()); - assertTrue(sameColor(new Color(148, 198, 0), r3.getFontColor())); - assertNull(sh3.getFillColor()); - assertNull(sh3.getLineColor()); - - XSLFPictureShape sh4 = (XSLFPictureShape)shapes2.get(1); - XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides().get(4).getShapes().get(1); - assertArrayEquals(sh4.getPictureData().getData(), srcPic.getPictureData().getData()); - - ppt.close(); - } - - @Test - public void testMergeSlides() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - String[] pptx = {"shapes.pptx", "themes.pptx", "layouts.pptx", "backgrounds.pptx"}; - - for(String arg : pptx){ - XMLSlideShow src = XSLFTestDataSamples.openSampleDocument(arg); - - for(XSLFSlide srcSlide : src.getSlides()){ - ppt.createSlide().importContent(srcSlide); - } - } - assertEquals(30, ppt.getSlides().size()); - - ppt.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.apache.poi.sl.TestCommonSL.sameColor; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.awt.Color; +import java.io.IOException; +import java.util.List; + +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFSlide { + + @Test + public void testReadShapes() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + List slides = ppt.getSlides(); + + XSLFSlide slide1 = slides.get(0); + List shapes1 = slide1.getShapes(); + assertEquals(7, shapes1.size()); + assertEquals("TextBox 3", shapes1.get(0).getShapeName()); + assertTrue(shapes1.get(0) instanceof XSLFTextBox); + XSLFAutoShape sh0 = (XSLFAutoShape)shapes1.get(0); + assertEquals("Learning PPTX", sh0.getText()); + + + assertEquals("Straight Connector 5", shapes1.get(1).getShapeName()); + assertTrue(shapes1.get(1) instanceof XSLFConnectorShape); + + assertEquals("Freeform 6", shapes1.get(2).getShapeName()); + assertTrue(shapes1.get(2) instanceof XSLFFreeformShape); + XSLFAutoShape sh2 = (XSLFAutoShape)shapes1.get(2); + assertEquals("Cloud", sh2.getText()); + + assertEquals("Picture 1", shapes1.get(3).getShapeName()); + assertTrue(shapes1.get(3) instanceof XSLFPictureShape); + + assertEquals("Table 2", shapes1.get(4).getShapeName()); + assertTrue(shapes1.get(4) instanceof XSLFGraphicFrame); + + assertEquals("Straight Arrow Connector 7", shapes1.get(5).getShapeName()); + assertTrue(shapes1.get(5) instanceof XSLFConnectorShape); + + assertEquals("Elbow Connector 9", shapes1.get(6).getShapeName()); + assertTrue(shapes1.get(6) instanceof XSLFConnectorShape); + + // titles on slide2 + XSLFSlide slide2 = slides.get(1); + List shapes2 = slide2.getShapes(); + assertEquals(2, shapes2.size()); + assertTrue(shapes2.get(0) instanceof XSLFAutoShape); + assertEquals("PPTX Title", ((XSLFAutoShape)shapes2.get(0)).getText()); + assertTrue(shapes2.get(1) instanceof XSLFAutoShape); + assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape)shapes2.get(1)).getText()); + + // group shape on slide3 + XSLFSlide slide3 = slides.get(2); + List shapes3 = slide3.getShapes(); + assertEquals(1, shapes3.size()); + assertTrue(shapes3.get(0) instanceof XSLFGroupShape); + List groupShapes = ((XSLFGroupShape)shapes3.get(0)).getShapes(); + assertEquals(3, groupShapes.size()); + assertTrue(groupShapes.get(0) instanceof XSLFAutoShape); + assertEquals("Rectangle 1", groupShapes.get(0).getShapeName()); + + assertTrue(groupShapes.get(1) instanceof XSLFAutoShape); + assertEquals("Oval 2", groupShapes.get(1).getShapeName()); + + assertTrue(groupShapes.get(2) instanceof XSLFAutoShape); + assertEquals("Right Arrow 3", groupShapes.get(2).getShapeName()); + + XSLFSlide slide4 = slides.get(3); + List shapes4 = slide4.getShapes(); + assertEquals(1, shapes4.size()); + assertTrue(shapes4.get(0) instanceof XSLFTable); + XSLFTable tbl = (XSLFTable)shapes4.get(0); + assertEquals(3, tbl.getNumberOfColumns()); + assertEquals(6, tbl.getNumberOfRows()); + + ppt.close(); + } + + @Test + public void testCreateSlide() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + assertEquals(0, ppt.getSlides().size()); + + XSLFSlide slide = ppt.createSlide(); + assertTrue(slide.getFollowMasterGraphics()); + slide.setFollowMasterGraphics(false); + assertFalse(slide.getFollowMasterGraphics()); + slide.setFollowMasterGraphics(true); + assertTrue(slide.getFollowMasterGraphics()); + + ppt.close(); + } + + @Test + public void testImportContent() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + + XMLSlideShow src = XSLFTestDataSamples.openSampleDocument("themes.pptx"); + + // create a blank slide and import content from the 4th slide of themes.pptx + XSLFSlide slide1 = ppt.createSlide().importContent(src.getSlides().get(3)); + List shapes1 = slide1.getShapes(); + assertEquals(2, shapes1.size()); + + XSLFTextShape sh1 = (XSLFTextShape)shapes1.get(0); + assertEquals("Austin Theme", sh1.getText()); + XSLFTextRun r1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals("Century Gothic", r1.getFontFamily()); + assertEquals(40.0, r1.getFontSize(), 0); + assertTrue(r1.isBold()); + assertTrue(r1.isItalic()); + assertTrue(sameColor(new Color(148, 198, 0), r1.getFontColor())); + assertNull(sh1.getFillColor()); + assertNull(sh1.getLineColor()); + + XSLFTextShape sh2 = (XSLFTextShape)shapes1.get(1); + assertEquals( + "Text in a autoshape is white\n" + + "Fill: RGB(148, 198,0)", sh2.getText()); + XSLFTextRun r2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals("Century Gothic", r2.getFontFamily()); + assertEquals(18.0, r2.getFontSize(), 0); + assertFalse(r2.isBold()); + assertFalse(r2.isItalic()); + assertTrue(sameColor(Color.white, r2.getFontColor())); + assertEquals(new Color(148, 198, 0), sh2.getFillColor()); + assertEquals(new Color(148, 198, 0), sh2.getLineColor()); // slightly different from PowerPoint! + + // the 5th slide has a picture and a texture fill + XSLFSlide slide2 = ppt.createSlide().importContent(src.getSlides().get(4)); + List shapes2 = slide2.getShapes(); + assertEquals(2, shapes2.size()); + + XSLFTextShape sh3 = (XSLFTextShape)shapes2.get(0); + assertEquals("This slide overrides master background with a texture fill", sh3.getText()); + XSLFTextRun r3 = sh3.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals("Century Gothic", r3.getFontFamily()); + //assertEquals(32.4.0, r3.getFontSize()); + assertTrue(r3.isBold()); + assertTrue(r3.isItalic()); + assertTrue(sameColor(new Color(148, 198, 0), r3.getFontColor())); + assertNull(sh3.getFillColor()); + assertNull(sh3.getLineColor()); + + XSLFPictureShape sh4 = (XSLFPictureShape)shapes2.get(1); + XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides().get(4).getShapes().get(1); + assertArrayEquals(sh4.getPictureData().getData(), srcPic.getPictureData().getData()); + + ppt.close(); + } + + @Test + public void testMergeSlides() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + String[] pptx = {"shapes.pptx", "themes.pptx", "layouts.pptx", "backgrounds.pptx"}; + + for(String arg : pptx){ + XMLSlideShow src = XSLFTestDataSamples.openSampleDocument(arg); + + for(XSLFSlide srcSlide : src.getSlides()){ + ppt.createSlide().importContent(srcSlide); + } + } + assertEquals(30, ppt.getSlides().size()); + + ppt.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java index 0f0f0bc227..61e4438f27 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShow.java @@ -1,149 +1,149 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; - -import java.awt.Dimension; -import java.io.IOException; -import java.util.List; - -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; - -/** - * @author Yegor Kozlov - */ -public class TestXSLFSlideShow { - @Test - public void testCreateSlide() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - assertEquals(0, ppt.getSlides().size()); - - XSLFSlide slide1 = ppt.createSlide(); - assertEquals(1, ppt.getSlides().size()); - assertSame(slide1, ppt.getSlides().get(0)); - - List rels = slide1.getRelations(); - assertEquals(1, rels.size()); - assertEquals(slide1.getSlideMaster().getLayout(SlideLayout.BLANK), rels.get(0)); - - XSLFSlide slide2 = ppt.createSlide(); - assertEquals(2, ppt.getSlides().size()); - assertSame(slide2, ppt.getSlides().get(1)); - - ppt.setSlideOrder(slide2, 0); - assertSame(slide2, ppt.getSlides().get(0)); - assertSame(slide1, ppt.getSlides().get(1)); - - XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt); - assertEquals(2, ppt2.getSlides().size()); - rels = ppt2.getSlides().get(0).getRelations(); - - ppt2.close(); - ppt.close(); - } - - @Test - public void testRemoveSlide() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - assertEquals(0, ppt.getSlides().size()); - - XSLFSlide slide1 = ppt.createSlide(); - XSLFSlide slide2 = ppt.createSlide(); - - assertEquals(2, ppt.getSlides().size()); - assertSame(slide1, ppt.getSlides().get(0)); - assertSame(slide2, ppt.getSlides().get(1)); - - XSLFSlide removedSlide = ppt.removeSlide(0); - assertSame(slide1, removedSlide); - - assertEquals(1, ppt.getSlides().size()); - assertSame(slide2, ppt.getSlides().get(0)); - - XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt); - assertEquals(1, ppt2.getSlides().size()); - - ppt2.close(); - ppt.close(); - } - - @Test - public void testDimension() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - Dimension sz = ppt.getPageSize(); - assertEquals(720, sz.width); - assertEquals(540, sz.height); - ppt.setPageSize(new Dimension(792, 612)); - sz = ppt.getPageSize(); - assertEquals(792, sz.width); - assertEquals(612, sz.height); - ppt.close(); - } - - @Test - public void testSlideMasters() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - List masters = ppt.getSlideMasters(); - assertEquals(1, masters.size()); - - XSLFSlide slide = ppt.createSlide(); - assertSame(masters.get(0), slide.getSlideMaster()); - ppt.close(); - } - - @Test - public void testSlideLayout() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - List masters = ppt.getSlideMasters(); - assertEquals(1, masters.size()); - - XSLFSlide slide = ppt.createSlide(); - XSLFSlideLayout layout = slide.getSlideLayout(); - assertNotNull(layout); - - assertSame(masters.get(0), layout.getSlideMaster()); - ppt.close(); - } - - @Test - public void testSlideLayoutNames() throws IOException { - final String names[] = { - "Blank", "Title Only", "Section Header", "Picture with Caption", "Title and Content" - , "Title Slide", "Title and Vertical Text", "Vertical Title and Text", "Comparison" - , "Two Content", "Content with Caption" - }; - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx"); - for (String name : names) { - assertNotNull(ppt.findLayout(name)); - } - final SlideLayout layTypes[] = { - SlideLayout.BLANK, SlideLayout.TITLE_ONLY, SlideLayout.SECTION_HEADER - , SlideLayout.PIC_TX, SlideLayout.TITLE_AND_CONTENT, SlideLayout.TITLE - , SlideLayout.VERT_TX, SlideLayout.VERT_TITLE_AND_TX, SlideLayout.TWO_TX_TWO_OBJ - , SlideLayout.TWO_OBJ, SlideLayout.OBJ_TX - }; - for (SlideLayout sl : layTypes){ - assertNotNull(ppt.getSlideMasters().get(0).getLayout(sl)); - } - ppt.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +import java.awt.Dimension; +import java.io.IOException; +import java.util.List; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFSlideShow { + @Test + public void testCreateSlide() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + assertEquals(0, ppt.getSlides().size()); + + XSLFSlide slide1 = ppt.createSlide(); + assertEquals(1, ppt.getSlides().size()); + assertSame(slide1, ppt.getSlides().get(0)); + + List rels = slide1.getRelations(); + assertEquals(1, rels.size()); + assertEquals(slide1.getSlideMaster().getLayout(SlideLayout.BLANK), rels.get(0)); + + XSLFSlide slide2 = ppt.createSlide(); + assertEquals(2, ppt.getSlides().size()); + assertSame(slide2, ppt.getSlides().get(1)); + + ppt.setSlideOrder(slide2, 0); + assertSame(slide2, ppt.getSlides().get(0)); + assertSame(slide1, ppt.getSlides().get(1)); + + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt); + assertEquals(2, ppt2.getSlides().size()); + rels = ppt2.getSlides().get(0).getRelations(); + + ppt2.close(); + ppt.close(); + } + + @Test + public void testRemoveSlide() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + assertEquals(0, ppt.getSlides().size()); + + XSLFSlide slide1 = ppt.createSlide(); + XSLFSlide slide2 = ppt.createSlide(); + + assertEquals(2, ppt.getSlides().size()); + assertSame(slide1, ppt.getSlides().get(0)); + assertSame(slide2, ppt.getSlides().get(1)); + + XSLFSlide removedSlide = ppt.removeSlide(0); + assertSame(slide1, removedSlide); + + assertEquals(1, ppt.getSlides().size()); + assertSame(slide2, ppt.getSlides().get(0)); + + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt); + assertEquals(1, ppt2.getSlides().size()); + + ppt2.close(); + ppt.close(); + } + + @Test + public void testDimension() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + Dimension sz = ppt.getPageSize(); + assertEquals(720, sz.width); + assertEquals(540, sz.height); + ppt.setPageSize(new Dimension(792, 612)); + sz = ppt.getPageSize(); + assertEquals(792, sz.width); + assertEquals(612, sz.height); + ppt.close(); + } + + @Test + public void testSlideMasters() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + List masters = ppt.getSlideMasters(); + assertEquals(1, masters.size()); + + XSLFSlide slide = ppt.createSlide(); + assertSame(masters.get(0), slide.getSlideMaster()); + ppt.close(); + } + + @Test + public void testSlideLayout() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + List masters = ppt.getSlideMasters(); + assertEquals(1, masters.size()); + + XSLFSlide slide = ppt.createSlide(); + XSLFSlideLayout layout = slide.getSlideLayout(); + assertNotNull(layout); + + assertSame(masters.get(0), layout.getSlideMaster()); + ppt.close(); + } + + @Test + public void testSlideLayoutNames() throws IOException { + final String names[] = { + "Blank", "Title Only", "Section Header", "Picture with Caption", "Title and Content" + , "Title Slide", "Title and Vertical Text", "Vertical Title and Text", "Comparison" + , "Two Content", "Content with Caption" + }; + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx"); + for (String name : names) { + assertNotNull(ppt.findLayout(name)); + } + final SlideLayout layTypes[] = { + SlideLayout.BLANK, SlideLayout.TITLE_ONLY, SlideLayout.SECTION_HEADER + , SlideLayout.PIC_TX, SlideLayout.TITLE_AND_CONTENT, SlideLayout.TITLE + , SlideLayout.VERT_TX, SlideLayout.VERT_TITLE_AND_TX, SlideLayout.TWO_TX_TWO_OBJ + , SlideLayout.TWO_OBJ, SlideLayout.OBJ_TX + }; + for (SlideLayout sl : layTypes){ + assertNotNull(ppt.getSlideMasters().get(0).getLayout(sl)); + } + ppt.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java index 1d77a019df..736d276d92 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java @@ -1,218 +1,218 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.List; - -import org.apache.poi.sl.draw.DrawFactory; -import org.apache.poi.sl.usermodel.Slide; -import org.apache.poi.sl.usermodel.TableCell.BorderEdge; -import org.apache.poi.sl.usermodel.VerticalAlignment; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; - -public class TestXSLFTable { - @Test - public void testRead() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); - - XSLFSlide slide = ppt.getSlides().get(3); - List shapes = slide.getShapes(); - assertEquals(1, shapes.size()); - assertTrue(shapes.get(0) instanceof XSLFTable); - XSLFTable tbl = (XSLFTable)shapes.get(0); - assertEquals(3, tbl.getNumberOfColumns()); - assertEquals(6, tbl.getNumberOfRows()); - assertNotNull(tbl.getCTTable()); - - List rows = tbl.getRows(); - assertEquals(6, rows.size()); - - assertEquals(90.0, tbl.getColumnWidth(0), 0); - assertEquals(240.0, tbl.getColumnWidth(1), 0); - assertEquals(150.0, tbl.getColumnWidth(2), 0); - - for(XSLFTableRow row : tbl){ - // all rows have the same height - assertEquals(29.2, row.getHeight(), 0); - } - - XSLFTableRow row0 = rows.get(0); - List cells0 = row0.getCells(); - assertEquals(3, cells0.size()); - assertEquals("header1", cells0.get(0).getText()); - assertEquals("header2", cells0.get(1).getText()); - assertEquals("header3", cells0.get(2).getText()); - - XSLFTableRow row1 = rows.get(1); - List cells1 = row1.getCells(); - assertEquals(3, cells1.size()); - assertEquals("A1", cells1.get(0).getText()); - assertEquals("B1", cells1.get(1).getText()); - assertEquals("C1", cells1.get(2).getText()); - - ppt.close(); - } - - @Test - public void testCreate() throws IOException { - XMLSlideShow ppt1 = new XMLSlideShow(); - XSLFSlide slide = ppt1.createSlide(); - - XSLFTable tbl = slide.createTable(); - assertNotNull(tbl.getCTTable()); - assertNotNull(tbl.getCTTable().getTblGrid()); - assertNotNull(tbl.getCTTable().getTblPr()); - assertTrue(tbl.getXmlObject() instanceof CTGraphicalObjectFrame); - assertEquals("Table 1", tbl.getShapeName()); - assertEquals(2, tbl.getShapeId()); - assertEquals(0, tbl.getRows().size()); - assertEquals(0, tbl.getCTTable().sizeOfTrArray()); - assertEquals(0, tbl.getCTTable().getTblGrid().sizeOfGridColArray()); - - assertEquals(0, tbl.getNumberOfColumns()); - assertEquals(0, tbl.getNumberOfRows()); - - XSLFTableRow row0 = tbl.addRow(); - assertNotNull(row0.getXmlObject()); - assertEquals(1, tbl.getNumberOfRows()); - assertSame(row0, tbl.getRows().get(0)); - assertEquals(20.0, row0.getHeight(), 0); - row0.setHeight(30.0); - assertEquals(30.0, row0.getHeight(), 0); - - assertEquals(0, row0.getCells().size()); - XSLFTableCell cell0 = row0.addCell(); - assertNotNull(cell0.getXmlObject()); - // by default table cell has no borders - CTTableCell tc = (CTTableCell)cell0.getXmlObject(); - assertTrue(tc.getTcPr().getLnB().isSetNoFill()); - assertTrue(tc.getTcPr().getLnT().isSetNoFill()); - assertTrue(tc.getTcPr().getLnL().isSetNoFill()); - assertTrue(tc.getTcPr().getLnR().isSetNoFill()); - - assertSame(cell0, row0.getCells().get(0)); - assertEquals(1, tbl.getNumberOfColumns()); - assertEquals(100.0, tbl.getColumnWidth(0), 0); - cell0.addNewTextParagraph().addNewTextRun().setText("POI"); - assertEquals("POI", cell0.getText()); - - XSLFTableCell cell1 = row0.addCell(); - assertSame(cell1, row0.getCells().get(1)); - assertEquals(2, tbl.getNumberOfColumns()); - assertEquals(100.0, tbl.getColumnWidth(1), 0); - cell1.addNewTextParagraph().addNewTextRun().setText("Apache"); - assertEquals("Apache", cell1.getText()); - - for (BorderEdge edge : BorderEdge.values()) { - assertNull(cell1.getBorderWidth(edge)); - cell1.setBorderWidth(edge, 2.0); - assertEquals(2.0, cell1.getBorderWidth(edge), 0); - assertNull(cell1.getBorderColor(edge)); - cell1.setBorderColor(edge, Color.yellow); - assertEquals(Color.yellow, cell1.getBorderColor(edge)); - } - - assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment()); - cell1.setVerticalAlignment(VerticalAlignment.MIDDLE); - assertEquals(VerticalAlignment.MIDDLE, cell1.getVerticalAlignment()); - cell1.setVerticalAlignment(null); - assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment()); - - XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); - ppt1.close(); - - slide = ppt2.getSlides().get(0); - tbl = (XSLFTable)slide.getShapes().get(0); - assertEquals(2, tbl.getNumberOfColumns()); - assertEquals(1, tbl.getNumberOfRows()); - assertEquals("POI", tbl.getCell(0, 0).getText()); - assertEquals("Apache", tbl.getCell(0, 1).getText()); - - ppt2.close(); - } - - @Test - public void removeTable() throws IOException { - XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); - XSLFSlide sl = ss.getSlides().get(0); - XSLFTable tab = (XSLFTable)sl.getShapes().get(4); - sl.removeShape(tab); - - XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss); - ss.close(); - - sl = ss2.getSlides().get(0); - for (XSLFShape s : sl.getShapes()) { - assertFalse(s instanceof XSLFTable); - } - - ss2.close(); - } - - @Test - public void checkTextHeight() throws IOException { - // from bug 59686 - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide sl = ppt.createSlide(); - XSLFTable tab = sl.createTable(); - tab.setAnchor(new Rectangle2D.Double(50,50,300,50)); - XSLFTableRow tr = tab.addRow(); - XSLFTableCell tc0 = tr.addCell(); - tc0.setText("bla bla bla bla"); - tab.setColumnWidth(0, 50); - - // usually text height == 88, but font rendering is plattform dependent - // so we use something more reliable - assertTrue(tc0.getTextHeight() > 50); - assertEquals(0, tc0.getLineWidth(), 0); - - ppt.close(); - } - - @Test - public void checkNullPointerException() { - XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("au.asn.aes.www_conferences_2011_presentations_Fri_20Room4Level4_20930_20Maloney.pptx"); - Dimension pgsize = ss.getPageSize(); - for (Slide s : ss.getSlides()) { - BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = img.createGraphics(); - - // draw stuff - s.draw(graphics); - - graphics.dispose(); - img.flush(); - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; + +import org.apache.poi.sl.draw.DrawFactory; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.TableCell.BorderEdge; +import org.apache.poi.sl.usermodel.VerticalAlignment; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; +import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; + +public class TestXSLFTable { + @Test + public void testRead() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + + XSLFSlide slide = ppt.getSlides().get(3); + List shapes = slide.getShapes(); + assertEquals(1, shapes.size()); + assertTrue(shapes.get(0) instanceof XSLFTable); + XSLFTable tbl = (XSLFTable)shapes.get(0); + assertEquals(3, tbl.getNumberOfColumns()); + assertEquals(6, tbl.getNumberOfRows()); + assertNotNull(tbl.getCTTable()); + + List rows = tbl.getRows(); + assertEquals(6, rows.size()); + + assertEquals(90.0, tbl.getColumnWidth(0), 0); + assertEquals(240.0, tbl.getColumnWidth(1), 0); + assertEquals(150.0, tbl.getColumnWidth(2), 0); + + for(XSLFTableRow row : tbl){ + // all rows have the same height + assertEquals(29.2, row.getHeight(), 0); + } + + XSLFTableRow row0 = rows.get(0); + List cells0 = row0.getCells(); + assertEquals(3, cells0.size()); + assertEquals("header1", cells0.get(0).getText()); + assertEquals("header2", cells0.get(1).getText()); + assertEquals("header3", cells0.get(2).getText()); + + XSLFTableRow row1 = rows.get(1); + List cells1 = row1.getCells(); + assertEquals(3, cells1.size()); + assertEquals("A1", cells1.get(0).getText()); + assertEquals("B1", cells1.get(1).getText()); + assertEquals("C1", cells1.get(2).getText()); + + ppt.close(); + } + + @Test + public void testCreate() throws IOException { + XMLSlideShow ppt1 = new XMLSlideShow(); + XSLFSlide slide = ppt1.createSlide(); + + XSLFTable tbl = slide.createTable(); + assertNotNull(tbl.getCTTable()); + assertNotNull(tbl.getCTTable().getTblGrid()); + assertNotNull(tbl.getCTTable().getTblPr()); + assertTrue(tbl.getXmlObject() instanceof CTGraphicalObjectFrame); + assertEquals("Table 1", tbl.getShapeName()); + assertEquals(2, tbl.getShapeId()); + assertEquals(0, tbl.getRows().size()); + assertEquals(0, tbl.getCTTable().sizeOfTrArray()); + assertEquals(0, tbl.getCTTable().getTblGrid().sizeOfGridColArray()); + + assertEquals(0, tbl.getNumberOfColumns()); + assertEquals(0, tbl.getNumberOfRows()); + + XSLFTableRow row0 = tbl.addRow(); + assertNotNull(row0.getXmlObject()); + assertEquals(1, tbl.getNumberOfRows()); + assertSame(row0, tbl.getRows().get(0)); + assertEquals(20.0, row0.getHeight(), 0); + row0.setHeight(30.0); + assertEquals(30.0, row0.getHeight(), 0); + + assertEquals(0, row0.getCells().size()); + XSLFTableCell cell0 = row0.addCell(); + assertNotNull(cell0.getXmlObject()); + // by default table cell has no borders + CTTableCell tc = (CTTableCell)cell0.getXmlObject(); + assertTrue(tc.getTcPr().getLnB().isSetNoFill()); + assertTrue(tc.getTcPr().getLnT().isSetNoFill()); + assertTrue(tc.getTcPr().getLnL().isSetNoFill()); + assertTrue(tc.getTcPr().getLnR().isSetNoFill()); + + assertSame(cell0, row0.getCells().get(0)); + assertEquals(1, tbl.getNumberOfColumns()); + assertEquals(100.0, tbl.getColumnWidth(0), 0); + cell0.addNewTextParagraph().addNewTextRun().setText("POI"); + assertEquals("POI", cell0.getText()); + + XSLFTableCell cell1 = row0.addCell(); + assertSame(cell1, row0.getCells().get(1)); + assertEquals(2, tbl.getNumberOfColumns()); + assertEquals(100.0, tbl.getColumnWidth(1), 0); + cell1.addNewTextParagraph().addNewTextRun().setText("Apache"); + assertEquals("Apache", cell1.getText()); + + for (BorderEdge edge : BorderEdge.values()) { + assertNull(cell1.getBorderWidth(edge)); + cell1.setBorderWidth(edge, 2.0); + assertEquals(2.0, cell1.getBorderWidth(edge), 0); + assertNull(cell1.getBorderColor(edge)); + cell1.setBorderColor(edge, Color.yellow); + assertEquals(Color.yellow, cell1.getBorderColor(edge)); + } + + assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment()); + cell1.setVerticalAlignment(VerticalAlignment.MIDDLE); + assertEquals(VerticalAlignment.MIDDLE, cell1.getVerticalAlignment()); + cell1.setVerticalAlignment(null); + assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment()); + + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt1.close(); + + slide = ppt2.getSlides().get(0); + tbl = (XSLFTable)slide.getShapes().get(0); + assertEquals(2, tbl.getNumberOfColumns()); + assertEquals(1, tbl.getNumberOfRows()); + assertEquals("POI", tbl.getCell(0, 0).getText()); + assertEquals("Apache", tbl.getCell(0, 1).getText()); + + ppt2.close(); + } + + @Test + public void removeTable() throws IOException { + XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("shapes.pptx"); + XSLFSlide sl = ss.getSlides().get(0); + XSLFTable tab = (XSLFTable)sl.getShapes().get(4); + sl.removeShape(tab); + + XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss); + ss.close(); + + sl = ss2.getSlides().get(0); + for (XSLFShape s : sl.getShapes()) { + assertFalse(s instanceof XSLFTable); + } + + ss2.close(); + } + + @Test + public void checkTextHeight() throws IOException { + // from bug 59686 + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide sl = ppt.createSlide(); + XSLFTable tab = sl.createTable(); + tab.setAnchor(new Rectangle2D.Double(50,50,300,50)); + XSLFTableRow tr = tab.addRow(); + XSLFTableCell tc0 = tr.addCell(); + tc0.setText("bla bla bla bla"); + tab.setColumnWidth(0, 50); + + // usually text height == 88, but font rendering is plattform dependent + // so we use something more reliable + assertTrue(tc0.getTextHeight() > 50); + assertEquals(0, tc0.getLineWidth(), 0); + + ppt.close(); + } + + @Test + public void checkNullPointerException() { + XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("au.asn.aes.www_conferences_2011_presentations_Fri_20Room4Level4_20930_20Maloney.pptx"); + Dimension pgsize = ss.getPageSize(); + for (Slide s : ss.getSlides()) { + BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = img.createGraphics(); + + // draw stuff + s.draw(graphics); + + graphics.dispose(); + img.flush(); + } + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTableStyles.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTableStyles.java index 12369937ea..710363747c 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTableStyles.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTableStyles.java @@ -1,38 +1,38 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.io.IOException; - -import org.junit.Test; - -public class TestXSLFTableStyles { - - @Test - public void testRead() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFTableStyles tblStyles = ppt.getTableStyles(); - assertNotNull(tblStyles); - - assertEquals(0, tblStyles.getStyles().size()); - - ppt.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; + +import org.junit.Test; + +public class TestXSLFTableStyles { + + @Test + public void testRead() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFTableStyles tblStyles = ppt.getTableStyles(); + assertNotNull(tblStyles); + + assertEquals(0, tblStyles.getStyles().size()); + + ppt.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java index 15352b448b..6edc3bdf21 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java @@ -1,90 +1,90 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import java.io.IOException; - -import org.apache.poi.sl.usermodel.Placeholder; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; - -/** - * @author Yegor Kozlov - */ -public class TestXSLFTextBox { - - @Test - public void testPlaceholder() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - XSLFTextBox shape = slide.createTextBox(); - assertNull(shape.getTextType()); - shape.setPlaceholder(Placeholder.TITLE); - assertEquals(Placeholder.TITLE, shape.getTextType()); - shape.setPlaceholder(null); - assertNull(shape.getTextType()); - shape.setText("Apache POI"); - - ppt.close(); - } - - /** - * text box inherits default text proeprties from presentation.xml - */ - @Test - public void testDefaultTextStyle() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - - // default character properties for paragraphs with level=1 - CTTextCharacterProperties pPr = ppt.getCTPresentation().getDefaultTextStyle().getLvl1PPr().getDefRPr(); - - XSLFTextBox shape = slide.createTextBox(); - shape.setText("Apache POI"); - assertEquals(1, shape.getTextParagraphs().size()); - assertEquals(1, shape.getTextParagraphs().get(0).getTextRuns().size()); - - XSLFTextRun r = shape.getTextParagraphs().get(0).getTextRuns().get(0); - - assertEquals(1800, pPr.getSz()); - assertEquals(18.0, r.getFontSize(), 0); - assertEquals("Calibri", r.getFontFamily()); - - pPr.setSz(900); - pPr.getLatin().setTypeface("Arial"); - assertEquals(9.0, r.getFontSize(), 0); - assertEquals("Arial", r.getFontFamily()); - - // unset font size in presentation.xml. The value should be taken from master slide - // from /p:sldMaster/p:txStyles/p:otherStyle/a:lvl1pPr/a:defRPr - ppt.getCTPresentation().getDefaultTextStyle().getLvl1PPr().getDefRPr().unsetSz(); - pPr = slide.getSlideMaster().getXmlObject().getTxStyles().getOtherStyle().getLvl1PPr().getDefRPr(); - assertEquals(1800, pPr.getSz()); - assertEquals(18.0, r.getFontSize(), 0); - pPr.setSz(2000); - assertEquals(20.0, r.getFontSize(), 0); - - pPr.unsetSz(); // Should never be - assertNull(r.getFontSize()); - - ppt.close(); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.io.IOException; + +import org.apache.poi.sl.usermodel.Placeholder; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFTextBox { + + @Test + public void testPlaceholder() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + XSLFTextBox shape = slide.createTextBox(); + assertNull(shape.getTextType()); + shape.setPlaceholder(Placeholder.TITLE); + assertEquals(Placeholder.TITLE, shape.getTextType()); + shape.setPlaceholder(null); + assertNull(shape.getTextType()); + shape.setText("Apache POI"); + + ppt.close(); + } + + /** + * text box inherits default text proeprties from presentation.xml + */ + @Test + public void testDefaultTextStyle() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + + // default character properties for paragraphs with level=1 + CTTextCharacterProperties pPr = ppt.getCTPresentation().getDefaultTextStyle().getLvl1PPr().getDefRPr(); + + XSLFTextBox shape = slide.createTextBox(); + shape.setText("Apache POI"); + assertEquals(1, shape.getTextParagraphs().size()); + assertEquals(1, shape.getTextParagraphs().get(0).getTextRuns().size()); + + XSLFTextRun r = shape.getTextParagraphs().get(0).getTextRuns().get(0); + + assertEquals(1800, pPr.getSz()); + assertEquals(18.0, r.getFontSize(), 0); + assertEquals("Calibri", r.getFontFamily()); + + pPr.setSz(900); + pPr.getLatin().setTypeface("Arial"); + assertEquals(9.0, r.getFontSize(), 0); + assertEquals("Arial", r.getFontFamily()); + + // unset font size in presentation.xml. The value should be taken from master slide + // from /p:sldMaster/p:txStyles/p:otherStyle/a:lvl1pPr/a:defRPr + ppt.getCTPresentation().getDefaultTextStyle().getLvl1PPr().getDefRPr().unsetSz(); + pPr = slide.getSlideMaster().getXmlObject().getTxStyles().getOtherStyle().getLvl1PPr().getDefRPr(); + assertEquals(1800, pPr.getSz()); + assertEquals(18.0, r.getFontSize(), 0); + pPr.setSz(2000); + assertEquals(20.0, r.getFontSize(), 0); + + pPr.unsetSz(); // Should never be + assertNull(r.getFontSize()); + + ppt.close(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java index 9d710cd70e..7d165387b4 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java @@ -1,394 +1,394 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.apache.poi.sl.TestCommonSL.sameColor; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.List; - -import org.apache.poi.sl.draw.DrawTextFragment; -import org.apache.poi.sl.draw.DrawTextParagraph; -import org.apache.poi.sl.usermodel.AutoNumberingScheme; -import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Assume; -import org.junit.Test; - -/** - * @author Yegor Kozlov - */ -public class TestXSLFTextParagraph { - // private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class); - - static class DrawTextParagraphProxy extends DrawTextParagraph { - DrawTextParagraphProxy(XSLFTextParagraph p) { - super(p); - } - - @Override - public void breakText(Graphics2D graphics) { - super.breakText(graphics); - } - - @Override - public double getWrappingWidth(boolean firstLine, Graphics2D graphics) { - return super.getWrappingWidth(firstLine, graphics); - } - - public List getLines() { - return lines; - } - } - - @Test - public void testWrappingWidth() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - XSLFTextShape sh = slide.createAutoShape(); - sh.setLineColor(Color.black); - - XSLFTextParagraph p = sh.addNewTextParagraph(); - p.addNewTextRun().setText( - "Paragraph formatting allows for more granular control " + - "of text within a shape. Properties here apply to all text " + - "residing within the corresponding paragraph."); - - Rectangle2D anchor = new Rectangle2D.Double(50, 50, 300, 200); - sh.setAnchor(anchor); - - DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); - - Double leftInset = sh.getLeftInset(); - Double rightInset = sh.getRightInset(); - assertEquals(7.2, leftInset, 0); - assertEquals(7.2, rightInset, 0); - - Double leftMargin = p.getLeftMargin(); - assertEquals(0.0, leftMargin, 0); - - Double indent = p.getIndent(); - assertNull(indent); // default - - double expectedWidth; - - // Case 1: bullet=false, leftMargin=0, indent=0. - expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(285.6, expectedWidth, 0); // 300 - 7.2 - 7.2 - 0 - assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); - assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); - - p.setLeftMargin(36d); // 0.5" - leftMargin = p.getLeftMargin(); - assertEquals(36.0, leftMargin, 0); - expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(249.6, expectedWidth, 1E-5); // 300 - 7.2 - 7.2 - 36 - assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); - assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); - - // increase insets, the wrapping width should get smaller - sh.setLeftInset(10); - sh.setRightInset(10); - leftInset = sh.getLeftInset(); - rightInset = sh.getRightInset(); - assertEquals(10.0, leftInset, 0); - assertEquals(10.0, rightInset, 0); - expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 - assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); - assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); - - // set a positive indent of a 0.5 inch. This means "First Line" indentation: - // |<--- indent -->|Here goes first line of the text - // Here go other lines (second and subsequent) - - p.setIndent(36.0); // 0.5" - indent = p.getIndent(); - assertEquals(36.0, indent, 0); - expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin - indent; - assertEquals(208.0, expectedWidth, 0); // 300 - 10 - 10 - 36 - 6.4 - assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is indented - // other lines are not indented - expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 - assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); - - // set a negative indent of a 1 inch. This means "Hanging" indentation: - // Here goes first line of the text - // |<--- indent -->|Here go other lines (second and subsequent) - p.setIndent(-72.0); // 1" - indent = p.getIndent(); - assertEquals(-72.0, indent, 0); - expectedWidth = anchor.getWidth() - leftInset - rightInset; - assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10 - assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is NOT indented - // other lines are indented by leftMargin (the value of indent is not used) - expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 - assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); - - ppt.close(); - } - - /** - * test breaking test into lines. - * This test requires that the Arial font is available and will run only on windows - */ - @Test - public void testBreakLines() throws IOException { - String os = System.getProperty("os.name"); - Assume.assumeTrue("Skipping testBreakLines(), it is executed only on Windows machines", (os != null && os.contains("Windows"))); - - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - XSLFTextShape sh = slide.createAutoShape(); - - XSLFTextParagraph p = sh.addNewTextParagraph(); - XSLFTextRun r = p.addNewTextRun(); - r.setFontFamily("Arial"); // this should always be available - r.setFontSize(12d); - r.setText( - "Paragraph formatting allows for more granular control " + - "of text within a shape. Properties here apply to all text " + - "residing within the corresponding paragraph."); - - sh.setAnchor(new Rectangle2D.Double(50, 50, 300, 200)); - DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); - - BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - Graphics2D graphics = img.createGraphics(); - - List lines; - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(4, lines.size()); - - // decrease the shape width from 300 pt to 100 pt - sh.setAnchor(new Rectangle2D.Double(50, 50, 100, 200)); - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(12, lines.size()); - - // decrease the shape width from 300 pt to 100 pt - sh.setAnchor(new Rectangle2D.Double(50, 50, 600, 200)); - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(2, lines.size()); - - // set left and right margins to 200pt. This leaves 200pt for wrapping text - sh.setLeftInset(200); - sh.setRightInset(200); - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(5, lines.size()); - - r.setText("Apache POI"); - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(1, lines.size()); - assertEquals("Apache POI", lines.get(0).getString()); - - r.setText("Apache\nPOI"); - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(2, lines.size()); - assertEquals("Apache", lines.get(0).getString()); - assertEquals("POI", lines.get(1).getString()); - - // trailing newlines are ignored - r.setText("Apache\nPOI\n"); - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(2, lines.size()); - assertEquals("Apache", lines.get(0).getString()); - assertEquals("POI", lines.get(1).getString()); - - XSLFAutoShape sh2 = slide.createAutoShape(); - sh2.setAnchor(new Rectangle2D.Double(50, 50, 300, 200)); - XSLFTextParagraph p2 = sh2.addNewTextParagraph(); - XSLFTextRun r2 = p2.addNewTextRun(); - r2.setFontFamily("serif"); // this should always be available - r2.setFontSize(30d); - r2.setText("Apache\n"); - XSLFTextRun r3 = p2.addNewTextRun(); - r3.setFontFamily("serif"); // this should always be available - r3.setFontSize(10d); - r3.setText("POI"); - dtp = new DrawTextParagraphProxy(p2); - dtp.breakText(graphics); - lines = dtp.getLines(); - assertEquals(2, lines.size()); - assertEquals("Apache", lines.get(0).getString()); - assertEquals("POI", lines.get(1).getString()); - // the first line is at least two times higher than the second - assertTrue(lines.get(0).getHeight() > lines.get(1).getHeight()*2); - - ppt.close(); - } - - @Test - public void testThemeInheritance() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx"); - List shapes = ppt.getSlides().get(0).getShapes(); - XSLFTextShape sh1 = (XSLFTextShape)shapes.get(0); - assertEquals("Apache", sh1.getText()); - assertEquals(TextAlign.CENTER, sh1.getTextParagraphs().get(0).getTextAlign()); - XSLFTextShape sh2 = (XSLFTextShape)shapes.get(1); - assertEquals("Software", sh2.getText()); - assertEquals(TextAlign.CENTER, sh2.getTextParagraphs().get(0).getTextAlign()); - XSLFTextShape sh3 = (XSLFTextShape)shapes.get(2); - assertEquals("Foundation", sh3.getText()); - assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign()); - ppt.close(); - } - - @Test - public void testParagraphProperties() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - XSLFTextShape sh = slide.createAutoShape(); - - XSLFTextParagraph p = sh.addNewTextParagraph(); - assertFalse(p.isBullet()); - p.setBullet(true); - assertTrue(p.isBullet()); - - assertEquals("\u2022", p.getBulletCharacter()); - p.setBulletCharacter("*"); - assertEquals("*", p.getBulletCharacter()); - - assertEquals("Arial", p.getBulletFont()); - p.setBulletFont("Calibri"); - assertEquals("Calibri", p.getBulletFont()); - - assertEquals(null, p.getBulletFontColor()); - p.setBulletFontColor(Color.red); - assertTrue(sameColor(Color.red, p.getBulletFontColor())); - - assertNull(p.getBulletFontSize()); - p.setBulletFontSize(200.); - assertEquals(200., p.getBulletFontSize(), 0); - p.setBulletFontSize(-20.); - assertEquals(-20.0, p.getBulletFontSize(), 0); - - assertEquals(72.0, p.getDefaultTabSize(), 0); - - assertNull(p.getIndent()); - p.setIndent(72.0); - assertEquals(72.0, p.getIndent(), 0); - p.setIndent(-1d); // the value of -1.0 resets to the defaults (not any more ...) - assertEquals(-1d, p.getIndent(), 0); - p.setIndent(null); - assertNull(p.getIndent()); - - assertEquals(0.0, p.getLeftMargin(), 0); - p.setLeftMargin(72.0); - assertEquals(72.0, p.getLeftMargin(), 0); - p.setLeftMargin(-1.0); // the value of -1.0 resets to the defaults - assertEquals(-1.0, p.getLeftMargin(), 0); - p.setLeftMargin(null); - assertEquals(0d, p.getLeftMargin(), 0); // default will be taken from master - - assertEquals(0, p.getIndentLevel()); - p.setIndentLevel(1); - assertEquals(1, p.getIndentLevel()); - p.setIndentLevel(2); - assertEquals(2, p.getIndentLevel()); - - assertNull(p.getLineSpacing()); - p.setLineSpacing(200.); - assertEquals(200.0, p.getLineSpacing(), 0); - p.setLineSpacing(-15.); - assertEquals(-15.0, p.getLineSpacing(), 0); - - assertNull(p.getSpaceAfter()); - p.setSpaceAfter(200.); - assertEquals(200.0, p.getSpaceAfter(), 0); - p.setSpaceAfter(-15.); - assertEquals(-15.0, p.getSpaceAfter(), 0); - p.setSpaceAfter(null); - assertNull(p.getSpaceAfter()); - p.setSpaceAfter(null); - assertNull(p.getSpaceAfter()); - - assertNull(p.getSpaceBefore()); - p.setSpaceBefore(200.); - assertEquals(200.0, p.getSpaceBefore(), 0); - p.setSpaceBefore(-15.); - assertEquals(-15.0, p.getSpaceBefore(), 0); - p.setSpaceBefore(null); - assertNull(p.getSpaceBefore()); - p.setSpaceBefore(null); - assertNull(p.getSpaceBefore()); - - assertEquals(TextAlign.LEFT, p.getTextAlign()); - p.setTextAlign(TextAlign.RIGHT); - assertEquals(TextAlign.RIGHT, p.getTextAlign()); - - p.setBullet(false); - assertFalse(p.isBullet()); - - p.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenBoth, 1); - - double tabStop = p.getTabStop(0); - assertEquals(0.0, tabStop, 0); - - p.addTabStop(100.); - assertEquals(100., p.getTabStop(0), 0); - - assertEquals(72.0, p.getDefaultTabSize(), 0); - - ppt.close(); - } - - @Test(expected = IllegalStateException.class) - public void testLineBreak() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - try { - XSLFSlide slide = ppt.createSlide(); - XSLFTextShape sh = slide.createAutoShape(); - - XSLFTextParagraph p = sh.addNewTextParagraph(); - XSLFTextRun r1 = p.addNewTextRun(); - r1.setText("Hello,"); - XSLFTextRun r2 = p.addLineBreak(); - assertEquals("\n", r2.getRawText()); - r2.setFontSize(10.0); - assertEquals(10.0, r2.getFontSize(), 0); - XSLFTextRun r3 = p.addNewTextRun(); - r3.setText("World!"); - r3.setFontSize(20.0); - XSLFTextRun r4 = p.addLineBreak(); - assertEquals(20.0, r4.getFontSize(), 0); - - assertEquals("Hello,\nWorld!\n",sh.getText()); - - // "You cannot change text of a line break, it is always '\\n'" - r2.setText("aaa"); - } finally { - ppt.close(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.apache.poi.sl.TestCommonSL.sameColor; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; + +import org.apache.poi.sl.draw.DrawTextFragment; +import org.apache.poi.sl.draw.DrawTextParagraph; +import org.apache.poi.sl.usermodel.AutoNumberingScheme; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Assume; +import org.junit.Test; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFTextParagraph { + // private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class); + + static class DrawTextParagraphProxy extends DrawTextParagraph { + DrawTextParagraphProxy(XSLFTextParagraph p) { + super(p); + } + + @Override + public void breakText(Graphics2D graphics) { + super.breakText(graphics); + } + + @Override + public double getWrappingWidth(boolean firstLine, Graphics2D graphics) { + return super.getWrappingWidth(firstLine, graphics); + } + + public List getLines() { + return lines; + } + } + + @Test + public void testWrappingWidth() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFTextShape sh = slide.createAutoShape(); + sh.setLineColor(Color.black); + + XSLFTextParagraph p = sh.addNewTextParagraph(); + p.addNewTextRun().setText( + "Paragraph formatting allows for more granular control " + + "of text within a shape. Properties here apply to all text " + + "residing within the corresponding paragraph."); + + Rectangle2D anchor = new Rectangle2D.Double(50, 50, 300, 200); + sh.setAnchor(anchor); + + DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); + + Double leftInset = sh.getLeftInset(); + Double rightInset = sh.getRightInset(); + assertEquals(7.2, leftInset, 0); + assertEquals(7.2, rightInset, 0); + + Double leftMargin = p.getLeftMargin(); + assertEquals(0.0, leftMargin, 0); + + Double indent = p.getIndent(); + assertNull(indent); // default + + double expectedWidth; + + // Case 1: bullet=false, leftMargin=0, indent=0. + expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; + assertEquals(285.6, expectedWidth, 0); // 300 - 7.2 - 7.2 - 0 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); + + p.setLeftMargin(36d); // 0.5" + leftMargin = p.getLeftMargin(); + assertEquals(36.0, leftMargin, 0); + expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; + assertEquals(249.6, expectedWidth, 1E-5); // 300 - 7.2 - 7.2 - 36 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); + + // increase insets, the wrapping width should get smaller + sh.setLeftInset(10); + sh.setRightInset(10); + leftInset = sh.getLeftInset(); + rightInset = sh.getRightInset(); + assertEquals(10.0, leftInset, 0); + assertEquals(10.0, rightInset, 0); + expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; + assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); + + // set a positive indent of a 0.5 inch. This means "First Line" indentation: + // |<--- indent -->|Here goes first line of the text + // Here go other lines (second and subsequent) + + p.setIndent(36.0); // 0.5" + indent = p.getIndent(); + assertEquals(36.0, indent, 0); + expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin - indent; + assertEquals(208.0, expectedWidth, 0); // 300 - 10 - 10 - 36 - 6.4 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is indented + // other lines are not indented + expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; + assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); + + // set a negative indent of a 1 inch. This means "Hanging" indentation: + // Here goes first line of the text + // |<--- indent -->|Here go other lines (second and subsequent) + p.setIndent(-72.0); // 1" + indent = p.getIndent(); + assertEquals(-72.0, indent, 0); + expectedWidth = anchor.getWidth() - leftInset - rightInset; + assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is NOT indented + // other lines are indented by leftMargin (the value of indent is not used) + expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; + assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); + + ppt.close(); + } + + /** + * test breaking test into lines. + * This test requires that the Arial font is available and will run only on windows + */ + @Test + public void testBreakLines() throws IOException { + String os = System.getProperty("os.name"); + Assume.assumeTrue("Skipping testBreakLines(), it is executed only on Windows machines", (os != null && os.contains("Windows"))); + + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFTextShape sh = slide.createAutoShape(); + + XSLFTextParagraph p = sh.addNewTextParagraph(); + XSLFTextRun r = p.addNewTextRun(); + r.setFontFamily("Arial"); // this should always be available + r.setFontSize(12d); + r.setText( + "Paragraph formatting allows for more granular control " + + "of text within a shape. Properties here apply to all text " + + "residing within the corresponding paragraph."); + + sh.setAnchor(new Rectangle2D.Double(50, 50, 300, 200)); + DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); + + BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + Graphics2D graphics = img.createGraphics(); + + List lines; + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(4, lines.size()); + + // decrease the shape width from 300 pt to 100 pt + sh.setAnchor(new Rectangle2D.Double(50, 50, 100, 200)); + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(12, lines.size()); + + // decrease the shape width from 300 pt to 100 pt + sh.setAnchor(new Rectangle2D.Double(50, 50, 600, 200)); + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(2, lines.size()); + + // set left and right margins to 200pt. This leaves 200pt for wrapping text + sh.setLeftInset(200); + sh.setRightInset(200); + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(5, lines.size()); + + r.setText("Apache POI"); + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(1, lines.size()); + assertEquals("Apache POI", lines.get(0).getString()); + + r.setText("Apache\nPOI"); + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(2, lines.size()); + assertEquals("Apache", lines.get(0).getString()); + assertEquals("POI", lines.get(1).getString()); + + // trailing newlines are ignored + r.setText("Apache\nPOI\n"); + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(2, lines.size()); + assertEquals("Apache", lines.get(0).getString()); + assertEquals("POI", lines.get(1).getString()); + + XSLFAutoShape sh2 = slide.createAutoShape(); + sh2.setAnchor(new Rectangle2D.Double(50, 50, 300, 200)); + XSLFTextParagraph p2 = sh2.addNewTextParagraph(); + XSLFTextRun r2 = p2.addNewTextRun(); + r2.setFontFamily("serif"); // this should always be available + r2.setFontSize(30d); + r2.setText("Apache\n"); + XSLFTextRun r3 = p2.addNewTextRun(); + r3.setFontFamily("serif"); // this should always be available + r3.setFontSize(10d); + r3.setText("POI"); + dtp = new DrawTextParagraphProxy(p2); + dtp.breakText(graphics); + lines = dtp.getLines(); + assertEquals(2, lines.size()); + assertEquals("Apache", lines.get(0).getString()); + assertEquals("POI", lines.get(1).getString()); + // the first line is at least two times higher than the second + assertTrue(lines.get(0).getHeight() > lines.get(1).getHeight()*2); + + ppt.close(); + } + + @Test + public void testThemeInheritance() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx"); + List shapes = ppt.getSlides().get(0).getShapes(); + XSLFTextShape sh1 = (XSLFTextShape)shapes.get(0); + assertEquals("Apache", sh1.getText()); + assertEquals(TextAlign.CENTER, sh1.getTextParagraphs().get(0).getTextAlign()); + XSLFTextShape sh2 = (XSLFTextShape)shapes.get(1); + assertEquals("Software", sh2.getText()); + assertEquals(TextAlign.CENTER, sh2.getTextParagraphs().get(0).getTextAlign()); + XSLFTextShape sh3 = (XSLFTextShape)shapes.get(2); + assertEquals("Foundation", sh3.getText()); + assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign()); + ppt.close(); + } + + @Test + public void testParagraphProperties() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFTextShape sh = slide.createAutoShape(); + + XSLFTextParagraph p = sh.addNewTextParagraph(); + assertFalse(p.isBullet()); + p.setBullet(true); + assertTrue(p.isBullet()); + + assertEquals("\u2022", p.getBulletCharacter()); + p.setBulletCharacter("*"); + assertEquals("*", p.getBulletCharacter()); + + assertEquals("Arial", p.getBulletFont()); + p.setBulletFont("Calibri"); + assertEquals("Calibri", p.getBulletFont()); + + assertEquals(null, p.getBulletFontColor()); + p.setBulletFontColor(Color.red); + assertTrue(sameColor(Color.red, p.getBulletFontColor())); + + assertNull(p.getBulletFontSize()); + p.setBulletFontSize(200.); + assertEquals(200., p.getBulletFontSize(), 0); + p.setBulletFontSize(-20.); + assertEquals(-20.0, p.getBulletFontSize(), 0); + + assertEquals(72.0, p.getDefaultTabSize(), 0); + + assertNull(p.getIndent()); + p.setIndent(72.0); + assertEquals(72.0, p.getIndent(), 0); + p.setIndent(-1d); // the value of -1.0 resets to the defaults (not any more ...) + assertEquals(-1d, p.getIndent(), 0); + p.setIndent(null); + assertNull(p.getIndent()); + + assertEquals(0.0, p.getLeftMargin(), 0); + p.setLeftMargin(72.0); + assertEquals(72.0, p.getLeftMargin(), 0); + p.setLeftMargin(-1.0); // the value of -1.0 resets to the defaults + assertEquals(-1.0, p.getLeftMargin(), 0); + p.setLeftMargin(null); + assertEquals(0d, p.getLeftMargin(), 0); // default will be taken from master + + assertEquals(0, p.getIndentLevel()); + p.setIndentLevel(1); + assertEquals(1, p.getIndentLevel()); + p.setIndentLevel(2); + assertEquals(2, p.getIndentLevel()); + + assertNull(p.getLineSpacing()); + p.setLineSpacing(200.); + assertEquals(200.0, p.getLineSpacing(), 0); + p.setLineSpacing(-15.); + assertEquals(-15.0, p.getLineSpacing(), 0); + + assertNull(p.getSpaceAfter()); + p.setSpaceAfter(200.); + assertEquals(200.0, p.getSpaceAfter(), 0); + p.setSpaceAfter(-15.); + assertEquals(-15.0, p.getSpaceAfter(), 0); + p.setSpaceAfter(null); + assertNull(p.getSpaceAfter()); + p.setSpaceAfter(null); + assertNull(p.getSpaceAfter()); + + assertNull(p.getSpaceBefore()); + p.setSpaceBefore(200.); + assertEquals(200.0, p.getSpaceBefore(), 0); + p.setSpaceBefore(-15.); + assertEquals(-15.0, p.getSpaceBefore(), 0); + p.setSpaceBefore(null); + assertNull(p.getSpaceBefore()); + p.setSpaceBefore(null); + assertNull(p.getSpaceBefore()); + + assertEquals(TextAlign.LEFT, p.getTextAlign()); + p.setTextAlign(TextAlign.RIGHT); + assertEquals(TextAlign.RIGHT, p.getTextAlign()); + + p.setBullet(false); + assertFalse(p.isBullet()); + + p.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenBoth, 1); + + double tabStop = p.getTabStop(0); + assertEquals(0.0, tabStop, 0); + + p.addTabStop(100.); + assertEquals(100., p.getTabStop(0), 0); + + assertEquals(72.0, p.getDefaultTabSize(), 0); + + ppt.close(); + } + + @Test(expected = IllegalStateException.class) + public void testLineBreak() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + try { + XSLFSlide slide = ppt.createSlide(); + XSLFTextShape sh = slide.createAutoShape(); + + XSLFTextParagraph p = sh.addNewTextParagraph(); + XSLFTextRun r1 = p.addNewTextRun(); + r1.setText("Hello,"); + XSLFTextRun r2 = p.addLineBreak(); + assertEquals("\n", r2.getRawText()); + r2.setFontSize(10.0); + assertEquals(10.0, r2.getFontSize(), 0); + XSLFTextRun r3 = p.addNewTextRun(); + r3.setText("World!"); + r3.setFontSize(20.0); + XSLFTextRun r4 = p.addLineBreak(); + assertEquals(20.0, r4.getFontSize(), 0); + + assertEquals("Hello,\nWorld!\n",sh.getText()); + + // "You cannot change text of a line break, it is always '\\n'" + r2.setText("aaa"); + } finally { + ppt.close(); + } + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java index 5b2fa7b2ac..de6085433f 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java @@ -1,80 +1,80 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xslf.usermodel; - -import static org.apache.poi.sl.TestCommonSL.sameColor; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.awt.Color; -import java.io.IOException; - -import org.junit.Test; - -/** - * @author Yegor Kozlov - */ -public class TestXSLFTextRun { - - @Test - public void testRunProperties() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - XSLFTextShape sh = slide.createAutoShape(); - - XSLFTextRun r = sh.addNewTextParagraph().addNewTextRun(); - assertEquals("en-US", r.getRPr(true).getLang()); - - assertEquals(0., r.getCharacterSpacing(), 0); - r.setCharacterSpacing(3); - assertEquals(3., r.getCharacterSpacing(), 0); - r.setCharacterSpacing(-3); - assertEquals(-3., r.getCharacterSpacing(), 0); - r.setCharacterSpacing(0); - assertEquals(0., r.getCharacterSpacing(), 0); - assertFalse(r.getRPr(true).isSetSpc()); - - assertTrue(sameColor(Color.black, r.getFontColor())); - r.setFontColor(Color.red); - assertTrue(sameColor(Color.red, r.getFontColor())); - - assertEquals("Calibri", r.getFontFamily()); - r.setFontFamily("Arial"); - assertEquals("Arial", r.getFontFamily()); - - assertEquals(18.0, r.getFontSize(), 0); - r.setFontSize(13.0); - assertEquals(13.0, r.getFontSize(), 0); - - assertEquals(false, r.isSuperscript()); - r.setSuperscript(true); - assertEquals(true, r.isSuperscript()); - r.setSuperscript(false); - assertEquals(false, r.isSuperscript()); - - assertEquals(false, r.isSubscript()); - r.setSubscript(true); - assertEquals(true, r.isSubscript()); - r.setSubscript(false); - assertEquals(false, r.isSubscript()); - - ppt.close(); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xslf.usermodel; + +import static org.apache.poi.sl.TestCommonSL.sameColor; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.awt.Color; +import java.io.IOException; + +import org.junit.Test; + +/** + * @author Yegor Kozlov + */ +public class TestXSLFTextRun { + + @Test + public void testRunProperties() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + XSLFSlide slide = ppt.createSlide(); + XSLFTextShape sh = slide.createAutoShape(); + + XSLFTextRun r = sh.addNewTextParagraph().addNewTextRun(); + assertEquals("en-US", r.getRPr(true).getLang()); + + assertEquals(0., r.getCharacterSpacing(), 0); + r.setCharacterSpacing(3); + assertEquals(3., r.getCharacterSpacing(), 0); + r.setCharacterSpacing(-3); + assertEquals(-3., r.getCharacterSpacing(), 0); + r.setCharacterSpacing(0); + assertEquals(0., r.getCharacterSpacing(), 0); + assertFalse(r.getRPr(true).isSetSpc()); + + assertTrue(sameColor(Color.black, r.getFontColor())); + r.setFontColor(Color.red); + assertTrue(sameColor(Color.red, r.getFontColor())); + + assertEquals("Calibri", r.getFontFamily()); + r.setFontFamily("Arial"); + assertEquals("Arial", r.getFontFamily()); + + assertEquals(18.0, r.getFontSize(), 0); + r.setFontSize(13.0); + assertEquals(13.0, r.getFontSize(), 0); + + assertEquals(false, r.isSuperscript()); + r.setSuperscript(true); + assertEquals(true, r.isSuperscript()); + r.setSuperscript(false); + assertEquals(false, r.isSuperscript()); + + assertEquals(false, r.isSubscript()); + r.setSubscript(true); + assertEquals(true, r.isSubscript()); + r.setSubscript(false); + assertEquals(false, r.isSubscript()); + + ppt.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java index 13024e6fdb..9cf4adcd83 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java @@ -1,944 +1,944 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.apache.poi.sl.TestCommonSL.sameColor; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeFalse; -import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr; - -import java.awt.Color; -import java.io.File; -import java.io.IOException; -import java.util.List; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.hslf.usermodel.HSLFTextShape; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.SlideShowFactory; -import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; -import org.apache.poi.sl.usermodel.VerticalAlignment; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; -import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; - -public class TestXSLFTextShape { - private static boolean xslfOnly = false; - - @BeforeClass - public static void checkHslf() { - try { - Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); - } catch (Exception e) { - xslfOnly = true; - } - } - - @Test - public void testLayouts() throws IOException { - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx"); - - List slide = ppt.getSlides(); - - verifySlide1(slide.get(0)); - verifySlide2(slide.get(1)); - verifySlide3(slide.get(2)); - verifySlide4(slide.get(3)); - verifySlide7(slide.get(6)); - verifySlide8(slide.get(7)); - verifySlide10(slide.get(9)); - - ppt.close(); - } - - void verifySlide1(XSLFSlide slide){ - XSLFSlideLayout layout = slide.getSlideLayout(); - List shapes = slide.getShapes(); - assertEquals("Title Slide",layout.getName()); - - XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); - CTPlaceholder ph1 = shape1.getCTPlaceholder(); - assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape1).getXfrm()); - - XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); - assertNotNull(getSpPr(masterShape1).getXfrm()); - assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); - - CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && - !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && - !bodyPr1.isSetAnchor() - ); - assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); - - // now check text properties - assertEquals("Centered Title", shape1.getText()); - XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals("Calibri", r1.getFontFamily()); - assertEquals(44.0, r1.getFontSize(), 0); - assertTrue(sameColor(Color.black, r1.getFontColor())); - - XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); - CTPlaceholder ph2 = shape2.getCTPlaceholder(); - assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape2).getXfrm()); - - XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); - assertNotNull(getSpPr(masterShape2).getXfrm()); - assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); - - CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && - !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && - !bodyPr2.isSetAnchor() - ); - assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); - - assertEquals("subtitle", shape2.getText()); - XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals("Calibri", r2.getFontFamily()); - assertEquals(32.0, r2.getFontSize(), 0); - // TODO fix calculation of tint - //assertEquals(new Color(137, 137, 137), r2.getFontColor()); - } - - void verifySlide2(XSLFSlide slide){ - XSLFSlideLayout layout = slide.getSlideLayout(); - List shapes = slide.getShapes(); - assertEquals("Title and Content",layout.getName()); - - XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); - CTPlaceholder ph1 = shape1.getCTPlaceholder(); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape1).getXfrm()); - - XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); - // layout does not have anchor info either, it is in the slide master - assertNull(getSpPr(masterShape1).getXfrm()); - masterShape1 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph1); - assertNotNull(getSpPr(masterShape1).getXfrm()); - assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); - - CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && - !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && - !bodyPr1.isSetAnchor() - ); - assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); - - // now check text properties - assertEquals("Title", shape1.getText()); - XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals("Calibri", r1.getFontFamily()); - assertEquals(44.0, r1.getFontSize(), 0); - assertTrue(sameColor(Color.black, r1.getFontColor())); - - XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); - CTPlaceholder ph2 = shape2.getCTPlaceholder(); - assertFalse(ph2.isSetType()); // - assertTrue(ph2.isSetIdx()); - assertEquals(1, ph2.getIdx()); - // anchor is not defined in the shape - assertNull(getSpPr(shape2).getXfrm()); - - XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); - // anchor of the body text is missing in the slide layout, llokup in the slide master - assertNull(getSpPr(masterShape2).getXfrm()); - masterShape2 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph2); - assertNotNull(getSpPr(masterShape2).getXfrm()); - assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); - - CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && - !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && - !bodyPr2.isSetAnchor() - ); - assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); - - XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(0, pr1.getParentParagraph().getIndentLevel()); - assertEquals("Content", pr1.getRawText()); - assertEquals("Calibri", pr1.getFontFamily()); - assertEquals(32.0, pr1.getFontSize(), 0); - assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr1.getParentParagraph().getBulletFont()); - - XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0); - assertEquals(1, pr2.getParentParagraph().getIndentLevel()); - assertEquals("Level 2", pr2.getRawText()); - assertEquals("Calibri", pr2.getFontFamily()); - assertEquals(28.0, pr2.getFontSize(), 0); - assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr2.getParentParagraph().getBulletFont()); - - XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0); - assertEquals(2, pr3.getParentParagraph().getIndentLevel()); - assertEquals("Level 3", pr3.getRawText()); - assertEquals("Calibri", pr3.getFontFamily()); - assertEquals(24.0, pr3.getFontSize(), 0); - assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr3.getParentParagraph().getBulletFont()); - - XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0); - assertEquals(3, pr4.getParentParagraph().getIndentLevel()); - assertEquals("Level 4", pr4.getRawText()); - assertEquals("Calibri", pr4.getFontFamily()); - assertEquals(20.0, pr4.getFontSize(), 0); - assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr4.getParentParagraph().getBulletFont()); - - XSLFTextRun pr5 = shape2.getTextParagraphs().get(4).getTextRuns().get(0); - assertEquals(4, pr5.getParentParagraph().getIndentLevel()); - assertEquals("Level 5", pr5.getRawText()); - assertEquals("Calibri", pr5.getFontFamily()); - assertEquals(20.0, pr5.getFontSize(), 0); - assertEquals(162.0, pr5.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u00bb", pr5.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr5.getParentParagraph().getBulletFont()); - - } - - void verifySlide3(XSLFSlide slide){ - XSLFSlideLayout layout = slide.getSlideLayout(); - List shapes = slide.getShapes(); - assertEquals("Section Header",layout.getName()); - - XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); - CTPlaceholder ph1 = shape1.getCTPlaceholder(); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape1).getXfrm()); - - XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); - assertNotNull(getSpPr(masterShape1).getXfrm()); - assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); - - CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && - !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && - !bodyPr1.isSetAnchor() - ); - assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.TOP, shape1.getVerticalAlignment()); - - // now check text properties - assertEquals("Section Title", shape1.getText()); - XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign()); - assertEquals("Calibri", r1.getFontFamily()); - assertEquals(40.0, r1.getFontSize(), 0); - assertTrue(sameColor(Color.black, r1.getFontColor())); - assertTrue(r1.isBold()); - assertFalse(r1.isItalic()); - assertFalse(r1.isUnderlined()); - - XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); - CTPlaceholder ph2 = shape2.getCTPlaceholder(); - assertEquals(STPlaceholderType.BODY, ph2.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape2).getXfrm()); - - XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); - assertNotNull(getSpPr(masterShape2).getXfrm()); - assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); - - CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && - !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && - !bodyPr2.isSetAnchor() - ); - assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.BOTTOM, shape2.getVerticalAlignment()); - - assertEquals("Section Header", shape2.getText()); - XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(TextAlign.LEFT, r2.getParentParagraph().getTextAlign()); - assertEquals("Calibri", r2.getFontFamily()); - assertEquals(20.0, r2.getFontSize(), 0); - // TODO fix calculation of tint - //assertEquals(new Color(137, 137, 137), r2.getFontColor()); - } - - void verifySlide4(XSLFSlide slide){ - XSLFSlideLayout layout = slide.getSlideLayout(); - List shapes = slide.getShapes(); - assertEquals("Two Content",layout.getName()); - - XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); - CTPlaceholder ph1 = shape1.getCTPlaceholder(); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape1).getXfrm()); - - XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); - // layout does not have anchor info either, it is in the slide master - assertNull(getSpPr(masterShape1).getXfrm()); - masterShape1 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph1); - assertNotNull(getSpPr(masterShape1).getXfrm()); - assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); - - CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && - !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && - !bodyPr1.isSetAnchor() - ); - assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); - - // now check text properties - assertEquals("Title", shape1.getText()); - XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); - assertEquals("Calibri", r1.getFontFamily()); - assertEquals(44.0, r1.getFontSize(), 0); - assertTrue(sameColor(Color.black, r1.getFontColor())); - - XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); - CTPlaceholder ph2 = shape2.getCTPlaceholder(); - assertFalse(ph2.isSetType()); - assertTrue(ph2.isSetIdx()); - assertEquals(1, ph2.getIdx()); // - // anchor is not defined in the shape - assertNull(getSpPr(shape2).getXfrm()); - - XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); - assertNotNull(getSpPr(masterShape2).getXfrm()); - assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); - - CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && - !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && - !bodyPr2.isSetAnchor() - ); - assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); - - XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(0, pr1.getParentParagraph().getIndentLevel()); - assertEquals("Left", pr1.getRawText()); - assertEquals("Calibri", pr1.getFontFamily()); - assertEquals(28.0, pr1.getFontSize(), 0); - assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr1.getParentParagraph().getBulletFont()); - - XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0); - assertEquals(1, pr2.getParentParagraph().getIndentLevel()); - assertEquals("Level 2", pr2.getParentParagraph().getText()); - assertEquals("Calibri", pr2.getFontFamily()); - assertEquals(24.0, pr2.getFontSize(), 0); - assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr2.getParentParagraph().getBulletFont()); - - XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0); - assertEquals(2, pr3.getParentParagraph().getIndentLevel()); - assertEquals("Level 3", pr3.getParentParagraph().getText()); - assertEquals("Calibri", pr3.getFontFamily()); - assertEquals(20.0, pr3.getFontSize(), 0); - assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr3.getParentParagraph().getBulletFont()); - - XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0); - assertEquals(3, pr4.getParentParagraph().getIndentLevel()); - assertEquals("Level 4", pr4.getParentParagraph().getText()); - assertEquals("Calibri", pr4.getFontFamily()); - assertEquals(18.0, pr4.getFontSize(), 0); - assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr4.getParentParagraph().getBulletFont()); - - XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2); - XSLFTextRun pr5 = shape3.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(0, pr5.getParentParagraph().getIndentLevel()); - assertEquals("Right", pr5.getRawText()); - assertEquals("Calibri", pr5.getFontFamily()); - assertTrue(sameColor(Color.black, pr5.getFontColor())); - } - - @SuppressWarnings("unused") - void verifySlide5(XSLFSlide slide){ - XSLFSlideLayout layout = slide.getSlideLayout(); - List shapes = slide.getShapes(); - // TODO - } - - void verifySlide7(XSLFSlide slide){ - XSLFSlideLayout layout = slide.getSlideLayout(); - List shapes = slide.getShapes(); - assertEquals("Blank",layout.getName()); - - XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); - CTPlaceholder ph1 = shape1.getCTPlaceholder(); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape1).getXfrm()); - - CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && - !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && - !bodyPr1.isSetAnchor() - ); - assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); - - // now check text properties - assertEquals("Blank with Default Title", shape1.getText()); - XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); - assertEquals("Calibri", r1.getFontFamily()); - assertEquals(44.0, r1.getFontSize(), 0); - assertTrue(sameColor(Color.black, r1.getFontColor())); - assertFalse(r1.isBold()); - - XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); - - CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && - !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && - !bodyPr2.isSetAnchor() - ); - assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); - - XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(0, pr1.getParentParagraph().getIndentLevel()); - assertEquals("Default Text", pr1.getRawText()); - assertEquals("Calibri", pr1.getFontFamily()); - assertEquals(18.0, pr1.getFontSize(), 0); - - XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2); - assertEquals("Default", shape3.getTextParagraphs().get(0).getText()); - assertEquals("Text with levels", shape3.getTextParagraphs().get(1).getText()); - assertEquals("Level 1", shape3.getTextParagraphs().get(2).getText()); - assertEquals("Level 2", shape3.getTextParagraphs().get(3).getText()); - assertEquals("Level 3", shape3.getTextParagraphs().get(4).getText()); - - for(int p = 0; p < 5; p++) { - XSLFTextParagraph pr = shape3.getTextParagraphs().get(p); - assertEquals("Calibri", pr.getTextRuns().get(0).getFontFamily()); - assertEquals(18.0, pr.getTextRuns().get(0).getFontSize(), 0); - } - } - - void verifySlide8(XSLFSlide slide){ - XSLFSlideLayout layout = slide.getSlideLayout(); - List shapes = slide.getShapes(); - assertEquals("Content with Caption",layout.getName()); - - XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); - CTPlaceholder ph1 = shape1.getCTPlaceholder(); - assertEquals(STPlaceholderType.TITLE, ph1.getType()); - // anchor is not defined in the shape - assertNull(getSpPr(shape1).getXfrm()); - - XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); - // layout does not have anchor info either, it is in the slide master - assertNotNull(getSpPr(masterShape1).getXfrm()); - assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); - - CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && - !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && - !bodyPr1.isSetAnchor() - ); - assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.BOTTOM, shape1.getVerticalAlignment()); - - // now check text properties - assertEquals("Caption", shape1.getText()); - XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign()); - assertEquals("Calibri", r1.getFontFamily()); - assertEquals(20.0, r1.getFontSize(), 0); - assertTrue(sameColor(Color.black, r1.getFontColor())); - assertTrue(r1.isBold()); - - XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); - CTPlaceholder ph2 = shape2.getCTPlaceholder(); - assertFalse(ph2.isSetType()); - assertTrue(ph2.isSetIdx()); - assertEquals(1, ph2.getIdx()); - // anchor is not defined in the shape - assertNull(getSpPr(shape2).getXfrm()); - - XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); - assertNotNull(getSpPr(masterShape2).getXfrm()); - assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); - - CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); - // none of the following properties are set in the shapes and fetched from the master shape - assertTrue( - !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && - !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && - !bodyPr2.isSetAnchor() - ); - assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" - assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" - assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" - assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" - assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); - - XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(0, pr1.getParentParagraph().getIndentLevel()); - assertEquals("Level 1", pr1.getRawText()); - assertEquals("Calibri", pr1.getFontFamily()); - assertEquals(32.0, pr1.getFontSize(), 0); - assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr1.getParentParagraph().getBulletFont()); - - XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0); - assertEquals(1, pr2.getParentParagraph().getIndentLevel()); - assertEquals("Level 2", pr2.getParentParagraph().getText()); - assertEquals("Calibri", pr2.getFontFamily()); - assertEquals(28.0, pr2.getFontSize(), 0); - assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr2.getParentParagraph().getBulletFont()); - - XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0); - assertEquals(2, pr3.getParentParagraph().getIndentLevel()); - assertEquals("Level 3", pr3.getParentParagraph().getText()); - assertEquals("Calibri", pr3.getFontFamily()); - assertEquals(24.0, pr3.getFontSize(), 0); - assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr3.getParentParagraph().getBulletFont()); - - XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0); - assertEquals(3, pr4.getParentParagraph().getIndentLevel()); - assertEquals("Level 4", pr4.getParentParagraph().getText()); - assertEquals("Calibri", pr4.getFontFamily()); - assertEquals(20.0, pr4.getFontSize(), 0); - assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0); - assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter()); - assertEquals("Arial", pr4.getParentParagraph().getBulletFont()); - - XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2); - assertEquals(VerticalAlignment.TOP, shape3.getVerticalAlignment()); - assertEquals("Content with caption", shape3.getText()); - - pr1 = shape3.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(0, pr1.getParentParagraph().getIndentLevel()); - assertEquals("Content with caption", pr1.getRawText()); - assertEquals("Calibri", pr1.getFontFamily()); - assertEquals(14.0, pr1.getFontSize(), 0); - - } - - void verifySlide10(XSLFSlide slide){ - XSLFTextShape footer = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_FTR); - - // now check text properties - assertEquals("Apache Software Foundation", footer.getText()); - assertEquals(VerticalAlignment.MIDDLE, footer.getVerticalAlignment()); - - XSLFTextRun r1 = footer.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); - assertEquals("Calibri", r1.getFontFamily()); - assertEquals(12.0, r1.getFontSize(), 0); - // TODO calculation of tint is incorrect - assertTrue(sameColor(new Color(64,64,64), r1.getFontColor())); - - XSLFTextShape dt = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_DT); - assertEquals("Friday, October 21, 2011", dt.getText()); - - XSLFTextShape sldNum = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_SLD_NUM); - assertEquals("10", sldNum.getText()); - } - - @Test - public void testTitleStyles() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlideMaster master = ppt.getSlideMasters().get(0); - XSLFTheme theme = master.getTheme(); - XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE); - XSLFSlide slide = ppt.createSlide(layout) ; - assertSame(layout, slide.getSlideLayout()); - assertSame(master, slide.getSlideMaster()); - - XSLFTextShape titleShape = slide.getPlaceholder(0); - titleShape.setText("Apache POI"); - XSLFTextParagraph paragraph = titleShape.getTextParagraphs().get(0); - XSLFTextRun textRun = paragraph.getTextRuns().get(0); - - // level 1 : default title style on the master slide - // /p:sldMaster/p:txStyles/p:titleStyle/a:lvl1pPr - CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getTitleStyle().getLvl1PPr(); - CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); - assertEquals(4400, lv1CPr.getSz()); - assertEquals(44.0, textRun.getFontSize(), 0); - assertEquals("+mj-lt", lv1CPr.getLatin().getTypeface()); - assertEquals("Calibri", theme.getMajorFont()); - assertEquals("Calibri", textRun.getFontFamily()); - lv1CPr.setSz(3200); - assertEquals(32.0, textRun.getFontSize(), 0); - lv1CPr.getLatin().setTypeface("Arial"); - assertEquals("Arial", textRun.getFontFamily()); - assertEquals(STTextAlignType.CTR, lv1PPr.getAlgn()); - assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); - lv1PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); - - // level 2: title placeholder on the master slide - // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="title"] - XSLFTextShape tx2 = master.getPlaceholder(0); - CTTextParagraphProperties lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); - CTTextCharacterProperties lv2CPr = lv2PPr.addNewDefRPr(); - lv2CPr.setSz(3300); - assertEquals(33.0, textRun.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", textRun.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, paragraph.getTextAlign()); - - - // level 3: title placeholder on the slide layout - // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] - XSLFTextShape tx3 = layout.getPlaceholder(0); - CTTextParagraphProperties lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); - CTTextCharacterProperties lv3CPr = lv3PPr.addNewDefRPr(); - lv3CPr.setSz(3400); - assertEquals(34.0, textRun.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", textRun.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); - - // level 4: default text properties in the shape itself - // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr - CTTextParagraphProperties lv4PPr = titleShape.getTextBody(true).getLstStyle().addNewLvl1PPr(); - CTTextCharacterProperties lv4CPr = lv4PPr.addNewDefRPr(); - lv4CPr.setSz(3500); - assertEquals(35.0, textRun.getFontSize(), 0); - lv4CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", textRun.getFontFamily()); - lv4PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); - - // level 5: text properties are defined in the text run - CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr(); - CTTextCharacterProperties lv5CPr = textRun.getRPr(false); - lv5CPr.setSz(3600); - assertEquals(36.0, textRun.getFontSize(), 0); - lv5CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", textRun.getFontFamily()); - lv5PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); - - ppt.close(); - } - - @Test - public void testBodyStyles() throws IOException { - XMLSlideShow ppt = new XMLSlideShow(); - - XSLFSlideMaster master = ppt.getSlideMasters().get(0); - XSLFTheme theme = master.getTheme(); - XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE_AND_CONTENT); - XSLFSlide slide = ppt.createSlide(layout) ; - assertSame(layout, slide.getSlideLayout()); - assertSame(master, slide.getSlideMaster()); - - XSLFTextShape tx1 = slide.getPlaceholder(1); - tx1.clearText(); - - XSLFTextParagraph p1 = tx1.addNewTextParagraph(); - assertEquals(0, p1.getIndentLevel()); - XSLFTextRun r1 = p1.addNewTextRun(); - r1.setText("Apache POI"); - - XSLFTextParagraph p2 = tx1.addNewTextParagraph(); - p2.setIndentLevel(1); - assertEquals(1, p2.getIndentLevel()); - XSLFTextRun r2 = p2.addNewTextRun(); - r2.setText("HSLF"); - - XSLFTextParagraph p3 = tx1.addNewTextParagraph(); - p3.setIndentLevel(2); - assertEquals(2, p3.getIndentLevel()); - XSLFTextRun r3 = p3.addNewTextRun(); - r3.setText("XSLF"); - - // level 1 : default title style on the master slide - // /p:sldMaster/p:txStyles/p:bodyStyle/a:lvl1pPr - CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl1PPr(); - CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); - CTTextParagraphProperties lv2PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl2PPr(); - CTTextCharacterProperties lv2CPr = lv2PPr.getDefRPr(); - CTTextParagraphProperties lv3PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl3PPr(); - CTTextCharacterProperties lv3CPr = lv3PPr.getDefRPr(); - // lv1 - assertEquals(3200, lv1CPr.getSz()); - assertEquals(32.0, r1.getFontSize(), 0); - assertEquals("+mn-lt", lv1CPr.getLatin().getTypeface()); - assertEquals("Calibri", theme.getMinorFont()); - assertEquals("Calibri", r1.getFontFamily()); - lv1CPr.setSz(3300); - assertEquals(33.0, r1.getFontSize(), 0); - lv1CPr.getLatin().setTypeface("Arial"); - assertEquals("Arial", r1.getFontFamily()); - assertEquals(STTextAlignType.L, lv1PPr.getAlgn()); - assertEquals(TextAlign.LEFT, p1.getTextAlign()); - lv1PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, p1.getTextAlign()); - //lv2 - assertEquals(2800, lv2CPr.getSz()); - assertEquals(28.0, r2.getFontSize(), 0); - lv2CPr.setSz(3300); - assertEquals(33.0, r2.getFontSize(), 0); - lv2CPr.getLatin().setTypeface("Times"); - assertEquals("Times", r2.getFontFamily()); - assertEquals(STTextAlignType.L, lv2PPr.getAlgn()); - assertEquals(TextAlign.LEFT, p2.getTextAlign()); - lv2PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, p2.getTextAlign()); - //lv3 - assertEquals(2400, lv3CPr.getSz()); - assertEquals(24.0, r3.getFontSize(), 0); - lv3CPr.setSz(2500); - assertEquals(25.0, r3.getFontSize(), 0); - lv3CPr.getLatin().setTypeface("Courier New"); - assertEquals("Courier New", r3.getFontFamily()); - assertEquals(STTextAlignType.L, lv3PPr.getAlgn()); - assertEquals(TextAlign.LEFT, p3.getTextAlign()); - lv3PPr.setAlgn(STTextAlignType.R); - assertEquals(TextAlign.RIGHT, p3.getTextAlign()); - - - // level 2: body placeholder on the master slide - // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="body"] - XSLFTextShape tx2 = master.getPlaceholder(1); - assertEquals(Placeholder.BODY, tx2.getTextType()); - - lv1PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); - lv1CPr = lv1PPr.addNewDefRPr(); - lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl2PPr(); - lv2CPr = lv2PPr.addNewDefRPr(); - lv3PPr = tx2.getTextBody(true).getLstStyle().addNewLvl3PPr(); - lv3CPr = lv3PPr.addNewDefRPr(); - - lv1CPr.setSz(3300); - assertEquals(33.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p1.getTextAlign()); - - lv2CPr.setSz(3300); - assertEquals(33.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p2.getTextAlign()); - - lv3CPr.setSz(3300); - assertEquals(33.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Times"); - assertEquals("Times", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p3.getTextAlign()); - - // level 3: body placeholder on the slide layout - // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] - XSLFTextShape tx3 = layout.getPlaceholder(1); - assertEquals(Placeholder.BODY, tx2.getTextType()); - lv1PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); - lv1CPr = lv1PPr.addNewDefRPr(); - lv2PPr = tx3.getTextBody(true).getLstStyle().addNewLvl2PPr(); - lv2CPr = lv2PPr.addNewDefRPr(); - lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl3PPr(); - lv3CPr = lv3PPr.addNewDefRPr(); - - lv1CPr.setSz(3400); - assertEquals(34.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p1.getTextAlign()); - - lv2CPr.setSz(3400); - assertEquals(34.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p2.getTextAlign()); - - lv3CPr.setSz(3400); - assertEquals(34.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Courier New"); - assertEquals("Courier New", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p3.getTextAlign()); - - // level 4: default text properties in the shape itself - // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr - lv1PPr = tx1.getTextBody(true).getLstStyle().addNewLvl1PPr(); - lv1CPr = lv1PPr.addNewDefRPr(); - lv2PPr = tx1.getTextBody(true).getLstStyle().addNewLvl2PPr(); - lv2CPr = lv2PPr.addNewDefRPr(); - lv3PPr = tx1.getTextBody(true).getLstStyle().addNewLvl3PPr(); - lv3CPr = lv3PPr.addNewDefRPr(); - - lv1CPr.setSz(3500); - assertEquals(35.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p1.getTextAlign()); - - lv2CPr.setSz(3500); - assertEquals(35.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p2.getTextAlign()); - - lv3CPr.setSz(3500); - assertEquals(35.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Arial"); - assertEquals("Arial", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.L); - assertEquals(TextAlign.LEFT, p3.getTextAlign()); - - // level 5: text properties are defined in the text run - lv1PPr = p1.getXmlObject().isSetPPr() ? p1.getXmlObject().getPPr() : p1.getXmlObject().addNewPPr(); - lv1CPr = r1.getRPr(false); - lv2PPr = p2.getXmlObject().isSetPPr() ? p2.getXmlObject().getPPr() : p2.getXmlObject().addNewPPr(); - lv2CPr = r2.getRPr(false); - lv3PPr = p3.getXmlObject().isSetPPr() ? p3.getXmlObject().getPPr() : p3.getXmlObject().addNewPPr(); - lv3CPr = r3.getRPr(false); - - lv1CPr.setSz(3600); - assertEquals(36.0, r1.getFontSize(), 0); - lv1CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", r1.getFontFamily()); - lv1PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p1.getTextAlign()); - - lv2CPr.setSz(3600); - assertEquals(36.0, r2.getFontSize(), 0); - lv2CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", r2.getFontFamily()); - lv2PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p2.getTextAlign()); - - lv3CPr.setSz(3600); - assertEquals(36.0, r3.getFontSize(), 0); - lv3CPr.addNewLatin().setTypeface("Calibri"); - assertEquals("Calibri", r3.getFontFamily()); - lv3PPr.setAlgn(STTextAlignType.CTR); - assertEquals(TextAlign.CENTER, p3.getTextAlign()); - - ppt.close(); - } - - @Test - public void metroBlob() throws IOException { - assumeFalse(xslfOnly); - File f = POIDataSamples.getSlideShowInstance().getFile("bug52297.ppt"); - SlideShow ppt = SlideShowFactory.create(f); - HSLFTextShape sh = (HSLFTextShape)ppt.getSlides().get(1).getShapes().get(3); - XSLFAutoShape xsh = (XSLFAutoShape)sh.getMetroShape(); - String textExp = " ___ ___ ___ ________ __ _______ ___ ___________ __________ __ _____ ___ ___ ___ _______ ____ ______ ___________ _____________ ___ _______ ______ ____ ______ __ ___________ __________ ___ _________ _____ ________ __________ ___ _______ __________ "; - String textAct = xsh.getText(); - ppt.close(); - assertEquals(textExp, textAct); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.apache.poi.sl.TestCommonSL.sameColor; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; +import static org.apache.poi.xslf.usermodel.TestXSLFSimpleShape.getSpPr; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.hslf.usermodel.HSLFTextShape; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; +import org.apache.poi.sl.usermodel.VerticalAlignment; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; +import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; +import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; + +public class TestXSLFTextShape { + private static boolean xslfOnly = false; + + @BeforeClass + public static void checkHslf() { + try { + Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); + } catch (Exception e) { + xslfOnly = true; + } + } + + @Test + public void testLayouts() throws IOException { + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx"); + + List slide = ppt.getSlides(); + + verifySlide1(slide.get(0)); + verifySlide2(slide.get(1)); + verifySlide3(slide.get(2)); + verifySlide4(slide.get(3)); + verifySlide7(slide.get(6)); + verifySlide8(slide.get(7)); + verifySlide10(slide.get(9)); + + ppt.close(); + } + + void verifySlide1(XSLFSlide slide){ + XSLFSlideLayout layout = slide.getSlideLayout(); + List shapes = slide.getShapes(); + assertEquals("Title Slide",layout.getName()); + + XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); + CTPlaceholder ph1 = shape1.getCTPlaceholder(); + assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape1).getXfrm()); + + XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); + assertNotNull(getSpPr(masterShape1).getXfrm()); + assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); + + CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && + !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && + !bodyPr1.isSetAnchor() + ); + assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); + + // now check text properties + assertEquals("Centered Title", shape1.getText()); + XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals("Calibri", r1.getFontFamily()); + assertEquals(44.0, r1.getFontSize(), 0); + assertTrue(sameColor(Color.black, r1.getFontColor())); + + XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); + CTPlaceholder ph2 = shape2.getCTPlaceholder(); + assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape2).getXfrm()); + + XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); + assertNotNull(getSpPr(masterShape2).getXfrm()); + assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); + + CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && + !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && + !bodyPr2.isSetAnchor() + ); + assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); + + assertEquals("subtitle", shape2.getText()); + XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals("Calibri", r2.getFontFamily()); + assertEquals(32.0, r2.getFontSize(), 0); + // TODO fix calculation of tint + //assertEquals(new Color(137, 137, 137), r2.getFontColor()); + } + + void verifySlide2(XSLFSlide slide){ + XSLFSlideLayout layout = slide.getSlideLayout(); + List shapes = slide.getShapes(); + assertEquals("Title and Content",layout.getName()); + + XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); + CTPlaceholder ph1 = shape1.getCTPlaceholder(); + assertEquals(STPlaceholderType.TITLE, ph1.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape1).getXfrm()); + + XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); + // layout does not have anchor info either, it is in the slide master + assertNull(getSpPr(masterShape1).getXfrm()); + masterShape1 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph1); + assertNotNull(getSpPr(masterShape1).getXfrm()); + assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); + + CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && + !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && + !bodyPr1.isSetAnchor() + ); + assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); + + // now check text properties + assertEquals("Title", shape1.getText()); + XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals("Calibri", r1.getFontFamily()); + assertEquals(44.0, r1.getFontSize(), 0); + assertTrue(sameColor(Color.black, r1.getFontColor())); + + XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); + CTPlaceholder ph2 = shape2.getCTPlaceholder(); + assertFalse(ph2.isSetType()); // + assertTrue(ph2.isSetIdx()); + assertEquals(1, ph2.getIdx()); + // anchor is not defined in the shape + assertNull(getSpPr(shape2).getXfrm()); + + XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); + // anchor of the body text is missing in the slide layout, llokup in the slide master + assertNull(getSpPr(masterShape2).getXfrm()); + masterShape2 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph2); + assertNotNull(getSpPr(masterShape2).getXfrm()); + assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); + + CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && + !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && + !bodyPr2.isSetAnchor() + ); + assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); + + XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(0, pr1.getParentParagraph().getIndentLevel()); + assertEquals("Content", pr1.getRawText()); + assertEquals("Calibri", pr1.getFontFamily()); + assertEquals(32.0, pr1.getFontSize(), 0); + assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr1.getParentParagraph().getBulletFont()); + + XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0); + assertEquals(1, pr2.getParentParagraph().getIndentLevel()); + assertEquals("Level 2", pr2.getRawText()); + assertEquals("Calibri", pr2.getFontFamily()); + assertEquals(28.0, pr2.getFontSize(), 0); + assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr2.getParentParagraph().getBulletFont()); + + XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0); + assertEquals(2, pr3.getParentParagraph().getIndentLevel()); + assertEquals("Level 3", pr3.getRawText()); + assertEquals("Calibri", pr3.getFontFamily()); + assertEquals(24.0, pr3.getFontSize(), 0); + assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr3.getParentParagraph().getBulletFont()); + + XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0); + assertEquals(3, pr4.getParentParagraph().getIndentLevel()); + assertEquals("Level 4", pr4.getRawText()); + assertEquals("Calibri", pr4.getFontFamily()); + assertEquals(20.0, pr4.getFontSize(), 0); + assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr4.getParentParagraph().getBulletFont()); + + XSLFTextRun pr5 = shape2.getTextParagraphs().get(4).getTextRuns().get(0); + assertEquals(4, pr5.getParentParagraph().getIndentLevel()); + assertEquals("Level 5", pr5.getRawText()); + assertEquals("Calibri", pr5.getFontFamily()); + assertEquals(20.0, pr5.getFontSize(), 0); + assertEquals(162.0, pr5.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u00bb", pr5.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr5.getParentParagraph().getBulletFont()); + + } + + void verifySlide3(XSLFSlide slide){ + XSLFSlideLayout layout = slide.getSlideLayout(); + List shapes = slide.getShapes(); + assertEquals("Section Header",layout.getName()); + + XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); + CTPlaceholder ph1 = shape1.getCTPlaceholder(); + assertEquals(STPlaceholderType.TITLE, ph1.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape1).getXfrm()); + + XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); + assertNotNull(getSpPr(masterShape1).getXfrm()); + assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); + + CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && + !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && + !bodyPr1.isSetAnchor() + ); + assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.TOP, shape1.getVerticalAlignment()); + + // now check text properties + assertEquals("Section Title", shape1.getText()); + XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign()); + assertEquals("Calibri", r1.getFontFamily()); + assertEquals(40.0, r1.getFontSize(), 0); + assertTrue(sameColor(Color.black, r1.getFontColor())); + assertTrue(r1.isBold()); + assertFalse(r1.isItalic()); + assertFalse(r1.isUnderlined()); + + XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); + CTPlaceholder ph2 = shape2.getCTPlaceholder(); + assertEquals(STPlaceholderType.BODY, ph2.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape2).getXfrm()); + + XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); + assertNotNull(getSpPr(masterShape2).getXfrm()); + assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); + + CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && + !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && + !bodyPr2.isSetAnchor() + ); + assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.BOTTOM, shape2.getVerticalAlignment()); + + assertEquals("Section Header", shape2.getText()); + XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(TextAlign.LEFT, r2.getParentParagraph().getTextAlign()); + assertEquals("Calibri", r2.getFontFamily()); + assertEquals(20.0, r2.getFontSize(), 0); + // TODO fix calculation of tint + //assertEquals(new Color(137, 137, 137), r2.getFontColor()); + } + + void verifySlide4(XSLFSlide slide){ + XSLFSlideLayout layout = slide.getSlideLayout(); + List shapes = slide.getShapes(); + assertEquals("Two Content",layout.getName()); + + XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); + CTPlaceholder ph1 = shape1.getCTPlaceholder(); + assertEquals(STPlaceholderType.TITLE, ph1.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape1).getXfrm()); + + XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); + // layout does not have anchor info either, it is in the slide master + assertNull(getSpPr(masterShape1).getXfrm()); + masterShape1 = (XSLFTextShape)layout.getSlideMaster().getPlaceholder(ph1); + assertNotNull(getSpPr(masterShape1).getXfrm()); + assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); + + CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && + !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && + !bodyPr1.isSetAnchor() + ); + assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); + + // now check text properties + assertEquals("Title", shape1.getText()); + XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); + assertEquals("Calibri", r1.getFontFamily()); + assertEquals(44.0, r1.getFontSize(), 0); + assertTrue(sameColor(Color.black, r1.getFontColor())); + + XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); + CTPlaceholder ph2 = shape2.getCTPlaceholder(); + assertFalse(ph2.isSetType()); + assertTrue(ph2.isSetIdx()); + assertEquals(1, ph2.getIdx()); // + // anchor is not defined in the shape + assertNull(getSpPr(shape2).getXfrm()); + + XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); + assertNotNull(getSpPr(masterShape2).getXfrm()); + assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); + + CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && + !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && + !bodyPr2.isSetAnchor() + ); + assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); + + XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(0, pr1.getParentParagraph().getIndentLevel()); + assertEquals("Left", pr1.getRawText()); + assertEquals("Calibri", pr1.getFontFamily()); + assertEquals(28.0, pr1.getFontSize(), 0); + assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr1.getParentParagraph().getBulletFont()); + + XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0); + assertEquals(1, pr2.getParentParagraph().getIndentLevel()); + assertEquals("Level 2", pr2.getParentParagraph().getText()); + assertEquals("Calibri", pr2.getFontFamily()); + assertEquals(24.0, pr2.getFontSize(), 0); + assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr2.getParentParagraph().getBulletFont()); + + XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0); + assertEquals(2, pr3.getParentParagraph().getIndentLevel()); + assertEquals("Level 3", pr3.getParentParagraph().getText()); + assertEquals("Calibri", pr3.getFontFamily()); + assertEquals(20.0, pr3.getFontSize(), 0); + assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr3.getParentParagraph().getBulletFont()); + + XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0); + assertEquals(3, pr4.getParentParagraph().getIndentLevel()); + assertEquals("Level 4", pr4.getParentParagraph().getText()); + assertEquals("Calibri", pr4.getFontFamily()); + assertEquals(18.0, pr4.getFontSize(), 0); + assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr4.getParentParagraph().getBulletFont()); + + XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2); + XSLFTextRun pr5 = shape3.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(0, pr5.getParentParagraph().getIndentLevel()); + assertEquals("Right", pr5.getRawText()); + assertEquals("Calibri", pr5.getFontFamily()); + assertTrue(sameColor(Color.black, pr5.getFontColor())); + } + + @SuppressWarnings("unused") + void verifySlide5(XSLFSlide slide){ + XSLFSlideLayout layout = slide.getSlideLayout(); + List shapes = slide.getShapes(); + // TODO + } + + void verifySlide7(XSLFSlide slide){ + XSLFSlideLayout layout = slide.getSlideLayout(); + List shapes = slide.getShapes(); + assertEquals("Blank",layout.getName()); + + XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); + CTPlaceholder ph1 = shape1.getCTPlaceholder(); + assertEquals(STPlaceholderType.TITLE, ph1.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape1).getXfrm()); + + CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && + !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && + !bodyPr1.isSetAnchor() + ); + assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment()); + + // now check text properties + assertEquals("Blank with Default Title", shape1.getText()); + XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); + assertEquals("Calibri", r1.getFontFamily()); + assertEquals(44.0, r1.getFontSize(), 0); + assertTrue(sameColor(Color.black, r1.getFontColor())); + assertFalse(r1.isBold()); + + XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); + + CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && + !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && + !bodyPr2.isSetAnchor() + ); + assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); + + XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(0, pr1.getParentParagraph().getIndentLevel()); + assertEquals("Default Text", pr1.getRawText()); + assertEquals("Calibri", pr1.getFontFamily()); + assertEquals(18.0, pr1.getFontSize(), 0); + + XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2); + assertEquals("Default", shape3.getTextParagraphs().get(0).getText()); + assertEquals("Text with levels", shape3.getTextParagraphs().get(1).getText()); + assertEquals("Level 1", shape3.getTextParagraphs().get(2).getText()); + assertEquals("Level 2", shape3.getTextParagraphs().get(3).getText()); + assertEquals("Level 3", shape3.getTextParagraphs().get(4).getText()); + + for(int p = 0; p < 5; p++) { + XSLFTextParagraph pr = shape3.getTextParagraphs().get(p); + assertEquals("Calibri", pr.getTextRuns().get(0).getFontFamily()); + assertEquals(18.0, pr.getTextRuns().get(0).getFontSize(), 0); + } + } + + void verifySlide8(XSLFSlide slide){ + XSLFSlideLayout layout = slide.getSlideLayout(); + List shapes = slide.getShapes(); + assertEquals("Content with Caption",layout.getName()); + + XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0); + CTPlaceholder ph1 = shape1.getCTPlaceholder(); + assertEquals(STPlaceholderType.TITLE, ph1.getType()); + // anchor is not defined in the shape + assertNull(getSpPr(shape1).getXfrm()); + + XSLFTextShape masterShape1 = (XSLFTextShape)layout.getPlaceholder(ph1); + // layout does not have anchor info either, it is in the slide master + assertNotNull(getSpPr(masterShape1).getXfrm()); + assertEquals(masterShape1.getAnchor(), shape1.getAnchor()); + + CTTextBodyProperties bodyPr1 = shape1.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr1.isSetLIns() && !bodyPr1.isSetRIns() && + !bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() && + !bodyPr1.isSetAnchor() + ); + assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape1.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape1.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.BOTTOM, shape1.getVerticalAlignment()); + + // now check text properties + assertEquals("Caption", shape1.getText()); + XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign()); + assertEquals("Calibri", r1.getFontFamily()); + assertEquals(20.0, r1.getFontSize(), 0); + assertTrue(sameColor(Color.black, r1.getFontColor())); + assertTrue(r1.isBold()); + + XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); + CTPlaceholder ph2 = shape2.getCTPlaceholder(); + assertFalse(ph2.isSetType()); + assertTrue(ph2.isSetIdx()); + assertEquals(1, ph2.getIdx()); + // anchor is not defined in the shape + assertNull(getSpPr(shape2).getXfrm()); + + XSLFTextShape masterShape2 = (XSLFTextShape)layout.getPlaceholder(ph2); + assertNotNull(getSpPr(masterShape2).getXfrm()); + assertEquals(masterShape2.getAnchor(), shape2.getAnchor()); + + CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr(); + // none of the following properties are set in the shapes and fetched from the master shape + assertTrue( + !bodyPr2.isSetLIns() && !bodyPr2.isSetRIns() && + !bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() && + !bodyPr2.isSetAnchor() + ); + assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1" + assertEquals(7.2, shape2.getRightInset(), 0); // 0.1" + assertEquals(3.6, shape2.getTopInset(), 0); // 0.05" + assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05" + assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment()); + + XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(0, pr1.getParentParagraph().getIndentLevel()); + assertEquals("Level 1", pr1.getRawText()); + assertEquals("Calibri", pr1.getFontFamily()); + assertEquals(32.0, pr1.getFontSize(), 0); + assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr1.getParentParagraph().getBulletFont()); + + XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0); + assertEquals(1, pr2.getParentParagraph().getIndentLevel()); + assertEquals("Level 2", pr2.getParentParagraph().getText()); + assertEquals("Calibri", pr2.getFontFamily()); + assertEquals(28.0, pr2.getFontSize(), 0); + assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr2.getParentParagraph().getBulletFont()); + + XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0); + assertEquals(2, pr3.getParentParagraph().getIndentLevel()); + assertEquals("Level 3", pr3.getParentParagraph().getText()); + assertEquals("Calibri", pr3.getFontFamily()); + assertEquals(24.0, pr3.getFontSize(), 0); + assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr3.getParentParagraph().getBulletFont()); + + XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0); + assertEquals(3, pr4.getParentParagraph().getIndentLevel()); + assertEquals("Level 4", pr4.getParentParagraph().getText()); + assertEquals("Calibri", pr4.getFontFamily()); + assertEquals(20.0, pr4.getFontSize(), 0); + assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0); + assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter()); + assertEquals("Arial", pr4.getParentParagraph().getBulletFont()); + + XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2); + assertEquals(VerticalAlignment.TOP, shape3.getVerticalAlignment()); + assertEquals("Content with caption", shape3.getText()); + + pr1 = shape3.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(0, pr1.getParentParagraph().getIndentLevel()); + assertEquals("Content with caption", pr1.getRawText()); + assertEquals("Calibri", pr1.getFontFamily()); + assertEquals(14.0, pr1.getFontSize(), 0); + + } + + void verifySlide10(XSLFSlide slide){ + XSLFTextShape footer = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_FTR); + + // now check text properties + assertEquals("Apache Software Foundation", footer.getText()); + assertEquals(VerticalAlignment.MIDDLE, footer.getVerticalAlignment()); + + XSLFTextRun r1 = footer.getTextParagraphs().get(0).getTextRuns().get(0); + assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); + assertEquals("Calibri", r1.getFontFamily()); + assertEquals(12.0, r1.getFontSize(), 0); + // TODO calculation of tint is incorrect + assertTrue(sameColor(new Color(64,64,64), r1.getFontColor())); + + XSLFTextShape dt = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_DT); + assertEquals("Friday, October 21, 2011", dt.getText()); + + XSLFTextShape sldNum = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_SLD_NUM); + assertEquals("10", sldNum.getText()); + } + + @Test + public void testTitleStyles() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + + XSLFSlideMaster master = ppt.getSlideMasters().get(0); + XSLFTheme theme = master.getTheme(); + XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE); + XSLFSlide slide = ppt.createSlide(layout) ; + assertSame(layout, slide.getSlideLayout()); + assertSame(master, slide.getSlideMaster()); + + XSLFTextShape titleShape = slide.getPlaceholder(0); + titleShape.setText("Apache POI"); + XSLFTextParagraph paragraph = titleShape.getTextParagraphs().get(0); + XSLFTextRun textRun = paragraph.getTextRuns().get(0); + + // level 1 : default title style on the master slide + // /p:sldMaster/p:txStyles/p:titleStyle/a:lvl1pPr + CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getTitleStyle().getLvl1PPr(); + CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); + assertEquals(4400, lv1CPr.getSz()); + assertEquals(44.0, textRun.getFontSize(), 0); + assertEquals("+mj-lt", lv1CPr.getLatin().getTypeface()); + assertEquals("Calibri", theme.getMajorFont()); + assertEquals("Calibri", textRun.getFontFamily()); + lv1CPr.setSz(3200); + assertEquals(32.0, textRun.getFontSize(), 0); + lv1CPr.getLatin().setTypeface("Arial"); + assertEquals("Arial", textRun.getFontFamily()); + assertEquals(STTextAlignType.CTR, lv1PPr.getAlgn()); + assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); + lv1PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); + + // level 2: title placeholder on the master slide + // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="title"] + XSLFTextShape tx2 = master.getPlaceholder(0); + CTTextParagraphProperties lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); + CTTextCharacterProperties lv2CPr = lv2PPr.addNewDefRPr(); + lv2CPr.setSz(3300); + assertEquals(33.0, textRun.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", textRun.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, paragraph.getTextAlign()); + + + // level 3: title placeholder on the slide layout + // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] + XSLFTextShape tx3 = layout.getPlaceholder(0); + CTTextParagraphProperties lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); + CTTextCharacterProperties lv3CPr = lv3PPr.addNewDefRPr(); + lv3CPr.setSz(3400); + assertEquals(34.0, textRun.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", textRun.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); + + // level 4: default text properties in the shape itself + // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr + CTTextParagraphProperties lv4PPr = titleShape.getTextBody(true).getLstStyle().addNewLvl1PPr(); + CTTextCharacterProperties lv4CPr = lv4PPr.addNewDefRPr(); + lv4CPr.setSz(3500); + assertEquals(35.0, textRun.getFontSize(), 0); + lv4CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", textRun.getFontFamily()); + lv4PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, paragraph.getTextAlign()); + + // level 5: text properties are defined in the text run + CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr(); + CTTextCharacterProperties lv5CPr = textRun.getRPr(false); + lv5CPr.setSz(3600); + assertEquals(36.0, textRun.getFontSize(), 0); + lv5CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", textRun.getFontFamily()); + lv5PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); + + ppt.close(); + } + + @Test + public void testBodyStyles() throws IOException { + XMLSlideShow ppt = new XMLSlideShow(); + + XSLFSlideMaster master = ppt.getSlideMasters().get(0); + XSLFTheme theme = master.getTheme(); + XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE_AND_CONTENT); + XSLFSlide slide = ppt.createSlide(layout) ; + assertSame(layout, slide.getSlideLayout()); + assertSame(master, slide.getSlideMaster()); + + XSLFTextShape tx1 = slide.getPlaceholder(1); + tx1.clearText(); + + XSLFTextParagraph p1 = tx1.addNewTextParagraph(); + assertEquals(0, p1.getIndentLevel()); + XSLFTextRun r1 = p1.addNewTextRun(); + r1.setText("Apache POI"); + + XSLFTextParagraph p2 = tx1.addNewTextParagraph(); + p2.setIndentLevel(1); + assertEquals(1, p2.getIndentLevel()); + XSLFTextRun r2 = p2.addNewTextRun(); + r2.setText("HSLF"); + + XSLFTextParagraph p3 = tx1.addNewTextParagraph(); + p3.setIndentLevel(2); + assertEquals(2, p3.getIndentLevel()); + XSLFTextRun r3 = p3.addNewTextRun(); + r3.setText("XSLF"); + + // level 1 : default title style on the master slide + // /p:sldMaster/p:txStyles/p:bodyStyle/a:lvl1pPr + CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl1PPr(); + CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr(); + CTTextParagraphProperties lv2PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl2PPr(); + CTTextCharacterProperties lv2CPr = lv2PPr.getDefRPr(); + CTTextParagraphProperties lv3PPr = master.getXmlObject().getTxStyles().getBodyStyle().getLvl3PPr(); + CTTextCharacterProperties lv3CPr = lv3PPr.getDefRPr(); + // lv1 + assertEquals(3200, lv1CPr.getSz()); + assertEquals(32.0, r1.getFontSize(), 0); + assertEquals("+mn-lt", lv1CPr.getLatin().getTypeface()); + assertEquals("Calibri", theme.getMinorFont()); + assertEquals("Calibri", r1.getFontFamily()); + lv1CPr.setSz(3300); + assertEquals(33.0, r1.getFontSize(), 0); + lv1CPr.getLatin().setTypeface("Arial"); + assertEquals("Arial", r1.getFontFamily()); + assertEquals(STTextAlignType.L, lv1PPr.getAlgn()); + assertEquals(TextAlign.LEFT, p1.getTextAlign()); + lv1PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, p1.getTextAlign()); + //lv2 + assertEquals(2800, lv2CPr.getSz()); + assertEquals(28.0, r2.getFontSize(), 0); + lv2CPr.setSz(3300); + assertEquals(33.0, r2.getFontSize(), 0); + lv2CPr.getLatin().setTypeface("Times"); + assertEquals("Times", r2.getFontFamily()); + assertEquals(STTextAlignType.L, lv2PPr.getAlgn()); + assertEquals(TextAlign.LEFT, p2.getTextAlign()); + lv2PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, p2.getTextAlign()); + //lv3 + assertEquals(2400, lv3CPr.getSz()); + assertEquals(24.0, r3.getFontSize(), 0); + lv3CPr.setSz(2500); + assertEquals(25.0, r3.getFontSize(), 0); + lv3CPr.getLatin().setTypeface("Courier New"); + assertEquals("Courier New", r3.getFontFamily()); + assertEquals(STTextAlignType.L, lv3PPr.getAlgn()); + assertEquals(TextAlign.LEFT, p3.getTextAlign()); + lv3PPr.setAlgn(STTextAlignType.R); + assertEquals(TextAlign.RIGHT, p3.getTextAlign()); + + + // level 2: body placeholder on the master slide + // /p:sldMaster/p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="body"] + XSLFTextShape tx2 = master.getPlaceholder(1); + assertEquals(Placeholder.BODY, tx2.getTextType()); + + lv1PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr(); + lv1CPr = lv1PPr.addNewDefRPr(); + lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl2PPr(); + lv2CPr = lv2PPr.addNewDefRPr(); + lv3PPr = tx2.getTextBody(true).getLstStyle().addNewLvl3PPr(); + lv3CPr = lv3PPr.addNewDefRPr(); + + lv1CPr.setSz(3300); + assertEquals(33.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p1.getTextAlign()); + + lv2CPr.setSz(3300); + assertEquals(33.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p2.getTextAlign()); + + lv3CPr.setSz(3300); + assertEquals(33.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Times"); + assertEquals("Times", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p3.getTextAlign()); + + // level 3: body placeholder on the slide layout + // /p:sldLayout /p:cSld/p:spTree/p:sp/p:nvPr/p:ph[@type="ctrTitle"] + XSLFTextShape tx3 = layout.getPlaceholder(1); + assertEquals(Placeholder.BODY, tx2.getTextType()); + lv1PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr(); + lv1CPr = lv1PPr.addNewDefRPr(); + lv2PPr = tx3.getTextBody(true).getLstStyle().addNewLvl2PPr(); + lv2CPr = lv2PPr.addNewDefRPr(); + lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl3PPr(); + lv3CPr = lv3PPr.addNewDefRPr(); + + lv1CPr.setSz(3400); + assertEquals(34.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p1.getTextAlign()); + + lv2CPr.setSz(3400); + assertEquals(34.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p2.getTextAlign()); + + lv3CPr.setSz(3400); + assertEquals(34.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Courier New"); + assertEquals("Courier New", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p3.getTextAlign()); + + // level 4: default text properties in the shape itself + // ./p:sp/p:txBody/a:lstStyle/a:lvl1pPr + lv1PPr = tx1.getTextBody(true).getLstStyle().addNewLvl1PPr(); + lv1CPr = lv1PPr.addNewDefRPr(); + lv2PPr = tx1.getTextBody(true).getLstStyle().addNewLvl2PPr(); + lv2CPr = lv2PPr.addNewDefRPr(); + lv3PPr = tx1.getTextBody(true).getLstStyle().addNewLvl3PPr(); + lv3CPr = lv3PPr.addNewDefRPr(); + + lv1CPr.setSz(3500); + assertEquals(35.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p1.getTextAlign()); + + lv2CPr.setSz(3500); + assertEquals(35.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p2.getTextAlign()); + + lv3CPr.setSz(3500); + assertEquals(35.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Arial"); + assertEquals("Arial", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.L); + assertEquals(TextAlign.LEFT, p3.getTextAlign()); + + // level 5: text properties are defined in the text run + lv1PPr = p1.getXmlObject().isSetPPr() ? p1.getXmlObject().getPPr() : p1.getXmlObject().addNewPPr(); + lv1CPr = r1.getRPr(false); + lv2PPr = p2.getXmlObject().isSetPPr() ? p2.getXmlObject().getPPr() : p2.getXmlObject().addNewPPr(); + lv2CPr = r2.getRPr(false); + lv3PPr = p3.getXmlObject().isSetPPr() ? p3.getXmlObject().getPPr() : p3.getXmlObject().addNewPPr(); + lv3CPr = r3.getRPr(false); + + lv1CPr.setSz(3600); + assertEquals(36.0, r1.getFontSize(), 0); + lv1CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", r1.getFontFamily()); + lv1PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p1.getTextAlign()); + + lv2CPr.setSz(3600); + assertEquals(36.0, r2.getFontSize(), 0); + lv2CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", r2.getFontFamily()); + lv2PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p2.getTextAlign()); + + lv3CPr.setSz(3600); + assertEquals(36.0, r3.getFontSize(), 0); + lv3CPr.addNewLatin().setTypeface("Calibri"); + assertEquals("Calibri", r3.getFontFamily()); + lv3PPr.setAlgn(STTextAlignType.CTR); + assertEquals(TextAlign.CENTER, p3.getTextAlign()); + + ppt.close(); + } + + @Test + public void metroBlob() throws IOException { + assumeFalse(xslfOnly); + File f = POIDataSamples.getSlideShowInstance().getFile("bug52297.ppt"); + SlideShow ppt = SlideShowFactory.create(f); + HSLFTextShape sh = (HSLFTextShape)ppt.getSlides().get(1).getShapes().get(3); + XSLFAutoShape xsh = (XSLFAutoShape)sh.getMetroShape(); + String textExp = " ___ ___ ___ ________ __ _______ ___ ___________ __________ __ _____ ___ ___ ___ _______ ____ ______ ___________ _____________ ___ _______ ______ ____ ______ __ ___________ __________ ___ _________ _____ ________ __________ ___ _______ __________ "; + String textAct = xsh.getText(); + ppt.close(); + assertEquals(textExp, textAct); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java index a181e4f8ff..1a504e7950 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java @@ -1,171 +1,171 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xslf.usermodel; - -import static org.apache.poi.sl.TestCommonSL.sameColor; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.awt.Color; -import java.util.List; - -import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; -import org.apache.poi.xslf.XSLFTestDataSamples; -import org.junit.Test; - -/** - * test reading properties from a multi-theme and multi-master document - * - * @author Yegor Kozlov - */ -public class TestXSLFTheme { - @Test - public void testRead(){ - XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("themes.pptx"); - List slides = ppt.getSlides(); - - slide1(slides.get(0)); - slide2(slides.get(1)); - slide3(slides.get(2)); - slide4(slides.get(3)); - slide5(slides.get(4)); - slide6(slides.get(5)); - slide7(slides.get(6)); - slide8(slides.get(7)); - slide9(slides.get(8)); - slide10(slides.get(9)); - } - - private XSLFShape getShape(XSLFSheet sheet, String name){ - for(XSLFShape sh : sheet.getShapes()){ - if(sh.getShapeName().equals(name)) { - return sh; - } - } - throw new IllegalArgumentException("Shape not found: " + name); - } - - void slide1(XSLFSlide slide){ - assertEquals(Color.WHITE, slide.getBackground().getFillColor()); - - XSLFTheme theme = slide.getTheme(); - assertEquals("Office Theme", theme.getName()); - - XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 3"); - XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(Color.white, run1.getFontColor())); - assertEquals(new Color(79, 129, 189), sh1.getFillColor()); - assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill - - } - - void slide2(XSLFSlide slide){ - // Background 2, darker 10% - // YK: PPT shows slightly different color: new Color(221, 217, 195) - assertEquals(new Color(221, 217, 195), slide.getBackground().getFillColor()); - } - - void slide3(XSLFSlide slide){ - PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); - assertTrue(fs instanceof GradientPaint); - } - - void slide4(XSLFSlide slide){ - PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); - assertTrue(fs instanceof GradientPaint); - - XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 4"); - XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(Color.white, run1.getFontColor())); - assertEquals(new Color(148, 198, 0), sh1.getFillColor()); - assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill - - XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 3"); - XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); - assertNull(sh2.getFillColor()); // no fill - - assertTrue(slide.getSlideLayout().getFollowMasterGraphics()); - } - - void slide5(XSLFSlide slide){ - PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); - assertTrue(fs instanceof TexturePaint); - - XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 1"); - XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); - assertNull(sh2.getFillColor()); // no fill - // font size is 40pt and scale factor is 90% - assertEquals(36.0, run2.getFontSize(), 0); - - assertTrue(slide.getSlideLayout().getFollowMasterGraphics()); - } - - void slide6(XSLFSlide slide){ - - XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Subtitle 3"); - XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(new Color(66, 66, 66), run1.getFontColor())); - assertNull(sh1.getFillColor()); // no fill - - XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 2"); - XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); - assertNull(sh2.getFillColor()); // no fill - - assertFalse(slide.getSlideLayout().getFollowMasterGraphics()); - } - - void slide7(XSLFSlide slide){ - - //YK: PPT reports a slightly different color: r=189,g=239,b=87 - assertEquals(new Color(189, 239, 87), slide.getBackground().getFillColor()); - - assertFalse(slide.getFollowMasterGraphics()); - } - - void slide8(XSLFSlide slide){ - PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); - assertTrue(fs instanceof TexturePaint); - } - - void slide9(XSLFSlide slide){ - PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); - assertTrue(fs instanceof TexturePaint); - } - - void slide10(XSLFSlide slide){ - PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); - assertTrue(fs instanceof GradientPaint); - - XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Title 3"); - XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(Color.white, run1.getFontColor())); - assertNull(sh1.getFillColor()); // no fill - - XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Subtitle 4"); - XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertTrue(sameColor(Color.white, run2.getFontColor())); - assertNull(sh2.getFillColor()); // no fill - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xslf.usermodel; + +import static org.apache.poi.sl.TestCommonSL.sameColor; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.awt.Color; +import java.util.List; + +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; + +/** + * test reading properties from a multi-theme and multi-master document + * + * @author Yegor Kozlov + */ +public class TestXSLFTheme { + @Test + public void testRead(){ + XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("themes.pptx"); + List slides = ppt.getSlides(); + + slide1(slides.get(0)); + slide2(slides.get(1)); + slide3(slides.get(2)); + slide4(slides.get(3)); + slide5(slides.get(4)); + slide6(slides.get(5)); + slide7(slides.get(6)); + slide8(slides.get(7)); + slide9(slides.get(8)); + slide10(slides.get(9)); + } + + private XSLFShape getShape(XSLFSheet sheet, String name){ + for(XSLFShape sh : sheet.getShapes()){ + if(sh.getShapeName().equals(name)) { + return sh; + } + } + throw new IllegalArgumentException("Shape not found: " + name); + } + + void slide1(XSLFSlide slide){ + assertEquals(Color.WHITE, slide.getBackground().getFillColor()); + + XSLFTheme theme = slide.getTheme(); + assertEquals("Office Theme", theme.getName()); + + XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 3"); + XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(Color.white, run1.getFontColor())); + assertEquals(new Color(79, 129, 189), sh1.getFillColor()); + assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill + + } + + void slide2(XSLFSlide slide){ + // Background 2, darker 10% + // YK: PPT shows slightly different color: new Color(221, 217, 195) + assertEquals(new Color(221, 217, 195), slide.getBackground().getFillColor()); + } + + void slide3(XSLFSlide slide){ + PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); + assertTrue(fs instanceof GradientPaint); + } + + void slide4(XSLFSlide slide){ + PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); + assertTrue(fs instanceof GradientPaint); + + XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 4"); + XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(Color.white, run1.getFontColor())); + assertEquals(new Color(148, 198, 0), sh1.getFillColor()); + assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill + + XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 3"); + XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); + assertNull(sh2.getFillColor()); // no fill + + assertTrue(slide.getSlideLayout().getFollowMasterGraphics()); + } + + void slide5(XSLFSlide slide){ + PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); + assertTrue(fs instanceof TexturePaint); + + XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 1"); + XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); + assertNull(sh2.getFillColor()); // no fill + // font size is 40pt and scale factor is 90% + assertEquals(36.0, run2.getFontSize(), 0); + + assertTrue(slide.getSlideLayout().getFollowMasterGraphics()); + } + + void slide6(XSLFSlide slide){ + + XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Subtitle 3"); + XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(new Color(66, 66, 66), run1.getFontColor())); + assertNull(sh1.getFillColor()); // no fill + + XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 2"); + XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); + assertNull(sh2.getFillColor()); // no fill + + assertFalse(slide.getSlideLayout().getFollowMasterGraphics()); + } + + void slide7(XSLFSlide slide){ + + //YK: PPT reports a slightly different color: r=189,g=239,b=87 + assertEquals(new Color(189, 239, 87), slide.getBackground().getFillColor()); + + assertFalse(slide.getFollowMasterGraphics()); + } + + void slide8(XSLFSlide slide){ + PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); + assertTrue(fs instanceof TexturePaint); + } + + void slide9(XSLFSlide slide){ + PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); + assertTrue(fs instanceof TexturePaint); + } + + void slide10(XSLFSlide slide){ + PaintStyle fs = slide.getBackground().getFillStyle().getPaint(); + assertTrue(fs instanceof GradientPaint); + + XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Title 3"); + XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(Color.white, run1.getFontColor())); + assertNull(sh1.getFillColor()); // no fill + + XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Subtitle 4"); + XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); + assertTrue(sameColor(Color.white, run2.getFontColor())); + assertNull(sh2.getFillColor()); // no fill + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/TestXSSFCloneSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/TestXSSFCloneSheet.java index 36f7ef0198..1c3cfe25dc 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/TestXSSFCloneSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/TestXSSFCloneSheet.java @@ -1,93 +1,93 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xssf; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import org.apache.poi.hssf.HSSFITestDataProvider; -import org.apache.poi.ss.usermodel.BaseTestCloneSheet; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.junit.Before; -import org.junit.Test; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class TestXSSFCloneSheet extends BaseTestCloneSheet { - public TestXSSFCloneSheet() { - super(HSSFITestDataProvider.instance); - } - - private static final String OTHER_SHEET_NAME = "Another"; - private static final String VALID_SHEET_NAME = "Sheet01"; - private XSSFWorkbook wb; - - @Before - public void setUp() { - wb = new XSSFWorkbook(); - wb.createSheet(VALID_SHEET_NAME); - } - - @Test - public void testCloneSheetIntStringValidName() { - XSSFSheet cloned = wb.cloneSheet(0, OTHER_SHEET_NAME); - assertEquals(OTHER_SHEET_NAME, cloned.getSheetName()); - assertEquals(2, wb.getNumberOfSheets()); - } - - @Test - public void testCloneSheetIntStringInvalidName() { - try { - wb.cloneSheet(0, VALID_SHEET_NAME); - fail("Should fail"); - } catch (IllegalArgumentException e) { - // expected here - } - assertEquals(1, wb.getNumberOfSheets()); - } - - @Test - public void test60512() throws IOException { - XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("60512.xlsm"); - - assertEquals(1, wb.getNumberOfSheets()); - Sheet sheet = wb.cloneSheet(0); - assertNotNull(sheet); - assertEquals(2, wb.getNumberOfSheets()); - - - Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); - assertNotNull(wbBack); - wbBack.close(); - - OutputStream str = new FileOutputStream("/tmp/60512.xlsx"); - try { - wb.write(str); - } finally { - str.close(); - } - - wb.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.apache.poi.hssf.HSSFITestDataProvider; +import org.apache.poi.ss.usermodel.BaseTestCloneSheet; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class TestXSSFCloneSheet extends BaseTestCloneSheet { + public TestXSSFCloneSheet() { + super(HSSFITestDataProvider.instance); + } + + private static final String OTHER_SHEET_NAME = "Another"; + private static final String VALID_SHEET_NAME = "Sheet01"; + private XSSFWorkbook wb; + + @Before + public void setUp() { + wb = new XSSFWorkbook(); + wb.createSheet(VALID_SHEET_NAME); + } + + @Test + public void testCloneSheetIntStringValidName() { + XSSFSheet cloned = wb.cloneSheet(0, OTHER_SHEET_NAME); + assertEquals(OTHER_SHEET_NAME, cloned.getSheetName()); + assertEquals(2, wb.getNumberOfSheets()); + } + + @Test + public void testCloneSheetIntStringInvalidName() { + try { + wb.cloneSheet(0, VALID_SHEET_NAME); + fail("Should fail"); + } catch (IllegalArgumentException e) { + // expected here + } + assertEquals(1, wb.getNumberOfSheets()); + } + + @Test + public void test60512() throws IOException { + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("60512.xlsm"); + + assertEquals(1, wb.getNumberOfSheets()); + Sheet sheet = wb.cloneSheet(0); + assertNotNull(sheet); + assertEquals(2, wb.getNumberOfSheets()); + + + Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); + assertNotNull(wbBack); + wbBack.close(); + + OutputStream str = new FileOutputStream("/tmp/60512.xlsx"); + try { + wb.write(str); + } finally { + str.close(); + } + + wb.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/model/TestThemesTable.java b/src/ooxml/testcases/org/apache/poi/xssf/model/TestThemesTable.java index ffeceb2898..b91c88c2c8 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/model/TestThemesTable.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/model/TestThemesTable.java @@ -1,263 +1,263 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xssf.model; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.io.FileOutputStream; -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Map; - -import org.apache.commons.codec.binary.Hex; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.XSSFTestDataSamples; -import org.apache.poi.xssf.model.ThemesTable.ThemeElement; -import org.apache.poi.xssf.usermodel.XSSFCell; -import org.apache.poi.xssf.usermodel.XSSFCellStyle; -import org.apache.poi.xssf.usermodel.XSSFColor; -import org.apache.poi.xssf.usermodel.XSSFFont; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.junit.Test; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; - -public class TestThemesTable { - private final String testFileSimple = "Themes.xlsx"; - private final String testFileComplex = "Themes2.xlsx"; - // TODO .xls version available too, add HSSF support then check - - // What colours they should show up as - private static String rgbExpected[] = { - "ffffff", // Lt1 - "000000", // Dk1 - "eeece1", // Lt2 - "1f497d", // DK2 - "4f81bd", // Accent1 - "c0504d", // Accent2 - "9bbb59", // Accent3 - "8064a2", // Accent4 - "4bacc6", // Accent5 - "f79646", // Accent6 - "0000ff", // Hlink - "800080" // FolHlink - }; - - @Test - public void testThemesTableColors() throws Exception { - // Load our two test workbooks - XSSFWorkbook simple = XSSFTestDataSamples.openSampleWorkbook(testFileSimple); - XSSFWorkbook complex = XSSFTestDataSamples.openSampleWorkbook(testFileComplex); - // Save and re-load them, to check for stability across that - XSSFWorkbook simpleRS = XSSFTestDataSamples.writeOutAndReadBack(simple); - XSSFWorkbook complexRS = XSSFTestDataSamples.writeOutAndReadBack(complex); - // Fetch fresh copies to test with - simple = XSSFTestDataSamples.openSampleWorkbook(testFileSimple); - complex = XSSFTestDataSamples.openSampleWorkbook(testFileComplex); - // Files and descriptions - Map workbooks = new LinkedHashMap(); - workbooks.put(testFileSimple, simple); - workbooks.put("Re-Saved_" + testFileSimple, simpleRS); - workbooks.put(testFileComplex, complex); - workbooks.put("Re-Saved_" + testFileComplex, complexRS); - - // Sanity check - assertEquals(rgbExpected.length, rgbExpected.length); - - // For offline testing - boolean createFiles = false; - - // Check each workbook in turn, and verify that the colours - // for the theme-applied cells in Column A are correct - for (String whatWorkbook : workbooks.keySet()) { - XSSFWorkbook workbook = workbooks.get(whatWorkbook); - XSSFSheet sheet = workbook.getSheetAt(0); - int startRN = 0; - if (whatWorkbook.endsWith(testFileComplex)) startRN++; - - for (int rn=startRN; rn workbooks = new LinkedHashMap(); + workbooks.put(testFileSimple, simple); + workbooks.put("Re-Saved_" + testFileSimple, simpleRS); + workbooks.put(testFileComplex, complex); + workbooks.put("Re-Saved_" + testFileComplex, complexRS); + + // Sanity check + assertEquals(rgbExpected.length, rgbExpected.length); + + // For offline testing + boolean createFiles = false; + + // Check each workbook in turn, and verify that the colours + // for the theme-applied cells in Column A are correct + for (String whatWorkbook : workbooks.keySet()) { + XSSFWorkbook workbook = workbooks.get(whatWorkbook); + XSSFSheet sheet = workbook.getSheetAt(0); + int startRN = 0; + if (whatWorkbook.endsWith(testFileComplex)) startRN++; + + for (int rn=startRN; rn lst = sheet.getDataValidations(); //<-- works - assertEquals(0, lst.size()); - - //create the cell that will have the validation applied - sheet.createRow(0).createCell(0); - - DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper(); - DataValidationConstraint constraint = dataValidationHelper.createCustomConstraint("SUM($A$1:$A$1) <= 3500"); - CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0); - DataValidation validation = dataValidationHelper.createValidation(constraint, addressList); - sheet.addValidationData(validation); - - // this line caused XmlValueOutOfRangeException , see Bugzilla 3965 - lst = sheet.getDataValidations(); - assertEquals(1, lst.size()); - } finally { - wb.close(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.streaming; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.apache.poi.ss.usermodel.BaseTestDataValidation; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.SXSSFITestDataProvider; +import org.junit.Test; + +public class TestSXSSFDataValidation extends BaseTestDataValidation { + + public TestSXSSFDataValidation(){ + super(SXSSFITestDataProvider.instance); + } + + @Test + public void test53965() throws Exception { + SXSSFWorkbook wb = new SXSSFWorkbook(); + try { + Sheet sheet = wb.createSheet(); + List lst = sheet.getDataValidations(); //<-- works + assertEquals(0, lst.size()); + + //create the cell that will have the validation applied + sheet.createRow(0).createCell(0); + + DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = dataValidationHelper.createCustomConstraint("SUM($A$1:$A$1) <= 3500"); + CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0); + DataValidation validation = dataValidationHelper.createValidation(constraint, addressList); + sheet.addValidationData(validation); + + // this line caused XmlValueOutOfRangeException , see Bugzilla 3965 + lst = sheet.getDataValidations(); + assertEquals(1, lst.size()); + } finally { + wb.close(); + } + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java index 874db823d4..0892d10176 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java @@ -1,400 +1,400 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xssf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.Charset; -import java.util.Calendar; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.RichTextString; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellUtil; -import org.apache.poi.ss.util.RegionUtil; -import org.apache.poi.util.LocaleUtil; -import org.apache.poi.xssf.SXSSFITestDataProvider; -import org.apache.poi.xssf.XSSFTestDataSamples; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.junit.Test; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow; - -/** - * @author centic - * - * This testcase contains tests for bugs that are yet to be fixed. Therefore, - * the standard ant test target does not run these tests. Run this testcase with - * the single-test target. The names of the tests usually correspond to the - * Bugzilla id's PLEASE MOVE tests from this class to TestBugs once the bugs are - * fixed, so that they are then run automatically. - */ -public final class TestUnfixedBugs { - @Test - public void testBug54084Unicode() throws IOException { - // sample XLSX with the same text-contents as the text-file above - XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("54084 - Greek - beyond BMP.xlsx"); - - verifyBug54084Unicode(wb); - -// OutputStream baos = new FileOutputStream("/tmp/test.xlsx"); -// try { -// wb.write(baos); -// } finally { -// baos.close(); -// } - - // now write the file and read it back in - XSSFWorkbook wbWritten = XSSFTestDataSamples.writeOutAndReadBack(wb); - verifyBug54084Unicode(wbWritten); - - // finally also write it out via the streaming interface and verify that we still can read it back in - SXSSFWorkbook swb = new SXSSFWorkbook(wb); - Workbook wbStreamingWritten = SXSSFITestDataProvider.instance.writeOutAndReadBack(swb); - verifyBug54084Unicode(wbStreamingWritten); - - wbWritten.close(); - swb.close(); - wbStreamingWritten.close(); - wb.close(); - } - - private void verifyBug54084Unicode(Workbook wb) { - // expected data is stored in UTF-8 in a text-file - byte data[] = HSSFTestDataSamples.getTestDataFileContent("54084 - Greek - beyond BMP.txt"); - String testData = new String(data, Charset.forName("UTF-8")).trim(); - - Sheet sheet = wb.getSheetAt(0); - Row row = sheet.getRow(0); - Cell cell = row.getCell(0); - - String value = cell.getStringCellValue(); - //System.out.println(value); - - assertEquals("The data in the text-file should exactly match the data that we read from the workbook", testData, value); - } - - @Test - public void test54071() throws Exception { - Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("54071.xlsx"); - Sheet sheet = workbook.getSheetAt(0); - int rows = sheet.getPhysicalNumberOfRows(); - System.out.println(">> file rows is:"+(rows-1)+" <<"); - Row title = sheet.getRow(0); - - Date prev = null; - for (int row = 1; row < rows; row++) { - Row rowObj = sheet.getRow(row); - for (int col = 0; col < 1; col++) { - String titleName = title.getCell(col).toString(); - Cell cell = rowObj.getCell(col); - if (titleName.startsWith("time")) { - // here the output will produce ...59 or ...58 for the rows, probably POI is - // doing some different rounding or some other small difference... - System.out.println("==Time:"+cell.getDateCellValue()); - if(prev != null) { - assertEquals(prev, cell.getDateCellValue()); - } - - prev = cell.getDateCellValue(); - } - } - } - - workbook.close(); - } - - @Test - public void test54071Simple() { - double value1 = 41224.999988425923; - double value2 = 41224.999988368058; - - int wholeDays1 = (int)Math.floor(value1); - int millisecondsInDay1 = (int)((value1 - wholeDays1) * DateUtil.DAY_MILLISECONDS + 0.5); - - int wholeDays2 = (int)Math.floor(value2); - int millisecondsInDay2 = (int)((value2 - wholeDays2) * DateUtil.DAY_MILLISECONDS + 0.5); - - assertEquals(wholeDays1, wholeDays2); - // here we see that the time-value is 5 milliseconds apart, one is 86399000 and the other is 86398995, - // thus one is one second higher than the other - assertEquals("The time-values are 5 milliseconds apart", - millisecondsInDay1, millisecondsInDay2); - - // when we do the calendar-stuff, there is a boolean which determines if - // the milliseconds are rounded or not, having this at "false" causes the - // second to be different here! - int startYear = 1900; - int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't - Calendar calendar1 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays1 + dayAdjust); - calendar1.set(Calendar.MILLISECOND, millisecondsInDay1); - // this is the rounding part: - calendar1.add(Calendar.MILLISECOND, 500); - calendar1.clear(Calendar.MILLISECOND); - - Calendar calendar2 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays2 + dayAdjust); - calendar2.set(Calendar.MILLISECOND, millisecondsInDay2); - // this is the rounding part: - calendar2.add(Calendar.MILLISECOND, 500); - calendar2.clear(Calendar.MILLISECOND); - - // now the calendars are equal - assertEquals(calendar1, calendar2); - - assertEquals(DateUtil.getJavaDate(value1, false), DateUtil.getJavaDate(value2, false)); - } - - // When this is fixed, the test case should go to BaseTestXCell with - // adjustments to use _testDataProvider to also verify this for XSSF - @Test - public void testBug57294() throws IOException { - Workbook wb = SXSSFITestDataProvider.instance.createWorkbook(); - - Sheet sheet = wb.createSheet(); - Row row = sheet.createRow(0); - Cell cell = row.createCell(0); - - RichTextString str = new XSSFRichTextString("Test rich text string"); - str.applyFont(2, 4, (short)0); - assertEquals(3, str.numFormattingRuns()); - cell.setCellValue(str); - - Workbook wbBack = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb); - wb.close(); - - // re-read after serializing and reading back - Cell cellBack = wbBack.getSheetAt(0).getRow(0).getCell(0); - assertNotNull(cellBack); - RichTextString strBack = cellBack.getRichStringCellValue(); - assertNotNull(strBack); - assertEquals(3, strBack.numFormattingRuns()); - assertEquals(0, strBack.getIndexOfFormattingRun(0)); - assertEquals(2, strBack.getIndexOfFormattingRun(1)); - assertEquals(4, strBack.getIndexOfFormattingRun(2)); - - wbBack.close(); - } - - @Test - public void testBug55752() throws IOException { - Workbook wb = new XSSFWorkbook(); - try { - Sheet sheet = wb.createSheet("test"); - - for (int i = 0; i < 4; i++) { - Row row = sheet.createRow(i); - for (int j = 0; j < 2; j++) { - Cell cell = row.createCell(j); - cell.setCellStyle(wb.createCellStyle()); - } - } - - // set content - Row row1 = sheet.getRow(0); - row1.getCell(0).setCellValue("AAA"); - Row row2 = sheet.getRow(1); - row2.getCell(0).setCellValue("BBB"); - Row row3 = sheet.getRow(2); - row3.getCell(0).setCellValue("CCC"); - Row row4 = sheet.getRow(3); - row4.getCell(0).setCellValue("DDD"); - - // merge cells - CellRangeAddress range1 = new CellRangeAddress(0, 0, 0, 1); - sheet.addMergedRegion(range1); - CellRangeAddress range2 = new CellRangeAddress(1, 1, 0, 1); - sheet.addMergedRegion(range2); - CellRangeAddress range3 = new CellRangeAddress(2, 2, 0, 1); - sheet.addMergedRegion(range3); - assertEquals(0, range3.getFirstColumn()); - assertEquals(1, range3.getLastColumn()); - assertEquals(2, range3.getLastRow()); - CellRangeAddress range4 = new CellRangeAddress(3, 3, 0, 1); - sheet.addMergedRegion(range4); - - // set border - RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, range1, sheet, wb); - - row2.getCell(0).getCellStyle().setBorderBottom(CellStyle.BORDER_THIN); - row2.getCell(1).getCellStyle().setBorderBottom(CellStyle.BORDER_THIN); - - Cell cell0 = CellUtil.getCell(row3, 0); - CellUtil.setCellStyleProperty(cell0, CellUtil.BORDER_BOTTOM, CellStyle.BORDER_THIN); - Cell cell1 = CellUtil.getCell(row3, 1); - CellUtil.setCellStyleProperty(cell1, CellUtil.BORDER_BOTTOM, CellStyle.BORDER_THIN); - - RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, range4, sheet, wb); - - // write to file - OutputStream stream = new FileOutputStream(new File("C:/temp/55752.xlsx")); - try { - wb.write(stream); - } finally { - stream.close(); - } - } finally { - wb.close(); - } - } - - @Test - public void test57423() throws IOException { - Workbook wb = XSSFTestDataSamples.openSampleWorkbook("57423.xlsx"); - - Sheet testSheet = wb.getSheetAt(0); - - // row shift (negative or positive) causes corrupted output xlsx file when the shift value is bigger - // than the number of rows being shifted - // Excel 2010 on opening the output file says: - // "Excel found unreadable content" and offers recovering the file by removing the unreadable content - // This can be observed in cases like the following: - // negative shift of 1 row by less than -1 - // negative shift of 2 rows by less than -2 - // positive shift of 1 row by 2 or more - // positive shift of 2 rows by 3 or more - - //testSheet.shiftRows(4, 5, -3); - testSheet.shiftRows(10, 10, 2); - - checkRows57423(testSheet); - - Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); - - /*FileOutputStream stream = new FileOutputStream("C:\\temp\\57423.xlsx"); - try { - wb.write(stream); - } finally { - stream.close(); - }*/ - - wb.close(); - - checkRows57423(wbBack.getSheetAt(0)); - - wbBack.close(); - } - - private void checkRows57423(Sheet testSheet) throws IOException { - checkRow57423(testSheet, 0, "0"); - checkRow57423(testSheet, 1, "1"); - checkRow57423(testSheet, 2, "2"); - checkRow57423(testSheet, 3, "3"); - checkRow57423(testSheet, 4, "4"); - checkRow57423(testSheet, 5, "5"); - checkRow57423(testSheet, 6, "6"); - checkRow57423(testSheet, 7, "7"); - checkRow57423(testSheet, 8, "8"); - checkRow57423(testSheet, 9, "9"); - - assertNull("Row number 10 should be gone after the shift", - testSheet.getRow(10)); - - checkRow57423(testSheet, 11, "11"); - checkRow57423(testSheet, 12, "10"); - checkRow57423(testSheet, 13, "13"); - checkRow57423(testSheet, 14, "14"); - checkRow57423(testSheet, 15, "15"); - checkRow57423(testSheet, 16, "16"); - checkRow57423(testSheet, 17, "17"); - checkRow57423(testSheet, 18, "18"); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - ((XSSFSheet)testSheet).write(stream); - } finally { - stream.close(); - } - - // verify that the resulting XML has the rows in correct order as required by Excel - String xml = new String(stream.toByteArray(), "UTF-8"); - int posR12 = xml.indexOf(" shapes = drawing.getShapes(); - str.append("drawing.getShapes().size() = " + shapes.size()); - Iterator it = shapes.iterator(); - while(it.hasNext()) { - XSSFShape shape = it.next(); - str.append(", " + shape.toString()); - str.append(", Col1:"+((XSSFClientAnchor)shape.getAnchor()).getCol1()); - str.append(", Col2:"+((XSSFClientAnchor)shape.getAnchor()).getCol2()); - str.append(", Row1:"+((XSSFClientAnchor)shape.getAnchor()).getRow1()); - str.append(", Row2:"+((XSSFClientAnchor)shape.getAnchor()).getRow2()); - } - - assertEquals("Having shapes: " + str, - expectedShapes, shapes.size()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Calendar; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellUtil; +import org.apache.poi.ss.util.RegionUtil; +import org.apache.poi.util.LocaleUtil; +import org.apache.poi.xssf.SXSSFITestDataProvider; +import org.apache.poi.xssf.XSSFTestDataSamples; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.junit.Test; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow; + +/** + * @author centic + * + * This testcase contains tests for bugs that are yet to be fixed. Therefore, + * the standard ant test target does not run these tests. Run this testcase with + * the single-test target. The names of the tests usually correspond to the + * Bugzilla id's PLEASE MOVE tests from this class to TestBugs once the bugs are + * fixed, so that they are then run automatically. + */ +public final class TestUnfixedBugs { + @Test + public void testBug54084Unicode() throws IOException { + // sample XLSX with the same text-contents as the text-file above + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("54084 - Greek - beyond BMP.xlsx"); + + verifyBug54084Unicode(wb); + +// OutputStream baos = new FileOutputStream("/tmp/test.xlsx"); +// try { +// wb.write(baos); +// } finally { +// baos.close(); +// } + + // now write the file and read it back in + XSSFWorkbook wbWritten = XSSFTestDataSamples.writeOutAndReadBack(wb); + verifyBug54084Unicode(wbWritten); + + // finally also write it out via the streaming interface and verify that we still can read it back in + SXSSFWorkbook swb = new SXSSFWorkbook(wb); + Workbook wbStreamingWritten = SXSSFITestDataProvider.instance.writeOutAndReadBack(swb); + verifyBug54084Unicode(wbStreamingWritten); + + wbWritten.close(); + swb.close(); + wbStreamingWritten.close(); + wb.close(); + } + + private void verifyBug54084Unicode(Workbook wb) { + // expected data is stored in UTF-8 in a text-file + byte data[] = HSSFTestDataSamples.getTestDataFileContent("54084 - Greek - beyond BMP.txt"); + String testData = new String(data, Charset.forName("UTF-8")).trim(); + + Sheet sheet = wb.getSheetAt(0); + Row row = sheet.getRow(0); + Cell cell = row.getCell(0); + + String value = cell.getStringCellValue(); + //System.out.println(value); + + assertEquals("The data in the text-file should exactly match the data that we read from the workbook", testData, value); + } + + @Test + public void test54071() throws Exception { + Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("54071.xlsx"); + Sheet sheet = workbook.getSheetAt(0); + int rows = sheet.getPhysicalNumberOfRows(); + System.out.println(">> file rows is:"+(rows-1)+" <<"); + Row title = sheet.getRow(0); + + Date prev = null; + for (int row = 1; row < rows; row++) { + Row rowObj = sheet.getRow(row); + for (int col = 0; col < 1; col++) { + String titleName = title.getCell(col).toString(); + Cell cell = rowObj.getCell(col); + if (titleName.startsWith("time")) { + // here the output will produce ...59 or ...58 for the rows, probably POI is + // doing some different rounding or some other small difference... + System.out.println("==Time:"+cell.getDateCellValue()); + if(prev != null) { + assertEquals(prev, cell.getDateCellValue()); + } + + prev = cell.getDateCellValue(); + } + } + } + + workbook.close(); + } + + @Test + public void test54071Simple() { + double value1 = 41224.999988425923; + double value2 = 41224.999988368058; + + int wholeDays1 = (int)Math.floor(value1); + int millisecondsInDay1 = (int)((value1 - wholeDays1) * DateUtil.DAY_MILLISECONDS + 0.5); + + int wholeDays2 = (int)Math.floor(value2); + int millisecondsInDay2 = (int)((value2 - wholeDays2) * DateUtil.DAY_MILLISECONDS + 0.5); + + assertEquals(wholeDays1, wholeDays2); + // here we see that the time-value is 5 milliseconds apart, one is 86399000 and the other is 86398995, + // thus one is one second higher than the other + assertEquals("The time-values are 5 milliseconds apart", + millisecondsInDay1, millisecondsInDay2); + + // when we do the calendar-stuff, there is a boolean which determines if + // the milliseconds are rounded or not, having this at "false" causes the + // second to be different here! + int startYear = 1900; + int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't + Calendar calendar1 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays1 + dayAdjust); + calendar1.set(Calendar.MILLISECOND, millisecondsInDay1); + // this is the rounding part: + calendar1.add(Calendar.MILLISECOND, 500); + calendar1.clear(Calendar.MILLISECOND); + + Calendar calendar2 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays2 + dayAdjust); + calendar2.set(Calendar.MILLISECOND, millisecondsInDay2); + // this is the rounding part: + calendar2.add(Calendar.MILLISECOND, 500); + calendar2.clear(Calendar.MILLISECOND); + + // now the calendars are equal + assertEquals(calendar1, calendar2); + + assertEquals(DateUtil.getJavaDate(value1, false), DateUtil.getJavaDate(value2, false)); + } + + // When this is fixed, the test case should go to BaseTestXCell with + // adjustments to use _testDataProvider to also verify this for XSSF + @Test + public void testBug57294() throws IOException { + Workbook wb = SXSSFITestDataProvider.instance.createWorkbook(); + + Sheet sheet = wb.createSheet(); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + + RichTextString str = new XSSFRichTextString("Test rich text string"); + str.applyFont(2, 4, (short)0); + assertEquals(3, str.numFormattingRuns()); + cell.setCellValue(str); + + Workbook wbBack = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb); + wb.close(); + + // re-read after serializing and reading back + Cell cellBack = wbBack.getSheetAt(0).getRow(0).getCell(0); + assertNotNull(cellBack); + RichTextString strBack = cellBack.getRichStringCellValue(); + assertNotNull(strBack); + assertEquals(3, strBack.numFormattingRuns()); + assertEquals(0, strBack.getIndexOfFormattingRun(0)); + assertEquals(2, strBack.getIndexOfFormattingRun(1)); + assertEquals(4, strBack.getIndexOfFormattingRun(2)); + + wbBack.close(); + } + + @Test + public void testBug55752() throws IOException { + Workbook wb = new XSSFWorkbook(); + try { + Sheet sheet = wb.createSheet("test"); + + for (int i = 0; i < 4; i++) { + Row row = sheet.createRow(i); + for (int j = 0; j < 2; j++) { + Cell cell = row.createCell(j); + cell.setCellStyle(wb.createCellStyle()); + } + } + + // set content + Row row1 = sheet.getRow(0); + row1.getCell(0).setCellValue("AAA"); + Row row2 = sheet.getRow(1); + row2.getCell(0).setCellValue("BBB"); + Row row3 = sheet.getRow(2); + row3.getCell(0).setCellValue("CCC"); + Row row4 = sheet.getRow(3); + row4.getCell(0).setCellValue("DDD"); + + // merge cells + CellRangeAddress range1 = new CellRangeAddress(0, 0, 0, 1); + sheet.addMergedRegion(range1); + CellRangeAddress range2 = new CellRangeAddress(1, 1, 0, 1); + sheet.addMergedRegion(range2); + CellRangeAddress range3 = new CellRangeAddress(2, 2, 0, 1); + sheet.addMergedRegion(range3); + assertEquals(0, range3.getFirstColumn()); + assertEquals(1, range3.getLastColumn()); + assertEquals(2, range3.getLastRow()); + CellRangeAddress range4 = new CellRangeAddress(3, 3, 0, 1); + sheet.addMergedRegion(range4); + + // set border + RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, range1, sheet, wb); + + row2.getCell(0).getCellStyle().setBorderBottom(CellStyle.BORDER_THIN); + row2.getCell(1).getCellStyle().setBorderBottom(CellStyle.BORDER_THIN); + + Cell cell0 = CellUtil.getCell(row3, 0); + CellUtil.setCellStyleProperty(cell0, CellUtil.BORDER_BOTTOM, CellStyle.BORDER_THIN); + Cell cell1 = CellUtil.getCell(row3, 1); + CellUtil.setCellStyleProperty(cell1, CellUtil.BORDER_BOTTOM, CellStyle.BORDER_THIN); + + RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, range4, sheet, wb); + + // write to file + OutputStream stream = new FileOutputStream(new File("C:/temp/55752.xlsx")); + try { + wb.write(stream); + } finally { + stream.close(); + } + } finally { + wb.close(); + } + } + + @Test + public void test57423() throws IOException { + Workbook wb = XSSFTestDataSamples.openSampleWorkbook("57423.xlsx"); + + Sheet testSheet = wb.getSheetAt(0); + + // row shift (negative or positive) causes corrupted output xlsx file when the shift value is bigger + // than the number of rows being shifted + // Excel 2010 on opening the output file says: + // "Excel found unreadable content" and offers recovering the file by removing the unreadable content + // This can be observed in cases like the following: + // negative shift of 1 row by less than -1 + // negative shift of 2 rows by less than -2 + // positive shift of 1 row by 2 or more + // positive shift of 2 rows by 3 or more + + //testSheet.shiftRows(4, 5, -3); + testSheet.shiftRows(10, 10, 2); + + checkRows57423(testSheet); + + Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); + + /*FileOutputStream stream = new FileOutputStream("C:\\temp\\57423.xlsx"); + try { + wb.write(stream); + } finally { + stream.close(); + }*/ + + wb.close(); + + checkRows57423(wbBack.getSheetAt(0)); + + wbBack.close(); + } + + private void checkRows57423(Sheet testSheet) throws IOException { + checkRow57423(testSheet, 0, "0"); + checkRow57423(testSheet, 1, "1"); + checkRow57423(testSheet, 2, "2"); + checkRow57423(testSheet, 3, "3"); + checkRow57423(testSheet, 4, "4"); + checkRow57423(testSheet, 5, "5"); + checkRow57423(testSheet, 6, "6"); + checkRow57423(testSheet, 7, "7"); + checkRow57423(testSheet, 8, "8"); + checkRow57423(testSheet, 9, "9"); + + assertNull("Row number 10 should be gone after the shift", + testSheet.getRow(10)); + + checkRow57423(testSheet, 11, "11"); + checkRow57423(testSheet, 12, "10"); + checkRow57423(testSheet, 13, "13"); + checkRow57423(testSheet, 14, "14"); + checkRow57423(testSheet, 15, "15"); + checkRow57423(testSheet, 16, "16"); + checkRow57423(testSheet, 17, "17"); + checkRow57423(testSheet, 18, "18"); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + ((XSSFSheet)testSheet).write(stream); + } finally { + stream.close(); + } + + // verify that the resulting XML has the rows in correct order as required by Excel + String xml = new String(stream.toByteArray(), "UTF-8"); + int posR12 = xml.indexOf(" shapes = drawing.getShapes(); + str.append("drawing.getShapes().size() = " + shapes.size()); + Iterator it = shapes.iterator(); + while(it.hasNext()) { + XSSFShape shape = it.next(); + str.append(", " + shape.toString()); + str.append(", Col1:"+((XSSFClientAnchor)shape.getAnchor()).getCol1()); + str.append(", Col2:"+((XSSFClientAnchor)shape.getAnchor()).getCol2()); + str.append(", Row1:"+((XSSFClientAnchor)shape.getAnchor()).getRow1()); + str.append(", Row2:"+((XSSFClientAnchor)shape.getAnchor()).getRow2()); + } + + assertEquals("Having shapes: " + str, + expectedShapes, shapes.size()); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java index a73a0cf7cf..1aa8b3165a 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java @@ -1,59 +1,59 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.xssf.usermodel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.io.IOException; - -import org.apache.poi.ss.usermodel.BaseTestConditionalFormatting; -import org.apache.poi.ss.usermodel.Color; -import org.apache.poi.xssf.XSSFITestDataProvider; -import org.junit.Test; - -/** - * XSSF-specific Conditional Formatting tests - */ -public class TestXSSFConditionalFormatting extends BaseTestConditionalFormatting { - public TestXSSFConditionalFormatting(){ - super(XSSFITestDataProvider.instance); - } - - @Override - protected void assertColour(String hexExpected, Color actual) { - assertNotNull("Colour must be given", actual); - XSSFColor colour = (XSSFColor)actual; - if (hexExpected.length() == 8) { - assertEquals(hexExpected, colour.getARGBHex()); - } else { - assertEquals(hexExpected, colour.getARGBHex().substring(2)); - } - } - - @Test - public void testRead() throws IOException { - testRead("WithConditionalFormatting.xlsx"); - } - - @Test - public void testReadOffice2007() throws IOException { - testReadOffice2007("NewStyleConditionalFormattings.xlsx"); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xssf.usermodel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; + +import org.apache.poi.ss.usermodel.BaseTestConditionalFormatting; +import org.apache.poi.ss.usermodel.Color; +import org.apache.poi.xssf.XSSFITestDataProvider; +import org.junit.Test; + +/** + * XSSF-specific Conditional Formatting tests + */ +public class TestXSSFConditionalFormatting extends BaseTestConditionalFormatting { + public TestXSSFConditionalFormatting(){ + super(XSSFITestDataProvider.instance); + } + + @Override + protected void assertColour(String hexExpected, Color actual) { + assertNotNull("Colour must be given", actual); + XSSFColor colour = (XSSFColor)actual; + if (hexExpected.length() == 8) { + assertEquals(hexExpected, colour.getARGBHex()); + } else { + assertEquals(hexExpected, colour.getARGBHex().substring(2)); + } + } + + @Test + public void testRead() throws IOException { + testRead("WithConditionalFormatting.xlsx"); + } + + @Test + public void testReadOffice2007() throws IOException { + testReadOffice2007("NewStyleConditionalFormattings.xlsx"); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFLineChartData.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFLineChartData.java index 2bfb06bf8e..e5ee56b504 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFLineChartData.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFLineChartData.java @@ -1,76 +1,76 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel.charts; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; - -import org.apache.poi.ss.usermodel.Chart; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.charts.AxisPosition; -import org.apache.poi.ss.usermodel.charts.ChartAxis; -import org.apache.poi.ss.usermodel.charts.ChartDataSource; -import org.apache.poi.ss.usermodel.charts.DataSources; -import org.apache.poi.ss.usermodel.charts.LineChartData; -import org.apache.poi.ss.usermodel.charts.LineChartSeries; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.SheetBuilder; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.junit.Test; - -/** - * Tests for XSSF Line Charts - */ -public class TestXSSFLineChartData { - - private static final Object[][] plotData = { - {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}, - {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - }; - - @Test - public void testOneSeriePlot() throws IOException { - Workbook wb = new XSSFWorkbook(); - Sheet sheet = new SheetBuilder(wb, plotData).build(); - Drawing drawing = sheet.createDrawingPatriarch(); - ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 10, 30); - Chart chart = drawing.createChart(anchor); - - ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); - ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); - - LineChartData lineChartData = - chart.getChartDataFactory().createLineChartData(); - - ChartDataSource xs = DataSources.fromStringCellRange(sheet, CellRangeAddress.valueOf("A1:J1")); - ChartDataSource ys = DataSources.fromNumericCellRange(sheet, CellRangeAddress.valueOf("A2:J2")); - LineChartSeries series = lineChartData.addSeries(xs, ys); - - assertNotNull(series); - assertEquals(1, lineChartData.getSeries().size()); - assertTrue(lineChartData.getSeries().contains(series)); - - chart.plot(lineChartData, bottomAxis, leftAxis); - wb.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel.charts; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.apache.poi.ss.usermodel.Chart; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.charts.AxisPosition; +import org.apache.poi.ss.usermodel.charts.ChartAxis; +import org.apache.poi.ss.usermodel.charts.ChartDataSource; +import org.apache.poi.ss.usermodel.charts.DataSources; +import org.apache.poi.ss.usermodel.charts.LineChartData; +import org.apache.poi.ss.usermodel.charts.LineChartSeries; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.SheetBuilder; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; + +/** + * Tests for XSSF Line Charts + */ +public class TestXSSFLineChartData { + + private static final Object[][] plotData = { + {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + }; + + @Test + public void testOneSeriePlot() throws IOException { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = new SheetBuilder(wb, plotData).build(); + Drawing drawing = sheet.createDrawingPatriarch(); + ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 10, 30); + Chart chart = drawing.createChart(anchor); + + ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM); + ChartAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT); + + LineChartData lineChartData = + chart.getChartDataFactory().createLineChartData(); + + ChartDataSource xs = DataSources.fromStringCellRange(sheet, CellRangeAddress.valueOf("A1:J1")); + ChartDataSource ys = DataSources.fromNumericCellRange(sheet, CellRangeAddress.valueOf("A2:J2")); + LineChartSeries series = lineChartData.addSeries(xs, ys); + + assertNotNull(series); + assertEquals(1, lineChartData.getSeries().size()); + assertTrue(lineChartData.getSeries().contains(series)); + + chart.plot(lineChartData, bottomAxis, leftAxis); + wb.close(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFManualLayout.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFManualLayout.java index 97438c0678..73df559144 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFManualLayout.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/charts/TestXSSFManualLayout.java @@ -1,120 +1,120 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xssf.usermodel.charts; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; - -import org.apache.poi.ss.usermodel.Chart; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.charts.ChartLegend; -import org.apache.poi.ss.usermodel.charts.LayoutMode; -import org.apache.poi.ss.usermodel.charts.LayoutTarget; -import org.apache.poi.ss.usermodel.charts.ManualLayout; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public final class TestXSSFManualLayout { - - private Workbook wb; - private ManualLayout layout; - - @Before - public void createEmptyLayout() { - wb = new XSSFWorkbook(); - Sheet sheet = wb.createSheet(); - Drawing drawing = sheet.createDrawingPatriarch(); - ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 10, 30); - Chart chart = drawing.createChart(anchor); - ChartLegend legend = chart.getOrCreateLegend(); - layout = legend.getManualLayout(); - } - - @After - public void closeWB() throws IOException { - wb.close(); - } - - /* - * Accessor methods are not trivial. They use lazy underlying bean - * initialization so there can be some errors (NPE, for example). - */ - @Test - public void testAccessorMethods() { - final double newRatio = 1.1; - final double newCoordinate = 0.3; - final LayoutMode nonDefaultMode = LayoutMode.FACTOR; - final LayoutTarget nonDefaultTarget = LayoutTarget.OUTER; - - layout.setWidthRatio(newRatio); - assertTrue(layout.getWidthRatio() == newRatio); - - layout.setHeightRatio(newRatio); - assertTrue(layout.getHeightRatio() == newRatio); - - layout.setX(newCoordinate); - assertTrue(layout.getX() == newCoordinate); - - layout.setY(newCoordinate); - assertTrue(layout.getY() == newCoordinate); - - layout.setXMode(nonDefaultMode); - assertTrue(layout.getXMode() == nonDefaultMode); - - layout.setYMode(nonDefaultMode); - assertTrue(layout.getYMode() == nonDefaultMode); - - layout.setWidthMode(nonDefaultMode); - assertTrue(layout.getWidthMode() == nonDefaultMode); - - layout.setHeightMode(nonDefaultMode); - assertTrue(layout.getHeightMode() == nonDefaultMode); - - layout.setTarget(nonDefaultTarget); - assertTrue(layout.getTarget() == nonDefaultTarget); - - } - - /* - * Layout must have reasonable default values and must not throw - * any exceptions. - */ - @Test - public void testDefaultValues() { - assertNotNull(layout.getTarget()); - assertNotNull(layout.getXMode()); - assertNotNull(layout.getYMode()); - assertNotNull(layout.getHeightMode()); - assertNotNull(layout.getWidthMode()); - /* - * According to interface, 0.0 should be returned for - * uninitialized double properties. - */ - assertTrue(layout.getX() == 0.0); - assertTrue(layout.getY() == 0.0); - assertTrue(layout.getWidthRatio() == 0.0); - assertTrue(layout.getHeightRatio() == 0.0); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel.charts; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.apache.poi.ss.usermodel.Chart; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.charts.ChartLegend; +import org.apache.poi.ss.usermodel.charts.LayoutMode; +import org.apache.poi.ss.usermodel.charts.LayoutTarget; +import org.apache.poi.ss.usermodel.charts.ManualLayout; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public final class TestXSSFManualLayout { + + private Workbook wb; + private ManualLayout layout; + + @Before + public void createEmptyLayout() { + wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet(); + Drawing drawing = sheet.createDrawingPatriarch(); + ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 10, 30); + Chart chart = drawing.createChart(anchor); + ChartLegend legend = chart.getOrCreateLegend(); + layout = legend.getManualLayout(); + } + + @After + public void closeWB() throws IOException { + wb.close(); + } + + /* + * Accessor methods are not trivial. They use lazy underlying bean + * initialization so there can be some errors (NPE, for example). + */ + @Test + public void testAccessorMethods() { + final double newRatio = 1.1; + final double newCoordinate = 0.3; + final LayoutMode nonDefaultMode = LayoutMode.FACTOR; + final LayoutTarget nonDefaultTarget = LayoutTarget.OUTER; + + layout.setWidthRatio(newRatio); + assertTrue(layout.getWidthRatio() == newRatio); + + layout.setHeightRatio(newRatio); + assertTrue(layout.getHeightRatio() == newRatio); + + layout.setX(newCoordinate); + assertTrue(layout.getX() == newCoordinate); + + layout.setY(newCoordinate); + assertTrue(layout.getY() == newCoordinate); + + layout.setXMode(nonDefaultMode); + assertTrue(layout.getXMode() == nonDefaultMode); + + layout.setYMode(nonDefaultMode); + assertTrue(layout.getYMode() == nonDefaultMode); + + layout.setWidthMode(nonDefaultMode); + assertTrue(layout.getWidthMode() == nonDefaultMode); + + layout.setHeightMode(nonDefaultMode); + assertTrue(layout.getHeightMode() == nonDefaultMode); + + layout.setTarget(nonDefaultTarget); + assertTrue(layout.getTarget() == nonDefaultTarget); + + } + + /* + * Layout must have reasonable default values and must not throw + * any exceptions. + */ + @Test + public void testDefaultValues() { + assertNotNull(layout.getTarget()); + assertNotNull(layout.getXMode()); + assertNotNull(layout.getYMode()); + assertNotNull(layout.getHeightMode()); + assertNotNull(layout.getWidthMode()); + /* + * According to interface, 0.0 should be returned for + * uninitialized double properties. + */ + assertTrue(layout.getX() == 0.0); + assertTrue(layout.getY() == 0.0); + assertTrue(layout.getWidthRatio() == 0.0); + assertTrue(layout.getHeightRatio() == 0.0); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java b/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java index 7243f114d6..e3311ff2fb 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java @@ -33,24 +33,24 @@ import org.junit.runners.Suite; /** * Collects all tests for org.apache.poi.xwpf and sub-packages. - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - TestXWPFBugs.class, - org.apache.poi.xwpf.usermodel.TestXWPFBugs.class, - TestXWPFDocument.class, - TestXWPFWordExtractor.class, - TestXWPFHeaderFooterPolicy.class, - TestXWPFHeader.class, - TestXWPFHeadings.class, - TestXWPFParagraph.class, - TestXWPFRun.class, - TestXWPFTable.class, - TestXWPFStyles.class, - TestXWPFPictureData.class, - TestXWPFNumbering.class, - TestAllExtendedProperties.class, - TestPackageCorePropertiesGetKeywords.class -}) -public final class AllXWPFTests { + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestXWPFBugs.class, + org.apache.poi.xwpf.usermodel.TestXWPFBugs.class, + TestXWPFDocument.class, + TestXWPFWordExtractor.class, + TestXWPFHeaderFooterPolicy.class, + TestXWPFHeader.class, + TestXWPFHeadings.class, + TestXWPFParagraph.class, + TestXWPFRun.class, + TestXWPFTable.class, + TestXWPFStyles.class, + TestXWPFPictureData.class, + TestXWPFNumbering.class, + TestAllExtendedProperties.class, + TestPackageCorePropertiesGetKeywords.class +}) +public final class AllXWPFTests { } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java index ff955dadb6..707e9b83d5 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java @@ -17,12 +17,12 @@ package org.apache.poi.xwpf; -import java.io.IOException; - -import junit.framework.TestCase; -import org.apache.poi.POIXMLProperties.CoreProperties; -import org.apache.poi.openxml4j.opc.PackageProperties; -import org.apache.poi.xwpf.usermodel.XWPFDocument; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.POIXMLProperties.CoreProperties; +import org.apache.poi.openxml4j.opc.PackageProperties; +import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTDigSigBlob; import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties; import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTVectorLpstr; @@ -30,76 +30,76 @@ import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTVect /** * Tests if the {@link CoreProperties#getKeywords()} method. This test has been - * submitted because even though the - * {@link PackageProperties#getKeywordsProperty()} had been present before, the - * {@link CoreProperties#getKeywords()} had been missing. - *

    - * The author of this has added {@link CoreProperties#getKeywords()} and - * {@link CoreProperties#setKeywords(String)} and this test is supposed to test - * them. - * - * @author Antoni Mylka - */ -public final class TestAllExtendedProperties extends TestCase { - public void testGetAllExtendedProperties() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); - CTProperties ctProps = doc.getProperties().getExtendedProperties().getUnderlyingProperties(); - assertEquals("Microsoft Office Word", ctProps.getApplication()); - assertEquals("14.0000", ctProps.getAppVersion()); - assertEquals(57, ctProps.getCharacters()); - assertEquals(66, ctProps.getCharactersWithSpaces()); - assertEquals("", ctProps.getCompany()); - assertNull(ctProps.getDigSig()); - assertEquals(0, ctProps.getDocSecurity()); - assertNotNull(ctProps.getDomNode()); - - CTVectorVariant vec = ctProps.getHeadingPairs(); - assertEquals(2, vec.getVector().sizeOfVariantArray()); - assertEquals("Title", vec.getVector().getVariantArray(0).getLpstr()); - assertEquals(1, vec.getVector().getVariantArray(1).getI4()); - - assertFalse(ctProps.isSetHiddenSlides()); - assertEquals(0, ctProps.getHiddenSlides()); - assertFalse(ctProps.isSetHLinks()); - assertNull(ctProps.getHLinks()); - assertNull(ctProps.getHyperlinkBase()); - assertTrue(ctProps.isSetHyperlinksChanged()); - assertFalse(ctProps.getHyperlinksChanged()); - assertEquals(1, ctProps.getLines()); - assertTrue(ctProps.isSetLinksUpToDate()); - assertFalse(ctProps.getLinksUpToDate()); - assertNull(ctProps.getManager()); - assertFalse(ctProps.isSetMMClips()); - assertEquals(0, ctProps.getMMClips()); - assertFalse(ctProps.isSetNotes()); - assertEquals(0, ctProps.getNotes()); - assertEquals(1, ctProps.getPages()); - assertEquals(1, ctProps.getParagraphs()); - assertNull(ctProps.getPresentationFormat()); - assertTrue(ctProps.isSetScaleCrop()); - assertFalse(ctProps.getScaleCrop()); - assertTrue(ctProps.isSetSharedDoc()); - assertFalse(ctProps.getSharedDoc()); - assertFalse(ctProps.isSetSlides()); - assertEquals(0, ctProps.getSlides()); - assertEquals("Normal.dotm", ctProps.getTemplate()); - - CTVectorLpstr vec2 = ctProps.getTitlesOfParts(); - assertEquals(1, vec2.getVector().sizeOfLpstrArray()); - assertEquals("Example Word 2010 Document", vec2.getVector().getLpstrArray(0)); - - assertEquals(3, ctProps.getTotalTime()); - assertEquals(10, ctProps.getWords()); - - // Check the digital signature part - // Won't be there in this file, but we - // need to do this check so that the - // appropriate parts end up in the - // smaller ooxml schemas file - CTDigSigBlob blob = ctProps.getDigSig(); - assertNull(blob); - - blob = CTDigSigBlob.Factory.newInstance(); - blob.setBlob(new byte[]{2, 6, 7, 2, 3, 4, 5, 1, 2, 3}); - } -} + * submitted because even though the + * {@link PackageProperties#getKeywordsProperty()} had been present before, the + * {@link CoreProperties#getKeywords()} had been missing. + *

    + * The author of this has added {@link CoreProperties#getKeywords()} and + * {@link CoreProperties#setKeywords(String)} and this test is supposed to test + * them. + * + * @author Antoni Mylka + */ +public final class TestAllExtendedProperties extends TestCase { + public void testGetAllExtendedProperties() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); + CTProperties ctProps = doc.getProperties().getExtendedProperties().getUnderlyingProperties(); + assertEquals("Microsoft Office Word", ctProps.getApplication()); + assertEquals("14.0000", ctProps.getAppVersion()); + assertEquals(57, ctProps.getCharacters()); + assertEquals(66, ctProps.getCharactersWithSpaces()); + assertEquals("", ctProps.getCompany()); + assertNull(ctProps.getDigSig()); + assertEquals(0, ctProps.getDocSecurity()); + assertNotNull(ctProps.getDomNode()); + + CTVectorVariant vec = ctProps.getHeadingPairs(); + assertEquals(2, vec.getVector().sizeOfVariantArray()); + assertEquals("Title", vec.getVector().getVariantArray(0).getLpstr()); + assertEquals(1, vec.getVector().getVariantArray(1).getI4()); + + assertFalse(ctProps.isSetHiddenSlides()); + assertEquals(0, ctProps.getHiddenSlides()); + assertFalse(ctProps.isSetHLinks()); + assertNull(ctProps.getHLinks()); + assertNull(ctProps.getHyperlinkBase()); + assertTrue(ctProps.isSetHyperlinksChanged()); + assertFalse(ctProps.getHyperlinksChanged()); + assertEquals(1, ctProps.getLines()); + assertTrue(ctProps.isSetLinksUpToDate()); + assertFalse(ctProps.getLinksUpToDate()); + assertNull(ctProps.getManager()); + assertFalse(ctProps.isSetMMClips()); + assertEquals(0, ctProps.getMMClips()); + assertFalse(ctProps.isSetNotes()); + assertEquals(0, ctProps.getNotes()); + assertEquals(1, ctProps.getPages()); + assertEquals(1, ctProps.getParagraphs()); + assertNull(ctProps.getPresentationFormat()); + assertTrue(ctProps.isSetScaleCrop()); + assertFalse(ctProps.getScaleCrop()); + assertTrue(ctProps.isSetSharedDoc()); + assertFalse(ctProps.getSharedDoc()); + assertFalse(ctProps.isSetSlides()); + assertEquals(0, ctProps.getSlides()); + assertEquals("Normal.dotm", ctProps.getTemplate()); + + CTVectorLpstr vec2 = ctProps.getTitlesOfParts(); + assertEquals(1, vec2.getVector().sizeOfLpstrArray()); + assertEquals("Example Word 2010 Document", vec2.getVector().getLpstrArray(0)); + + assertEquals(3, ctProps.getTotalTime()); + assertEquals(10, ctProps.getWords()); + + // Check the digital signature part + // Won't be there in this file, but we + // need to do this check so that the + // appropriate parts end up in the + // smaller ooxml schemas file + CTDigSigBlob blob = ctProps.getDigSig(); + assertNull(blob); + + blob = CTDigSigBlob.Factory.newInstance(); + blob.setBlob(new byte[]{2, 6, 7, 2, 3, 4, 5, 1, 2, 3}); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java index 85a21f12b7..d53c5c14de 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java @@ -17,34 +17,34 @@ package org.apache.poi.xwpf; -import java.io.IOException; - -import junit.framework.TestCase; -import org.apache.poi.POIXMLProperties.CoreProperties; -import org.apache.poi.openxml4j.opc.PackageProperties; -import org.apache.poi.xwpf.usermodel.XWPFDocument; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.POIXMLProperties.CoreProperties; +import org.apache.poi.openxml4j.opc.PackageProperties; +import org.apache.poi.xwpf.usermodel.XWPFDocument; /** * Tests if the {@link CoreProperties#getKeywords()} method. This test has been - * submitted because even though the - * {@link PackageProperties#getKeywordsProperty()} had been present before, the - * {@link CoreProperties#getKeywords()} had been missing. - *

    - * The author of this has added {@link CoreProperties#getKeywords()} and - * {@link CoreProperties#setKeywords(String)} and this test is supposed to test - * them. - * - * @author Antoni Mylka - */ -public final class TestPackageCorePropertiesGetKeywords extends TestCase { - public void testGetSetKeywords() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); - String keywords = doc.getProperties().getCoreProperties().getKeywords(); - assertEquals("extractor, test, rdf", keywords); - - doc.getProperties().getCoreProperties().setKeywords("test, keywords"); - doc = XWPFTestDataSamples.writeOutAndReadBack(doc); - keywords = doc.getProperties().getCoreProperties().getKeywords(); - assertEquals("test, keywords", keywords); - } -} + * submitted because even though the + * {@link PackageProperties#getKeywordsProperty()} had been present before, the + * {@link CoreProperties#getKeywords()} had been missing. + *

    + * The author of this has added {@link CoreProperties#getKeywords()} and + * {@link CoreProperties#setKeywords(String)} and this test is supposed to test + * them. + * + * @author Antoni Mylka + */ +public final class TestPackageCorePropertiesGetKeywords extends TestCase { + public void testGetSetKeywords() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); + String keywords = doc.getProperties().getCoreProperties().getKeywords(); + assertEquals("extractor, test, rdf", keywords); + + doc.getProperties().getCoreProperties().setKeywords("test, keywords"); + doc = XWPFTestDataSamples.writeOutAndReadBack(doc); + keywords = doc.getProperties().getCoreProperties().getKeywords(); + assertEquals("test, keywords", keywords); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java index 92f738ce13..377d98b33c 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java @@ -1,127 +1,127 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xwpf; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import javax.crypto.Cipher; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.poifs.crypt.CipherAlgorithm; -import org.apache.poi.poifs.crypt.Decryptor; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.xwpf.extractor.XWPFWordExtractor; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.xmlbeans.XmlException; -import org.junit.Assume; -import org.junit.Test; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.DocumentDocument; - -public class TestXWPFBugs { - /** - * A word document that's encrypted with non-standard - * Encryption options, and no cspname section. See bug 53475 - */ - @Test - public void bug53475NoCSPName() throws Exception { - File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx"); - NPOIFSFileSystem filesystem = new NPOIFSFileSystem(file, true); - - // Check the encryption details - EncryptionInfo info = new EncryptionInfo(filesystem); - assertEquals(128, info.getHeader().getKeySize()); - assertEquals(CipherAlgorithm.aes128, info.getHeader().getCipherAlgorithm()); - assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithmEx()); - - // Check it can be decoded - Decryptor d = Decryptor.getInstance(info); - assertTrue("Unable to process: document is encrypted", d.verifyPassword("solrcell")); - - // Check we can read the word document in that - InputStream dataStream = d.getDataStream(filesystem); - OPCPackage opc = OPCPackage.open(dataStream); - XWPFDocument doc = new XWPFDocument(opc); - XWPFWordExtractor ex = new XWPFWordExtractor(doc); - String text = ex.getText(); - assertNotNull(text); - assertEquals("This is password protected Word document.", text.trim()); - ex.close(); - - filesystem.close(); - } - - /** - * A word document with aes-256, i.e. aes is always 128 bit (= 128 bit block size), - * but the key can be 128/192/256 bits - */ - @Test - public void bug53475_aes256() throws Exception { - int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); - Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); - - File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx"); - NPOIFSFileSystem filesystem = new NPOIFSFileSystem(file, true); - - // Check the encryption details - EncryptionInfo info = new EncryptionInfo(filesystem); - assertEquals(16, info.getHeader().getBlockSize()); - assertEquals(256, info.getHeader().getKeySize()); - assertEquals(CipherAlgorithm.aes256, info.getHeader().getCipherAlgorithm()); - assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithmEx()); - - // Check it can be decoded - Decryptor d = Decryptor.getInstance(info); - assertTrue("Unable to process: document is encrypted", d.verifyPassword("pass")); - - // Check we can read the word document in that - InputStream dataStream = d.getDataStream(filesystem); - OPCPackage opc = OPCPackage.open(dataStream); - XWPFDocument doc = new XWPFDocument(opc); - XWPFWordExtractor ex = new XWPFWordExtractor(doc); - String text = ex.getText(); - assertNotNull(text); - // I know ... a stupid typo, maybe next time ... - assertEquals("The is a password protected document.", text.trim()); - ex.close(); - - filesystem.close(); - } - - - @Test - public void bug59058() throws IOException, XmlException { - String files[] = { "bug57031.docx", "bug59058.docx" }; - for (String f : files) { - ZipFile zf = new ZipFile(POIDataSamples.getDocumentInstance().getFile(f)); - ZipEntry entry = zf.getEntry("word/document.xml"); - DocumentDocument document = DocumentDocument.Factory.parse(zf.getInputStream(entry)); - assertNotNull(document); - zf.close(); - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xwpf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import javax.crypto.Cipher; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.poifs.crypt.CipherAlgorithm; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.xwpf.extractor.XWPFWordExtractor; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.xmlbeans.XmlException; +import org.junit.Assume; +import org.junit.Test; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.DocumentDocument; + +public class TestXWPFBugs { + /** + * A word document that's encrypted with non-standard + * Encryption options, and no cspname section. See bug 53475 + */ + @Test + public void bug53475NoCSPName() throws Exception { + File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx"); + NPOIFSFileSystem filesystem = new NPOIFSFileSystem(file, true); + + // Check the encryption details + EncryptionInfo info = new EncryptionInfo(filesystem); + assertEquals(128, info.getHeader().getKeySize()); + assertEquals(CipherAlgorithm.aes128, info.getHeader().getCipherAlgorithm()); + assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithmEx()); + + // Check it can be decoded + Decryptor d = Decryptor.getInstance(info); + assertTrue("Unable to process: document is encrypted", d.verifyPassword("solrcell")); + + // Check we can read the word document in that + InputStream dataStream = d.getDataStream(filesystem); + OPCPackage opc = OPCPackage.open(dataStream); + XWPFDocument doc = new XWPFDocument(opc); + XWPFWordExtractor ex = new XWPFWordExtractor(doc); + String text = ex.getText(); + assertNotNull(text); + assertEquals("This is password protected Word document.", text.trim()); + ex.close(); + + filesystem.close(); + } + + /** + * A word document with aes-256, i.e. aes is always 128 bit (= 128 bit block size), + * but the key can be 128/192/256 bits + */ + @Test + public void bug53475_aes256() throws Exception { + int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES"); + Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647); + + File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx"); + NPOIFSFileSystem filesystem = new NPOIFSFileSystem(file, true); + + // Check the encryption details + EncryptionInfo info = new EncryptionInfo(filesystem); + assertEquals(16, info.getHeader().getBlockSize()); + assertEquals(256, info.getHeader().getKeySize()); + assertEquals(CipherAlgorithm.aes256, info.getHeader().getCipherAlgorithm()); + assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithmEx()); + + // Check it can be decoded + Decryptor d = Decryptor.getInstance(info); + assertTrue("Unable to process: document is encrypted", d.verifyPassword("pass")); + + // Check we can read the word document in that + InputStream dataStream = d.getDataStream(filesystem); + OPCPackage opc = OPCPackage.open(dataStream); + XWPFDocument doc = new XWPFDocument(opc); + XWPFWordExtractor ex = new XWPFWordExtractor(doc); + String text = ex.getText(); + assertNotNull(text); + // I know ... a stupid typo, maybe next time ... + assertEquals("The is a password protected document.", text.trim()); + ex.close(); + + filesystem.close(); + } + + + @Test + public void bug59058() throws IOException, XmlException { + String files[] = { "bug57031.docx", "bug59058.docx" }; + for (String f : files) { + ZipFile zf = new ZipFile(POIDataSamples.getDocumentInstance().getFile(f)); + ZipEntry entry = zf.getEntry("word/document.xml"); + DocumentDocument document = DocumentDocument.Factory.parse(zf.getInputStream(entry)); + assertNotNull(document); + zf.close(); + } + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/XWPFTestDataSamples.java b/src/ooxml/testcases/org/apache/poi/xwpf/XWPFTestDataSamples.java index d7f2222404..14cb582b3a 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/XWPFTestDataSamples.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/XWPFTestDataSamples.java @@ -1,53 +1,53 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xwpf; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.util.IOUtils; -import org.apache.poi.xwpf.usermodel.XWPFDocument; - -/** - * @author Yegor Kozlov - */ -public class XWPFTestDataSamples { - - public static XWPFDocument openSampleDocument(String sampleName) throws IOException { - InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(sampleName); - return new XWPFDocument(is); - } - - public static XWPFDocument writeOutAndReadBack(XWPFDocument doc) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); - doc.write(baos); - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - return new XWPFDocument(bais); - } - - public static byte[] getImage(String filename) throws IOException { - InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(filename); - try { - return IOUtils.toByteArray(is); - } finally { - is.close(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xwpf; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +/** + * @author Yegor Kozlov + */ +public class XWPFTestDataSamples { + + public static XWPFDocument openSampleDocument(String sampleName) throws IOException { + InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(sampleName); + return new XWPFDocument(is); + } + + public static XWPFDocument writeOutAndReadBack(XWPFDocument doc) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + doc.write(baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + return new XWPFDocument(bais); + } + + public static byte[] getImage(String filename) throws IOException { + InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(filename); + try { + return IOUtils.toByteArray(is); + } finally { + is.close(); + } + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java b/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java index d12020b516..1b81c2a9e5 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java @@ -17,64 +17,64 @@ package org.apache.poi.xwpf.model; -import java.io.IOException; - -import junit.framework.TestCase; -import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun; import org.apache.poi.xwpf.usermodel.XWPFParagraph; /** - * Tests for the various XWPF decorators - */ -public class TestXWPFDecorators extends TestCase { - private XWPFDocument simple; - private XWPFDocument hyperlink; - private XWPFDocument comments; - + * Tests for the various XWPF decorators + */ +public class TestXWPFDecorators extends TestCase { + private XWPFDocument simple; + private XWPFDocument hyperlink; + private XWPFDocument comments; + @Override - protected void setUp() throws IOException { - simple = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); - hyperlink = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); - comments = XWPFTestDataSamples.openSampleDocument("WordWithAttachments.docx"); - } - - public void testHyperlink() { - XWPFParagraph ps; - XWPFParagraph ph; - assertEquals(7, simple.getParagraphs().size()); - assertEquals(5, hyperlink.getParagraphs().size()); - - // Simple text - ps = simple.getParagraphs().get(0); - assertEquals("I am a test document", ps.getParagraphText()); - assertEquals(1, ps.getRuns().size()); - - ph = hyperlink.getParagraphs().get(4); - assertEquals("We have a hyperlink here, and another.", ph.getParagraphText()); - assertEquals(3, ph.getRuns().size()); - - - // The proper way to do hyperlinks(!) - assertFalse(ps.getRuns().get(0) instanceof XWPFHyperlinkRun); - assertFalse(ph.getRuns().get(0) instanceof XWPFHyperlinkRun); - assertTrue(ph.getRuns().get(1) instanceof XWPFHyperlinkRun); - assertFalse(ph.getRuns().get(2) instanceof XWPFHyperlinkRun); - - XWPFHyperlinkRun link = (XWPFHyperlinkRun) ph.getRuns().get(1); - assertEquals("http://poi.apache.org/", link.getHyperlink(hyperlink).getURL()); - } - - public void testComments() { - int numComments = 0; - for (XWPFParagraph p : comments.getParagraphs()) { - XWPFCommentsDecorator d = new XWPFCommentsDecorator(p, null); - if (d.getCommentText().length() > 0) { - numComments++; - assertEquals("\tComment by", d.getCommentText().substring(0, 11)); - } - } - assertEquals(3, numComments); - } -} + protected void setUp() throws IOException { + simple = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); + hyperlink = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); + comments = XWPFTestDataSamples.openSampleDocument("WordWithAttachments.docx"); + } + + public void testHyperlink() { + XWPFParagraph ps; + XWPFParagraph ph; + assertEquals(7, simple.getParagraphs().size()); + assertEquals(5, hyperlink.getParagraphs().size()); + + // Simple text + ps = simple.getParagraphs().get(0); + assertEquals("I am a test document", ps.getParagraphText()); + assertEquals(1, ps.getRuns().size()); + + ph = hyperlink.getParagraphs().get(4); + assertEquals("We have a hyperlink here, and another.", ph.getParagraphText()); + assertEquals(3, ph.getRuns().size()); + + + // The proper way to do hyperlinks(!) + assertFalse(ps.getRuns().get(0) instanceof XWPFHyperlinkRun); + assertFalse(ph.getRuns().get(0) instanceof XWPFHyperlinkRun); + assertTrue(ph.getRuns().get(1) instanceof XWPFHyperlinkRun); + assertFalse(ph.getRuns().get(2) instanceof XWPFHyperlinkRun); + + XWPFHyperlinkRun link = (XWPFHyperlinkRun) ph.getRuns().get(1); + assertEquals("http://poi.apache.org/", link.getHyperlink(hyperlink).getURL()); + } + + public void testComments() { + int numComments = 0; + for (XWPFParagraph p : comments.getParagraphs()) { + XWPFCommentsDecorator d = new XWPFCommentsDecorator(p, null); + if (d.getCommentText().length() > 0) { + numComments++; + assertEquals("\tComment by", d.getCommentText().substring(0, 11)); + } + } + assertEquals(3, numComments); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFMetroShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFMetroShape.java index 894818eb46..205f3e6e52 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFMetroShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFMetroShape.java @@ -1,89 +1,89 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.lang.reflect.Method; - -import org.apache.poi.ddf.AbstractEscherOptRecord; -import org.apache.poi.ddf.EscherComplexProperty; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherTertiaryOptRecord; -import org.apache.poi.hslf.usermodel.HSLFShape; -import org.apache.poi.sl.usermodel.Shape; -import org.apache.poi.util.Internal; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * Experimental class for metro blobs, i.e. an alternative escher property - * containing an ooxml representation of the shape - */ -@Internal -public class HSLFMetroShape> { - private static final POILogger LOGGER = POILogFactory.getLogger(HSLFMetroShape.class); - - private final HSLFShape shape; - - public HSLFMetroShape(HSLFShape shape) { - this.shape = shape; - } - - /** - * @return the bytes of the metro blob, which are bytes of an OPCPackage, i.e. a zip stream - */ - public byte[] getMetroBytes() { - EscherComplexProperty ep = getMetroProp(); - return (ep == null) ? null : ep.getComplexData(); - } - - /** - * @return if there's a metro blob to extract - */ - public boolean hasMetroBlob() { - return getMetroProp() != null; - } - - private EscherComplexProperty getMetroProp() { - AbstractEscherOptRecord opt = shape.getEscherChild(EscherTertiaryOptRecord.RECORD_ID); - return (opt == null) ? null : (EscherComplexProperty)opt.lookup(EscherProperties.GROUPSHAPE__METROBLOB); - } - - /** - * @return the metro blob shape or null if either there's no metro blob or the ooxml classes - * aren't in the classpath - */ - @SuppressWarnings("unchecked") - public T getShape() { - byte metroBytes[] = getMetroBytes(); - if (metroBytes == null) { - return null; - } - - // org.apache.poi.xslf.usermodel.XSLFMetroShape - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - try { - Class ms = cl.loadClass("org.apache.poi.xslf.usermodel.XSLFMetroShape"); - Method m = ms.getMethod("parseShape", byte[].class); - return (T)m.invoke(null, new Object[]{metroBytes}); - } catch (Exception e) { - LOGGER.log(POILogger.ERROR, "can't process metro blob, check if all dependencies for POI OOXML are in the classpath.", e); - return null; - } - } -} - +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.lang.reflect.Method; + +import org.apache.poi.ddf.AbstractEscherOptRecord; +import org.apache.poi.ddf.EscherComplexProperty; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherTertiaryOptRecord; +import org.apache.poi.hslf.usermodel.HSLFShape; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.util.Internal; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * Experimental class for metro blobs, i.e. an alternative escher property + * containing an ooxml representation of the shape + */ +@Internal +public class HSLFMetroShape> { + private static final POILogger LOGGER = POILogFactory.getLogger(HSLFMetroShape.class); + + private final HSLFShape shape; + + public HSLFMetroShape(HSLFShape shape) { + this.shape = shape; + } + + /** + * @return the bytes of the metro blob, which are bytes of an OPCPackage, i.e. a zip stream + */ + public byte[] getMetroBytes() { + EscherComplexProperty ep = getMetroProp(); + return (ep == null) ? null : ep.getComplexData(); + } + + /** + * @return if there's a metro blob to extract + */ + public boolean hasMetroBlob() { + return getMetroProp() != null; + } + + private EscherComplexProperty getMetroProp() { + AbstractEscherOptRecord opt = shape.getEscherChild(EscherTertiaryOptRecord.RECORD_ID); + return (opt == null) ? null : (EscherComplexProperty)opt.lookup(EscherProperties.GROUPSHAPE__METROBLOB); + } + + /** + * @return the metro blob shape or null if either there's no metro blob or the ooxml classes + * aren't in the classpath + */ + @SuppressWarnings("unchecked") + public T getShape() { + byte metroBytes[] = getMetroBytes(); + if (metroBytes == null) { + return null; + } + + // org.apache.poi.xslf.usermodel.XSLFMetroShape + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + try { + Class ms = cl.loadClass("org.apache.poi.xslf.usermodel.XSLFMetroShape"); + Method m = ms.getMethod("parseShape", byte[].class); + return (T)m.invoke(null, new Object[]{metroBytes}); + } catch (Exception e) { + LOGGER.log(POILogger.ERROR, "can't process metro blob, check if all dependencies for POI OOXML are in the classpath.", e); + return null; + } + } +} + diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TabStopPropCollection.java b/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TabStopPropCollection.java index d1046a1f04..55267eacf0 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TabStopPropCollection.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TabStopPropCollection.java @@ -1,123 +1,123 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model.textproperties; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianConsts; - -/** - * Container for tabstop lists - */ -public class TabStopPropCollection extends TextProp { - public enum TabStopType { - LEFT(0), CENTER(1), RIGHT(2), DECIMAL(3); - private final int val; - TabStopType(int val) { - this.val = val; - } - public static TabStopType fromRecordVal(int val) { - for (TabStopType tst : values()) { - if (tst.val == val) return tst; - } - return LEFT; - } - } - - public static class TabStop { - /** - * If the TextPFException record that contains this TabStop structure also contains a - * leftMargin, then the value of position is relative to the left margin of the paragraph; - * otherwise, the value is relative to the left side of the paragraph. - * - * If a TextRuler record contains this TabStop structure, the value is relative to the - * left side of the text ruler. - */ - private int position; - - /** - * A enumeration that specifies how text aligns at the tab stop. - */ - private TabStopType type; - - public TabStop(int position, TabStopType type) { - this.position = position; - this.type = type; - } - - public int getPosition() { - return position; - } - - public void setPosition(int position) { - this.position = position; - } - - public TabStopType getType() { - return type; - } - - public void setType(TabStopType type) { - this.type = type; - } - } - - private List tabStops = new ArrayList(); - - public TabStopPropCollection() { - super(0, 0x100000, "tabStops"); - } - - /** - * Parses the tabstops from TxMasterStyle record - * - * @param data the data stream - * @param offset the offset within the data - */ - public void parseProperty(byte data[], int offset) { - int count = LittleEndian.getUShort(data, offset); - int off = offset + LittleEndianConsts.SHORT_SIZE; - for (int i=0; i(); - for (TabStop ts : tabStops) { - TabStop tso = new TabStop(ts.getPosition(), ts.getType()); - other.tabStops.add(tso); - } - return other; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model.textproperties; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * Container for tabstop lists + */ +public class TabStopPropCollection extends TextProp { + public enum TabStopType { + LEFT(0), CENTER(1), RIGHT(2), DECIMAL(3); + private final int val; + TabStopType(int val) { + this.val = val; + } + public static TabStopType fromRecordVal(int val) { + for (TabStopType tst : values()) { + if (tst.val == val) return tst; + } + return LEFT; + } + } + + public static class TabStop { + /** + * If the TextPFException record that contains this TabStop structure also contains a + * leftMargin, then the value of position is relative to the left margin of the paragraph; + * otherwise, the value is relative to the left side of the paragraph. + * + * If a TextRuler record contains this TabStop structure, the value is relative to the + * left side of the text ruler. + */ + private int position; + + /** + * A enumeration that specifies how text aligns at the tab stop. + */ + private TabStopType type; + + public TabStop(int position, TabStopType type) { + this.position = position; + this.type = type; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public TabStopType getType() { + return type; + } + + public void setType(TabStopType type) { + this.type = type; + } + } + + private List tabStops = new ArrayList(); + + public TabStopPropCollection() { + super(0, 0x100000, "tabStops"); + } + + /** + * Parses the tabstops from TxMasterStyle record + * + * @param data the data stream + * @param offset the offset within the data + */ + public void parseProperty(byte data[], int offset) { + int count = LittleEndian.getUShort(data, offset); + int off = offset + LittleEndianConsts.SHORT_SIZE; + for (int i=0; i(); + for (TabStop ts : tabStops) { + TabStop tso = new TabStop(ts.getPosition(), ts.getType()); + other.tabStops.add(tso); + } + return other; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/WrapFlagsTextProp.java b/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/WrapFlagsTextProp.java index eaacbff575..88e88a82e5 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/WrapFlagsTextProp.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/WrapFlagsTextProp.java @@ -1,30 +1,30 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model.textproperties; - -public class WrapFlagsTextProp extends BitMaskTextProp { - public static final int CHAR_WRAP_IDX = 0; - public static final int WORD_WRAO_IDX = 1; - public static final int OVERFLOW_IDX = 2; - - public static final String NAME = "wrapFlags"; - - public WrapFlagsTextProp() { - super(2, 0xE0000, NAME, "charWrap", "wordWrap", "overflow"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model.textproperties; + +public class WrapFlagsTextProp extends BitMaskTextProp { + public static final int CHAR_WRAP_IDX = 0; + public static final int WORD_WRAO_IDX = 1; + public static final int OVERFLOW_IDX = 2; + + public static final String NAME = "wrapFlags"; + + public WrapFlagsTextProp() { + super(2, 0xE0000, NAME, "charWrap", "wordWrap", "overflow"); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java b/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java index 2bac1ca221..4a944516bb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java @@ -1,75 +1,75 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.record; - -import org.apache.poi.ddf.*; -import org.apache.poi.util.*; - -/** - * An atom record that specifies whether a shape is a placeholder shape. - * The number, position, and type of placeholder shapes are determined by - * the slide layout as specified in the SlideAtom record. - */ -public class EscherPlaceholder extends EscherRecord { - public static final short RECORD_ID = RecordTypes.OEPlaceholderAtom.typeID; - public static final String RECORD_DESCRIPTION = "msofbtClientTextboxPlaceholder"; - - private int position = -1; - private byte placementId = 0; - private byte size = 0; - private short unused = 0; - - public EscherPlaceholder() {} - - public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { - int bytesRemaining = readHeader( data, offset ); - - position = LittleEndian.getInt(data, offset+8); - placementId = data[offset+12]; - size = data[offset+13]; - unused = LittleEndian.getShort(data, offset+14); - - assert(bytesRemaining + 8 == 16); - return bytesRemaining + 8; - } - - public int serialize(int offset, byte[] data, EscherSerializationListener listener) { - listener.beforeRecordSerialize( offset, getRecordId(), this ); - - LittleEndian.putShort(data, offset, getOptions()); - LittleEndian.putShort(data, offset+2, getRecordId()); - LittleEndian.putInt(data, offset+4, 8); - LittleEndian.putInt(data, offset+8, position); - LittleEndian.putByte(data, offset+12, placementId); - LittleEndian.putByte(data, offset+13, size); - LittleEndian.putShort(data, offset+14, unused); - - listener.afterRecordSerialize( offset+getRecordSize(), getRecordId(), getRecordSize(), this ); - return getRecordSize(); - } - - public int getRecordSize() { - return 8 + 8; - } - - public String getRecordName() { - return "ClientTextboxPlaceholder"; - } - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import org.apache.poi.ddf.*; +import org.apache.poi.util.*; + +/** + * An atom record that specifies whether a shape is a placeholder shape. + * The number, position, and type of placeholder shapes are determined by + * the slide layout as specified in the SlideAtom record. + */ +public class EscherPlaceholder extends EscherRecord { + public static final short RECORD_ID = RecordTypes.OEPlaceholderAtom.typeID; + public static final String RECORD_DESCRIPTION = "msofbtClientTextboxPlaceholder"; + + private int position = -1; + private byte placementId = 0; + private byte size = 0; + private short unused = 0; + + public EscherPlaceholder() {} + + public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { + int bytesRemaining = readHeader( data, offset ); + + position = LittleEndian.getInt(data, offset+8); + placementId = data[offset+12]; + size = data[offset+13]; + unused = LittleEndian.getShort(data, offset+14); + + assert(bytesRemaining + 8 == 16); + return bytesRemaining + 8; + } + + public int serialize(int offset, byte[] data, EscherSerializationListener listener) { + listener.beforeRecordSerialize( offset, getRecordId(), this ); + + LittleEndian.putShort(data, offset, getOptions()); + LittleEndian.putShort(data, offset+2, getRecordId()); + LittleEndian.putInt(data, offset+4, 8); + LittleEndian.putInt(data, offset+8, position); + LittleEndian.putByte(data, offset+12, placementId); + LittleEndian.putByte(data, offset+13, size); + LittleEndian.putShort(data, offset+14, unused); + + listener.afterRecordSerialize( offset+getRecordSize(), getRecordId(), getRecordSize(), this ); + return getRecordSize(); + } + + public int getRecordSize() { + return 8 + 8; + } + + public String getRecordName() { + return "ClientTextboxPlaceholder"; + } + + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java index fa362c8dd0..1381e6ab6c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java @@ -1,94 +1,94 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.record; - -import org.apache.poi.util.LittleEndian; -import java.io.IOException; -import java.io.OutputStream; - -/** - * ExObjRefAtom (3009). - *

    - * An atom record that specifies a reference to an external object. - *

    - */ - -public final class ExObjRefAtom extends RecordAtom { - private byte[] _header; - - /** - * A 4-byte unsigned integer that specifies a reference to an external object. - * It MUST be equal to the value of the exObjId field of an ExMediaAtom record - * or the value of the exObjId field of an ExOleObjAtom record. - */ - private int exObjIdRef; - - /** - * Create a new instance of ExObjRefAtom - */ - public ExObjRefAtom() { - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 0); - LittleEndian.putUShort(_header, 2, (int)getRecordType()); - LittleEndian.putInt(_header, 4, 4); - exObjIdRef = 0; - } - - /** - * Build an instance of ExObjRefAtom from on-disk data - * - * @param source the source data as a byte array. - * @param start the start offset into the byte array. - * @param len the length of the slice in the byte array. - */ - protected ExObjRefAtom(byte[] source, int start, int len) { - _header = new byte[8]; - int offset = start; - System.arraycopy(source,start,_header,0,8); - offset += _header.length; - exObjIdRef = (int)LittleEndian.getUInt(source, offset); - } - - /** - * @return type of this record {@link RecordTypes#ExObjRefAtom}. - */ - public long getRecordType() { - return RecordTypes.ExObjRefAtom.typeID; - } - - public int getExObjIdRef(){ - return exObjIdRef; - } - - public void setExObjIdRef(int id){ - exObjIdRef = id; - } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - out.write(_header); - - byte[] recdata = new byte[4]; - LittleEndian.putUInt(recdata, 0, exObjIdRef); - - out.write(recdata); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import org.apache.poi.util.LittleEndian; +import java.io.IOException; +import java.io.OutputStream; + +/** + * ExObjRefAtom (3009). + *

    + * An atom record that specifies a reference to an external object. + *

    + */ + +public final class ExObjRefAtom extends RecordAtom { + private byte[] _header; + + /** + * A 4-byte unsigned integer that specifies a reference to an external object. + * It MUST be equal to the value of the exObjId field of an ExMediaAtom record + * or the value of the exObjId field of an ExOleObjAtom record. + */ + private int exObjIdRef; + + /** + * Create a new instance of ExObjRefAtom + */ + public ExObjRefAtom() { + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)getRecordType()); + LittleEndian.putInt(_header, 4, 4); + exObjIdRef = 0; + } + + /** + * Build an instance of ExObjRefAtom from on-disk data + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected ExObjRefAtom(byte[] source, int start, int len) { + _header = new byte[8]; + int offset = start; + System.arraycopy(source,start,_header,0,8); + offset += _header.length; + exObjIdRef = (int)LittleEndian.getUInt(source, offset); + } + + /** + * @return type of this record {@link RecordTypes#ExObjRefAtom}. + */ + public long getRecordType() { + return RecordTypes.ExObjRefAtom.typeID; + } + + public int getExObjIdRef(){ + return exObjIdRef; + } + + public void setExObjIdRef(int id){ + exObjIdRef = id; + } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + + byte[] recdata = new byte[4]; + LittleEndian.putUInt(recdata, 0, exObjIdRef); + + out.write(recdata); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java index e6a2cdcacf..e2975de789 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java @@ -1,120 +1,120 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.record; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherRecordFactory; -import org.apache.poi.ddf.EscherSerializationListener; -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.util.LittleEndian; - -/** - * An atom record that specifies whether a shape is a placeholder shape. - * The number, position, and type of placeholder shapes are determined by - * the slide layout as specified in the SlideAtom record. - * - * @since POI 3.14-Beta2 - */ -public class HSLFEscherClientDataRecord extends EscherClientDataRecord { - - private final List _childRecords = new ArrayList(); - - public List getHSLFChildRecords() { - return _childRecords; - } - - public void removeChild(Class childClass) { - Iterator iter = _childRecords.iterator(); - while (iter.hasNext()) { - if (childClass.isInstance(iter.next())) { - iter.remove(); - } - } - } - - public void addChild(Record childRecord) { - _childRecords.add(childRecord); - } - - @Override - public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { - int bytesRemaining = readHeader( data, offset ); - byte remainingData[] = new byte[bytesRemaining]; - System.arraycopy(data, offset+8, remainingData, 0, bytesRemaining); - setRemainingData(remainingData); - return bytesRemaining + 8; - } - - @Override - public int serialize(int offset, byte[] data, EscherSerializationListener listener) { - listener.beforeRecordSerialize( offset, getRecordId(), this ); - - LittleEndian.putShort(data, offset, getOptions()); - LittleEndian.putShort(data, offset+2, getRecordId()); - - byte childBytes[] = getRemainingData(); - - LittleEndian.putInt(data, offset+4, childBytes.length); - System.arraycopy(childBytes, 0, data, offset+8, childBytes.length); - int recordSize = 8+childBytes.length; - listener.afterRecordSerialize( offset+recordSize, getRecordId(), recordSize, this ); - return recordSize; - } - - @Override - public int getRecordSize() { - return 8 + getRemainingData().length; - } - - @Override - public byte[] getRemainingData() { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - try { - for (Record r : _childRecords) { - r.writeOut(bos); - } - } catch (IOException e) { - throw new HSLFException(e); - } - return bos.toByteArray(); - } - - @Override - public void setRemainingData( byte[] remainingData ) { - _childRecords.clear(); - int offset = 0; - while (offset < remainingData.length) { - Record r = Record.buildRecordAtOffset(remainingData, offset); - _childRecords.add(r); - long rlen = LittleEndian.getUInt(remainingData,offset+4); - offset += 8 + rlen; - } - } - - public String getRecordName() { - return "HSLFClientData"; - } - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherRecordFactory; +import org.apache.poi.ddf.EscherSerializationListener; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.util.LittleEndian; + +/** + * An atom record that specifies whether a shape is a placeholder shape. + * The number, position, and type of placeholder shapes are determined by + * the slide layout as specified in the SlideAtom record. + * + * @since POI 3.14-Beta2 + */ +public class HSLFEscherClientDataRecord extends EscherClientDataRecord { + + private final List _childRecords = new ArrayList(); + + public List getHSLFChildRecords() { + return _childRecords; + } + + public void removeChild(Class childClass) { + Iterator iter = _childRecords.iterator(); + while (iter.hasNext()) { + if (childClass.isInstance(iter.next())) { + iter.remove(); + } + } + } + + public void addChild(Record childRecord) { + _childRecords.add(childRecord); + } + + @Override + public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { + int bytesRemaining = readHeader( data, offset ); + byte remainingData[] = new byte[bytesRemaining]; + System.arraycopy(data, offset+8, remainingData, 0, bytesRemaining); + setRemainingData(remainingData); + return bytesRemaining + 8; + } + + @Override + public int serialize(int offset, byte[] data, EscherSerializationListener listener) { + listener.beforeRecordSerialize( offset, getRecordId(), this ); + + LittleEndian.putShort(data, offset, getOptions()); + LittleEndian.putShort(data, offset+2, getRecordId()); + + byte childBytes[] = getRemainingData(); + + LittleEndian.putInt(data, offset+4, childBytes.length); + System.arraycopy(childBytes, 0, data, offset+8, childBytes.length); + int recordSize = 8+childBytes.length; + listener.afterRecordSerialize( offset+recordSize, getRecordId(), recordSize, this ); + return recordSize; + } + + @Override + public int getRecordSize() { + return 8 + getRemainingData().length; + } + + @Override + public byte[] getRemainingData() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + for (Record r : _childRecords) { + r.writeOut(bos); + } + } catch (IOException e) { + throw new HSLFException(e); + } + return bos.toByteArray(); + } + + @Override + public void setRemainingData( byte[] remainingData ) { + _childRecords.clear(); + int offset = 0; + while (offset < remainingData.length) { + Record r = Record.buildRecordAtOffset(remainingData, offset); + _childRecords.add(r); + long rlen = LittleEndian.getUInt(remainingData,offset+4); + offset += 8 + rlen; + } + } + + public String getRecordName() { + return "HSLFClientData"; + } + + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java index bd8d507cb4..0e23e49302 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java @@ -1,67 +1,67 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.record; - -import java.lang.reflect.Constructor; -import java.util.Map; - -import org.apache.poi.ddf.*; -import org.apache.poi.util.LittleEndian; - -/** - * Generates escher records when provided the byte array containing those records. - * - * @see EscherRecordFactory - */ -public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory { - private static Class[] escherRecordClasses = { EscherPlaceholder.class, HSLFEscherClientDataRecord.class }; - private static Map> recordsMap = recordsToMap( escherRecordClasses ); - - - /** - * Creates an instance of the escher record factory - */ - public HSLFEscherRecordFactory() { - // no instance initialisation - } - - @Override - public EscherRecord createRecord(byte[] data, int offset) { - short options = LittleEndian.getShort( data, offset ); - short recordId = LittleEndian.getShort( data, offset + 2 ); - // int remainingBytes = LittleEndian.getInt( data, offset + 4 ); - - Constructor recordConstructor = recordsMap.get(Short.valueOf(recordId)); - if (recordConstructor == null) { - return super.createRecord(data, offset); - } - EscherRecord escherRecord = null; - try { - escherRecord = recordConstructor.newInstance(new Object[] {}); - } catch (Exception e) { - return super.createRecord(data, offset); - } - escherRecord.setRecordId(recordId); - escherRecord.setOptions(options); - if (escherRecord instanceof EscherContainerRecord) { - ((EscherContainerRecord)escherRecord).fillFields(data, offset, this); - } - - return escherRecord; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.lang.reflect.Constructor; +import java.util.Map; + +import org.apache.poi.ddf.*; +import org.apache.poi.util.LittleEndian; + +/** + * Generates escher records when provided the byte array containing those records. + * + * @see EscherRecordFactory + */ +public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory { + private static Class[] escherRecordClasses = { EscherPlaceholder.class, HSLFEscherClientDataRecord.class }; + private static Map> recordsMap = recordsToMap( escherRecordClasses ); + + + /** + * Creates an instance of the escher record factory + */ + public HSLFEscherRecordFactory() { + // no instance initialisation + } + + @Override + public EscherRecord createRecord(byte[] data, int offset) { + short options = LittleEndian.getShort( data, offset ); + short recordId = LittleEndian.getShort( data, offset + 2 ); + // int remainingBytes = LittleEndian.getInt( data, offset + 4 ); + + Constructor recordConstructor = recordsMap.get(Short.valueOf(recordId)); + if (recordConstructor == null) { + return super.createRecord(data, offset); + } + EscherRecord escherRecord = null; + try { + escherRecord = recordConstructor.newInstance(new Object[] {}); + } catch (Exception e) { + return super.createRecord(data, offset); + } + escherRecord.setRecordId(recordId); + escherRecord.setOptions(options); + if (escherRecord instanceof EscherContainerRecord) { + ((EscherContainerRecord)escherRecord).fillFields(data, offset, this); + } + + return escherRecord; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/SSSlideInfoAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/SSSlideInfoAtom.java index 931f5dc70a..b087b66b0b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/SSSlideInfoAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/SSSlideInfoAtom.java @@ -1,289 +1,289 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.record; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianConsts; - -/** - * A SlideShowSlideInfo Atom (type 1017).
    - *
    - * - * An atom record that specifies which transition effects to perform - * during a slide show, and how to advance to the next presentation slide.
    - *
    - * - * Combination of effectType and effectDirection: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    typedescriptiondirection
    0cut0x00 = no transition, 0x01 = black transition
    1random0x00
    2blinds0x00 = vertical, 0x01 = horizontal
    3checkerlike blinds
    4cover0x00 = left, 0x01 = up, 0x02 = right, 0x03 = down, 0x04 = left/up, 0x05 = right/up, 0x06 left/down, 0x07 = left/down
    5dissolve0x00
    6fade0x00
    7uncoverlike cover
    8random barslike blinds
    9stripslike 0x04 - 0x07 of cover
    10wipelike 0x00 - 0x03 of cover
    11box in/out0x00 = out, 0x01 = in
    13split0x00 = horizontally out, 0x01 = horizontally in, 0x02 = vertically out, 0x03 = vertically in
    17diamond0x00
    18plus0x00
    19wedge0x00
    20pushlike 0x00 - 0x03 of cover
    21comblike blinds
    22newsflash0x00
    23alphafade0x00
    26wheelnumber of radial divisions (0x01,0x02,0x03,0x04,0x08)
    27circle0x00
    255undefined0x00
    - */ -public class SSSlideInfoAtom extends RecordAtom { - /** - * A bit that specifies whether the presentation slide can be - * manually advanced by the user during the slide show. - */ - public static final int MANUAL_ADVANCE_BIT = 1 << 0; - - /** - * A bit that specifies whether the corresponding slide is - * hidden and is not displayed during the slide show. - */ - public static final int HIDDEN_BIT = 1 << 2; - - /** - * A bit that specifies whether to play the sound specified by soundIfRef. - */ - public static final int SOUND_BIT = 1 << 4; - - /** - * A bit that specifies whether the sound specified by soundIdRef is - * looped continuously when playing until the next sound plays. - */ - public static final int LOOP_SOUND_BIT = 1 << 6; - - /** - * A bit that specifies whether to stop any currently playing - * sound when the transition starts. - */ - public static final int STOP_SOUND_BIT = 1 << 8; - - /** - * A bit that specifies whether the slide will automatically - * advance after slideTime milliseconds during the slide show. - */ - public static final int AUTO_ADVANCE_BIT = 1 << 10; - - /** - * A bit that specifies whether to display the cursor during - * the slide show. - */ - public static final int CURSOR_VISIBLE_BIT = 1 << 12; - - // public static int RESERVED1_BIT = 1 << 1; - // public static int RESERVED2_BIT = 1 << 3; - // public static int RESERVED3_BIT = 1 << 5; - // public static int RESERVED4_BIT = 1 << 7; - // public static int RESERVED5_BIT = 1 << 9; - // public static int RESERVED6_BIT = 1 << 11; - // public static int RESERVED7_BIT = 1 << 13 | 1 << 14 | 1 << 15; - - private static final long _type = RecordTypes.SSSlideInfoAtom.typeID; - - private byte[] _header; - - /** - * A signed integer that specifies an amount of time, in milliseconds, to wait - * before advancing to the next presentation slide. It MUST be greater than or equal to 0 and - * less than or equal to 86399000. It MUST be ignored unless AUTO_ADVANCE_BIT is TRUE. - */ - private int _slideTime = 0; - - /** - * A SoundIdRef that specifies which sound to play when the transition starts. - */ - private int _soundIdRef = 0; - - /** - * A byte that specifies the variant of effectType. In combination of the effectType - * there are further restriction and specification of this field. - */ - private short _effectDirection = 0; // byte - - /** - * A byte that specifies which transition is used when transitioning to the - * next presentation slide during a slide show. Exact rendering of any transition is - * determined by the rendering application. As such, the same transition can have - * many variations depending on the implementation. - */ - private short _effectType = 0; // byte - - /** - * Various flags - see bitmask for more details - */ - private short _effectTransitionFlags = 0; - - /** - * A byte value that specifies how long the transition takes to run. - * (0x00 = 0.75 seconds, 0x01 = 0.5 seconds, 0x02 = 0.25 seconds) - */ - private short _speed = 0; // byte - private byte[] _unused; // 3-byte - - public SSSlideInfoAtom() { - _header = new byte[8]; - LittleEndian.putShort(_header, 0, (short)0); - LittleEndian.putShort(_header, 2, (short)_type); - LittleEndian.putShort(_header, 4, (short)0x10); - LittleEndian.putShort(_header, 6, (short)0); - _unused = new byte[3]; - } - - public SSSlideInfoAtom(byte[] source, int offset, int len) { - int ofs = offset; - - // Sanity Checking - if(len != 24) len = 24; - assert(source.length >= offset+len); - - // Get the header - _header = LittleEndian.getByteArray(source,ofs,8); - ofs += _header.length; - - assert(LittleEndian.getShort(_header, 0) == 0); - assert(LittleEndian.getShort(_header, 2) == RecordTypes.SSSlideInfoAtom.typeID); - assert(LittleEndian.getShort(_header, 4) == 0x10); - assert(LittleEndian.getShort(_header, 6) == 0); - - _slideTime = LittleEndian.getInt(source, ofs); - assert(0 <= _slideTime && _slideTime <= 86399000); - ofs += LittleEndianConsts.INT_SIZE; - _soundIdRef = LittleEndian.getInt(source, ofs); - ofs += LittleEndianConsts.INT_SIZE; - _effectDirection = LittleEndian.getUByte(source, ofs); - ofs += LittleEndianConsts.BYTE_SIZE; - _effectType = LittleEndian.getUByte(source, ofs); - ofs += LittleEndianConsts.BYTE_SIZE; - _effectTransitionFlags = LittleEndian.getShort(source, ofs); - ofs += LittleEndianConsts.SHORT_SIZE; - _speed = LittleEndian.getUByte(source, ofs); - ofs += LittleEndianConsts.BYTE_SIZE; - _unused = LittleEndian.getByteArray(source,ofs,3); - } - - /** - * Write the contents of the record back, so it can be written - * to disk - */ - public void writeOut(OutputStream out) throws IOException { - // Header - size or type unchanged - out.write(_header); - writeLittleEndian(_slideTime, out); - writeLittleEndian(_soundIdRef, out); - - byte byteBuf[] = new byte[LittleEndianConsts.BYTE_SIZE]; - LittleEndian.putUByte(byteBuf, 0, _effectDirection); - out.write(byteBuf); - LittleEndian.putUByte(byteBuf, 0, _effectType); - out.write(byteBuf); - - writeLittleEndian(_effectTransitionFlags, out); - LittleEndian.putUByte(byteBuf, 0, _speed); - out.write(byteBuf); - - assert(_unused.length == 3); - out.write(_unused); - } - - /** - * We are of type 1017 - */ - public long getRecordType() { return _type; } - - - public int getSlideTime() { - return _slideTime; - } - - public void setSlideTime(int slideTime) { - this._slideTime = slideTime; - } - - public int getSoundIdRef() { - return _soundIdRef; - } - - public void setSoundIdRef(int soundIdRef) { - this._soundIdRef = soundIdRef; - } - - public short getEffectDirection() { - return _effectDirection; - } - - public void setEffectDirection(short effectDirection) { - this._effectDirection = effectDirection; - } - - public short getEffectType() { - return _effectType; - } - - public void setEffectType(short effectType) { - this._effectType = effectType; - } - - public short getEffectTransitionFlags() { - return _effectTransitionFlags; - } - - public void setEffectTransitionFlags(short effectTransitionFlags) { - this._effectTransitionFlags = effectTransitionFlags; - } - - /** - * Use one of the bitmasks MANUAL_ADVANCE_BIT ... CURSOR_VISIBLE_BIT - * @param bitmask - * @param enabled - */ - public void setEffectTransitionFlagByBit(int bitmask, boolean enabled) { - if (enabled) { - _effectTransitionFlags |= bitmask; - } else { - _effectTransitionFlags &= (0xFFFF ^ bitmask); - } - } - - public boolean getEffectTransitionFlagByBit(int bitmask) { - return ((_effectTransitionFlags & bitmask) != 0); - } - - public short getSpeed() { - return _speed; - } - - public void setSpeed(short speed) { - this._speed = speed; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.LittleEndianConsts; + +/** + * A SlideShowSlideInfo Atom (type 1017).
    + *
    + * + * An atom record that specifies which transition effects to perform + * during a slide show, and how to advance to the next presentation slide.
    + *
    + * + * Combination of effectType and effectDirection: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    typedescriptiondirection
    0cut0x00 = no transition, 0x01 = black transition
    1random0x00
    2blinds0x00 = vertical, 0x01 = horizontal
    3checkerlike blinds
    4cover0x00 = left, 0x01 = up, 0x02 = right, 0x03 = down, 0x04 = left/up, 0x05 = right/up, 0x06 left/down, 0x07 = left/down
    5dissolve0x00
    6fade0x00
    7uncoverlike cover
    8random barslike blinds
    9stripslike 0x04 - 0x07 of cover
    10wipelike 0x00 - 0x03 of cover
    11box in/out0x00 = out, 0x01 = in
    13split0x00 = horizontally out, 0x01 = horizontally in, 0x02 = vertically out, 0x03 = vertically in
    17diamond0x00
    18plus0x00
    19wedge0x00
    20pushlike 0x00 - 0x03 of cover
    21comblike blinds
    22newsflash0x00
    23alphafade0x00
    26wheelnumber of radial divisions (0x01,0x02,0x03,0x04,0x08)
    27circle0x00
    255undefined0x00
    + */ +public class SSSlideInfoAtom extends RecordAtom { + /** + * A bit that specifies whether the presentation slide can be + * manually advanced by the user during the slide show. + */ + public static final int MANUAL_ADVANCE_BIT = 1 << 0; + + /** + * A bit that specifies whether the corresponding slide is + * hidden and is not displayed during the slide show. + */ + public static final int HIDDEN_BIT = 1 << 2; + + /** + * A bit that specifies whether to play the sound specified by soundIfRef. + */ + public static final int SOUND_BIT = 1 << 4; + + /** + * A bit that specifies whether the sound specified by soundIdRef is + * looped continuously when playing until the next sound plays. + */ + public static final int LOOP_SOUND_BIT = 1 << 6; + + /** + * A bit that specifies whether to stop any currently playing + * sound when the transition starts. + */ + public static final int STOP_SOUND_BIT = 1 << 8; + + /** + * A bit that specifies whether the slide will automatically + * advance after slideTime milliseconds during the slide show. + */ + public static final int AUTO_ADVANCE_BIT = 1 << 10; + + /** + * A bit that specifies whether to display the cursor during + * the slide show. + */ + public static final int CURSOR_VISIBLE_BIT = 1 << 12; + + // public static int RESERVED1_BIT = 1 << 1; + // public static int RESERVED2_BIT = 1 << 3; + // public static int RESERVED3_BIT = 1 << 5; + // public static int RESERVED4_BIT = 1 << 7; + // public static int RESERVED5_BIT = 1 << 9; + // public static int RESERVED6_BIT = 1 << 11; + // public static int RESERVED7_BIT = 1 << 13 | 1 << 14 | 1 << 15; + + private static final long _type = RecordTypes.SSSlideInfoAtom.typeID; + + private byte[] _header; + + /** + * A signed integer that specifies an amount of time, in milliseconds, to wait + * before advancing to the next presentation slide. It MUST be greater than or equal to 0 and + * less than or equal to 86399000. It MUST be ignored unless AUTO_ADVANCE_BIT is TRUE. + */ + private int _slideTime = 0; + + /** + * A SoundIdRef that specifies which sound to play when the transition starts. + */ + private int _soundIdRef = 0; + + /** + * A byte that specifies the variant of effectType. In combination of the effectType + * there are further restriction and specification of this field. + */ + private short _effectDirection = 0; // byte + + /** + * A byte that specifies which transition is used when transitioning to the + * next presentation slide during a slide show. Exact rendering of any transition is + * determined by the rendering application. As such, the same transition can have + * many variations depending on the implementation. + */ + private short _effectType = 0; // byte + + /** + * Various flags - see bitmask for more details + */ + private short _effectTransitionFlags = 0; + + /** + * A byte value that specifies how long the transition takes to run. + * (0x00 = 0.75 seconds, 0x01 = 0.5 seconds, 0x02 = 0.25 seconds) + */ + private short _speed = 0; // byte + private byte[] _unused; // 3-byte + + public SSSlideInfoAtom() { + _header = new byte[8]; + LittleEndian.putShort(_header, 0, (short)0); + LittleEndian.putShort(_header, 2, (short)_type); + LittleEndian.putShort(_header, 4, (short)0x10); + LittleEndian.putShort(_header, 6, (short)0); + _unused = new byte[3]; + } + + public SSSlideInfoAtom(byte[] source, int offset, int len) { + int ofs = offset; + + // Sanity Checking + if(len != 24) len = 24; + assert(source.length >= offset+len); + + // Get the header + _header = LittleEndian.getByteArray(source,ofs,8); + ofs += _header.length; + + assert(LittleEndian.getShort(_header, 0) == 0); + assert(LittleEndian.getShort(_header, 2) == RecordTypes.SSSlideInfoAtom.typeID); + assert(LittleEndian.getShort(_header, 4) == 0x10); + assert(LittleEndian.getShort(_header, 6) == 0); + + _slideTime = LittleEndian.getInt(source, ofs); + assert(0 <= _slideTime && _slideTime <= 86399000); + ofs += LittleEndianConsts.INT_SIZE; + _soundIdRef = LittleEndian.getInt(source, ofs); + ofs += LittleEndianConsts.INT_SIZE; + _effectDirection = LittleEndian.getUByte(source, ofs); + ofs += LittleEndianConsts.BYTE_SIZE; + _effectType = LittleEndian.getUByte(source, ofs); + ofs += LittleEndianConsts.BYTE_SIZE; + _effectTransitionFlags = LittleEndian.getShort(source, ofs); + ofs += LittleEndianConsts.SHORT_SIZE; + _speed = LittleEndian.getUByte(source, ofs); + ofs += LittleEndianConsts.BYTE_SIZE; + _unused = LittleEndian.getByteArray(source,ofs,3); + } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + // Header - size or type unchanged + out.write(_header); + writeLittleEndian(_slideTime, out); + writeLittleEndian(_soundIdRef, out); + + byte byteBuf[] = new byte[LittleEndianConsts.BYTE_SIZE]; + LittleEndian.putUByte(byteBuf, 0, _effectDirection); + out.write(byteBuf); + LittleEndian.putUByte(byteBuf, 0, _effectType); + out.write(byteBuf); + + writeLittleEndian(_effectTransitionFlags, out); + LittleEndian.putUByte(byteBuf, 0, _speed); + out.write(byteBuf); + + assert(_unused.length == 3); + out.write(_unused); + } + + /** + * We are of type 1017 + */ + public long getRecordType() { return _type; } + + + public int getSlideTime() { + return _slideTime; + } + + public void setSlideTime(int slideTime) { + this._slideTime = slideTime; + } + + public int getSoundIdRef() { + return _soundIdRef; + } + + public void setSoundIdRef(int soundIdRef) { + this._soundIdRef = soundIdRef; + } + + public short getEffectDirection() { + return _effectDirection; + } + + public void setEffectDirection(short effectDirection) { + this._effectDirection = effectDirection; + } + + public short getEffectType() { + return _effectType; + } + + public void setEffectType(short effectType) { + this._effectType = effectType; + } + + public short getEffectTransitionFlags() { + return _effectTransitionFlags; + } + + public void setEffectTransitionFlags(short effectTransitionFlags) { + this._effectTransitionFlags = effectTransitionFlags; + } + + /** + * Use one of the bitmasks MANUAL_ADVANCE_BIT ... CURSOR_VISIBLE_BIT + * @param bitmask + * @param enabled + */ + public void setEffectTransitionFlagByBit(int bitmask, boolean enabled) { + if (enabled) { + _effectTransitionFlags |= bitmask; + } else { + _effectTransitionFlags &= (0xFFFF ^ bitmask); + } + } + + public boolean getEffectTransitionFlagByBit(int bitmask) { + return ((_effectTransitionFlags & bitmask) != 0); + } + + public short getSpeed() { + return _speed; + } + + public void setSpeed(short speed) { + this._speed = speed; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java index 73ef2bfdf6..c76699abd5 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TextSpecInfoRun.java @@ -1,346 +1,346 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.record; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.poi.util.*; - -public class TextSpecInfoRun { - /** - * A enum that specifies the spelling status of a run of text. - */ - public enum SpellInfoEnum { - /** the text is spelled incorrectly. */ - error(new BitField(1)), - /** the text needs rechecking. */ - clean(new BitField(2)), - /** the text has a grammar error. */ - grammar(new BitField(4)), - /** the text is spelled correct */ - correct(new BitField(0)); - - final BitField bitField; - - SpellInfoEnum(BitField bitField) { - this.bitField = bitField; - } - } - - /** A bit that specifies whether the spellInfo field exists. */ - private static final BitField spellFld = new BitField(0X00000001); - /** A bit that specifies whether the lid field exists. */ - private static final BitField langFld = new BitField(0X00000002); - /** A bit that specifies whether the altLid field exists. */ - private static final BitField altLangFld = new BitField(0X00000004); - // unused1, unused2 - Undefined and MUST be ignored. - /** A bit that specifies whether the pp10runid, reserved3, and grammarError fields exist. */ - private static final BitField pp10extFld = new BitField(0X00000020); - /** A bit that specifies whether the bidi field exists. */ - private static final BitField bidiFld = new BitField(0X00000040); - // unused3 - Undefined and MUST be ignored. - // reserved1 - MUST be zero and MUST be ignored. - /** A bit that specifies whether the smartTags field exists. */ - private static final BitField smartTagFld = new BitField(0X00000200); - // reserved2 - MUST be zero and MUST be ignored. - - /** - * An optional unsigned integer that specifies an identifier for a character - * run that contains StyleTextProp11 data. It MUST exist if and only if pp10ext is TRUE. - **/ - private static final BitField pp10runidFld = new BitField(0X0000000F); - // reserved3 - An optional unsigned integer that MUST be zero, and MUST be ignored. It - // MUST exist if and only if fPp10ext is TRUE. - /** - * An optional bit that specifies a grammar error. It MUST exist if and - * only if fPp10ext is TRUE. - **/ - private static final BitField grammarErrorFld = new BitField(0X80000000); - - //Length of special info run. - private int length; - - //Special info mask of this run; - private int mask; - - // info fields as indicated by the mask. - // -1 means the bit is not set - - /** - * An optional SpellingFlags structure that specifies the spelling status of this - * text. It MUST exist if and only if spell is TRUE. - * The spellInfo.grammar sub-field MUST be zero. - *
    - * error (1 bit): A bit that specifies whether the text is spelled incorrectly.
    - * clean (1 bit): A bit that specifies whether the text needs rechecking.
    - * grammar (1 bit): A bit that specifies whether the text has a grammar error.
    - * reserved (13 bits): MUST be zero and MUST be ignored. - */ - private short spellInfo = -1; - - /** - * An optional TxLCID that specifies the language identifier of this text. - * It MUST exist if and only if lang is TRUE. - *
    - * 0x0000 = No language.
    - * 0x0013 = Any Dutch language is preferred over non-Dutch languages when proofing the text.
    - * 0x0400 = No proofing is performed on the text.
    - * > 0x0400 = A valid LCID as specified by [MS-LCID]. - */ - private short langId = -1; - - /** - * An optional TxLCID that specifies the alternate language identifier of this text. - * It MUST exist if and only if altLang is TRUE. - */ - private short altLangId = -1; - - /** - * An optional signed integer that specifies whether the text contains bidirectional - * characters. It MUST exist if and only if fBidi is TRUE. - * 0x0000 = Contains no bidirectional characters, - * 0x0001 = Contains bidirectional characters. - */ - private short bidi = -1; - - private int pp10extMask = -1; - private byte[] smartTagsBytes = null; - - /** - * Inits a TextSpecInfoRun with default values - * - * @param len the length of the one and only run - */ - public TextSpecInfoRun(int len) { - setLength(len); - setLangId((short)0); - } - - public TextSpecInfoRun(LittleEndianByteArrayInputStream source) { - length = source.readInt(); - mask = source.readInt(); - if (spellFld.isSet(mask)) { - spellInfo = source.readShort(); - } - if (langFld.isSet(mask)) { - langId = source.readShort(); - } - if (altLangFld.isSet(mask)) { - altLangId = source.readShort(); - } - if (bidiFld.isSet(mask)) { - bidi = source.readShort(); - } - if (pp10extFld.isSet(mask)) { - pp10extMask = source.readInt(); - } - if (smartTagFld.isSet(mask)) { - // An unsigned integer specifies the count of items in rgSmartTagIndex. - int count = source.readInt(); - smartTagsBytes = new byte[4+count*4]; - LittleEndian.putInt(smartTagsBytes, 0, count); - // An array of SmartTagIndex that specifies the indices. - // The count of items in the array is specified by count. - source.readFully(smartTagsBytes, 4, count*4); - } - } - - /** - * Write the contents of the record back, so it can be written - * to disk - * - * @param out the output stream to write to. - * @throws java.io.IOException if an error occurs. - */ - public void writeOut(OutputStream out) throws IOException { - final byte buf[] = new byte[4]; - LittleEndian.putInt(buf, 0, length); - out.write(buf); - LittleEndian.putInt(buf, 0, mask); - out.write(buf); - Object flds[] = { - spellFld, spellInfo, "spell info", - langFld, langId, "lang id", - altLangFld, altLangId, "alt lang id", - bidiFld, bidi, "bidi", - pp10extFld, pp10extMask, "pp10 extension field", - smartTagFld, smartTagsBytes, "smart tags" - }; - - for (int i=0; i 0; - out.write(bufB); - } else if (valO instanceof Integer) { - int valI = ((Integer)valO); - valid = (valI != -1); - LittleEndian.putInt(buf, 0, valI); - out.write(buf); - } else if (valO instanceof Short) { - short valS = ((Short)valO); - valid = (valS != -1); - LittleEndian.putShort(buf, 0, valS); - out.write(buf, 0, 2); - } else { - valid = false; - } - if (!valid) { - throw new IOException(flds[i+2]+" is activated, but its value is invalid"); - } - } - } - - /** - * @return Spelling status of this text. null if not defined. - */ - public SpellInfoEnum getSpellInfo(){ - if (spellInfo == -1) return null; - for (SpellInfoEnum si : new SpellInfoEnum[]{SpellInfoEnum.clean,SpellInfoEnum.error,SpellInfoEnum.grammar}) { - if (si.bitField.isSet(spellInfo)) return si; - } - return SpellInfoEnum.correct; - } - - /** - * @param spellInfo Spelling status of this text. null if not defined. - */ - public void setSpellInfo(SpellInfoEnum spellInfo) { - this.spellInfo = (spellInfo == null) - ? -1 - : (short)spellInfo.bitField.set(0); - mask = spellFld.setBoolean(mask, spellInfo != null); - } - - /** - * Windows LANGID for this text. - * - * @return Windows LANGID for this text, -1 if it's not set - */ - public short getLangId(){ - return langId; - } - - /** - * @param langId Windows LANGID for this text, -1 to unset - */ - public void setLangId(short langId) { - this.langId = langId; - mask = langFld.setBoolean(mask, langId != -1); - } - - /** - * Alternate Windows LANGID of this text; - * must be a valid non-East Asian LANGID if the text has an East Asian language, - * otherwise may be an East Asian LANGID or language neutral (zero). - * - * @return Alternate Windows LANGID of this text, -1 if it's not set - */ - public short getAltLangId(){ - return altLangId; - } - - public void setAltLangId(short altLangId) { - this.altLangId = altLangId; - mask = altLangFld.setBoolean(mask, altLangId != -1); - } - - /** - * @return Length of special info run. - */ - public int getLength() { - return length; - } - - /** - * @param length Length of special info run. - */ - public void setLength(int length) { - this.length = length; - } - - /** - * @return the bidirectional characters flag. false = not bidi, true = is bidi, null = not set - */ - public Boolean getBidi() { - return (bidi == -1 ? null : bidi != 0); - } - - /** - * @param bidi the bidirectional characters flag. false = not bidi, true = is bidi, null = not set - */ - public void setBidi(Boolean bidi) { - this.bidi = (bidi == null) ? -1 : (short)(bidi ? 1 : 0); - mask = bidiFld.setBoolean(mask, bidi != null); - } - - /** - * @return the unparsed smart tags - */ - public byte[] getSmartTagsBytes() { - return smartTagsBytes; - } - - /** - * @param smartTagsBytes the unparsed smart tags, null to unset - */ - public void setSmartTagsBytes(byte[] smartTagsBytes) { - this.smartTagsBytes = (smartTagsBytes == null) ? null : smartTagsBytes.clone(); - mask = smartTagFld.setBoolean(mask, smartTagsBytes != null); - } - - /** - * @return an identifier for a character run that contains StyleTextProp11 data. - */ - public int getPP10RunId() { - return (pp10extMask == -1 || !pp10extFld.isSet(mask)) ? -1 : pp10runidFld.getValue(pp10extMask); - - } - - /** - * @param pp10RunId an identifier for a character run that contains StyleTextProp11 data, -1 to unset - */ - public void setPP10RunId(int pp10RunId) { - if (pp10RunId == -1) { - pp10extMask = (getGrammarError() == null) ? -1 : pp10runidFld.clear(pp10extMask); - } else { - pp10extMask = pp10runidFld.setValue(pp10extMask, pp10RunId); - } - // if both parameters are invalid, remove the extension mask - mask = pp10extFld.setBoolean(mask, pp10extMask != -1); - } - - public Boolean getGrammarError() { - return (pp10extMask == -1 || !pp10extFld.isSet(mask)) ? null : grammarErrorFld.isSet(pp10extMask); - } - - public void getGrammarError(Boolean grammarError) { - if (grammarError == null) { - pp10extMask = (getPP10RunId() == -1) ? -1 : grammarErrorFld.clear(pp10extMask); - } else { - pp10extMask = grammarErrorFld.set(pp10extMask); - } - // if both parameters are invalid, remove the extension mask - mask = pp10extFld.setBoolean(mask, pp10extMask != -1); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.util.*; + +public class TextSpecInfoRun { + /** + * A enum that specifies the spelling status of a run of text. + */ + public enum SpellInfoEnum { + /** the text is spelled incorrectly. */ + error(new BitField(1)), + /** the text needs rechecking. */ + clean(new BitField(2)), + /** the text has a grammar error. */ + grammar(new BitField(4)), + /** the text is spelled correct */ + correct(new BitField(0)); + + final BitField bitField; + + SpellInfoEnum(BitField bitField) { + this.bitField = bitField; + } + } + + /** A bit that specifies whether the spellInfo field exists. */ + private static final BitField spellFld = new BitField(0X00000001); + /** A bit that specifies whether the lid field exists. */ + private static final BitField langFld = new BitField(0X00000002); + /** A bit that specifies whether the altLid field exists. */ + private static final BitField altLangFld = new BitField(0X00000004); + // unused1, unused2 - Undefined and MUST be ignored. + /** A bit that specifies whether the pp10runid, reserved3, and grammarError fields exist. */ + private static final BitField pp10extFld = new BitField(0X00000020); + /** A bit that specifies whether the bidi field exists. */ + private static final BitField bidiFld = new BitField(0X00000040); + // unused3 - Undefined and MUST be ignored. + // reserved1 - MUST be zero and MUST be ignored. + /** A bit that specifies whether the smartTags field exists. */ + private static final BitField smartTagFld = new BitField(0X00000200); + // reserved2 - MUST be zero and MUST be ignored. + + /** + * An optional unsigned integer that specifies an identifier for a character + * run that contains StyleTextProp11 data. It MUST exist if and only if pp10ext is TRUE. + **/ + private static final BitField pp10runidFld = new BitField(0X0000000F); + // reserved3 - An optional unsigned integer that MUST be zero, and MUST be ignored. It + // MUST exist if and only if fPp10ext is TRUE. + /** + * An optional bit that specifies a grammar error. It MUST exist if and + * only if fPp10ext is TRUE. + **/ + private static final BitField grammarErrorFld = new BitField(0X80000000); + + //Length of special info run. + private int length; + + //Special info mask of this run; + private int mask; + + // info fields as indicated by the mask. + // -1 means the bit is not set + + /** + * An optional SpellingFlags structure that specifies the spelling status of this + * text. It MUST exist if and only if spell is TRUE. + * The spellInfo.grammar sub-field MUST be zero. + *
    + * error (1 bit): A bit that specifies whether the text is spelled incorrectly.
    + * clean (1 bit): A bit that specifies whether the text needs rechecking.
    + * grammar (1 bit): A bit that specifies whether the text has a grammar error.
    + * reserved (13 bits): MUST be zero and MUST be ignored. + */ + private short spellInfo = -1; + + /** + * An optional TxLCID that specifies the language identifier of this text. + * It MUST exist if and only if lang is TRUE. + *
    + * 0x0000 = No language.
    + * 0x0013 = Any Dutch language is preferred over non-Dutch languages when proofing the text.
    + * 0x0400 = No proofing is performed on the text.
    + * > 0x0400 = A valid LCID as specified by [MS-LCID]. + */ + private short langId = -1; + + /** + * An optional TxLCID that specifies the alternate language identifier of this text. + * It MUST exist if and only if altLang is TRUE. + */ + private short altLangId = -1; + + /** + * An optional signed integer that specifies whether the text contains bidirectional + * characters. It MUST exist if and only if fBidi is TRUE. + * 0x0000 = Contains no bidirectional characters, + * 0x0001 = Contains bidirectional characters. + */ + private short bidi = -1; + + private int pp10extMask = -1; + private byte[] smartTagsBytes = null; + + /** + * Inits a TextSpecInfoRun with default values + * + * @param len the length of the one and only run + */ + public TextSpecInfoRun(int len) { + setLength(len); + setLangId((short)0); + } + + public TextSpecInfoRun(LittleEndianByteArrayInputStream source) { + length = source.readInt(); + mask = source.readInt(); + if (spellFld.isSet(mask)) { + spellInfo = source.readShort(); + } + if (langFld.isSet(mask)) { + langId = source.readShort(); + } + if (altLangFld.isSet(mask)) { + altLangId = source.readShort(); + } + if (bidiFld.isSet(mask)) { + bidi = source.readShort(); + } + if (pp10extFld.isSet(mask)) { + pp10extMask = source.readInt(); + } + if (smartTagFld.isSet(mask)) { + // An unsigned integer specifies the count of items in rgSmartTagIndex. + int count = source.readInt(); + smartTagsBytes = new byte[4+count*4]; + LittleEndian.putInt(smartTagsBytes, 0, count); + // An array of SmartTagIndex that specifies the indices. + // The count of items in the array is specified by count. + source.readFully(smartTagsBytes, 4, count*4); + } + } + + /** + * Write the contents of the record back, so it can be written + * to disk + * + * @param out the output stream to write to. + * @throws java.io.IOException if an error occurs. + */ + public void writeOut(OutputStream out) throws IOException { + final byte buf[] = new byte[4]; + LittleEndian.putInt(buf, 0, length); + out.write(buf); + LittleEndian.putInt(buf, 0, mask); + out.write(buf); + Object flds[] = { + spellFld, spellInfo, "spell info", + langFld, langId, "lang id", + altLangFld, altLangId, "alt lang id", + bidiFld, bidi, "bidi", + pp10extFld, pp10extMask, "pp10 extension field", + smartTagFld, smartTagsBytes, "smart tags" + }; + + for (int i=0; i 0; + out.write(bufB); + } else if (valO instanceof Integer) { + int valI = ((Integer)valO); + valid = (valI != -1); + LittleEndian.putInt(buf, 0, valI); + out.write(buf); + } else if (valO instanceof Short) { + short valS = ((Short)valO); + valid = (valS != -1); + LittleEndian.putShort(buf, 0, valS); + out.write(buf, 0, 2); + } else { + valid = false; + } + if (!valid) { + throw new IOException(flds[i+2]+" is activated, but its value is invalid"); + } + } + } + + /** + * @return Spelling status of this text. null if not defined. + */ + public SpellInfoEnum getSpellInfo(){ + if (spellInfo == -1) return null; + for (SpellInfoEnum si : new SpellInfoEnum[]{SpellInfoEnum.clean,SpellInfoEnum.error,SpellInfoEnum.grammar}) { + if (si.bitField.isSet(spellInfo)) return si; + } + return SpellInfoEnum.correct; + } + + /** + * @param spellInfo Spelling status of this text. null if not defined. + */ + public void setSpellInfo(SpellInfoEnum spellInfo) { + this.spellInfo = (spellInfo == null) + ? -1 + : (short)spellInfo.bitField.set(0); + mask = spellFld.setBoolean(mask, spellInfo != null); + } + + /** + * Windows LANGID for this text. + * + * @return Windows LANGID for this text, -1 if it's not set + */ + public short getLangId(){ + return langId; + } + + /** + * @param langId Windows LANGID for this text, -1 to unset + */ + public void setLangId(short langId) { + this.langId = langId; + mask = langFld.setBoolean(mask, langId != -1); + } + + /** + * Alternate Windows LANGID of this text; + * must be a valid non-East Asian LANGID if the text has an East Asian language, + * otherwise may be an East Asian LANGID or language neutral (zero). + * + * @return Alternate Windows LANGID of this text, -1 if it's not set + */ + public short getAltLangId(){ + return altLangId; + } + + public void setAltLangId(short altLangId) { + this.altLangId = altLangId; + mask = altLangFld.setBoolean(mask, altLangId != -1); + } + + /** + * @return Length of special info run. + */ + public int getLength() { + return length; + } + + /** + * @param length Length of special info run. + */ + public void setLength(int length) { + this.length = length; + } + + /** + * @return the bidirectional characters flag. false = not bidi, true = is bidi, null = not set + */ + public Boolean getBidi() { + return (bidi == -1 ? null : bidi != 0); + } + + /** + * @param bidi the bidirectional characters flag. false = not bidi, true = is bidi, null = not set + */ + public void setBidi(Boolean bidi) { + this.bidi = (bidi == null) ? -1 : (short)(bidi ? 1 : 0); + mask = bidiFld.setBoolean(mask, bidi != null); + } + + /** + * @return the unparsed smart tags + */ + public byte[] getSmartTagsBytes() { + return smartTagsBytes; + } + + /** + * @param smartTagsBytes the unparsed smart tags, null to unset + */ + public void setSmartTagsBytes(byte[] smartTagsBytes) { + this.smartTagsBytes = (smartTagsBytes == null) ? null : smartTagsBytes.clone(); + mask = smartTagFld.setBoolean(mask, smartTagsBytes != null); + } + + /** + * @return an identifier for a character run that contains StyleTextProp11 data. + */ + public int getPP10RunId() { + return (pp10extMask == -1 || !pp10extFld.isSet(mask)) ? -1 : pp10runidFld.getValue(pp10extMask); + + } + + /** + * @param pp10RunId an identifier for a character run that contains StyleTextProp11 data, -1 to unset + */ + public void setPP10RunId(int pp10RunId) { + if (pp10RunId == -1) { + pp10extMask = (getGrammarError() == null) ? -1 : pp10runidFld.clear(pp10extMask); + } else { + pp10extMask = pp10runidFld.setValue(pp10extMask, pp10RunId); + } + // if both parameters are invalid, remove the extension mask + mask = pp10extFld.setBoolean(mask, pp10extMask != -1); + } + + public Boolean getGrammarError() { + return (pp10extMask == -1 || !pp10extFld.isSet(mask)) ? null : grammarErrorFld.isSet(pp10extMask); + } + + public void getGrammarError(Boolean grammarError) { + if (grammarError == null) { + pp10extMask = (getPP10RunId() == -1) ? -1 : grammarErrorFld.clear(pp10extMask); + } else { + pp10extMask = grammarErrorFld.set(pp10extMask); + } + // if both parameters are invalid, remove the extension mask + mask = pp10extFld.setBoolean(mask, pp10extMask != -1); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFConnectorShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFConnectorShape.java index b36d3fcf14..d87f24b01b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFConnectorShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFConnectorShape.java @@ -1,65 +1,65 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.hslf.usermodel; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.sl.usermodel.ConnectorShape; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.util.Beta; - -/** - * Specifies a connection shape. - * - * This is currently only a dummy implementation. - */ -@Beta -public class HSLFConnectorShape extends HSLFSimpleShape -implements ConnectorShape { - - /** - * Create a ConnectorShape object and initialize it from the supplied Record container. - * - * @param escherRecord EscherSpContainer container which holds information about this shape - * @param parent the parent of the shape - */ - protected HSLFConnectorShape(EscherContainerRecord escherRecord, ShapeContainer parent){ - super(escherRecord, parent); - - } - - /** - * Create a new ConnectorShape. This constructor is used when a new shape is created. - * - * @param parent the parent of this Shape. For example, if this text box is a cell - * in a table then the parent is Table. - */ - public HSLFConnectorShape(ShapeContainer parent){ - super(null, parent); - createSpContainer(parent instanceof HSLFGroupShape); - } - - /** - * Create a new ConnectorShape. This constructor is used when a new shape is created. - * - */ - public HSLFConnectorShape(){ - this(null); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.hslf.usermodel; + +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.sl.usermodel.ConnectorShape; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.util.Beta; + +/** + * Specifies a connection shape. + * + * This is currently only a dummy implementation. + */ +@Beta +public class HSLFConnectorShape extends HSLFSimpleShape +implements ConnectorShape { + + /** + * Create a ConnectorShape object and initialize it from the supplied Record container. + * + * @param escherRecord EscherSpContainer container which holds information about this shape + * @param parent the parent of the shape + */ + protected HSLFConnectorShape(EscherContainerRecord escherRecord, ShapeContainer parent){ + super(escherRecord, parent); + + } + + /** + * Create a new ConnectorShape. This constructor is used when a new shape is created. + * + * @param parent the parent of this Shape. For example, if this text box is a cell + * in a table then the parent is Table. + */ + public HSLFConnectorShape(ShapeContainer parent){ + super(null, parent); + createSpContainer(parent instanceof HSLFGroupShape); + } + + /** + * Create a new ConnectorShape. This constructor is used when a new shape is created. + * + */ + public HSLFConnectorShape(){ + this(null); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeContainer.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeContainer.java index c09e2d6dda..8152befe25 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeContainer.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeContainer.java @@ -1,49 +1,49 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.hslf.usermodel; - -import org.apache.poi.sl.usermodel.PictureData; -import org.apache.poi.sl.usermodel.ShapeContainer; - -/** - * Common interface for shape containers, e.g. sheets or groups of shapes - */ -public interface HSLFShapeContainer extends ShapeContainer { - - @Override - HSLFAutoShape createAutoShape(); - - @Override - HSLFFreeformShape createFreeform(); - - @Override - HSLFTextBox createTextBox(); - - @Override - HSLFConnectorShape createConnector(); - - @Override - HSLFGroupShape createGroup(); - - @Override - HSLFPictureShape createPicture(PictureData pictureData); - - -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.hslf.usermodel; + +import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.sl.usermodel.ShapeContainer; + +/** + * Common interface for shape containers, e.g. sheets or groups of shapes + */ +public interface HSLFShapeContainer extends ShapeContainer { + + @Override + HSLFAutoShape createAutoShape(); + + @Override + HSLFFreeformShape createFreeform(); + + @Override + HSLFTextBox createTextBox(); + + @Override + HSLFConnectorShape createConnector(); + + @Override + HSLFGroupShape createGroup(); + + @Override + HSLFPictureShape createPicture(PictureData pictureData); + + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowFactory.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowFactory.java index 4c8f692699..fb216f1af4 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowFactory.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowFactory.java @@ -1,42 +1,42 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.usermodel; - -import java.io.IOException; - -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.SlideShowFactory; -import org.apache.poi.util.Internal; - -/** - * Helper class which is instantiated by reflection from - * {@link SlideShowFactory#create(java.io.File)} and similar - */ -@Internal -public class HSLFSlideShowFactory extends SlideShowFactory { - /** - * Creates a HSLFSlideShow from the given NPOIFSFileSystem - *

    Note that in order to properly release resources the - * SlideShow should be closed after use. - */ - public static SlideShow createSlideShow(NPOIFSFileSystem fs) throws IOException { - return new HSLFSlideShow(fs); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.usermodel; + +import java.io.IOException; + +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.util.Internal; + +/** + * Helper class which is instantiated by reflection from + * {@link SlideShowFactory#create(java.io.File)} and similar + */ +@Internal +public class HSLFSlideShowFactory extends SlideShowFactory { + /** + * Creates a HSLFSlideShow from the given NPOIFSFileSystem + *

    Note that in order to properly release resources the + * SlideShow should be closed after use. + */ + public static SlideShow createSlideShow(NPOIFSFileSystem fs) throws IOException { + return new HSLFSlideShow(fs); + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java index afe5d71264..9d39d3e9db 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java @@ -1,1650 +1,1650 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.usermodel; - -import static org.apache.poi.hslf.record.RecordTypes.OutlineTextRefAtom; - -import java.awt.Color; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.model.PPFont; -import org.apache.poi.hslf.model.textproperties.BitMaskTextProp; -import org.apache.poi.hslf.model.textproperties.FontAlignmentProp; -import org.apache.poi.hslf.model.textproperties.IndentProp; -import org.apache.poi.hslf.model.textproperties.ParagraphFlagsTextProp; -import org.apache.poi.hslf.model.textproperties.TextAlignmentProp; -import org.apache.poi.hslf.model.textproperties.TextPFException9; -import org.apache.poi.hslf.model.textproperties.TextProp; -import org.apache.poi.hslf.model.textproperties.TextPropCollection; -import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType; -import org.apache.poi.hslf.record.ColorSchemeAtom; -import org.apache.poi.hslf.record.EscherTextboxWrapper; -import org.apache.poi.hslf.record.FontCollection; -import org.apache.poi.hslf.record.InteractiveInfo; -import org.apache.poi.hslf.record.MasterTextPropAtom; -import org.apache.poi.hslf.record.OutlineTextRefAtom; -import org.apache.poi.hslf.record.PPDrawing; -import org.apache.poi.hslf.record.Record; -import org.apache.poi.hslf.record.RecordContainer; -import org.apache.poi.hslf.record.RecordTypes; -import org.apache.poi.hslf.record.RoundTripHFPlaceholder12; -import org.apache.poi.hslf.record.SlideListWithText; -import org.apache.poi.hslf.record.SlidePersistAtom; -import org.apache.poi.hslf.record.StyleTextProp9Atom; -import org.apache.poi.hslf.record.StyleTextPropAtom; -import org.apache.poi.hslf.record.TextBytesAtom; -import org.apache.poi.hslf.record.TextCharsAtom; -import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.record.TextRulerAtom; -import org.apache.poi.hslf.record.TextSpecInfoAtom; -import org.apache.poi.hslf.record.TxInteractiveInfoAtom; -import org.apache.poi.sl.draw.DrawPaint; -import org.apache.poi.sl.usermodel.AutoNumberingScheme; -import org.apache.poi.sl.usermodel.MasterSheet; -import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.apache.poi.sl.usermodel.Placeholder; -import org.apache.poi.sl.usermodel.TextParagraph; -import org.apache.poi.util.Internal; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.StringUtil; -import org.apache.poi.util.Units; - -/** - * This class represents a run of text in a powerpoint document. That - * run could be text on a sheet, or text in a note. - * It is only a very basic class for now - */ - -public final class HSLFTextParagraph implements TextParagraph { - protected static final POILogger logger = POILogFactory.getLogger(HSLFTextParagraph.class); - - /** - * How to align the text - */ - /* package */static final int AlignLeft = 0; - /* package */static final int AlignCenter = 1; - /* package */static final int AlignRight = 2; - /* package */static final int AlignJustify = 3; - - // Note: These fields are protected to help with unit testing - // Other classes shouldn't really go playing with them! - private final TextHeaderAtom _headerAtom; - private TextBytesAtom _byteAtom; - private TextCharsAtom _charAtom; - private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph); - private TextPropCollection _masterStyle; - - protected TextRulerAtom _ruler; - protected final List _runs = new ArrayList(); - protected HSLFTextShape _parentShape; - private HSLFSheet _sheet; - private int shapeId; - - private StyleTextProp9Atom styleTextProp9Atom; - - private boolean _dirty = false; - - private final List parentList; - - /** - * Constructs a Text Run from a Unicode text block. - * Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided. - * - * @param tha the TextHeaderAtom that defines what's what - * @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided - * @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided - * @param parentList the list which contains this paragraph - */ - /* package */ HSLFTextParagraph( - TextHeaderAtom tha, - TextBytesAtom tba, - TextCharsAtom tca, - List parentList - ) { - if (tha == null) { - throw new IllegalArgumentException("TextHeaderAtom must be set."); - } - _headerAtom = tha; - _byteAtom = tba; - _charAtom = tca; - this.parentList = parentList; - } - - /* package */HSLFTextParagraph(HSLFTextParagraph other) { - _headerAtom = other._headerAtom; - _byteAtom = other._byteAtom; - _charAtom = other._charAtom; - _parentShape = other._parentShape; - _sheet = other._sheet; - _ruler = other._ruler; - shapeId = other.shapeId; - _paragraphStyle.copy(other._paragraphStyle); - parentList = other.parentList; - } - - public void addTextRun(HSLFTextRun run) { - _runs.add(run); - } - - @Override - public List getTextRuns() { - return _runs; - } - - public TextPropCollection getParagraphStyle() { - return _paragraphStyle; - } - - public void setParagraphStyle(TextPropCollection paragraphStyle) { - _paragraphStyle.copy(paragraphStyle); - } - - /** - * Setting a master style reference - * - * @param paragraphStyle the master style reference - * - * @since POI 3.14-Beta1 - */ - @Internal - /* package */ void setMasterStyleReference(TextPropCollection masterStyle) { - _masterStyle = masterStyle; - } - - /** - * Supply the Sheet we belong to, which might have an assigned SlideShow - * Also passes it on to our child RichTextRuns - */ - public static void supplySheet(List paragraphs, HSLFSheet sheet) { - if (paragraphs == null) { - return; - } - for (HSLFTextParagraph p : paragraphs) { - p.supplySheet(sheet); - } - - assert(sheet.getSlideShow() != null); - } - - /** - * Supply the Sheet we belong to, which might have an assigned SlideShow - * Also passes it on to our child RichTextRuns - */ - private void supplySheet(HSLFSheet sheet) { - this._sheet = sheet; - - if (_runs == null) { - return; - } - for (HSLFTextRun rt : _runs) { - rt.updateSheet(); - } - } - - public HSLFSheet getSheet() { - return this._sheet; - } - - /** - * @return Shape ID - */ - protected int getShapeId() { - return shapeId; - } - - /** - * @param id Shape ID - */ - protected void setShapeId(int id) { - shapeId = id; - } - - /** - * @return 0-based index of the text run in the SLWT container - */ - protected int getIndex() { - return (_headerAtom != null) ? _headerAtom.getIndex() : -1; - } - - /** - * Sets the index of the paragraph in the SLWT container - * - * @param index - */ - protected void setIndex(int index) { - if (_headerAtom != null) { - _headerAtom.setIndex(index); - } - } - - /** - * Returns the type of the text, from the TextHeaderAtom. - * Possible values can be seen from TextHeaderAtom - * @see org.apache.poi.hslf.record.TextHeaderAtom - */ - public int getRunType() { - return (_headerAtom != null) ? _headerAtom.getTextType() : -1; - } - - public void setRunType(int runType) { - if (_headerAtom != null) { - _headerAtom.setTextType(runType); - } - } - - /** - * Is this Text Run one from a {@link PPDrawing}, or is it - * one from the {@link SlideListWithText}? - */ - public boolean isDrawingBased() { - return (getIndex() == -1); - } - - public TextRulerAtom getTextRuler() { - return _ruler; - } - - public TextRulerAtom createTextRuler() { - _ruler = getTextRuler(); - if (_ruler == null) { - _ruler = TextRulerAtom.getParagraphInstance(); - Record childAfter = _byteAtom; - if (childAfter == null) { - childAfter = _charAtom; - } - if (childAfter == null) { - childAfter = _headerAtom; - } - _headerAtom.getParentRecord().addChildAfter(_ruler, childAfter); - } - return _ruler; - } - - /** - * Returns records that make up the list of text paragraphs - * (there can be misc InteractiveInfo, TxInteractiveInfo and other records) - * - * @return text run records - */ - public Record[] getRecords() { - Record r[] = _headerAtom.getParentRecord().getChildRecords(); - return getRecords(r, new int[] { 0 }, _headerAtom); - } - - private static Record[] getRecords(Record[] records, int[] startIdx, TextHeaderAtom headerAtom) { - if (records == null) { - throw new NullPointerException("records need to be set."); - } - - for (; startIdx[0] < records.length; startIdx[0]++) { - Record r = records[startIdx[0]]; - if (r instanceof TextHeaderAtom && (headerAtom == null || r == headerAtom)) { - break; - } - } - - if (startIdx[0] >= records.length) { - logger.log(POILogger.INFO, "header atom wasn't found - container might contain only an OutlineTextRefAtom"); - return new Record[0]; - } - - int length; - for (length = 1; startIdx[0] + length < records.length; length++) { - Record r = records[startIdx[0]+length]; - if (r instanceof TextHeaderAtom || r instanceof SlidePersistAtom) { - break; - } - } - - Record result[] = new Record[length]; - System.arraycopy(records, startIdx[0], result, 0, length); - startIdx[0] += length; - - return result; - } - - /** Numbered List info */ - public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) { - this.styleTextProp9Atom = styleTextProp9Atom; - } - - /** Numbered List info */ - public StyleTextProp9Atom getStyleTextProp9Atom() { - return this.styleTextProp9Atom; - } - - @Override - public Iterator iterator() { - return _runs.iterator(); - } - - @Override - public Double getLeftMargin() { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "text.offset"); - return (tp == null) ? null : Units.masterToPoints(tp.getValue()); - } - - @Override - public void setLeftMargin(Double leftMargin) { - Integer val = (leftMargin == null) ? null : Units.pointsToMaster(leftMargin); - setParagraphTextPropVal("text.offset", val); - } - - @Override - public Double getRightMargin() { - // TODO: find out, how to determine this value - return null; - } - - @Override - public void setRightMargin(Double rightMargin) { - // TODO: find out, how to set this value - } - - @Override - public Double getIndent() { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.offset"); - return (tp == null) ? null : Units.masterToPoints(tp.getValue()); - } - - @Override - public void setIndent(Double indent) { - Integer val = (indent == null) ? null : Units.pointsToMaster(indent); - setParagraphTextPropVal("bullet.offset", val); - } - - @Override - public String getDefaultFontFamily() { - String typeface = null; - if (!_runs.isEmpty()) { - typeface = _runs.get(0).getFontFamily(); - } - return (typeface != null) ? typeface : "Arial"; - } - - @Override - public Double getDefaultFontSize() { - Double d = null; - if (!_runs.isEmpty()) { - d = _runs.get(0).getFontSize(); - } - - return (d != null) ? d : 12d; - } - - @Override - public void setTextAlign(TextAlign align) { - Integer alignInt = null; - if (align != null) { - switch (align) { - default: - case LEFT: alignInt = TextAlignmentProp.LEFT;break; - case CENTER: alignInt = TextAlignmentProp.CENTER; break; - case RIGHT: alignInt = TextAlignmentProp.RIGHT; break; - case DIST: alignInt = TextAlignmentProp.DISTRIBUTED; break; - case JUSTIFY: alignInt = TextAlignmentProp.JUSTIFY; break; - case JUSTIFY_LOW: alignInt = TextAlignmentProp.JUSTIFYLOW; break; - case THAI_DIST: alignInt = TextAlignmentProp.THAIDISTRIBUTED; break; - } - } - setParagraphTextPropVal("alignment", alignInt); - } - - @Override - public TextAlign getTextAlign() { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "alignment"); - if (tp == null) { - return null; - } - switch (tp.getValue()) { - default: - case TextAlignmentProp.LEFT: return TextAlign.LEFT; - case TextAlignmentProp.CENTER: return TextAlign.CENTER; - case TextAlignmentProp.RIGHT: return TextAlign.RIGHT; - case TextAlignmentProp.JUSTIFY: return TextAlign.JUSTIFY; - case TextAlignmentProp.JUSTIFYLOW: return TextAlign.JUSTIFY_LOW; - case TextAlignmentProp.DISTRIBUTED: return TextAlign.DIST; - case TextAlignmentProp.THAIDISTRIBUTED: return TextAlign.THAI_DIST; - } - } - - @Override - public FontAlign getFontAlign() { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, FontAlignmentProp.NAME); - if (tp == null) { - return null; - } - - switch (tp.getValue()) { - case FontAlignmentProp.BASELINE: return FontAlign.BASELINE; - case FontAlignmentProp.TOP: return FontAlign.TOP; - case FontAlignmentProp.CENTER: return FontAlign.CENTER; - case FontAlignmentProp.BOTTOM: return FontAlign.BOTTOM; - default: return FontAlign.AUTO; - } - } - - public AutoNumberingScheme getAutoNumberingScheme() { - if (styleTextProp9Atom == null) { - return null; - } - TextPFException9[] ant = styleTextProp9Atom.getAutoNumberTypes(); - int level = getIndentLevel(); - if (ant == null || level == -1 || level >= ant.length) { - return null; - } - return ant[level].getAutoNumberScheme(); - } - - public Integer getAutoNumberingStartAt() { - if (styleTextProp9Atom == null) { - return null; - } - TextPFException9[] ant = styleTextProp9Atom.getAutoNumberTypes(); - int level = getIndentLevel(); - if (ant == null || level >= ant.length) { - return null; - } - Short startAt = ant[level].getAutoNumberStartNumber(); - assert(startAt != null); - return startAt.intValue(); - } - - - @Override - public BulletStyle getBulletStyle() { - if (!isBullet() && getAutoNumberingScheme() == null) { - return null; - } - - return new BulletStyle() { - @Override - public String getBulletCharacter() { - Character chr = HSLFTextParagraph.this.getBulletChar(); - return (chr == null || chr == 0) ? "" : "" + chr; - } - - @Override - public String getBulletFont() { - return HSLFTextParagraph.this.getBulletFont(); - } - - @Override - public Double getBulletFontSize() { - return HSLFTextParagraph.this.getBulletSize(); - } - - @Override - public void setBulletFontColor(Color color) { - setBulletFontColor(DrawPaint.createSolidPaint(color)); - } - - @Override - public void setBulletFontColor(PaintStyle color) { - if (!(color instanceof SolidPaint)) { - throw new IllegalArgumentException("HSLF only supports SolidPaint"); - } - SolidPaint sp = (SolidPaint)color; - Color col = DrawPaint.applyColorTransform(sp.getSolidColor()); - HSLFTextParagraph.this.setBulletColor(col); - } - - @Override - public PaintStyle getBulletFontColor() { - Color col = HSLFTextParagraph.this.getBulletColor(); - return DrawPaint.createSolidPaint(col); - } - - @Override - public AutoNumberingScheme getAutoNumberingScheme() { - return HSLFTextParagraph.this.getAutoNumberingScheme(); - } - - @Override - public Integer getAutoNumberingStartAt() { - return HSLFTextParagraph.this.getAutoNumberingStartAt(); - } - }; - } - - @Override - public void setBulletStyle(Object... styles) { - if (styles.length == 0) { - setBullet(false); - } else { - setBullet(true); - for (Object ostyle : styles) { - if (ostyle instanceof Number) { - setBulletSize(((Number)ostyle).doubleValue()); - } else if (ostyle instanceof Color) { - setBulletColor((Color)ostyle); - } else if (ostyle instanceof Character) { - setBulletChar((Character)ostyle); - } else if (ostyle instanceof String) { - setBulletFont((String)ostyle); - } else if (ostyle instanceof AutoNumberingScheme) { - throw new HSLFException("setting bullet auto-numberin scheme for HSLF not supported ... yet"); - } - } - } - } - - @Override - public HSLFTextShape getParentShape() { - return _parentShape; - } - - public void setParentShape(HSLFTextShape parentShape) { - _parentShape = parentShape; - } - - @Override - public int getIndentLevel() { - return _paragraphStyle == null ? 0 : _paragraphStyle.getIndentLevel(); - } - - @Override - public void setIndentLevel(int level) { - if( _paragraphStyle != null ) { - _paragraphStyle.setIndentLevel((short)level); - } - } - - /** - * Sets whether this rich text run has bullets - */ - public void setBullet(boolean flag) { - setFlag(ParagraphFlagsTextProp.BULLET_IDX, flag); - } - - /** - * Returns whether this rich text run has bullets - */ - public boolean isBullet() { - return getFlag(ParagraphFlagsTextProp.BULLET_IDX); - } - - /** - * Sets the bullet character - */ - public void setBulletChar(Character c) { - Integer val = (c == null) ? null : (int)c.charValue(); - setParagraphTextPropVal("bullet.char", val); - } - - /** - * Returns the bullet character - */ - public Character getBulletChar() { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.char"); - return (tp == null) ? null : (char)tp.getValue(); - } - - /** - * Sets the bullet size - */ - public void setBulletSize(Double size) { - setPctOrPoints("bullet.size", size); - } - - /** - * Returns the bullet size, null if unset - */ - public Double getBulletSize() { - return getPctOrPoints("bullet.size"); - } - - /** - * Sets the bullet color - */ - public void setBulletColor(Color color) { - Integer val = (color == null) ? null : new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB(); - setParagraphTextPropVal("bullet.color", val); - setFlag(ParagraphFlagsTextProp.BULLET_HARDCOLOR_IDX, (color != null)); - } - - /** - * Returns the bullet color - */ - public Color getBulletColor() { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.color"); - boolean hasColor = getFlag(ParagraphFlagsTextProp.BULLET_HARDCOLOR_IDX); - if (tp == null || !hasColor) { - // if bullet color is undefined, return color of first run - if (_runs.isEmpty()) { - return null; - } - - SolidPaint sp = _runs.get(0).getFontColor(); - if(sp == null) { - return null; - } - - return DrawPaint.applyColorTransform(sp.getSolidColor()); - } - - return getColorFromColorIndexStruct(tp.getValue(), _sheet); - } - - /** - * Sets the bullet font - */ - public void setBulletFont(String typeface) { - if (typeface == null) { - setPropVal(_paragraphStyle, _masterStyle, "bullet.font", null); - setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, false); - return; - } - - FontCollection fc = getSheet().getSlideShow().getFontCollection(); - int idx = fc.addFont(typeface); - - setParagraphTextPropVal("bullet.font", idx); - setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, true); - } - - /** - * Returns the bullet font - */ - public String getBulletFont() { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.font"); - boolean hasFont = getFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX); - if (tp == null || !hasFont) { - return getDefaultFontFamily(); - } - PPFont ppFont = getSheet().getSlideShow().getFont(tp.getValue()); - assert(ppFont != null); - return ppFont.getFontName(); - } - - @Override - public void setLineSpacing(Double lineSpacing) { - setPctOrPoints("linespacing", lineSpacing); - } - - @Override - public Double getLineSpacing() { - return getPctOrPoints("linespacing"); - } - - @Override - public void setSpaceBefore(Double spaceBefore) { - setPctOrPoints("spacebefore", spaceBefore); - } - - @Override - public Double getSpaceBefore() { - return getPctOrPoints("spacebefore"); - } - - @Override - public void setSpaceAfter(Double spaceAfter) { - setPctOrPoints("spaceafter", spaceAfter); - } - - @Override - public Double getSpaceAfter() { - return getPctOrPoints("spaceafter"); - } - - @Override - public Double getDefaultTabSize() { - // TODO: implement - return null; - } - - private Double getPctOrPoints(String propName) { - TextProp tp = getPropVal(_paragraphStyle, _masterStyle, propName); - if (tp == null) { - return null; - } - int val = tp.getValue(); - return (val < 0) ? Units.masterToPoints(val) : val; - } - - private void setPctOrPoints(String propName, Double dval) { - Integer ival = null; - if (dval != null) { - ival = (dval < 0) ? Units.pointsToMaster(dval) : dval.intValue(); - } - setParagraphTextPropVal(propName, ival); - } - - private boolean getFlag(int index) { - BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, _masterStyle, ParagraphFlagsTextProp.NAME); - return (tp == null) ? false : tp.getSubValue(index); - } - - private void setFlag(int index, boolean value) { - BitMaskTextProp tp = (BitMaskTextProp)_paragraphStyle.addWithName(ParagraphFlagsTextProp.NAME); - tp.setSubValue(value, index); - setDirty(); - } - - /** - * Fetch the value of the given Paragraph related TextProp. Returns null if - * that TextProp isn't present. If the TextProp isn't present, the value - * from the appropriate Master Sheet will apply. - * - * The propName can be a comma-separated list, in case multiple equivalent values - * are queried - */ - protected TextProp getPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) { - String propNames[] = propName.split(","); - for (String pn : propNames) { - TextProp prop = props.findByName(pn); - if (prop == null) { - continue; - } - - // Font properties (maybe other too???) can have an index of -1 - // so we check the master for this font index then - if (pn.contains("font") && prop.getValue() == -1) { - return getMasterPropVal(props, masterProps, pn); - } - - return prop; - } - - return getMasterPropVal(props, masterProps, propName); - } - - private TextProp getMasterPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) { - boolean isChar = props.getTextPropType() == TextPropType.character; - - // check if we can delegate to master for the property - if (!isChar) { - BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME); - boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0); - if (hardAttribute) { - return null; - } - } - - String propNames[] = propName.split(","); - if (masterProps == null) { - HSLFSheet sheet = getSheet(); - int txtype = getRunType(); - HSLFMasterSheet master = sheet.getMasterSheet(); - if (master == null) { - logger.log(POILogger.WARN, "MasterSheet is not available"); - return null; - } - - for (String pn : propNames) { - TextProp prop = master.getStyleAttribute(txtype, getIndentLevel(), pn, isChar); - if (prop != null) { - return prop; - } - } - } else { - for (String pn : propNames) { - TextProp prop = masterProps.findByName(pn); - if (prop != null) { - return prop; - } - } - } - - return null; - } - - /** - * Returns the named TextProp, either by fetching it (if it exists) or - * adding it (if it didn't) - * - * @param props the TextPropCollection to fetch from / add into - * @param name the name of the TextProp to fetch/add - * @param val the value, null if unset - */ - protected void setPropVal(TextPropCollection props, TextPropCollection masterProps, String name, Integer val) { - TextPropCollection pc = props; - if (getSheet() instanceof MasterSheet && masterProps != null) { - pc = masterProps; - } - - if (val == null) { - pc.removeByName(name); - return; - } - - // Fetch / Add the TextProp - TextProp tp = pc.addWithName(name); - tp.setValue(val); - } - - /** - * Check and add linebreaks to text runs leading other paragraphs - * - * @param paragraphs - */ - protected static void fixLineEndings(List paragraphs) { - HSLFTextRun lastRun = null; - for (HSLFTextParagraph p : paragraphs) { - if (lastRun != null && !lastRun.getRawText().endsWith("\r")) { - lastRun.setText(lastRun.getRawText() + "\r"); - } - List ltr = p.getTextRuns(); - if (ltr.isEmpty()) { - throw new HSLFException("paragraph without textruns found"); - } - lastRun = ltr.get(ltr.size() - 1); - assert (lastRun.getRawText() != null); - } - } - - /** - * Search for a StyleTextPropAtom is for this text header (list of paragraphs) - * - * @param header the header - * @param textLen the length of the rawtext, or -1 if the length is not known - */ - private static StyleTextPropAtom findStyleAtomPresent(TextHeaderAtom header, int textLen) { - boolean afterHeader = false; - StyleTextPropAtom style = null; - for (Record record : header.getParentRecord().getChildRecords()) { - long rt = record.getRecordType(); - if (afterHeader && rt == RecordTypes.TextHeaderAtom.typeID) { - // already on the next header, quit searching - break; - } - afterHeader |= (header == record); - if (afterHeader && rt == RecordTypes.StyleTextPropAtom.typeID) { - // found it - style = (StyleTextPropAtom) record; - } - } - - if (style == null) { - logger.log(POILogger.INFO, "styles atom doesn't exist. Creating dummy record for later saving."); - style = new StyleTextPropAtom((textLen < 0) ? 1 : textLen); - } else { - if (textLen >= 0) { - style.setParentTextSize(textLen); - } - } - - return style; - } - - /** - * Saves the modified paragraphs/textrun to the records. - * Also updates the styles to the correct text length. - */ - protected static void storeText(List paragraphs) { - fixLineEndings(paragraphs); - updateTextAtom(paragraphs); - updateStyles(paragraphs); - updateHyperlinks(paragraphs); - refreshRecords(paragraphs); - - for (HSLFTextParagraph p : paragraphs) { - p._dirty = false; - } - } - - /** - * Set the correct text atom depending on the multibyte usage - */ - private static void updateTextAtom(List paragraphs) { - final String rawText = toInternalString(getRawText(paragraphs)); - - // Will it fit in a 8 bit atom? - boolean isUnicode = StringUtil.hasMultibyte(rawText); - // isUnicode = true; - - TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; - TextBytesAtom byteAtom = paragraphs.get(0)._byteAtom; - TextCharsAtom charAtom = paragraphs.get(0)._charAtom; - StyleTextPropAtom styleAtom = findStyleAtomPresent(headerAtom, rawText.length()); - - // Store in the appropriate record - Record oldRecord = null, newRecord = null; - if (isUnicode) { - if (byteAtom != null || charAtom == null) { - oldRecord = byteAtom; - charAtom = new TextCharsAtom(); - } - newRecord = charAtom; - charAtom.setText(rawText); - } else { - if (charAtom != null || byteAtom == null) { - oldRecord = charAtom; - byteAtom = new TextBytesAtom(); - } - newRecord = byteAtom; - byte[] byteText = new byte[rawText.length()]; - StringUtil.putCompressedUnicode(rawText, byteText, 0); - byteAtom.setText(byteText); - } - assert (newRecord != null); - - RecordContainer _txtbox = headerAtom.getParentRecord(); - Record[] cr = _txtbox.getChildRecords(); - int /* headerIdx = -1, */ textIdx = -1, styleIdx = -1; - for (int i = 0; i < cr.length; i++) { - Record r = cr[i]; - if (r == headerAtom) { - ; // headerIdx = i; - } else if (r == oldRecord || r == newRecord) { - textIdx = i; - } else if (r == styleAtom) { - styleIdx = i; - } - } - - if (textIdx == -1) { - // the old record was never registered, ignore it - _txtbox.addChildAfter(newRecord, headerAtom); - // textIdx = headerIdx + 1; - } else { - // swap not appropriated records - noop if unchanged - cr[textIdx] = newRecord; - } - - if (styleIdx == -1) { - // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom - _txtbox.addChildAfter(styleAtom, newRecord); - } - - for (HSLFTextParagraph p : paragraphs) { - if (newRecord == byteAtom) { - p._byteAtom = byteAtom; - p._charAtom = null; - } else { - p._byteAtom = null; - p._charAtom = charAtom; - } - } - - } - - /** - * Update paragraph and character styles - merges them when subsequential styles match - */ - private static void updateStyles(List paragraphs) { - final String rawText = toInternalString(getRawText(paragraphs)); - TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; - StyleTextPropAtom styleAtom = findStyleAtomPresent(headerAtom, rawText.length()); - - // Update the text length for its Paragraph and Character stylings - // * reset the length, to the new string's length - // * add on +1 if the last block - - styleAtom.clearStyles(); - - TextPropCollection lastPTPC = null, lastRTPC = null, ptpc = null, rtpc = null; - for (HSLFTextParagraph para : paragraphs) { - ptpc = para.getParagraphStyle(); - ptpc.updateTextSize(0); - if (!ptpc.equals(lastPTPC)) { - lastPTPC = styleAtom.addParagraphTextPropCollection(0); - lastPTPC.copy(ptpc); - } - for (HSLFTextRun tr : para.getTextRuns()) { - rtpc = tr.getCharacterStyle(); - rtpc.updateTextSize(0); - if (!rtpc.equals(lastRTPC)) { - lastRTPC = styleAtom.addCharacterTextPropCollection(0); - lastRTPC.copy(rtpc); - } - int len = tr.getLength(); - ptpc.updateTextSize(ptpc.getCharactersCovered() + len); - rtpc.updateTextSize(len); - lastPTPC.updateTextSize(lastPTPC.getCharactersCovered() + len); - lastRTPC.updateTextSize(lastRTPC.getCharactersCovered() + len); - } - } - - if (lastPTPC == null || lastRTPC == null || ptpc == null || rtpc == null) { // NOSONAR - throw new HSLFException("Not all TextPropCollection could be determined."); - } - - ptpc.updateTextSize(ptpc.getCharactersCovered() + 1); - rtpc.updateTextSize(rtpc.getCharactersCovered() + 1); - lastPTPC.updateTextSize(lastPTPC.getCharactersCovered() + 1); - lastRTPC.updateTextSize(lastRTPC.getCharactersCovered() + 1); - - /** - * If TextSpecInfoAtom is present, we must update the text size in it, - * otherwise the ppt will be corrupted - */ - for (Record r : paragraphs.get(0).getRecords()) { - if (r instanceof TextSpecInfoAtom) { - ((TextSpecInfoAtom) r).setParentSize(rawText.length() + 1); - break; - } - } - } - - private static void updateHyperlinks(List paragraphs) { - TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; - RecordContainer _txtbox = headerAtom.getParentRecord(); - // remove existing hyperlink records - for (Record r : _txtbox.getChildRecords()) { - if (r instanceof InteractiveInfo || r instanceof TxInteractiveInfoAtom) { - _txtbox.removeChild(r); - } - } - // now go through all the textruns and check for hyperlinks - HSLFHyperlink lastLink = null; - for (HSLFTextParagraph para : paragraphs) { - for (HSLFTextRun run : para) { - HSLFHyperlink thisLink = run.getHyperlink(); - if (thisLink != null && thisLink == lastLink) { - // the hyperlink extends over this text run, increase its length - // TODO: the text run might be longer than the hyperlink - thisLink.setEndIndex(thisLink.getEndIndex()+run.getLength()); - } else { - if (lastLink != null) { - InteractiveInfo info = lastLink.getInfo(); - TxInteractiveInfoAtom txinfo = lastLink.getTextRunInfo(); - assert(info != null && txinfo != null); - _txtbox.appendChildRecord(info); - _txtbox.appendChildRecord(txinfo); - } - } - lastLink = thisLink; - } - } - - if (lastLink != null) { - InteractiveInfo info = lastLink.getInfo(); - TxInteractiveInfoAtom txinfo = lastLink.getTextRunInfo(); - assert(info != null && txinfo != null); - _txtbox.appendChildRecord(info); - _txtbox.appendChildRecord(txinfo); - } - } - - /** - * Writes the textbox records back to the document record - */ - private static void refreshRecords(List paragraphs) { - TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; - RecordContainer _txtbox = headerAtom.getParentRecord(); - if (_txtbox instanceof EscherTextboxWrapper) { - try { - ((EscherTextboxWrapper) _txtbox).writeOut(null); - } catch (IOException e) { - throw new HSLFException("failed dummy write", e); - } - } - } - - /** - * Adds the supplied text onto the end of the TextParagraphs, - * creating a new RichTextRun for it to sit in. - * - * @param text the text string used by this object. - */ - protected static HSLFTextRun appendText(List paragraphs, String text, boolean newParagraph) { - text = toInternalString(text); - - // check paragraphs - assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty()); - - HSLFTextParagraph htp = paragraphs.get(paragraphs.size() - 1); - HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size() - 1); - - boolean addParagraph = newParagraph; - for (String rawText : text.split("(?<=\r)")) { - // special case, if last text paragraph or run is empty, we will reuse it - boolean lastRunEmpty = (htr.getLength() == 0); - boolean lastParaEmpty = lastRunEmpty && (htp.getTextRuns().size() == 1); - - if (addParagraph && !lastParaEmpty) { - TextPropCollection tpc = htp.getParagraphStyle(); - HSLFTextParagraph prevHtp = htp; - htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom, paragraphs); - htp.getParagraphStyle().copy(tpc); - htp.setParentShape(prevHtp.getParentShape()); - htp.setShapeId(prevHtp.getShapeId()); - htp.supplySheet(prevHtp.getSheet()); - paragraphs.add(htp); - } - addParagraph = true; - - if (!lastRunEmpty) { - TextPropCollection tpc = htr.getCharacterStyle(); - htr = new HSLFTextRun(htp); - htr.getCharacterStyle().copy(tpc); - htp.addTextRun(htr); - } - htr.setText(rawText); - } - - storeText(paragraphs); - - return htr; - } - - /** - * Sets (overwrites) the current text. - * Uses the properties of the first paragraph / textrun - * - * @param text the text string used by this object. - */ - public static HSLFTextRun setText(List paragraphs, String text) { - // check paragraphs - assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty()); - - Iterator paraIter = paragraphs.iterator(); - HSLFTextParagraph htp = paraIter.next(); // keep first - assert (htp != null); - while (paraIter.hasNext()) { - paraIter.next(); - paraIter.remove(); - } - - Iterator runIter = htp.getTextRuns().iterator(); - if (runIter.hasNext()) { - HSLFTextRun htr = runIter.next(); - htr.setText(""); - while (runIter.hasNext()) { - runIter.next(); - runIter.remove(); - } - } else { - HSLFTextRun trun = new HSLFTextRun(htp); - htp.addTextRun(trun); - } - - return appendText(paragraphs, text, false); - } - - public static String getText(List paragraphs) { - assert (!paragraphs.isEmpty()); - String rawText = getRawText(paragraphs); - return toExternalString(rawText, paragraphs.get(0).getRunType()); - } - - public static String getRawText(List paragraphs) { - StringBuilder sb = new StringBuilder(); - for (HSLFTextParagraph p : paragraphs) { - for (HSLFTextRun r : p.getTextRuns()) { - sb.append(r.getRawText()); - } - } - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (HSLFTextRun r : getTextRuns()) { - sb.append(r.getRawText()); - } - return toExternalString(sb.toString(), getRunType()); - } - - /** - * Returns a new string with line breaks converted into internal ppt - * representation - */ - protected static String toInternalString(String s) { - String ns = s.replaceAll("\\r?\\n", "\r"); - return ns; - } - - /** - * Converts raw text from the text paragraphs to a formatted string, - * i.e. it converts certain control characters used in the raw txt - * - * @param rawText the raw text - * @param runType the run type of the shape, paragraph or headerAtom. - * use -1 if unknown - * @return the formatted string - */ - public static String toExternalString(String rawText, int runType) { - // PowerPoint seems to store files with \r as the line break - // The messes things up on everything but a Mac, so translate - // them to \n - String text = rawText.replace('\r', '\n'); - - switch (runType) { - // 0xB acts like cariage return in page titles and like blank in the - // others - case -1: - case org.apache.poi.hslf.record.TextHeaderAtom.TITLE_TYPE: - case org.apache.poi.hslf.record.TextHeaderAtom.CENTER_TITLE_TYPE: - text = text.replace((char) 0x0B, '\n'); - break; - default: - text = text.replace((char) 0x0B, ' '); - break; - } - - return text; - } - - /** - * For a given PPDrawing, grab all the TextRuns - */ - public static List> findTextParagraphs(PPDrawing ppdrawing, HSLFSheet sheet) { - List> runsV = new ArrayList>(); - for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) { - List p = findTextParagraphs(wrapper, sheet); - if (p != null) { - runsV.add(p); - } - } - return runsV; - } - - /** - * Scans through the supplied record array, looking for - * a TextHeaderAtom followed by one of a TextBytesAtom or - * a TextCharsAtom. Builds up TextRuns from these - * - * @param wrapper an EscherTextboxWrapper - */ - protected static List findTextParagraphs(EscherTextboxWrapper wrapper, HSLFSheet sheet) { - // propagate parents to parent-aware records - RecordContainer.handleParentAwareRecords(wrapper); - int shapeId = wrapper.getShapeId(); - List rv = null; - - OutlineTextRefAtom ota = (OutlineTextRefAtom)wrapper.findFirstOfType(OutlineTextRefAtom.typeID); - if (ota != null) { - // if we are based on an outline, there are no further records to be parsed from the wrapper - if (sheet == null) { - throw new HSLFException("Outline atom reference can't be solved without a sheet record"); - } - - List> sheetRuns = sheet.getTextParagraphs(); - assert (sheetRuns != null); - - int idx = ota.getTextIndex(); - for (List r : sheetRuns) { - if (r.isEmpty()) { - continue; - } - int ridx = r.get(0).getIndex(); - if (ridx > idx) { - break; - } - if (ridx == idx) { - if (rv == null) { - rv = r; - } else { - // create a new container - // TODO: ... is this case really happening? - rv = new ArrayList(rv); - rv.addAll(r); - } - } - } - if (rv == null || rv.isEmpty()) { - logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); - } - } else { - if (sheet != null) { - // check sheet runs first, so we get exactly the same paragraph list - List> sheetRuns = sheet.getTextParagraphs(); - assert (sheetRuns != null); - - for (List paras : sheetRuns) { - if (!paras.isEmpty() && paras.get(0)._headerAtom.getParentRecord() == wrapper) { - rv = paras; - break; - } - } - } - - if (rv == null) { - // if we haven't found the wrapper in the sheet runs, create a new paragraph list from its record - List> rvl = findTextParagraphs(wrapper.getChildRecords()); - switch (rvl.size()) { - case 0: break; // nothing found - case 1: rv = rvl.get(0); break; // normal case - default: - throw new HSLFException("TextBox contains more than one list of paragraphs."); - } - } - } - - if (rv != null) { - StyleTextProp9Atom styleTextProp9Atom = wrapper.getStyleTextProp9Atom(); - - for (HSLFTextParagraph htp : rv) { - htp.setShapeId(shapeId); - htp.setStyleTextProp9Atom(styleTextProp9Atom); - } - } - return rv; - } - - /** - * Scans through the supplied record array, looking for - * a TextHeaderAtom followed by one of a TextBytesAtom or - * a TextCharsAtom. Builds up TextRuns from these - * - * @param records the records to build from - */ - protected static List> findTextParagraphs(Record[] records) { - List> paragraphCollection = new ArrayList>(); - - int[] recordIdx = { 0 }; - - for (int slwtIndex = 0; recordIdx[0] < records.length; slwtIndex++) { - TextHeaderAtom header = null; - TextBytesAtom tbytes = null; - TextCharsAtom tchars = null; - TextRulerAtom ruler = null; - MasterTextPropAtom indents = null; - - for (Record r : getRecords(records, recordIdx, null)) { - long rt = r.getRecordType(); - if (RecordTypes.TextHeaderAtom.typeID == rt) { - header = (TextHeaderAtom) r; - } else if (RecordTypes.TextBytesAtom.typeID == rt) { - tbytes = (TextBytesAtom) r; - } else if (RecordTypes.TextCharsAtom.typeID == rt) { - tchars = (TextCharsAtom) r; - } else if (RecordTypes.TextRulerAtom.typeID == rt) { - ruler = (TextRulerAtom) r; - } else if (RecordTypes.MasterTextPropAtom.typeID == rt) { - indents = (MasterTextPropAtom) r; - } - // don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below - } - - if (header == null) { - break; - } - - if (header.getParentRecord() instanceof SlideListWithText) { - // runs found in PPDrawing are not linked with SlideListWithTexts - header.setIndex(slwtIndex); - } - - if (tbytes == null && tchars == null) { - tbytes = new TextBytesAtom(); - // don't add record yet - set it in storeText - logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving."); - } - - String rawText = (tchars != null) ? tchars.getText() : tbytes.getText(); - StyleTextPropAtom styles = findStyleAtomPresent(header, rawText.length()); - - List paragraphs = new ArrayList(); - paragraphCollection.add(paragraphs); - - // split, but keep delimiter - for (String para : rawText.split("(?<=\r)")) { - HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, paragraphs); - paragraphs.add(tpara); - tpara._ruler = ruler; - tpara.getParagraphStyle().updateTextSize(para.length()); - - HSLFTextRun trun = new HSLFTextRun(tpara); - tpara.addTextRun(trun); - trun.setText(para); - } - - applyCharacterStyles(paragraphs, styles.getCharacterStyles()); - applyParagraphStyles(paragraphs, styles.getParagraphStyles()); - if (indents != null) { - applyParagraphIndents(paragraphs, indents.getIndents()); - } - } - - if (paragraphCollection.isEmpty()) { - logger.log(POILogger.DEBUG, "No text records found."); - } - - return paragraphCollection; - } - - protected static void applyHyperlinks(List paragraphs) { - List links = HSLFHyperlink.find(paragraphs); - - for (HSLFHyperlink h : links) { - int csIdx = 0; - for (HSLFTextParagraph p : paragraphs) { - if (csIdx > h.getEndIndex()) { - break; - } - List runs = p.getTextRuns(); - for (int rlen=0,rIdx=0; rIdx < runs.size(); csIdx+=rlen, rIdx++) { - HSLFTextRun run = runs.get(rIdx); - rlen = run.getLength(); - if (csIdx < h.getEndIndex() && h.getStartIndex() < csIdx+rlen) { - String rawText = run.getRawText(); - int startIdx = h.getStartIndex()-csIdx; - if (startIdx > 0) { - // hyperlink starts within current textrun - HSLFTextRun newRun = new HSLFTextRun(p); - newRun.setCharacterStyle(run.getCharacterStyle()); - newRun.setText(rawText.substring(startIdx)); - run.setText(rawText.substring(0, startIdx)); - runs.add(rIdx+1, newRun); - rlen = startIdx; - continue; - } - int endIdx = Math.min(rlen, h.getEndIndex()-h.getStartIndex()); - if (endIdx < rlen) { - // hyperlink ends before end of current textrun - HSLFTextRun newRun = new HSLFTextRun(p); - newRun.setCharacterStyle(run.getCharacterStyle()); - newRun.setText(rawText.substring(0, endIdx)); - run.setText(rawText.substring(endIdx)); - runs.add(rIdx, newRun); - rlen = endIdx; - run = newRun; - } - run.setHyperlink(h); - } - } - } - } - } - - protected static void applyCharacterStyles(List paragraphs, List charStyles) { - int paraIdx = 0, runIdx = 0; - HSLFTextRun trun; - - for (int csIdx = 0; csIdx < charStyles.size(); csIdx++) { - TextPropCollection p = charStyles.get(csIdx); - for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle;) { - HSLFTextParagraph para = paragraphs.get(paraIdx); - List runs = para.getTextRuns(); - trun = runs.get(runIdx); - final int len = trun.getLength(); - - if (ccRun + len <= ccStyle) { - ccRun += len; - } else { - String text = trun.getRawText(); - trun.setText(text.substring(0, ccStyle - ccRun)); - - HSLFTextRun nextRun = new HSLFTextRun(para); - nextRun.setText(text.substring(ccStyle - ccRun)); - runs.add(runIdx + 1, nextRun); - - ccRun += ccStyle - ccRun; - } - - trun.setCharacterStyle(p); - - if (paraIdx == paragraphs.size()-1 && runIdx == runs.size()-1) { - if (csIdx < charStyles.size() - 1) { - // special case, empty trailing text run - HSLFTextRun nextRun = new HSLFTextRun(para); - nextRun.setText(""); - runs.add(nextRun); - ccRun++; - } else { - // need to add +1 to the last run of the last paragraph - trun.getCharacterStyle().updateTextSize(trun.getLength()+1); - ccRun++; - } - } - - // need to compare it again, in case a run has been added after - if (++runIdx == runs.size()) { - paraIdx++; - runIdx = 0; - } - } - } - } - - protected static void applyParagraphStyles(List paragraphs, List paraStyles) { - int paraIdx = 0; - for (TextPropCollection p : paraStyles) { - for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) { - if (paraIdx >= paragraphs.size()) { - return; - } - HSLFTextParagraph htp = paragraphs.get(paraIdx); - TextPropCollection pCopy = new TextPropCollection(0, TextPropType.paragraph); - pCopy.copy(p); - htp.setParagraphStyle(pCopy); - int len = 0; - for (HSLFTextRun trun : htp.getTextRuns()) { - len += trun.getLength(); - } - if (paraIdx == paragraphs.size()-1) { - len++; - } - pCopy.updateTextSize(len); - ccPara += len; - } - } - } - - protected static void applyParagraphIndents(List paragraphs, List paraStyles) { - int paraIdx = 0; - for (IndentProp p : paraStyles) { - for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) { - if (paraIdx >= paragraphs.size() || ccPara >= ccStyle-1) { - return; - } - HSLFTextParagraph para = paragraphs.get(paraIdx); - int len = 0; - for (HSLFTextRun trun : para.getTextRuns()) { - len += trun.getLength(); - } - para.setIndentLevel(p.getIndentLevel()); - ccPara += len + 1; - } - } - } - - public EscherTextboxWrapper getTextboxWrapper() { - return (EscherTextboxWrapper) _headerAtom.getParentRecord(); - } - - protected static Color getColorFromColorIndexStruct(int rgb, HSLFSheet sheet) { - int cidx = rgb >>> 24; - Color tmp; - switch (cidx) { - // Background ... Accent 3 color - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - if (sheet == null) { - return null; - } - ColorSchemeAtom ca = sheet.getColorScheme(); - tmp = new Color(ca.getColor(cidx), true); - break; - // Color is an sRGB value specified by red, green, and blue fields. - case 0xFE: - tmp = new Color(rgb, true); - break; - // Color is undefined. - default: - case 0xFF: - return null; - } - return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); - } - - /** - * Sets the value of the given Paragraph TextProp, add if required - * @param propName The name of the Paragraph TextProp - * @param val The value to set for the TextProp - */ - public void setParagraphTextPropVal(String propName, Integer val) { - setPropVal(_paragraphStyle, _masterStyle, propName, val); - setDirty(); - } - - /** - * marks this paragraph dirty, so its records will be renewed on save - */ - public void setDirty() { - _dirty = true; - } - - public boolean isDirty() { - return _dirty; - } - - /** - * Calculates the start index of the given text run - * - * @param textrun the text run to search for - * @return the start index with the paragraph collection or -1 if not found - */ - /* package */ int getStartIdxOfTextRun(HSLFTextRun textrun) { - int idx = 0; - for (HSLFTextParagraph p : parentList) { - for (HSLFTextRun r : p) { - if (r == textrun) { - return idx; - } - idx += r.getLength(); - } - } - return -1; - } - - /** - * {@inheritDoc} - * - * @see RoundTripHFPlaceholder12 - */ - @Override - public boolean isHeaderOrFooter() { - HSLFTextShape s = getParentShape(); - if (s == null) { - return false; - } - Placeholder ph = s.getPlaceholder(); - if (ph == null) { - return false; - } - switch (ph) { - case DATETIME: - case SLIDE_NUMBER: - case FOOTER: - case HEADER: - return true; - default: - return false; - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.usermodel; + +import static org.apache.poi.hslf.record.RecordTypes.OutlineTextRefAtom; + +import java.awt.Color; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hslf.model.PPFont; +import org.apache.poi.hslf.model.textproperties.BitMaskTextProp; +import org.apache.poi.hslf.model.textproperties.FontAlignmentProp; +import org.apache.poi.hslf.model.textproperties.IndentProp; +import org.apache.poi.hslf.model.textproperties.ParagraphFlagsTextProp; +import org.apache.poi.hslf.model.textproperties.TextAlignmentProp; +import org.apache.poi.hslf.model.textproperties.TextPFException9; +import org.apache.poi.hslf.model.textproperties.TextProp; +import org.apache.poi.hslf.model.textproperties.TextPropCollection; +import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType; +import org.apache.poi.hslf.record.ColorSchemeAtom; +import org.apache.poi.hslf.record.EscherTextboxWrapper; +import org.apache.poi.hslf.record.FontCollection; +import org.apache.poi.hslf.record.InteractiveInfo; +import org.apache.poi.hslf.record.MasterTextPropAtom; +import org.apache.poi.hslf.record.OutlineTextRefAtom; +import org.apache.poi.hslf.record.PPDrawing; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordContainer; +import org.apache.poi.hslf.record.RecordTypes; +import org.apache.poi.hslf.record.RoundTripHFPlaceholder12; +import org.apache.poi.hslf.record.SlideListWithText; +import org.apache.poi.hslf.record.SlidePersistAtom; +import org.apache.poi.hslf.record.StyleTextProp9Atom; +import org.apache.poi.hslf.record.StyleTextPropAtom; +import org.apache.poi.hslf.record.TextBytesAtom; +import org.apache.poi.hslf.record.TextCharsAtom; +import org.apache.poi.hslf.record.TextHeaderAtom; +import org.apache.poi.hslf.record.TextRulerAtom; +import org.apache.poi.hslf.record.TextSpecInfoAtom; +import org.apache.poi.hslf.record.TxInteractiveInfoAtom; +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.AutoNumberingScheme; +import org.apache.poi.sl.usermodel.MasterSheet; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.Placeholder; +import org.apache.poi.sl.usermodel.TextParagraph; +import org.apache.poi.util.Internal; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.StringUtil; +import org.apache.poi.util.Units; + +/** + * This class represents a run of text in a powerpoint document. That + * run could be text on a sheet, or text in a note. + * It is only a very basic class for now + */ + +public final class HSLFTextParagraph implements TextParagraph { + protected static final POILogger logger = POILogFactory.getLogger(HSLFTextParagraph.class); + + /** + * How to align the text + */ + /* package */static final int AlignLeft = 0; + /* package */static final int AlignCenter = 1; + /* package */static final int AlignRight = 2; + /* package */static final int AlignJustify = 3; + + // Note: These fields are protected to help with unit testing + // Other classes shouldn't really go playing with them! + private final TextHeaderAtom _headerAtom; + private TextBytesAtom _byteAtom; + private TextCharsAtom _charAtom; + private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph); + private TextPropCollection _masterStyle; + + protected TextRulerAtom _ruler; + protected final List _runs = new ArrayList(); + protected HSLFTextShape _parentShape; + private HSLFSheet _sheet; + private int shapeId; + + private StyleTextProp9Atom styleTextProp9Atom; + + private boolean _dirty = false; + + private final List parentList; + + /** + * Constructs a Text Run from a Unicode text block. + * Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided. + * + * @param tha the TextHeaderAtom that defines what's what + * @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided + * @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided + * @param parentList the list which contains this paragraph + */ + /* package */ HSLFTextParagraph( + TextHeaderAtom tha, + TextBytesAtom tba, + TextCharsAtom tca, + List parentList + ) { + if (tha == null) { + throw new IllegalArgumentException("TextHeaderAtom must be set."); + } + _headerAtom = tha; + _byteAtom = tba; + _charAtom = tca; + this.parentList = parentList; + } + + /* package */HSLFTextParagraph(HSLFTextParagraph other) { + _headerAtom = other._headerAtom; + _byteAtom = other._byteAtom; + _charAtom = other._charAtom; + _parentShape = other._parentShape; + _sheet = other._sheet; + _ruler = other._ruler; + shapeId = other.shapeId; + _paragraphStyle.copy(other._paragraphStyle); + parentList = other.parentList; + } + + public void addTextRun(HSLFTextRun run) { + _runs.add(run); + } + + @Override + public List getTextRuns() { + return _runs; + } + + public TextPropCollection getParagraphStyle() { + return _paragraphStyle; + } + + public void setParagraphStyle(TextPropCollection paragraphStyle) { + _paragraphStyle.copy(paragraphStyle); + } + + /** + * Setting a master style reference + * + * @param paragraphStyle the master style reference + * + * @since POI 3.14-Beta1 + */ + @Internal + /* package */ void setMasterStyleReference(TextPropCollection masterStyle) { + _masterStyle = masterStyle; + } + + /** + * Supply the Sheet we belong to, which might have an assigned SlideShow + * Also passes it on to our child RichTextRuns + */ + public static void supplySheet(List paragraphs, HSLFSheet sheet) { + if (paragraphs == null) { + return; + } + for (HSLFTextParagraph p : paragraphs) { + p.supplySheet(sheet); + } + + assert(sheet.getSlideShow() != null); + } + + /** + * Supply the Sheet we belong to, which might have an assigned SlideShow + * Also passes it on to our child RichTextRuns + */ + private void supplySheet(HSLFSheet sheet) { + this._sheet = sheet; + + if (_runs == null) { + return; + } + for (HSLFTextRun rt : _runs) { + rt.updateSheet(); + } + } + + public HSLFSheet getSheet() { + return this._sheet; + } + + /** + * @return Shape ID + */ + protected int getShapeId() { + return shapeId; + } + + /** + * @param id Shape ID + */ + protected void setShapeId(int id) { + shapeId = id; + } + + /** + * @return 0-based index of the text run in the SLWT container + */ + protected int getIndex() { + return (_headerAtom != null) ? _headerAtom.getIndex() : -1; + } + + /** + * Sets the index of the paragraph in the SLWT container + * + * @param index + */ + protected void setIndex(int index) { + if (_headerAtom != null) { + _headerAtom.setIndex(index); + } + } + + /** + * Returns the type of the text, from the TextHeaderAtom. + * Possible values can be seen from TextHeaderAtom + * @see org.apache.poi.hslf.record.TextHeaderAtom + */ + public int getRunType() { + return (_headerAtom != null) ? _headerAtom.getTextType() : -1; + } + + public void setRunType(int runType) { + if (_headerAtom != null) { + _headerAtom.setTextType(runType); + } + } + + /** + * Is this Text Run one from a {@link PPDrawing}, or is it + * one from the {@link SlideListWithText}? + */ + public boolean isDrawingBased() { + return (getIndex() == -1); + } + + public TextRulerAtom getTextRuler() { + return _ruler; + } + + public TextRulerAtom createTextRuler() { + _ruler = getTextRuler(); + if (_ruler == null) { + _ruler = TextRulerAtom.getParagraphInstance(); + Record childAfter = _byteAtom; + if (childAfter == null) { + childAfter = _charAtom; + } + if (childAfter == null) { + childAfter = _headerAtom; + } + _headerAtom.getParentRecord().addChildAfter(_ruler, childAfter); + } + return _ruler; + } + + /** + * Returns records that make up the list of text paragraphs + * (there can be misc InteractiveInfo, TxInteractiveInfo and other records) + * + * @return text run records + */ + public Record[] getRecords() { + Record r[] = _headerAtom.getParentRecord().getChildRecords(); + return getRecords(r, new int[] { 0 }, _headerAtom); + } + + private static Record[] getRecords(Record[] records, int[] startIdx, TextHeaderAtom headerAtom) { + if (records == null) { + throw new NullPointerException("records need to be set."); + } + + for (; startIdx[0] < records.length; startIdx[0]++) { + Record r = records[startIdx[0]]; + if (r instanceof TextHeaderAtom && (headerAtom == null || r == headerAtom)) { + break; + } + } + + if (startIdx[0] >= records.length) { + logger.log(POILogger.INFO, "header atom wasn't found - container might contain only an OutlineTextRefAtom"); + return new Record[0]; + } + + int length; + for (length = 1; startIdx[0] + length < records.length; length++) { + Record r = records[startIdx[0]+length]; + if (r instanceof TextHeaderAtom || r instanceof SlidePersistAtom) { + break; + } + } + + Record result[] = new Record[length]; + System.arraycopy(records, startIdx[0], result, 0, length); + startIdx[0] += length; + + return result; + } + + /** Numbered List info */ + public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) { + this.styleTextProp9Atom = styleTextProp9Atom; + } + + /** Numbered List info */ + public StyleTextProp9Atom getStyleTextProp9Atom() { + return this.styleTextProp9Atom; + } + + @Override + public Iterator iterator() { + return _runs.iterator(); + } + + @Override + public Double getLeftMargin() { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "text.offset"); + return (tp == null) ? null : Units.masterToPoints(tp.getValue()); + } + + @Override + public void setLeftMargin(Double leftMargin) { + Integer val = (leftMargin == null) ? null : Units.pointsToMaster(leftMargin); + setParagraphTextPropVal("text.offset", val); + } + + @Override + public Double getRightMargin() { + // TODO: find out, how to determine this value + return null; + } + + @Override + public void setRightMargin(Double rightMargin) { + // TODO: find out, how to set this value + } + + @Override + public Double getIndent() { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.offset"); + return (tp == null) ? null : Units.masterToPoints(tp.getValue()); + } + + @Override + public void setIndent(Double indent) { + Integer val = (indent == null) ? null : Units.pointsToMaster(indent); + setParagraphTextPropVal("bullet.offset", val); + } + + @Override + public String getDefaultFontFamily() { + String typeface = null; + if (!_runs.isEmpty()) { + typeface = _runs.get(0).getFontFamily(); + } + return (typeface != null) ? typeface : "Arial"; + } + + @Override + public Double getDefaultFontSize() { + Double d = null; + if (!_runs.isEmpty()) { + d = _runs.get(0).getFontSize(); + } + + return (d != null) ? d : 12d; + } + + @Override + public void setTextAlign(TextAlign align) { + Integer alignInt = null; + if (align != null) { + switch (align) { + default: + case LEFT: alignInt = TextAlignmentProp.LEFT;break; + case CENTER: alignInt = TextAlignmentProp.CENTER; break; + case RIGHT: alignInt = TextAlignmentProp.RIGHT; break; + case DIST: alignInt = TextAlignmentProp.DISTRIBUTED; break; + case JUSTIFY: alignInt = TextAlignmentProp.JUSTIFY; break; + case JUSTIFY_LOW: alignInt = TextAlignmentProp.JUSTIFYLOW; break; + case THAI_DIST: alignInt = TextAlignmentProp.THAIDISTRIBUTED; break; + } + } + setParagraphTextPropVal("alignment", alignInt); + } + + @Override + public TextAlign getTextAlign() { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "alignment"); + if (tp == null) { + return null; + } + switch (tp.getValue()) { + default: + case TextAlignmentProp.LEFT: return TextAlign.LEFT; + case TextAlignmentProp.CENTER: return TextAlign.CENTER; + case TextAlignmentProp.RIGHT: return TextAlign.RIGHT; + case TextAlignmentProp.JUSTIFY: return TextAlign.JUSTIFY; + case TextAlignmentProp.JUSTIFYLOW: return TextAlign.JUSTIFY_LOW; + case TextAlignmentProp.DISTRIBUTED: return TextAlign.DIST; + case TextAlignmentProp.THAIDISTRIBUTED: return TextAlign.THAI_DIST; + } + } + + @Override + public FontAlign getFontAlign() { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, FontAlignmentProp.NAME); + if (tp == null) { + return null; + } + + switch (tp.getValue()) { + case FontAlignmentProp.BASELINE: return FontAlign.BASELINE; + case FontAlignmentProp.TOP: return FontAlign.TOP; + case FontAlignmentProp.CENTER: return FontAlign.CENTER; + case FontAlignmentProp.BOTTOM: return FontAlign.BOTTOM; + default: return FontAlign.AUTO; + } + } + + public AutoNumberingScheme getAutoNumberingScheme() { + if (styleTextProp9Atom == null) { + return null; + } + TextPFException9[] ant = styleTextProp9Atom.getAutoNumberTypes(); + int level = getIndentLevel(); + if (ant == null || level == -1 || level >= ant.length) { + return null; + } + return ant[level].getAutoNumberScheme(); + } + + public Integer getAutoNumberingStartAt() { + if (styleTextProp9Atom == null) { + return null; + } + TextPFException9[] ant = styleTextProp9Atom.getAutoNumberTypes(); + int level = getIndentLevel(); + if (ant == null || level >= ant.length) { + return null; + } + Short startAt = ant[level].getAutoNumberStartNumber(); + assert(startAt != null); + return startAt.intValue(); + } + + + @Override + public BulletStyle getBulletStyle() { + if (!isBullet() && getAutoNumberingScheme() == null) { + return null; + } + + return new BulletStyle() { + @Override + public String getBulletCharacter() { + Character chr = HSLFTextParagraph.this.getBulletChar(); + return (chr == null || chr == 0) ? "" : "" + chr; + } + + @Override + public String getBulletFont() { + return HSLFTextParagraph.this.getBulletFont(); + } + + @Override + public Double getBulletFontSize() { + return HSLFTextParagraph.this.getBulletSize(); + } + + @Override + public void setBulletFontColor(Color color) { + setBulletFontColor(DrawPaint.createSolidPaint(color)); + } + + @Override + public void setBulletFontColor(PaintStyle color) { + if (!(color instanceof SolidPaint)) { + throw new IllegalArgumentException("HSLF only supports SolidPaint"); + } + SolidPaint sp = (SolidPaint)color; + Color col = DrawPaint.applyColorTransform(sp.getSolidColor()); + HSLFTextParagraph.this.setBulletColor(col); + } + + @Override + public PaintStyle getBulletFontColor() { + Color col = HSLFTextParagraph.this.getBulletColor(); + return DrawPaint.createSolidPaint(col); + } + + @Override + public AutoNumberingScheme getAutoNumberingScheme() { + return HSLFTextParagraph.this.getAutoNumberingScheme(); + } + + @Override + public Integer getAutoNumberingStartAt() { + return HSLFTextParagraph.this.getAutoNumberingStartAt(); + } + }; + } + + @Override + public void setBulletStyle(Object... styles) { + if (styles.length == 0) { + setBullet(false); + } else { + setBullet(true); + for (Object ostyle : styles) { + if (ostyle instanceof Number) { + setBulletSize(((Number)ostyle).doubleValue()); + } else if (ostyle instanceof Color) { + setBulletColor((Color)ostyle); + } else if (ostyle instanceof Character) { + setBulletChar((Character)ostyle); + } else if (ostyle instanceof String) { + setBulletFont((String)ostyle); + } else if (ostyle instanceof AutoNumberingScheme) { + throw new HSLFException("setting bullet auto-numberin scheme for HSLF not supported ... yet"); + } + } + } + } + + @Override + public HSLFTextShape getParentShape() { + return _parentShape; + } + + public void setParentShape(HSLFTextShape parentShape) { + _parentShape = parentShape; + } + + @Override + public int getIndentLevel() { + return _paragraphStyle == null ? 0 : _paragraphStyle.getIndentLevel(); + } + + @Override + public void setIndentLevel(int level) { + if( _paragraphStyle != null ) { + _paragraphStyle.setIndentLevel((short)level); + } + } + + /** + * Sets whether this rich text run has bullets + */ + public void setBullet(boolean flag) { + setFlag(ParagraphFlagsTextProp.BULLET_IDX, flag); + } + + /** + * Returns whether this rich text run has bullets + */ + public boolean isBullet() { + return getFlag(ParagraphFlagsTextProp.BULLET_IDX); + } + + /** + * Sets the bullet character + */ + public void setBulletChar(Character c) { + Integer val = (c == null) ? null : (int)c.charValue(); + setParagraphTextPropVal("bullet.char", val); + } + + /** + * Returns the bullet character + */ + public Character getBulletChar() { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.char"); + return (tp == null) ? null : (char)tp.getValue(); + } + + /** + * Sets the bullet size + */ + public void setBulletSize(Double size) { + setPctOrPoints("bullet.size", size); + } + + /** + * Returns the bullet size, null if unset + */ + public Double getBulletSize() { + return getPctOrPoints("bullet.size"); + } + + /** + * Sets the bullet color + */ + public void setBulletColor(Color color) { + Integer val = (color == null) ? null : new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB(); + setParagraphTextPropVal("bullet.color", val); + setFlag(ParagraphFlagsTextProp.BULLET_HARDCOLOR_IDX, (color != null)); + } + + /** + * Returns the bullet color + */ + public Color getBulletColor() { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.color"); + boolean hasColor = getFlag(ParagraphFlagsTextProp.BULLET_HARDCOLOR_IDX); + if (tp == null || !hasColor) { + // if bullet color is undefined, return color of first run + if (_runs.isEmpty()) { + return null; + } + + SolidPaint sp = _runs.get(0).getFontColor(); + if(sp == null) { + return null; + } + + return DrawPaint.applyColorTransform(sp.getSolidColor()); + } + + return getColorFromColorIndexStruct(tp.getValue(), _sheet); + } + + /** + * Sets the bullet font + */ + public void setBulletFont(String typeface) { + if (typeface == null) { + setPropVal(_paragraphStyle, _masterStyle, "bullet.font", null); + setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, false); + return; + } + + FontCollection fc = getSheet().getSlideShow().getFontCollection(); + int idx = fc.addFont(typeface); + + setParagraphTextPropVal("bullet.font", idx); + setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, true); + } + + /** + * Returns the bullet font + */ + public String getBulletFont() { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.font"); + boolean hasFont = getFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX); + if (tp == null || !hasFont) { + return getDefaultFontFamily(); + } + PPFont ppFont = getSheet().getSlideShow().getFont(tp.getValue()); + assert(ppFont != null); + return ppFont.getFontName(); + } + + @Override + public void setLineSpacing(Double lineSpacing) { + setPctOrPoints("linespacing", lineSpacing); + } + + @Override + public Double getLineSpacing() { + return getPctOrPoints("linespacing"); + } + + @Override + public void setSpaceBefore(Double spaceBefore) { + setPctOrPoints("spacebefore", spaceBefore); + } + + @Override + public Double getSpaceBefore() { + return getPctOrPoints("spacebefore"); + } + + @Override + public void setSpaceAfter(Double spaceAfter) { + setPctOrPoints("spaceafter", spaceAfter); + } + + @Override + public Double getSpaceAfter() { + return getPctOrPoints("spaceafter"); + } + + @Override + public Double getDefaultTabSize() { + // TODO: implement + return null; + } + + private Double getPctOrPoints(String propName) { + TextProp tp = getPropVal(_paragraphStyle, _masterStyle, propName); + if (tp == null) { + return null; + } + int val = tp.getValue(); + return (val < 0) ? Units.masterToPoints(val) : val; + } + + private void setPctOrPoints(String propName, Double dval) { + Integer ival = null; + if (dval != null) { + ival = (dval < 0) ? Units.pointsToMaster(dval) : dval.intValue(); + } + setParagraphTextPropVal(propName, ival); + } + + private boolean getFlag(int index) { + BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, _masterStyle, ParagraphFlagsTextProp.NAME); + return (tp == null) ? false : tp.getSubValue(index); + } + + private void setFlag(int index, boolean value) { + BitMaskTextProp tp = (BitMaskTextProp)_paragraphStyle.addWithName(ParagraphFlagsTextProp.NAME); + tp.setSubValue(value, index); + setDirty(); + } + + /** + * Fetch the value of the given Paragraph related TextProp. Returns null if + * that TextProp isn't present. If the TextProp isn't present, the value + * from the appropriate Master Sheet will apply. + * + * The propName can be a comma-separated list, in case multiple equivalent values + * are queried + */ + protected TextProp getPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) { + String propNames[] = propName.split(","); + for (String pn : propNames) { + TextProp prop = props.findByName(pn); + if (prop == null) { + continue; + } + + // Font properties (maybe other too???) can have an index of -1 + // so we check the master for this font index then + if (pn.contains("font") && prop.getValue() == -1) { + return getMasterPropVal(props, masterProps, pn); + } + + return prop; + } + + return getMasterPropVal(props, masterProps, propName); + } + + private TextProp getMasterPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) { + boolean isChar = props.getTextPropType() == TextPropType.character; + + // check if we can delegate to master for the property + if (!isChar) { + BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME); + boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0); + if (hardAttribute) { + return null; + } + } + + String propNames[] = propName.split(","); + if (masterProps == null) { + HSLFSheet sheet = getSheet(); + int txtype = getRunType(); + HSLFMasterSheet master = sheet.getMasterSheet(); + if (master == null) { + logger.log(POILogger.WARN, "MasterSheet is not available"); + return null; + } + + for (String pn : propNames) { + TextProp prop = master.getStyleAttribute(txtype, getIndentLevel(), pn, isChar); + if (prop != null) { + return prop; + } + } + } else { + for (String pn : propNames) { + TextProp prop = masterProps.findByName(pn); + if (prop != null) { + return prop; + } + } + } + + return null; + } + + /** + * Returns the named TextProp, either by fetching it (if it exists) or + * adding it (if it didn't) + * + * @param props the TextPropCollection to fetch from / add into + * @param name the name of the TextProp to fetch/add + * @param val the value, null if unset + */ + protected void setPropVal(TextPropCollection props, TextPropCollection masterProps, String name, Integer val) { + TextPropCollection pc = props; + if (getSheet() instanceof MasterSheet && masterProps != null) { + pc = masterProps; + } + + if (val == null) { + pc.removeByName(name); + return; + } + + // Fetch / Add the TextProp + TextProp tp = pc.addWithName(name); + tp.setValue(val); + } + + /** + * Check and add linebreaks to text runs leading other paragraphs + * + * @param paragraphs + */ + protected static void fixLineEndings(List paragraphs) { + HSLFTextRun lastRun = null; + for (HSLFTextParagraph p : paragraphs) { + if (lastRun != null && !lastRun.getRawText().endsWith("\r")) { + lastRun.setText(lastRun.getRawText() + "\r"); + } + List ltr = p.getTextRuns(); + if (ltr.isEmpty()) { + throw new HSLFException("paragraph without textruns found"); + } + lastRun = ltr.get(ltr.size() - 1); + assert (lastRun.getRawText() != null); + } + } + + /** + * Search for a StyleTextPropAtom is for this text header (list of paragraphs) + * + * @param header the header + * @param textLen the length of the rawtext, or -1 if the length is not known + */ + private static StyleTextPropAtom findStyleAtomPresent(TextHeaderAtom header, int textLen) { + boolean afterHeader = false; + StyleTextPropAtom style = null; + for (Record record : header.getParentRecord().getChildRecords()) { + long rt = record.getRecordType(); + if (afterHeader && rt == RecordTypes.TextHeaderAtom.typeID) { + // already on the next header, quit searching + break; + } + afterHeader |= (header == record); + if (afterHeader && rt == RecordTypes.StyleTextPropAtom.typeID) { + // found it + style = (StyleTextPropAtom) record; + } + } + + if (style == null) { + logger.log(POILogger.INFO, "styles atom doesn't exist. Creating dummy record for later saving."); + style = new StyleTextPropAtom((textLen < 0) ? 1 : textLen); + } else { + if (textLen >= 0) { + style.setParentTextSize(textLen); + } + } + + return style; + } + + /** + * Saves the modified paragraphs/textrun to the records. + * Also updates the styles to the correct text length. + */ + protected static void storeText(List paragraphs) { + fixLineEndings(paragraphs); + updateTextAtom(paragraphs); + updateStyles(paragraphs); + updateHyperlinks(paragraphs); + refreshRecords(paragraphs); + + for (HSLFTextParagraph p : paragraphs) { + p._dirty = false; + } + } + + /** + * Set the correct text atom depending on the multibyte usage + */ + private static void updateTextAtom(List paragraphs) { + final String rawText = toInternalString(getRawText(paragraphs)); + + // Will it fit in a 8 bit atom? + boolean isUnicode = StringUtil.hasMultibyte(rawText); + // isUnicode = true; + + TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; + TextBytesAtom byteAtom = paragraphs.get(0)._byteAtom; + TextCharsAtom charAtom = paragraphs.get(0)._charAtom; + StyleTextPropAtom styleAtom = findStyleAtomPresent(headerAtom, rawText.length()); + + // Store in the appropriate record + Record oldRecord = null, newRecord = null; + if (isUnicode) { + if (byteAtom != null || charAtom == null) { + oldRecord = byteAtom; + charAtom = new TextCharsAtom(); + } + newRecord = charAtom; + charAtom.setText(rawText); + } else { + if (charAtom != null || byteAtom == null) { + oldRecord = charAtom; + byteAtom = new TextBytesAtom(); + } + newRecord = byteAtom; + byte[] byteText = new byte[rawText.length()]; + StringUtil.putCompressedUnicode(rawText, byteText, 0); + byteAtom.setText(byteText); + } + assert (newRecord != null); + + RecordContainer _txtbox = headerAtom.getParentRecord(); + Record[] cr = _txtbox.getChildRecords(); + int /* headerIdx = -1, */ textIdx = -1, styleIdx = -1; + for (int i = 0; i < cr.length; i++) { + Record r = cr[i]; + if (r == headerAtom) { + ; // headerIdx = i; + } else if (r == oldRecord || r == newRecord) { + textIdx = i; + } else if (r == styleAtom) { + styleIdx = i; + } + } + + if (textIdx == -1) { + // the old record was never registered, ignore it + _txtbox.addChildAfter(newRecord, headerAtom); + // textIdx = headerIdx + 1; + } else { + // swap not appropriated records - noop if unchanged + cr[textIdx] = newRecord; + } + + if (styleIdx == -1) { + // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom + _txtbox.addChildAfter(styleAtom, newRecord); + } + + for (HSLFTextParagraph p : paragraphs) { + if (newRecord == byteAtom) { + p._byteAtom = byteAtom; + p._charAtom = null; + } else { + p._byteAtom = null; + p._charAtom = charAtom; + } + } + + } + + /** + * Update paragraph and character styles - merges them when subsequential styles match + */ + private static void updateStyles(List paragraphs) { + final String rawText = toInternalString(getRawText(paragraphs)); + TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; + StyleTextPropAtom styleAtom = findStyleAtomPresent(headerAtom, rawText.length()); + + // Update the text length for its Paragraph and Character stylings + // * reset the length, to the new string's length + // * add on +1 if the last block + + styleAtom.clearStyles(); + + TextPropCollection lastPTPC = null, lastRTPC = null, ptpc = null, rtpc = null; + for (HSLFTextParagraph para : paragraphs) { + ptpc = para.getParagraphStyle(); + ptpc.updateTextSize(0); + if (!ptpc.equals(lastPTPC)) { + lastPTPC = styleAtom.addParagraphTextPropCollection(0); + lastPTPC.copy(ptpc); + } + for (HSLFTextRun tr : para.getTextRuns()) { + rtpc = tr.getCharacterStyle(); + rtpc.updateTextSize(0); + if (!rtpc.equals(lastRTPC)) { + lastRTPC = styleAtom.addCharacterTextPropCollection(0); + lastRTPC.copy(rtpc); + } + int len = tr.getLength(); + ptpc.updateTextSize(ptpc.getCharactersCovered() + len); + rtpc.updateTextSize(len); + lastPTPC.updateTextSize(lastPTPC.getCharactersCovered() + len); + lastRTPC.updateTextSize(lastRTPC.getCharactersCovered() + len); + } + } + + if (lastPTPC == null || lastRTPC == null || ptpc == null || rtpc == null) { // NOSONAR + throw new HSLFException("Not all TextPropCollection could be determined."); + } + + ptpc.updateTextSize(ptpc.getCharactersCovered() + 1); + rtpc.updateTextSize(rtpc.getCharactersCovered() + 1); + lastPTPC.updateTextSize(lastPTPC.getCharactersCovered() + 1); + lastRTPC.updateTextSize(lastRTPC.getCharactersCovered() + 1); + + /** + * If TextSpecInfoAtom is present, we must update the text size in it, + * otherwise the ppt will be corrupted + */ + for (Record r : paragraphs.get(0).getRecords()) { + if (r instanceof TextSpecInfoAtom) { + ((TextSpecInfoAtom) r).setParentSize(rawText.length() + 1); + break; + } + } + } + + private static void updateHyperlinks(List paragraphs) { + TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; + RecordContainer _txtbox = headerAtom.getParentRecord(); + // remove existing hyperlink records + for (Record r : _txtbox.getChildRecords()) { + if (r instanceof InteractiveInfo || r instanceof TxInteractiveInfoAtom) { + _txtbox.removeChild(r); + } + } + // now go through all the textruns and check for hyperlinks + HSLFHyperlink lastLink = null; + for (HSLFTextParagraph para : paragraphs) { + for (HSLFTextRun run : para) { + HSLFHyperlink thisLink = run.getHyperlink(); + if (thisLink != null && thisLink == lastLink) { + // the hyperlink extends over this text run, increase its length + // TODO: the text run might be longer than the hyperlink + thisLink.setEndIndex(thisLink.getEndIndex()+run.getLength()); + } else { + if (lastLink != null) { + InteractiveInfo info = lastLink.getInfo(); + TxInteractiveInfoAtom txinfo = lastLink.getTextRunInfo(); + assert(info != null && txinfo != null); + _txtbox.appendChildRecord(info); + _txtbox.appendChildRecord(txinfo); + } + } + lastLink = thisLink; + } + } + + if (lastLink != null) { + InteractiveInfo info = lastLink.getInfo(); + TxInteractiveInfoAtom txinfo = lastLink.getTextRunInfo(); + assert(info != null && txinfo != null); + _txtbox.appendChildRecord(info); + _txtbox.appendChildRecord(txinfo); + } + } + + /** + * Writes the textbox records back to the document record + */ + private static void refreshRecords(List paragraphs) { + TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom; + RecordContainer _txtbox = headerAtom.getParentRecord(); + if (_txtbox instanceof EscherTextboxWrapper) { + try { + ((EscherTextboxWrapper) _txtbox).writeOut(null); + } catch (IOException e) { + throw new HSLFException("failed dummy write", e); + } + } + } + + /** + * Adds the supplied text onto the end of the TextParagraphs, + * creating a new RichTextRun for it to sit in. + * + * @param text the text string used by this object. + */ + protected static HSLFTextRun appendText(List paragraphs, String text, boolean newParagraph) { + text = toInternalString(text); + + // check paragraphs + assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty()); + + HSLFTextParagraph htp = paragraphs.get(paragraphs.size() - 1); + HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size() - 1); + + boolean addParagraph = newParagraph; + for (String rawText : text.split("(?<=\r)")) { + // special case, if last text paragraph or run is empty, we will reuse it + boolean lastRunEmpty = (htr.getLength() == 0); + boolean lastParaEmpty = lastRunEmpty && (htp.getTextRuns().size() == 1); + + if (addParagraph && !lastParaEmpty) { + TextPropCollection tpc = htp.getParagraphStyle(); + HSLFTextParagraph prevHtp = htp; + htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom, paragraphs); + htp.getParagraphStyle().copy(tpc); + htp.setParentShape(prevHtp.getParentShape()); + htp.setShapeId(prevHtp.getShapeId()); + htp.supplySheet(prevHtp.getSheet()); + paragraphs.add(htp); + } + addParagraph = true; + + if (!lastRunEmpty) { + TextPropCollection tpc = htr.getCharacterStyle(); + htr = new HSLFTextRun(htp); + htr.getCharacterStyle().copy(tpc); + htp.addTextRun(htr); + } + htr.setText(rawText); + } + + storeText(paragraphs); + + return htr; + } + + /** + * Sets (overwrites) the current text. + * Uses the properties of the first paragraph / textrun + * + * @param text the text string used by this object. + */ + public static HSLFTextRun setText(List paragraphs, String text) { + // check paragraphs + assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty()); + + Iterator paraIter = paragraphs.iterator(); + HSLFTextParagraph htp = paraIter.next(); // keep first + assert (htp != null); + while (paraIter.hasNext()) { + paraIter.next(); + paraIter.remove(); + } + + Iterator runIter = htp.getTextRuns().iterator(); + if (runIter.hasNext()) { + HSLFTextRun htr = runIter.next(); + htr.setText(""); + while (runIter.hasNext()) { + runIter.next(); + runIter.remove(); + } + } else { + HSLFTextRun trun = new HSLFTextRun(htp); + htp.addTextRun(trun); + } + + return appendText(paragraphs, text, false); + } + + public static String getText(List paragraphs) { + assert (!paragraphs.isEmpty()); + String rawText = getRawText(paragraphs); + return toExternalString(rawText, paragraphs.get(0).getRunType()); + } + + public static String getRawText(List paragraphs) { + StringBuilder sb = new StringBuilder(); + for (HSLFTextParagraph p : paragraphs) { + for (HSLFTextRun r : p.getTextRuns()) { + sb.append(r.getRawText()); + } + } + return sb.toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (HSLFTextRun r : getTextRuns()) { + sb.append(r.getRawText()); + } + return toExternalString(sb.toString(), getRunType()); + } + + /** + * Returns a new string with line breaks converted into internal ppt + * representation + */ + protected static String toInternalString(String s) { + String ns = s.replaceAll("\\r?\\n", "\r"); + return ns; + } + + /** + * Converts raw text from the text paragraphs to a formatted string, + * i.e. it converts certain control characters used in the raw txt + * + * @param rawText the raw text + * @param runType the run type of the shape, paragraph or headerAtom. + * use -1 if unknown + * @return the formatted string + */ + public static String toExternalString(String rawText, int runType) { + // PowerPoint seems to store files with \r as the line break + // The messes things up on everything but a Mac, so translate + // them to \n + String text = rawText.replace('\r', '\n'); + + switch (runType) { + // 0xB acts like cariage return in page titles and like blank in the + // others + case -1: + case org.apache.poi.hslf.record.TextHeaderAtom.TITLE_TYPE: + case org.apache.poi.hslf.record.TextHeaderAtom.CENTER_TITLE_TYPE: + text = text.replace((char) 0x0B, '\n'); + break; + default: + text = text.replace((char) 0x0B, ' '); + break; + } + + return text; + } + + /** + * For a given PPDrawing, grab all the TextRuns + */ + public static List> findTextParagraphs(PPDrawing ppdrawing, HSLFSheet sheet) { + List> runsV = new ArrayList>(); + for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) { + List p = findTextParagraphs(wrapper, sheet); + if (p != null) { + runsV.add(p); + } + } + return runsV; + } + + /** + * Scans through the supplied record array, looking for + * a TextHeaderAtom followed by one of a TextBytesAtom or + * a TextCharsAtom. Builds up TextRuns from these + * + * @param wrapper an EscherTextboxWrapper + */ + protected static List findTextParagraphs(EscherTextboxWrapper wrapper, HSLFSheet sheet) { + // propagate parents to parent-aware records + RecordContainer.handleParentAwareRecords(wrapper); + int shapeId = wrapper.getShapeId(); + List rv = null; + + OutlineTextRefAtom ota = (OutlineTextRefAtom)wrapper.findFirstOfType(OutlineTextRefAtom.typeID); + if (ota != null) { + // if we are based on an outline, there are no further records to be parsed from the wrapper + if (sheet == null) { + throw new HSLFException("Outline atom reference can't be solved without a sheet record"); + } + + List> sheetRuns = sheet.getTextParagraphs(); + assert (sheetRuns != null); + + int idx = ota.getTextIndex(); + for (List r : sheetRuns) { + if (r.isEmpty()) { + continue; + } + int ridx = r.get(0).getIndex(); + if (ridx > idx) { + break; + } + if (ridx == idx) { + if (rv == null) { + rv = r; + } else { + // create a new container + // TODO: ... is this case really happening? + rv = new ArrayList(rv); + rv.addAll(r); + } + } + } + if (rv == null || rv.isEmpty()) { + logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); + } + } else { + if (sheet != null) { + // check sheet runs first, so we get exactly the same paragraph list + List> sheetRuns = sheet.getTextParagraphs(); + assert (sheetRuns != null); + + for (List paras : sheetRuns) { + if (!paras.isEmpty() && paras.get(0)._headerAtom.getParentRecord() == wrapper) { + rv = paras; + break; + } + } + } + + if (rv == null) { + // if we haven't found the wrapper in the sheet runs, create a new paragraph list from its record + List> rvl = findTextParagraphs(wrapper.getChildRecords()); + switch (rvl.size()) { + case 0: break; // nothing found + case 1: rv = rvl.get(0); break; // normal case + default: + throw new HSLFException("TextBox contains more than one list of paragraphs."); + } + } + } + + if (rv != null) { + StyleTextProp9Atom styleTextProp9Atom = wrapper.getStyleTextProp9Atom(); + + for (HSLFTextParagraph htp : rv) { + htp.setShapeId(shapeId); + htp.setStyleTextProp9Atom(styleTextProp9Atom); + } + } + return rv; + } + + /** + * Scans through the supplied record array, looking for + * a TextHeaderAtom followed by one of a TextBytesAtom or + * a TextCharsAtom. Builds up TextRuns from these + * + * @param records the records to build from + */ + protected static List> findTextParagraphs(Record[] records) { + List> paragraphCollection = new ArrayList>(); + + int[] recordIdx = { 0 }; + + for (int slwtIndex = 0; recordIdx[0] < records.length; slwtIndex++) { + TextHeaderAtom header = null; + TextBytesAtom tbytes = null; + TextCharsAtom tchars = null; + TextRulerAtom ruler = null; + MasterTextPropAtom indents = null; + + for (Record r : getRecords(records, recordIdx, null)) { + long rt = r.getRecordType(); + if (RecordTypes.TextHeaderAtom.typeID == rt) { + header = (TextHeaderAtom) r; + } else if (RecordTypes.TextBytesAtom.typeID == rt) { + tbytes = (TextBytesAtom) r; + } else if (RecordTypes.TextCharsAtom.typeID == rt) { + tchars = (TextCharsAtom) r; + } else if (RecordTypes.TextRulerAtom.typeID == rt) { + ruler = (TextRulerAtom) r; + } else if (RecordTypes.MasterTextPropAtom.typeID == rt) { + indents = (MasterTextPropAtom) r; + } + // don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below + } + + if (header == null) { + break; + } + + if (header.getParentRecord() instanceof SlideListWithText) { + // runs found in PPDrawing are not linked with SlideListWithTexts + header.setIndex(slwtIndex); + } + + if (tbytes == null && tchars == null) { + tbytes = new TextBytesAtom(); + // don't add record yet - set it in storeText + logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving."); + } + + String rawText = (tchars != null) ? tchars.getText() : tbytes.getText(); + StyleTextPropAtom styles = findStyleAtomPresent(header, rawText.length()); + + List paragraphs = new ArrayList(); + paragraphCollection.add(paragraphs); + + // split, but keep delimiter + for (String para : rawText.split("(?<=\r)")) { + HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, paragraphs); + paragraphs.add(tpara); + tpara._ruler = ruler; + tpara.getParagraphStyle().updateTextSize(para.length()); + + HSLFTextRun trun = new HSLFTextRun(tpara); + tpara.addTextRun(trun); + trun.setText(para); + } + + applyCharacterStyles(paragraphs, styles.getCharacterStyles()); + applyParagraphStyles(paragraphs, styles.getParagraphStyles()); + if (indents != null) { + applyParagraphIndents(paragraphs, indents.getIndents()); + } + } + + if (paragraphCollection.isEmpty()) { + logger.log(POILogger.DEBUG, "No text records found."); + } + + return paragraphCollection; + } + + protected static void applyHyperlinks(List paragraphs) { + List links = HSLFHyperlink.find(paragraphs); + + for (HSLFHyperlink h : links) { + int csIdx = 0; + for (HSLFTextParagraph p : paragraphs) { + if (csIdx > h.getEndIndex()) { + break; + } + List runs = p.getTextRuns(); + for (int rlen=0,rIdx=0; rIdx < runs.size(); csIdx+=rlen, rIdx++) { + HSLFTextRun run = runs.get(rIdx); + rlen = run.getLength(); + if (csIdx < h.getEndIndex() && h.getStartIndex() < csIdx+rlen) { + String rawText = run.getRawText(); + int startIdx = h.getStartIndex()-csIdx; + if (startIdx > 0) { + // hyperlink starts within current textrun + HSLFTextRun newRun = new HSLFTextRun(p); + newRun.setCharacterStyle(run.getCharacterStyle()); + newRun.setText(rawText.substring(startIdx)); + run.setText(rawText.substring(0, startIdx)); + runs.add(rIdx+1, newRun); + rlen = startIdx; + continue; + } + int endIdx = Math.min(rlen, h.getEndIndex()-h.getStartIndex()); + if (endIdx < rlen) { + // hyperlink ends before end of current textrun + HSLFTextRun newRun = new HSLFTextRun(p); + newRun.setCharacterStyle(run.getCharacterStyle()); + newRun.setText(rawText.substring(0, endIdx)); + run.setText(rawText.substring(endIdx)); + runs.add(rIdx, newRun); + rlen = endIdx; + run = newRun; + } + run.setHyperlink(h); + } + } + } + } + } + + protected static void applyCharacterStyles(List paragraphs, List charStyles) { + int paraIdx = 0, runIdx = 0; + HSLFTextRun trun; + + for (int csIdx = 0; csIdx < charStyles.size(); csIdx++) { + TextPropCollection p = charStyles.get(csIdx); + for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle;) { + HSLFTextParagraph para = paragraphs.get(paraIdx); + List runs = para.getTextRuns(); + trun = runs.get(runIdx); + final int len = trun.getLength(); + + if (ccRun + len <= ccStyle) { + ccRun += len; + } else { + String text = trun.getRawText(); + trun.setText(text.substring(0, ccStyle - ccRun)); + + HSLFTextRun nextRun = new HSLFTextRun(para); + nextRun.setText(text.substring(ccStyle - ccRun)); + runs.add(runIdx + 1, nextRun); + + ccRun += ccStyle - ccRun; + } + + trun.setCharacterStyle(p); + + if (paraIdx == paragraphs.size()-1 && runIdx == runs.size()-1) { + if (csIdx < charStyles.size() - 1) { + // special case, empty trailing text run + HSLFTextRun nextRun = new HSLFTextRun(para); + nextRun.setText(""); + runs.add(nextRun); + ccRun++; + } else { + // need to add +1 to the last run of the last paragraph + trun.getCharacterStyle().updateTextSize(trun.getLength()+1); + ccRun++; + } + } + + // need to compare it again, in case a run has been added after + if (++runIdx == runs.size()) { + paraIdx++; + runIdx = 0; + } + } + } + } + + protected static void applyParagraphStyles(List paragraphs, List paraStyles) { + int paraIdx = 0; + for (TextPropCollection p : paraStyles) { + for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) { + if (paraIdx >= paragraphs.size()) { + return; + } + HSLFTextParagraph htp = paragraphs.get(paraIdx); + TextPropCollection pCopy = new TextPropCollection(0, TextPropType.paragraph); + pCopy.copy(p); + htp.setParagraphStyle(pCopy); + int len = 0; + for (HSLFTextRun trun : htp.getTextRuns()) { + len += trun.getLength(); + } + if (paraIdx == paragraphs.size()-1) { + len++; + } + pCopy.updateTextSize(len); + ccPara += len; + } + } + } + + protected static void applyParagraphIndents(List paragraphs, List paraStyles) { + int paraIdx = 0; + for (IndentProp p : paraStyles) { + for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) { + if (paraIdx >= paragraphs.size() || ccPara >= ccStyle-1) { + return; + } + HSLFTextParagraph para = paragraphs.get(paraIdx); + int len = 0; + for (HSLFTextRun trun : para.getTextRuns()) { + len += trun.getLength(); + } + para.setIndentLevel(p.getIndentLevel()); + ccPara += len + 1; + } + } + } + + public EscherTextboxWrapper getTextboxWrapper() { + return (EscherTextboxWrapper) _headerAtom.getParentRecord(); + } + + protected static Color getColorFromColorIndexStruct(int rgb, HSLFSheet sheet) { + int cidx = rgb >>> 24; + Color tmp; + switch (cidx) { + // Background ... Accent 3 color + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + if (sheet == null) { + return null; + } + ColorSchemeAtom ca = sheet.getColorScheme(); + tmp = new Color(ca.getColor(cidx), true); + break; + // Color is an sRGB value specified by red, green, and blue fields. + case 0xFE: + tmp = new Color(rgb, true); + break; + // Color is undefined. + default: + case 0xFF: + return null; + } + return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); + } + + /** + * Sets the value of the given Paragraph TextProp, add if required + * @param propName The name of the Paragraph TextProp + * @param val The value to set for the TextProp + */ + public void setParagraphTextPropVal(String propName, Integer val) { + setPropVal(_paragraphStyle, _masterStyle, propName, val); + setDirty(); + } + + /** + * marks this paragraph dirty, so its records will be renewed on save + */ + public void setDirty() { + _dirty = true; + } + + public boolean isDirty() { + return _dirty; + } + + /** + * Calculates the start index of the given text run + * + * @param textrun the text run to search for + * @return the start index with the paragraph collection or -1 if not found + */ + /* package */ int getStartIdxOfTextRun(HSLFTextRun textrun) { + int idx = 0; + for (HSLFTextParagraph p : parentList) { + for (HSLFTextRun r : p) { + if (r == textrun) { + return idx; + } + idx += r.getLength(); + } + } + return -1; + } + + /** + * {@inheritDoc} + * + * @see RoundTripHFPlaceholder12 + */ + @Override + public boolean isHeaderOrFooter() { + HSLFTextShape s = getParentShape(); + if (s == null) { + return false; + } + Placeholder ph = s.getPlaceholder(); + if (ph == null) { + return false; + } + switch (ph) { + case DATETIME: + case SLIDE_NUMBER: + case FOOTER: + case HEADER: + return true; + default: + return false; + } + } } \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java index 88a9766e9b..5014ae55ba 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java @@ -1,346 +1,346 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.draw; - -import java.awt.Color; -import java.awt.Shape; -import java.awt.geom.Area; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.WritableRaster; -import java.util.List; - -import org.apache.poi.hwmf.record.HwmfBrushStyle; -import org.apache.poi.hwmf.record.HwmfColorRef; -import org.apache.poi.hwmf.record.HwmfFont; -import org.apache.poi.hwmf.record.HwmfFill.WmfSetPolyfillMode.HwmfPolyfillMode; -import org.apache.poi.hwmf.record.HwmfHatchStyle; -import org.apache.poi.hwmf.record.HwmfMapMode; -import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode; -import org.apache.poi.hwmf.record.HwmfPalette.PaletteEntry; -import org.apache.poi.hwmf.record.HwmfPenStyle; -import org.apache.poi.hwmf.record.HwmfText.HwmfTextAlignment; -import org.apache.poi.hwmf.record.HwmfText.HwmfTextVerticalAlignment; - -public class HwmfDrawProperties { - private final Rectangle2D window; - private Rectangle2D viewport = null; - private final Point2D location; - private HwmfMapMode mapMode = HwmfMapMode.MM_ANISOTROPIC; - private HwmfColorRef backgroundColor = new HwmfColorRef(Color.BLACK); - private HwmfBrushStyle brushStyle = HwmfBrushStyle.BS_SOLID; - private HwmfColorRef brushColor = new HwmfColorRef(Color.BLACK); - private HwmfHatchStyle brushHatch = HwmfHatchStyle.HS_HORIZONTAL; - private BufferedImage brushBitmap = null; - private double penWidth = 1; - private HwmfPenStyle penStyle = HwmfPenStyle.valueOf(0); - private HwmfColorRef penColor = new HwmfColorRef(Color.BLACK); - private double penMiterLimit = 10; - private HwmfBkMode bkMode = HwmfBkMode.OPAQUE; - private HwmfPolyfillMode polyfillMode = HwmfPolyfillMode.WINDING; - private Shape region = null; - private List palette = null; - private int paletteOffset = 0; - private HwmfFont font = null; - private HwmfColorRef textColor = new HwmfColorRef(Color.BLACK); - private HwmfTextAlignment textAlignLatin = HwmfTextAlignment.LEFT; - private HwmfTextVerticalAlignment textVAlignLatin = HwmfTextVerticalAlignment.TOP; - private HwmfTextAlignment textAlignAsian = HwmfTextAlignment.RIGHT; - private HwmfTextVerticalAlignment textVAlignAsian = HwmfTextVerticalAlignment.TOP; - - public HwmfDrawProperties() { - window = new Rectangle2D.Double(0, 0, 1, 1); - viewport = null; - location = new Point2D.Double(0,0); - } - - public HwmfDrawProperties(HwmfDrawProperties other) { - this.window = (Rectangle2D)other.window.clone(); - this.viewport = (other.viewport == null) ? null : (Rectangle2D)other.viewport.clone(); - this.location = (Point2D)other.location.clone(); - this.mapMode = other.mapMode; - this.backgroundColor = (other.backgroundColor == null) ? null : other.backgroundColor.clone(); - this.brushStyle = other.brushStyle; - this.brushColor = other.brushColor.clone(); - this.brushHatch = other.brushHatch; - if (other.brushBitmap != null) { - ColorModel cm = other.brushBitmap.getColorModel(); - boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); - WritableRaster raster = other.brushBitmap.copyData(null); - this.brushBitmap = new BufferedImage(cm, raster, isAlphaPremultiplied, null); - } - this.penWidth = 1; - this.penStyle = (other.penStyle == null) ? null : other.penStyle.clone(); - this.penColor = (other.penColor == null) ? null : other.penColor.clone(); - this.penMiterLimit = other.penMiterLimit; - this.bkMode = other.bkMode; - this.polyfillMode = other.polyfillMode; - if (other.region instanceof Rectangle2D) { - this.region = ((Rectangle2D)other.region).getBounds2D(); - } else if (other.region instanceof Area) { - this.region = new Area(other.region); - } - this.palette = other.palette; - this.paletteOffset = other.paletteOffset; - this.font = other.font; - this.textColor = (other.textColor == null) ? null : other.textColor.clone(); - } - - public void setViewportExt(double width, double height) { - if (viewport == null) { - viewport = (Rectangle2D)window.clone(); - } - double x = viewport.getX(); - double y = viewport.getY(); - double w = (width != 0) ? width : viewport.getWidth(); - double h = (height != 0) ? height : viewport.getHeight(); - viewport.setRect(x, y, w, h); - } - - public void setViewportOrg(double x, double y) { - if (viewport == null) { - viewport = (Rectangle2D)window.clone(); - } - double w = viewport.getWidth(); - double h = viewport.getHeight(); - viewport.setRect(x, y, w, h); - } - - public Rectangle2D getViewport() { - return (viewport == null) ? null : (Rectangle2D)viewport.clone(); - } - - public void setWindowExt(double width, double height) { - double x = window.getX(); - double y = window.getY(); - double w = (width != 0) ? width : window.getWidth(); - double h = (height != 0) ? height : window.getHeight(); - window.setRect(x, y, w, h); - } - - public void setWindowOrg(double x, double y) { - double w = window.getWidth(); - double h = window.getHeight(); - window.setRect(x, y, w, h); - } - - public Rectangle2D getWindow() { - return (Rectangle2D)window.clone(); - } - - public void setLocation(double x, double y) { - location.setLocation(x, y); - } - - public Point2D getLocation() { - return (Point2D)location.clone(); - } - - public void setMapMode(HwmfMapMode mapMode) { - this.mapMode = mapMode; - } - - public HwmfMapMode getMapMode() { - return mapMode; - } - - public HwmfBrushStyle getBrushStyle() { - return brushStyle; - } - - public void setBrushStyle(HwmfBrushStyle brushStyle) { - this.brushStyle = brushStyle; - } - - public HwmfHatchStyle getBrushHatch() { - return brushHatch; - } - - public void setBrushHatch(HwmfHatchStyle brushHatch) { - this.brushHatch = brushHatch; - } - - public HwmfColorRef getBrushColor() { - return brushColor; - } - - public void setBrushColor(HwmfColorRef brushColor) { - this.brushColor = brushColor; - } - - public HwmfBkMode getBkMode() { - return bkMode; - } - - public void setBkMode(HwmfBkMode bkMode) { - this.bkMode = bkMode; - } - - public HwmfPenStyle getPenStyle() { - return penStyle; - } - - public void setPenStyle(HwmfPenStyle penStyle) { - this.penStyle = penStyle; - } - - public HwmfColorRef getPenColor() { - return penColor; - } - - public void setPenColor(HwmfColorRef penColor) { - this.penColor = penColor; - } - - public double getPenWidth() { - return penWidth; - } - - public void setPenWidth(double penWidth) { - this.penWidth = penWidth; - } - - public double getPenMiterLimit() { - return penMiterLimit; - } - - public void setPenMiterLimit(double penMiterLimit) { - this.penMiterLimit = penMiterLimit; - } - - public HwmfColorRef getBackgroundColor() { - return backgroundColor; - } - - public void setBackgroundColor(HwmfColorRef backgroundColor) { - this.backgroundColor = backgroundColor; - } - - public HwmfPolyfillMode getPolyfillMode() { - return polyfillMode; - } - - public void setPolyfillMode(HwmfPolyfillMode polyfillMode) { - this.polyfillMode = polyfillMode; - } - - public BufferedImage getBrushBitmap() { - return brushBitmap; - } - - public void setBrushBitmap(BufferedImage brushBitmap) { - this.brushBitmap = brushBitmap; - } - - - /** - * Gets the last stored region - * - * @return the last stored region - */ - public Shape getRegion() { - return region; - } - - /** - * Sets a region for further usage - * - * @param region a region object which is usually a rectangle - */ - public void setRegion(Shape region) { - this.region = region; - } - - /** - * Returns the current palette. - * Callers may modify the palette. - * - * @return the current palette or null, if it hasn't been set - */ - public List getPalette() { - return palette; - } - - /** - * Sets the current palette. - * It's the callers duty to set a modifiable copy of the palette. - * - * @param palette - */ - public void setPalette(List palette) { - this.palette = palette; - } - - public int getPaletteOffset() { - return paletteOffset; - } - - public void setPaletteOffset(int paletteOffset) { - this.paletteOffset = paletteOffset; - } - - public HwmfColorRef getTextColor() { - return textColor; - } - - public void setTextColor(HwmfColorRef textColor) { - this.textColor = textColor; - } - - public HwmfFont getFont() { - return font; - } - - public void setFont(HwmfFont font) { - this.font = font; - } - - public HwmfTextAlignment getTextAlignLatin() { - return textAlignLatin; - } - - public void setTextAlignLatin(HwmfTextAlignment textAlignLatin) { - this.textAlignLatin = textAlignLatin; - } - - public HwmfTextVerticalAlignment getTextVAlignLatin() { - return textVAlignLatin; - } - - public void setTextVAlignLatin(HwmfTextVerticalAlignment textVAlignLatin) { - this.textVAlignLatin = textVAlignLatin; - } - - public HwmfTextAlignment getTextAlignAsian() { - return textAlignAsian; - } - - public void setTextAlignAsian(HwmfTextAlignment textAlignAsian) { - this.textAlignAsian = textAlignAsian; - } - - public HwmfTextVerticalAlignment getTextVAlignAsian() { - return textVAlignAsian; - } - - public void setTextVAlignAsian(HwmfTextVerticalAlignment textVAlignAsian) { - this.textVAlignAsian = textVAlignAsian; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.draw; + +import java.awt.Color; +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.WritableRaster; +import java.util.List; + +import org.apache.poi.hwmf.record.HwmfBrushStyle; +import org.apache.poi.hwmf.record.HwmfColorRef; +import org.apache.poi.hwmf.record.HwmfFont; +import org.apache.poi.hwmf.record.HwmfFill.WmfSetPolyfillMode.HwmfPolyfillMode; +import org.apache.poi.hwmf.record.HwmfHatchStyle; +import org.apache.poi.hwmf.record.HwmfMapMode; +import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode; +import org.apache.poi.hwmf.record.HwmfPalette.PaletteEntry; +import org.apache.poi.hwmf.record.HwmfPenStyle; +import org.apache.poi.hwmf.record.HwmfText.HwmfTextAlignment; +import org.apache.poi.hwmf.record.HwmfText.HwmfTextVerticalAlignment; + +public class HwmfDrawProperties { + private final Rectangle2D window; + private Rectangle2D viewport = null; + private final Point2D location; + private HwmfMapMode mapMode = HwmfMapMode.MM_ANISOTROPIC; + private HwmfColorRef backgroundColor = new HwmfColorRef(Color.BLACK); + private HwmfBrushStyle brushStyle = HwmfBrushStyle.BS_SOLID; + private HwmfColorRef brushColor = new HwmfColorRef(Color.BLACK); + private HwmfHatchStyle brushHatch = HwmfHatchStyle.HS_HORIZONTAL; + private BufferedImage brushBitmap = null; + private double penWidth = 1; + private HwmfPenStyle penStyle = HwmfPenStyle.valueOf(0); + private HwmfColorRef penColor = new HwmfColorRef(Color.BLACK); + private double penMiterLimit = 10; + private HwmfBkMode bkMode = HwmfBkMode.OPAQUE; + private HwmfPolyfillMode polyfillMode = HwmfPolyfillMode.WINDING; + private Shape region = null; + private List palette = null; + private int paletteOffset = 0; + private HwmfFont font = null; + private HwmfColorRef textColor = new HwmfColorRef(Color.BLACK); + private HwmfTextAlignment textAlignLatin = HwmfTextAlignment.LEFT; + private HwmfTextVerticalAlignment textVAlignLatin = HwmfTextVerticalAlignment.TOP; + private HwmfTextAlignment textAlignAsian = HwmfTextAlignment.RIGHT; + private HwmfTextVerticalAlignment textVAlignAsian = HwmfTextVerticalAlignment.TOP; + + public HwmfDrawProperties() { + window = new Rectangle2D.Double(0, 0, 1, 1); + viewport = null; + location = new Point2D.Double(0,0); + } + + public HwmfDrawProperties(HwmfDrawProperties other) { + this.window = (Rectangle2D)other.window.clone(); + this.viewport = (other.viewport == null) ? null : (Rectangle2D)other.viewport.clone(); + this.location = (Point2D)other.location.clone(); + this.mapMode = other.mapMode; + this.backgroundColor = (other.backgroundColor == null) ? null : other.backgroundColor.clone(); + this.brushStyle = other.brushStyle; + this.brushColor = other.brushColor.clone(); + this.brushHatch = other.brushHatch; + if (other.brushBitmap != null) { + ColorModel cm = other.brushBitmap.getColorModel(); + boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); + WritableRaster raster = other.brushBitmap.copyData(null); + this.brushBitmap = new BufferedImage(cm, raster, isAlphaPremultiplied, null); + } + this.penWidth = 1; + this.penStyle = (other.penStyle == null) ? null : other.penStyle.clone(); + this.penColor = (other.penColor == null) ? null : other.penColor.clone(); + this.penMiterLimit = other.penMiterLimit; + this.bkMode = other.bkMode; + this.polyfillMode = other.polyfillMode; + if (other.region instanceof Rectangle2D) { + this.region = ((Rectangle2D)other.region).getBounds2D(); + } else if (other.region instanceof Area) { + this.region = new Area(other.region); + } + this.palette = other.palette; + this.paletteOffset = other.paletteOffset; + this.font = other.font; + this.textColor = (other.textColor == null) ? null : other.textColor.clone(); + } + + public void setViewportExt(double width, double height) { + if (viewport == null) { + viewport = (Rectangle2D)window.clone(); + } + double x = viewport.getX(); + double y = viewport.getY(); + double w = (width != 0) ? width : viewport.getWidth(); + double h = (height != 0) ? height : viewport.getHeight(); + viewport.setRect(x, y, w, h); + } + + public void setViewportOrg(double x, double y) { + if (viewport == null) { + viewport = (Rectangle2D)window.clone(); + } + double w = viewport.getWidth(); + double h = viewport.getHeight(); + viewport.setRect(x, y, w, h); + } + + public Rectangle2D getViewport() { + return (viewport == null) ? null : (Rectangle2D)viewport.clone(); + } + + public void setWindowExt(double width, double height) { + double x = window.getX(); + double y = window.getY(); + double w = (width != 0) ? width : window.getWidth(); + double h = (height != 0) ? height : window.getHeight(); + window.setRect(x, y, w, h); + } + + public void setWindowOrg(double x, double y) { + double w = window.getWidth(); + double h = window.getHeight(); + window.setRect(x, y, w, h); + } + + public Rectangle2D getWindow() { + return (Rectangle2D)window.clone(); + } + + public void setLocation(double x, double y) { + location.setLocation(x, y); + } + + public Point2D getLocation() { + return (Point2D)location.clone(); + } + + public void setMapMode(HwmfMapMode mapMode) { + this.mapMode = mapMode; + } + + public HwmfMapMode getMapMode() { + return mapMode; + } + + public HwmfBrushStyle getBrushStyle() { + return brushStyle; + } + + public void setBrushStyle(HwmfBrushStyle brushStyle) { + this.brushStyle = brushStyle; + } + + public HwmfHatchStyle getBrushHatch() { + return brushHatch; + } + + public void setBrushHatch(HwmfHatchStyle brushHatch) { + this.brushHatch = brushHatch; + } + + public HwmfColorRef getBrushColor() { + return brushColor; + } + + public void setBrushColor(HwmfColorRef brushColor) { + this.brushColor = brushColor; + } + + public HwmfBkMode getBkMode() { + return bkMode; + } + + public void setBkMode(HwmfBkMode bkMode) { + this.bkMode = bkMode; + } + + public HwmfPenStyle getPenStyle() { + return penStyle; + } + + public void setPenStyle(HwmfPenStyle penStyle) { + this.penStyle = penStyle; + } + + public HwmfColorRef getPenColor() { + return penColor; + } + + public void setPenColor(HwmfColorRef penColor) { + this.penColor = penColor; + } + + public double getPenWidth() { + return penWidth; + } + + public void setPenWidth(double penWidth) { + this.penWidth = penWidth; + } + + public double getPenMiterLimit() { + return penMiterLimit; + } + + public void setPenMiterLimit(double penMiterLimit) { + this.penMiterLimit = penMiterLimit; + } + + public HwmfColorRef getBackgroundColor() { + return backgroundColor; + } + + public void setBackgroundColor(HwmfColorRef backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public HwmfPolyfillMode getPolyfillMode() { + return polyfillMode; + } + + public void setPolyfillMode(HwmfPolyfillMode polyfillMode) { + this.polyfillMode = polyfillMode; + } + + public BufferedImage getBrushBitmap() { + return brushBitmap; + } + + public void setBrushBitmap(BufferedImage brushBitmap) { + this.brushBitmap = brushBitmap; + } + + + /** + * Gets the last stored region + * + * @return the last stored region + */ + public Shape getRegion() { + return region; + } + + /** + * Sets a region for further usage + * + * @param region a region object which is usually a rectangle + */ + public void setRegion(Shape region) { + this.region = region; + } + + /** + * Returns the current palette. + * Callers may modify the palette. + * + * @return the current palette or null, if it hasn't been set + */ + public List getPalette() { + return palette; + } + + /** + * Sets the current palette. + * It's the callers duty to set a modifiable copy of the palette. + * + * @param palette + */ + public void setPalette(List palette) { + this.palette = palette; + } + + public int getPaletteOffset() { + return paletteOffset; + } + + public void setPaletteOffset(int paletteOffset) { + this.paletteOffset = paletteOffset; + } + + public HwmfColorRef getTextColor() { + return textColor; + } + + public void setTextColor(HwmfColorRef textColor) { + this.textColor = textColor; + } + + public HwmfFont getFont() { + return font; + } + + public void setFont(HwmfFont font) { + this.font = font; + } + + public HwmfTextAlignment getTextAlignLatin() { + return textAlignLatin; + } + + public void setTextAlignLatin(HwmfTextAlignment textAlignLatin) { + this.textAlignLatin = textAlignLatin; + } + + public HwmfTextVerticalAlignment getTextVAlignLatin() { + return textVAlignLatin; + } + + public void setTextVAlignLatin(HwmfTextVerticalAlignment textVAlignLatin) { + this.textVAlignLatin = textVAlignLatin; + } + + public HwmfTextAlignment getTextAlignAsian() { + return textAlignAsian; + } + + public void setTextAlignAsian(HwmfTextAlignment textAlignAsian) { + this.textAlignAsian = textAlignAsian; + } + + public HwmfTextVerticalAlignment getTextVAlignAsian() { + return textVAlignAsian; + } + + public void setTextVAlignAsian(HwmfTextVerticalAlignment textVAlignAsian) { + this.textVAlignAsian = textVAlignAsian; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java index ef5af49e40..c18a2c6512 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java @@ -1,444 +1,444 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.draw; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.Paint; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.TexturePaint; -import java.awt.font.TextAttribute; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.nio.charset.Charset; -import java.text.AttributedString; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.NoSuchElementException; - -import org.apache.poi.hwmf.record.HwmfBrushStyle; -import org.apache.poi.hwmf.record.HwmfFont; -import org.apache.poi.hwmf.record.HwmfHatchStyle; -import org.apache.poi.hwmf.record.HwmfMapMode; -import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode; -import org.apache.poi.hwmf.record.HwmfObjectTableEntry; -import org.apache.poi.hwmf.record.HwmfPenStyle; -import org.apache.poi.hwmf.record.HwmfPenStyle.HwmfLineDash; -import org.apache.poi.sl.draw.DrawFactory; -import org.apache.poi.sl.draw.DrawFontManager; -import org.apache.poi.sl.draw.Drawable; -import org.apache.poi.util.LocaleUtil; - -public class HwmfGraphics { - - private static final Charset DEFAULT_CHARSET = LocaleUtil.CHARSET_1252; - private final Graphics2D graphicsCtx; - private final List propStack = new LinkedList(); - private HwmfDrawProperties prop = new HwmfDrawProperties(); - private List objectTable = new ArrayList(); - /** Bounding box from the placeable header */ - private final Rectangle2D bbox; - private final AffineTransform initialAT; - - /** - * Initialize a graphics context for wmf rendering - * - * @param graphicsCtx the graphics context to delegate drawing calls - * @param bbox the bounding box of the wmf (taken from the placeable header) - */ - public HwmfGraphics(Graphics2D graphicsCtx, Rectangle2D bbox) { - this.graphicsCtx = graphicsCtx; - this.bbox = (Rectangle2D)bbox.clone(); - this.initialAT = graphicsCtx.getTransform(); - DrawFactory.getInstance(graphicsCtx).fixFonts(graphicsCtx); - } - - public HwmfDrawProperties getProperties() { - return prop; - } - - public void draw(Shape shape) { - HwmfLineDash lineDash = prop.getPenStyle().getLineDash(); - if (lineDash == HwmfLineDash.NULL) { - // line is not drawn - return; - } - - BasicStroke stroke = getStroke(); - - // first draw a solid background line (depending on bkmode) - // only makes sense if the line is not solid - if (prop.getBkMode() == HwmfBkMode.OPAQUE && (lineDash != HwmfLineDash.SOLID && lineDash != HwmfLineDash.INSIDEFRAME)) { - graphicsCtx.setStroke(new BasicStroke(stroke.getLineWidth())); - graphicsCtx.setColor(prop.getBackgroundColor().getColor()); - graphicsCtx.draw(shape); - } - - // then draw the (dashed) line - graphicsCtx.setStroke(stroke); - graphicsCtx.setColor(prop.getPenColor().getColor()); - graphicsCtx.draw(shape); - } - - public void fill(Shape shape) { - if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) { -// GeneralPath gp = new GeneralPath(shape); -// gp.setWindingRule(prop.getPolyfillMode().awtFlag); - graphicsCtx.setPaint(getFill()); - graphicsCtx.fill(shape); - } - - draw(shape); - } - - protected BasicStroke getStroke() { - // TODO: fix line width calculation - float width = (float)prop.getPenWidth(); - if (width == 0) { - width = 1; - } - HwmfPenStyle ps = prop.getPenStyle(); - int cap = ps.getLineCap().awtFlag; - int join = ps.getLineJoin().awtFlag; - float miterLimit = (float)prop.getPenMiterLimit(); - float dashes[] = ps.getLineDash().dashes; - boolean dashAlt = ps.isAlternateDash(); - // This value is not an integer index into the dash pattern array. - // Instead, it is a floating-point value that specifies a linear distance. - float dashStart = (dashAlt && dashes != null && dashes.length > 1) ? dashes[0] : 0; - - return new BasicStroke(width, cap, join, miterLimit, dashes, dashStart); - } - - protected Paint getFill() { - switch (prop.getBrushStyle()) { - default: - case BS_INDEXED: - case BS_PATTERN8X8: - case BS_DIBPATTERN8X8: - case BS_MONOPATTERN: - case BS_NULL: return null; - case BS_PATTERN: - case BS_DIBPATTERN: - case BS_DIBPATTERNPT: return getPatternPaint(); - case BS_SOLID: return getSolidFill(); - case BS_HATCHED: return getHatchedFill(); - } - } - - protected Paint getSolidFill() { - return prop.getBrushColor().getColor(); - } - - protected Paint getHatchedFill() { - int dim = 7, mid = 3; - BufferedImage bi = new BufferedImage(dim, dim, BufferedImage.TYPE_4BYTE_ABGR); - Graphics2D g = bi.createGraphics(); - Color c = (prop.getBkMode() == HwmfBkMode.TRANSPARENT) - ? new Color(0, true) - : prop.getBackgroundColor().getColor(); - g.setColor(c); - g.fillRect(0, 0, dim, dim); - g.setColor(prop.getBrushColor().getColor()); - HwmfHatchStyle h = prop.getBrushHatch(); - if (h == HwmfHatchStyle.HS_HORIZONTAL || h == HwmfHatchStyle.HS_CROSS) { - g.drawLine(0, mid, dim, mid); - } - if (h == HwmfHatchStyle.HS_VERTICAL || h == HwmfHatchStyle.HS_CROSS) { - g.drawLine(mid, 0, mid, dim); - } - if (h == HwmfHatchStyle.HS_FDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) { - g.drawLine(0, 0, dim, dim); - } - if (h == HwmfHatchStyle.HS_BDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) { - g.drawLine(0, dim, dim, 0); - } - g.dispose(); - return new TexturePaint(bi, new Rectangle(0,0,dim,dim)); - } - - protected Paint getPatternPaint() { - BufferedImage bi = prop.getBrushBitmap(); - return (bi == null) ? null - : new TexturePaint(bi, new Rectangle(0,0,bi.getWidth(),bi.getHeight())); - } - - /** - * Adds an record of type {@link HwmfObjectTableEntry} to the object table. - * - * Every object is assigned the lowest available index-that is, the smallest - * numerical value-in the WMF Object Table. This binding happens at object creation, - * not when the object is used. - * Moreover, each object table index uniquely refers to an object. - * Indexes in the WMF Object Table always start at 0. - * - * @param entry - */ - public void addObjectTableEntry(HwmfObjectTableEntry entry) { - ListIterator oIter = objectTable.listIterator(); - while (oIter.hasNext()) { - HwmfObjectTableEntry tableEntry = oIter.next(); - if (tableEntry == null) { - oIter.set(entry); - return; - } - } - objectTable.add(entry); - } - - /** - * Applies the object table entry - * - * @param index the index of the object table entry (0-based) - * - * @throws IndexOutOfBoundsException if the index is out of range - * @throws NoSuchElementException if the entry was deleted before - */ - public void applyObjectTableEntry(int index) { - HwmfObjectTableEntry ote = objectTable.get(index); - if (ote == null) { - throw new NoSuchElementException("WMF reference exception - object table entry on index "+index+" was deleted before."); - } - ote.applyObject(this); - } - - /** - * Unsets (deletes) the object table entry for further usage - * - * When a META_DELETEOBJECT record (section 2.3.4.7) is received that specifies this - * object's particular index, the object's resources are released, the binding to its - * WMF Object Table index is ended, and the index value is returned to the pool of - * available indexes. The index will be reused, if needed, by a subsequent object - * created by another Object Record Type record. - * - * @param index the index (0-based) - * - * @throws IndexOutOfBoundsException if the index is out of range - */ - public void unsetObjectTableEntry(int index) { - objectTable.set(index, null); - } - - /** - * Saves the current properties to the stack - */ - public void saveProperties() { - propStack.add(prop); - prop = new HwmfDrawProperties(prop); - } - - /** - * Restores the properties from the stack - * - * @param index if the index is positive, the n-th element from the start is activated. - * If the index is negative, the n-th previous element relative to the current properties element is activated. - */ - public void restoreProperties(int index) { - if (index == 0) { - return; - } - int stackIndex = index; - if (stackIndex < 0) { - int curIdx = propStack.indexOf(prop); - if (curIdx == -1) { - // the current element is not pushed to the stacked, i.e. it's the last - curIdx = propStack.size(); - } - stackIndex = curIdx + index; - } - if (stackIndex == -1) { - // roll to last when curIdx == 0 - stackIndex = propStack.size()-1; - } - prop = propStack.get(stackIndex); - } - - /** - * After setting various window and viewport related properties, - * the underlying graphics context needs to be adapted. - * This methods gathers and sets the corresponding graphics transformations. - */ - public void updateWindowMapMode() { - Rectangle2D win = prop.getWindow(); - HwmfMapMode mapMode = prop.getMapMode(); - graphicsCtx.setTransform(initialAT); - - switch (mapMode) { - default: - case MM_ANISOTROPIC: - // scale window bounds to output bounds - graphicsCtx.scale(bbox.getWidth()/win.getWidth(), bbox.getHeight()/win.getHeight()); - graphicsCtx.translate(-win.getX(), -win.getY()); - break; - case MM_ISOTROPIC: - // TODO: to be validated ... - // like anisotropic, but use x-axis as reference - graphicsCtx.scale(bbox.getWidth()/win.getWidth(), bbox.getWidth()/win.getWidth()); - graphicsCtx.translate(-win.getX(), -win.getY()); - break; - case MM_LOMETRIC: - case MM_HIMETRIC: - case MM_LOENGLISH: - case MM_HIENGLISH: - case MM_TWIPS: { - // TODO: to be validated ... - GraphicsConfiguration gc = graphicsCtx.getDeviceConfiguration(); - graphicsCtx.transform(gc.getNormalizingTransform()); - graphicsCtx.scale(1./mapMode.scale, -1./mapMode.scale); - graphicsCtx.translate(-win.getX(), -win.getY()); - break; - } - case MM_TEXT: - // TODO: to be validated ... - break; - } - } - - public void drawString(byte[] text, Rectangle2D bounds) { - drawString(text, bounds, null); - } - - public void drawString(byte[] text, Rectangle2D bounds, int dx[]) { - HwmfFont font = prop.getFont(); - if (font == null || text == null || text.length == 0) { - return; - } - - double fontH = getFontHeight(font); - // TODO: another approx. ... - double fontW = fontH/1.8; - - int len = text.length; - Charset charset = (font.getCharSet().getCharset() == null)? - DEFAULT_CHARSET : font.getCharSet().getCharset(); - String textString = new String(text, charset); - AttributedString as = new AttributedString(textString); - if (dx == null || dx.length == 0) { - addAttributes(as, font); - } else { - int[] dxNormed = dx; - //for multi-byte encodings (e.g. Shift_JIS), the byte length - //might not equal the string length(). - //The x information is stored in dx[], an array parallel to the - //byte array text[]. dx[] stores the x info in the - //first byte of a multibyte character, but dx[] stores 0 - //for the other bytes in that character. - //We need to map this information to the String offsets - //dx[0] = 13 text[0] = -125 - //dx[1] = 0 text[1] = 118 - //dx[2] = 14 text[2] = -125 - //dx[3] = 0 text[3] = -115 - // needs to be remapped as: - //dxNormed[0] = 13 textString.get(0) = U+30D7 - //dxNormed[1] = 14 textString.get(1) = U+30ED - if (textString.length() != text.length) { - int codePoints = textString.codePointCount(0, textString.length()); - dxNormed = new int[codePoints]; - int dxPosition = 0; - for (int offset = 0; offset < textString.length(); ) { - dxNormed[offset] = dx[dxPosition]; - int[] chars = new int[1]; - int cp = textString.codePointAt(offset); - chars[0] = cp; - //now figure out how many bytes it takes to encode that - //code point in the charset - int byteLength = new String(chars, 0, chars.length).getBytes(charset).length; - dxPosition += byteLength; - offset += Character.charCount(cp); - } - } - for (int i = 0; i < dxNormed.length; i++) { - addAttributes(as, font); - // Tracking works as a prefix/advance space on characters whereas - // dx[...] is the complete width of the current char - // therefore we need to add the additional/suffix width to the next char - if (i < dxNormed.length - 1) { - as.addAttribute(TextAttribute.TRACKING, (dxNormed[i] - fontW) / fontH, i + 1, i + 2); - } - } - } - - - double angle = Math.toRadians(-font.getEscapement()/10.); - - - final AffineTransform at = graphicsCtx.getTransform(); - try { - graphicsCtx.translate(bounds.getX(), bounds.getY()+fontH); - graphicsCtx.rotate(angle); - if (prop.getBkMode() == HwmfBkMode.OPAQUE) { - // TODO: validate bounds - graphicsCtx.setBackground(prop.getBackgroundColor().getColor()); - graphicsCtx.fill(new Rectangle2D.Double(0, 0, bounds.getWidth(), bounds.getHeight())); - } - graphicsCtx.setColor(prop.getTextColor().getColor()); - graphicsCtx.drawString(as.getIterator(), 0, 0); // (float)bounds.getX(), (float)bounds.getY()); - } finally { - graphicsCtx.setTransform(at); - } - } - - private void addAttributes(AttributedString as, HwmfFont font) { - DrawFontManager fontHandler = (DrawFontManager)graphicsCtx.getRenderingHint(Drawable.FONT_HANDLER); - String fontFamily = null; - @SuppressWarnings("unchecked") - Map fontMap = (Map)graphicsCtx.getRenderingHint(Drawable.FONT_MAP); - if (fontMap != null && fontMap.containsKey(font.getFacename())) { - fontFamily = fontMap.get(font.getFacename()); - } - if (fontHandler != null) { - fontFamily = fontHandler.getRendererableFont(font.getFacename(), font.getPitchAndFamily()); - } - if (fontFamily == null) { - fontFamily = font.getFacename(); - } - - as.addAttribute(TextAttribute.FAMILY, fontFamily); - as.addAttribute(TextAttribute.SIZE, getFontHeight(font)); - as.addAttribute(TextAttribute.STRIKETHROUGH, font.isStrikeOut()); - if (font.isUnderline()) { - as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); - } - if (font.isItalic()) { - as.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE); - } - as.addAttribute(TextAttribute.WEIGHT, font.getWeight()); - } - - private double getFontHeight(HwmfFont font) { - // see HwmfFont#height for details - double fontHeight = font.getHeight(); - if (fontHeight == 0) { - return 12; - } else if (fontHeight < 0) { - return -fontHeight; - } else { - // TODO: fix font height calculation - // the height is given as font size + ascent + descent - // as an approximation we reduce the height by a static factor - return fontHeight*3/4; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.draw; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.TexturePaint; +import java.awt.font.TextAttribute; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.nio.charset.Charset; +import java.text.AttributedString; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; + +import org.apache.poi.hwmf.record.HwmfBrushStyle; +import org.apache.poi.hwmf.record.HwmfFont; +import org.apache.poi.hwmf.record.HwmfHatchStyle; +import org.apache.poi.hwmf.record.HwmfMapMode; +import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode; +import org.apache.poi.hwmf.record.HwmfObjectTableEntry; +import org.apache.poi.hwmf.record.HwmfPenStyle; +import org.apache.poi.hwmf.record.HwmfPenStyle.HwmfLineDash; +import org.apache.poi.sl.draw.DrawFactory; +import org.apache.poi.sl.draw.DrawFontManager; +import org.apache.poi.sl.draw.Drawable; +import org.apache.poi.util.LocaleUtil; + +public class HwmfGraphics { + + private static final Charset DEFAULT_CHARSET = LocaleUtil.CHARSET_1252; + private final Graphics2D graphicsCtx; + private final List propStack = new LinkedList(); + private HwmfDrawProperties prop = new HwmfDrawProperties(); + private List objectTable = new ArrayList(); + /** Bounding box from the placeable header */ + private final Rectangle2D bbox; + private final AffineTransform initialAT; + + /** + * Initialize a graphics context for wmf rendering + * + * @param graphicsCtx the graphics context to delegate drawing calls + * @param bbox the bounding box of the wmf (taken from the placeable header) + */ + public HwmfGraphics(Graphics2D graphicsCtx, Rectangle2D bbox) { + this.graphicsCtx = graphicsCtx; + this.bbox = (Rectangle2D)bbox.clone(); + this.initialAT = graphicsCtx.getTransform(); + DrawFactory.getInstance(graphicsCtx).fixFonts(graphicsCtx); + } + + public HwmfDrawProperties getProperties() { + return prop; + } + + public void draw(Shape shape) { + HwmfLineDash lineDash = prop.getPenStyle().getLineDash(); + if (lineDash == HwmfLineDash.NULL) { + // line is not drawn + return; + } + + BasicStroke stroke = getStroke(); + + // first draw a solid background line (depending on bkmode) + // only makes sense if the line is not solid + if (prop.getBkMode() == HwmfBkMode.OPAQUE && (lineDash != HwmfLineDash.SOLID && lineDash != HwmfLineDash.INSIDEFRAME)) { + graphicsCtx.setStroke(new BasicStroke(stroke.getLineWidth())); + graphicsCtx.setColor(prop.getBackgroundColor().getColor()); + graphicsCtx.draw(shape); + } + + // then draw the (dashed) line + graphicsCtx.setStroke(stroke); + graphicsCtx.setColor(prop.getPenColor().getColor()); + graphicsCtx.draw(shape); + } + + public void fill(Shape shape) { + if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) { +// GeneralPath gp = new GeneralPath(shape); +// gp.setWindingRule(prop.getPolyfillMode().awtFlag); + graphicsCtx.setPaint(getFill()); + graphicsCtx.fill(shape); + } + + draw(shape); + } + + protected BasicStroke getStroke() { + // TODO: fix line width calculation + float width = (float)prop.getPenWidth(); + if (width == 0) { + width = 1; + } + HwmfPenStyle ps = prop.getPenStyle(); + int cap = ps.getLineCap().awtFlag; + int join = ps.getLineJoin().awtFlag; + float miterLimit = (float)prop.getPenMiterLimit(); + float dashes[] = ps.getLineDash().dashes; + boolean dashAlt = ps.isAlternateDash(); + // This value is not an integer index into the dash pattern array. + // Instead, it is a floating-point value that specifies a linear distance. + float dashStart = (dashAlt && dashes != null && dashes.length > 1) ? dashes[0] : 0; + + return new BasicStroke(width, cap, join, miterLimit, dashes, dashStart); + } + + protected Paint getFill() { + switch (prop.getBrushStyle()) { + default: + case BS_INDEXED: + case BS_PATTERN8X8: + case BS_DIBPATTERN8X8: + case BS_MONOPATTERN: + case BS_NULL: return null; + case BS_PATTERN: + case BS_DIBPATTERN: + case BS_DIBPATTERNPT: return getPatternPaint(); + case BS_SOLID: return getSolidFill(); + case BS_HATCHED: return getHatchedFill(); + } + } + + protected Paint getSolidFill() { + return prop.getBrushColor().getColor(); + } + + protected Paint getHatchedFill() { + int dim = 7, mid = 3; + BufferedImage bi = new BufferedImage(dim, dim, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g = bi.createGraphics(); + Color c = (prop.getBkMode() == HwmfBkMode.TRANSPARENT) + ? new Color(0, true) + : prop.getBackgroundColor().getColor(); + g.setColor(c); + g.fillRect(0, 0, dim, dim); + g.setColor(prop.getBrushColor().getColor()); + HwmfHatchStyle h = prop.getBrushHatch(); + if (h == HwmfHatchStyle.HS_HORIZONTAL || h == HwmfHatchStyle.HS_CROSS) { + g.drawLine(0, mid, dim, mid); + } + if (h == HwmfHatchStyle.HS_VERTICAL || h == HwmfHatchStyle.HS_CROSS) { + g.drawLine(mid, 0, mid, dim); + } + if (h == HwmfHatchStyle.HS_FDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) { + g.drawLine(0, 0, dim, dim); + } + if (h == HwmfHatchStyle.HS_BDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) { + g.drawLine(0, dim, dim, 0); + } + g.dispose(); + return new TexturePaint(bi, new Rectangle(0,0,dim,dim)); + } + + protected Paint getPatternPaint() { + BufferedImage bi = prop.getBrushBitmap(); + return (bi == null) ? null + : new TexturePaint(bi, new Rectangle(0,0,bi.getWidth(),bi.getHeight())); + } + + /** + * Adds an record of type {@link HwmfObjectTableEntry} to the object table. + * + * Every object is assigned the lowest available index-that is, the smallest + * numerical value-in the WMF Object Table. This binding happens at object creation, + * not when the object is used. + * Moreover, each object table index uniquely refers to an object. + * Indexes in the WMF Object Table always start at 0. + * + * @param entry + */ + public void addObjectTableEntry(HwmfObjectTableEntry entry) { + ListIterator oIter = objectTable.listIterator(); + while (oIter.hasNext()) { + HwmfObjectTableEntry tableEntry = oIter.next(); + if (tableEntry == null) { + oIter.set(entry); + return; + } + } + objectTable.add(entry); + } + + /** + * Applies the object table entry + * + * @param index the index of the object table entry (0-based) + * + * @throws IndexOutOfBoundsException if the index is out of range + * @throws NoSuchElementException if the entry was deleted before + */ + public void applyObjectTableEntry(int index) { + HwmfObjectTableEntry ote = objectTable.get(index); + if (ote == null) { + throw new NoSuchElementException("WMF reference exception - object table entry on index "+index+" was deleted before."); + } + ote.applyObject(this); + } + + /** + * Unsets (deletes) the object table entry for further usage + * + * When a META_DELETEOBJECT record (section 2.3.4.7) is received that specifies this + * object's particular index, the object's resources are released, the binding to its + * WMF Object Table index is ended, and the index value is returned to the pool of + * available indexes. The index will be reused, if needed, by a subsequent object + * created by another Object Record Type record. + * + * @param index the index (0-based) + * + * @throws IndexOutOfBoundsException if the index is out of range + */ + public void unsetObjectTableEntry(int index) { + objectTable.set(index, null); + } + + /** + * Saves the current properties to the stack + */ + public void saveProperties() { + propStack.add(prop); + prop = new HwmfDrawProperties(prop); + } + + /** + * Restores the properties from the stack + * + * @param index if the index is positive, the n-th element from the start is activated. + * If the index is negative, the n-th previous element relative to the current properties element is activated. + */ + public void restoreProperties(int index) { + if (index == 0) { + return; + } + int stackIndex = index; + if (stackIndex < 0) { + int curIdx = propStack.indexOf(prop); + if (curIdx == -1) { + // the current element is not pushed to the stacked, i.e. it's the last + curIdx = propStack.size(); + } + stackIndex = curIdx + index; + } + if (stackIndex == -1) { + // roll to last when curIdx == 0 + stackIndex = propStack.size()-1; + } + prop = propStack.get(stackIndex); + } + + /** + * After setting various window and viewport related properties, + * the underlying graphics context needs to be adapted. + * This methods gathers and sets the corresponding graphics transformations. + */ + public void updateWindowMapMode() { + Rectangle2D win = prop.getWindow(); + HwmfMapMode mapMode = prop.getMapMode(); + graphicsCtx.setTransform(initialAT); + + switch (mapMode) { + default: + case MM_ANISOTROPIC: + // scale window bounds to output bounds + graphicsCtx.scale(bbox.getWidth()/win.getWidth(), bbox.getHeight()/win.getHeight()); + graphicsCtx.translate(-win.getX(), -win.getY()); + break; + case MM_ISOTROPIC: + // TODO: to be validated ... + // like anisotropic, but use x-axis as reference + graphicsCtx.scale(bbox.getWidth()/win.getWidth(), bbox.getWidth()/win.getWidth()); + graphicsCtx.translate(-win.getX(), -win.getY()); + break; + case MM_LOMETRIC: + case MM_HIMETRIC: + case MM_LOENGLISH: + case MM_HIENGLISH: + case MM_TWIPS: { + // TODO: to be validated ... + GraphicsConfiguration gc = graphicsCtx.getDeviceConfiguration(); + graphicsCtx.transform(gc.getNormalizingTransform()); + graphicsCtx.scale(1./mapMode.scale, -1./mapMode.scale); + graphicsCtx.translate(-win.getX(), -win.getY()); + break; + } + case MM_TEXT: + // TODO: to be validated ... + break; + } + } + + public void drawString(byte[] text, Rectangle2D bounds) { + drawString(text, bounds, null); + } + + public void drawString(byte[] text, Rectangle2D bounds, int dx[]) { + HwmfFont font = prop.getFont(); + if (font == null || text == null || text.length == 0) { + return; + } + + double fontH = getFontHeight(font); + // TODO: another approx. ... + double fontW = fontH/1.8; + + int len = text.length; + Charset charset = (font.getCharSet().getCharset() == null)? + DEFAULT_CHARSET : font.getCharSet().getCharset(); + String textString = new String(text, charset); + AttributedString as = new AttributedString(textString); + if (dx == null || dx.length == 0) { + addAttributes(as, font); + } else { + int[] dxNormed = dx; + //for multi-byte encodings (e.g. Shift_JIS), the byte length + //might not equal the string length(). + //The x information is stored in dx[], an array parallel to the + //byte array text[]. dx[] stores the x info in the + //first byte of a multibyte character, but dx[] stores 0 + //for the other bytes in that character. + //We need to map this information to the String offsets + //dx[0] = 13 text[0] = -125 + //dx[1] = 0 text[1] = 118 + //dx[2] = 14 text[2] = -125 + //dx[3] = 0 text[3] = -115 + // needs to be remapped as: + //dxNormed[0] = 13 textString.get(0) = U+30D7 + //dxNormed[1] = 14 textString.get(1) = U+30ED + if (textString.length() != text.length) { + int codePoints = textString.codePointCount(0, textString.length()); + dxNormed = new int[codePoints]; + int dxPosition = 0; + for (int offset = 0; offset < textString.length(); ) { + dxNormed[offset] = dx[dxPosition]; + int[] chars = new int[1]; + int cp = textString.codePointAt(offset); + chars[0] = cp; + //now figure out how many bytes it takes to encode that + //code point in the charset + int byteLength = new String(chars, 0, chars.length).getBytes(charset).length; + dxPosition += byteLength; + offset += Character.charCount(cp); + } + } + for (int i = 0; i < dxNormed.length; i++) { + addAttributes(as, font); + // Tracking works as a prefix/advance space on characters whereas + // dx[...] is the complete width of the current char + // therefore we need to add the additional/suffix width to the next char + if (i < dxNormed.length - 1) { + as.addAttribute(TextAttribute.TRACKING, (dxNormed[i] - fontW) / fontH, i + 1, i + 2); + } + } + } + + + double angle = Math.toRadians(-font.getEscapement()/10.); + + + final AffineTransform at = graphicsCtx.getTransform(); + try { + graphicsCtx.translate(bounds.getX(), bounds.getY()+fontH); + graphicsCtx.rotate(angle); + if (prop.getBkMode() == HwmfBkMode.OPAQUE) { + // TODO: validate bounds + graphicsCtx.setBackground(prop.getBackgroundColor().getColor()); + graphicsCtx.fill(new Rectangle2D.Double(0, 0, bounds.getWidth(), bounds.getHeight())); + } + graphicsCtx.setColor(prop.getTextColor().getColor()); + graphicsCtx.drawString(as.getIterator(), 0, 0); // (float)bounds.getX(), (float)bounds.getY()); + } finally { + graphicsCtx.setTransform(at); + } + } + + private void addAttributes(AttributedString as, HwmfFont font) { + DrawFontManager fontHandler = (DrawFontManager)graphicsCtx.getRenderingHint(Drawable.FONT_HANDLER); + String fontFamily = null; + @SuppressWarnings("unchecked") + Map fontMap = (Map)graphicsCtx.getRenderingHint(Drawable.FONT_MAP); + if (fontMap != null && fontMap.containsKey(font.getFacename())) { + fontFamily = fontMap.get(font.getFacename()); + } + if (fontHandler != null) { + fontFamily = fontHandler.getRendererableFont(font.getFacename(), font.getPitchAndFamily()); + } + if (fontFamily == null) { + fontFamily = font.getFacename(); + } + + as.addAttribute(TextAttribute.FAMILY, fontFamily); + as.addAttribute(TextAttribute.SIZE, getFontHeight(font)); + as.addAttribute(TextAttribute.STRIKETHROUGH, font.isStrikeOut()); + if (font.isUnderline()) { + as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); + } + if (font.isItalic()) { + as.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE); + } + as.addAttribute(TextAttribute.WEIGHT, font.getWeight()); + } + + private double getFontHeight(HwmfFont font) { + // see HwmfFont#height for details + double fontHeight = font.getHeight(); + if (fontHeight == 0) { + return 12; + } else if (fontHeight < 0) { + return -fontHeight; + } else { + // TODO: fix font height calculation + // the height is given as font size + ascent + descent + // as an approximation we reduce the height by a static factor + return fontHeight*3/4; + } + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfSLImageRenderer.java b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfSLImageRenderer.java index 9a785d06f3..34a677fa29 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfSLImageRenderer.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfSLImageRenderer.java @@ -1,124 +1,124 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.draw; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.RenderingHints; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.RescaleOp; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.hwmf.usermodel.HwmfPicture; -import org.apache.poi.sl.draw.DrawPictureShape; -import org.apache.poi.sl.draw.ImageRenderer; -import org.apache.poi.sl.usermodel.PictureData; -import org.apache.poi.util.Units; - -/** - * Helper class which is instantiated by {@link DrawPictureShape} - * via reflection - */ -public class HwmfSLImageRenderer implements ImageRenderer { - HwmfPicture image = null; - double alpha = 0; - - @Override - public void loadImage(InputStream data, String contentType) throws IOException { - if (!PictureData.PictureType.WMF.contentType.equals(contentType)) { - throw new IOException("Invalid picture type"); - } - image = new HwmfPicture(data); - } - - @Override - public void loadImage(byte[] data, String contentType) throws IOException { - if (!PictureData.PictureType.WMF.contentType.equals(contentType)) { - throw new IOException("Invalid picture type"); - } - image = new HwmfPicture(new ByteArrayInputStream(data)); - } - - @Override - public Dimension getDimension() { - int width = 0, height = 0; - if (image != null) { - Dimension dim = image.getSize(); - width = Units.pointsToPixel(dim.getWidth()); - // keep aspect ratio for height - height = Units.pointsToPixel(dim.getHeight()); - } - return new Dimension(width, height); - } - - @Override - public void setAlpha(double alpha) { - this.alpha = alpha; - } - - @Override - public BufferedImage getImage() { - return getImage(getDimension()); - } - - @Override - public BufferedImage getImage(Dimension dim) { - if (image == null) { - return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); - } - - BufferedImage bufImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics2D g = bufImg.createGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - image.draw(g, new Rectangle2D.Double(0,0,dim.getWidth(),dim.getHeight())); - g.dispose(); - - if (alpha != 0) { - BufferedImage newImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); - g = newImg.createGraphics(); - RescaleOp op = new RescaleOp(new float[]{1.0f, 1.0f, 1.0f, (float)alpha}, new float[]{0,0,0,0}, null); - g.drawImage(bufImg, op, 0, 0); - g.dispose(); - bufImg = newImg; - } - - return bufImg; - } - - @Override - public boolean drawImage(Graphics2D graphics, Rectangle2D anchor) { - return drawImage(graphics, anchor, null); - } - - @Override - public boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip) { - if (image == null) { - return false; - } else { - image.draw(graphics, anchor); - return true; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.draw; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.RescaleOp; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.hwmf.usermodel.HwmfPicture; +import org.apache.poi.sl.draw.DrawPictureShape; +import org.apache.poi.sl.draw.ImageRenderer; +import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.util.Units; + +/** + * Helper class which is instantiated by {@link DrawPictureShape} + * via reflection + */ +public class HwmfSLImageRenderer implements ImageRenderer { + HwmfPicture image = null; + double alpha = 0; + + @Override + public void loadImage(InputStream data, String contentType) throws IOException { + if (!PictureData.PictureType.WMF.contentType.equals(contentType)) { + throw new IOException("Invalid picture type"); + } + image = new HwmfPicture(data); + } + + @Override + public void loadImage(byte[] data, String contentType) throws IOException { + if (!PictureData.PictureType.WMF.contentType.equals(contentType)) { + throw new IOException("Invalid picture type"); + } + image = new HwmfPicture(new ByteArrayInputStream(data)); + } + + @Override + public Dimension getDimension() { + int width = 0, height = 0; + if (image != null) { + Dimension dim = image.getSize(); + width = Units.pointsToPixel(dim.getWidth()); + // keep aspect ratio for height + height = Units.pointsToPixel(dim.getHeight()); + } + return new Dimension(width, height); + } + + @Override + public void setAlpha(double alpha) { + this.alpha = alpha; + } + + @Override + public BufferedImage getImage() { + return getImage(getDimension()); + } + + @Override + public BufferedImage getImage(Dimension dim) { + if (image == null) { + return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + } + + BufferedImage bufImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g = bufImg.createGraphics(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + image.draw(g, new Rectangle2D.Double(0,0,dim.getWidth(),dim.getHeight())); + g.dispose(); + + if (alpha != 0) { + BufferedImage newImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); + g = newImg.createGraphics(); + RescaleOp op = new RescaleOp(new float[]{1.0f, 1.0f, 1.0f, (float)alpha}, new float[]{0,0,0,0}, null); + g.drawImage(bufImg, op, 0, 0); + g.dispose(); + bufImg = newImg; + } + + return bufImg; + } + + @Override + public boolean drawImage(Graphics2D graphics, Rectangle2D anchor) { + return drawImage(graphics, anchor, null); + } + + @Override + public boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip) { + if (image == null) { + return false; + } else { + image.draw(graphics, anchor); + return true; + } + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBinaryRasterOp.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBinaryRasterOp.java index 31ddcd76e8..a4fb1cb353 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBinaryRasterOp.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBinaryRasterOp.java @@ -1,112 +1,112 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -/** - * The BinaryRasterOperation Enumeration section lists the binary raster-operation codes. - * Rasteroperation codes define how metafile processing combines the bits from the selected - * pen with the bits in the destination bitmap. - * - * Each raster-operation code represents a Boolean operation in which the values of the pixels in the - * selected pen and the destination bitmap are combined. Following are the two operands used in these - * operations. - * - * - * - * - * - *
    OperandMeaning
    PSelected pen
    DDestination bitmap
    - * - * Following are the Boolean operators used in these operations. - * - * - * - * - * - * - *
    OperandMeaning
    aBitwise AND
    nBitwise NOT (inverse)
    oBitwise OR
    xBitwise exclusive OR (XOR)
    - * - * All Boolean operations are presented in reverse Polish notation. For example, the following - * operation replaces the values of the pixels in the destination bitmap with a combination of the pixel - * values of the pen and the selected brush: DPo. - * - * Each raster-operation code is a 32-bit integer whose high-order word is a Boolean operation index and - * whose low-order word is the operation code. The 16-bit operation index is a zero-extended, 8-bit - * value that represents all possible outcomes resulting from the Boolean operation on two parameters - * (in this case, the pen and destination values). For example, the operation indexes for the DPo and - * DPan operations are shown in the following list. - * - * - * - * - * - * - * - *
    PDDPoDPan
    0001
    0111
    1011
    1110
    - * - */ -public enum HwmfBinaryRasterOp { - /** 0, Pixel is always 0 */ - R2_BLACK(0x0001), - /** DPon, Pixel is the inverse of the R2_MERGEPEN color. */ - R2_NOTMERGEPEN(0x0002), - /** DPna, Pixel is a combination of the screen color and the inverse of the pen color. */ - R2_MASKNOTPEN(0x0003), - /** Pn, Pixel is the inverse of the pen color. */ - R2_NOTCOPYPEN(0x0004), - /** PDna, Pixel is a combination of the colors common to both the pen and the inverse of the screen. */ - R2_MASKPENNOT(0x0005), - /** Dn, Pixel is the inverse of the screen color. */ - R2_NOT(0x0006), - /** DPx, Pixel is a combination of the colors in the pen or in the screen, but not in both. */ - R2_XORPEN(0x0007), - /** DPan, Pixel is the inverse of the R2_MASKPEN color. */ - R2_NOTMASKPEN(0x0008), - /** DPa, Pixel is a combination of the colors common to both the pen and the screen. */ - R2_MASKPEN(0x0009), - /** DPxn, Pixel is the inverse of the R2_XORPEN color. */ - R2_NOTXORPEN(0x000A), - /** D, Pixel remains unchanged. */ - R2_NOP(0x000B), - /** DPno, Pixel is a combination of the colors common to both the screen and the inverse of the pen. */ - R2_MERGENOTPEN(0x000C), - /** P, Pixel is the pen color. */ - R2_COPYPEN(0x000D), - /** PDno, Pixel is a combination of the pen color and the inverse of the screen color.*/ - R2_MERGEPENNOT(0x000E), - /** DPo, Pixel is a combination of the pen color and the screen color. */ - R2_MERGEPEN(0x000F), - /** 1, Pixel is always 1 */ - R2_WHITE(0x0010); - - int opIndex; - - HwmfBinaryRasterOp(int opIndex) { - this.opIndex=opIndex; - } - - public static HwmfBinaryRasterOp valueOf(int opIndex) { - for (HwmfBinaryRasterOp bb : HwmfBinaryRasterOp.values()) { - if (bb.opIndex == opIndex) { - return bb; - } - } - return null; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +/** + * The BinaryRasterOperation Enumeration section lists the binary raster-operation codes. + * Rasteroperation codes define how metafile processing combines the bits from the selected + * pen with the bits in the destination bitmap. + * + * Each raster-operation code represents a Boolean operation in which the values of the pixels in the + * selected pen and the destination bitmap are combined. Following are the two operands used in these + * operations. + * + * + * + * + * + *
    OperandMeaning
    PSelected pen
    DDestination bitmap
    + * + * Following are the Boolean operators used in these operations. + * + * + * + * + * + * + *
    OperandMeaning
    aBitwise AND
    nBitwise NOT (inverse)
    oBitwise OR
    xBitwise exclusive OR (XOR)
    + * + * All Boolean operations are presented in reverse Polish notation. For example, the following + * operation replaces the values of the pixels in the destination bitmap with a combination of the pixel + * values of the pen and the selected brush: DPo. + * + * Each raster-operation code is a 32-bit integer whose high-order word is a Boolean operation index and + * whose low-order word is the operation code. The 16-bit operation index is a zero-extended, 8-bit + * value that represents all possible outcomes resulting from the Boolean operation on two parameters + * (in this case, the pen and destination values). For example, the operation indexes for the DPo and + * DPan operations are shown in the following list. + * + * + * + * + * + * + * + *
    PDDPoDPan
    0001
    0111
    1011
    1110
    + * + */ +public enum HwmfBinaryRasterOp { + /** 0, Pixel is always 0 */ + R2_BLACK(0x0001), + /** DPon, Pixel is the inverse of the R2_MERGEPEN color. */ + R2_NOTMERGEPEN(0x0002), + /** DPna, Pixel is a combination of the screen color and the inverse of the pen color. */ + R2_MASKNOTPEN(0x0003), + /** Pn, Pixel is the inverse of the pen color. */ + R2_NOTCOPYPEN(0x0004), + /** PDna, Pixel is a combination of the colors common to both the pen and the inverse of the screen. */ + R2_MASKPENNOT(0x0005), + /** Dn, Pixel is the inverse of the screen color. */ + R2_NOT(0x0006), + /** DPx, Pixel is a combination of the colors in the pen or in the screen, but not in both. */ + R2_XORPEN(0x0007), + /** DPan, Pixel is the inverse of the R2_MASKPEN color. */ + R2_NOTMASKPEN(0x0008), + /** DPa, Pixel is a combination of the colors common to both the pen and the screen. */ + R2_MASKPEN(0x0009), + /** DPxn, Pixel is the inverse of the R2_XORPEN color. */ + R2_NOTXORPEN(0x000A), + /** D, Pixel remains unchanged. */ + R2_NOP(0x000B), + /** DPno, Pixel is a combination of the colors common to both the screen and the inverse of the pen. */ + R2_MERGENOTPEN(0x000C), + /** P, Pixel is the pen color. */ + R2_COPYPEN(0x000D), + /** PDno, Pixel is a combination of the pen color and the inverse of the screen color.*/ + R2_MERGEPENNOT(0x000E), + /** DPo, Pixel is a combination of the pen color and the screen color. */ + R2_MERGEPEN(0x000F), + /** 1, Pixel is always 1 */ + R2_WHITE(0x0010); + + int opIndex; + + HwmfBinaryRasterOp(int opIndex) { + this.opIndex=opIndex; + } + + public static HwmfBinaryRasterOp valueOf(int opIndex) { + for (HwmfBinaryRasterOp bb : HwmfBinaryRasterOp.values()) { + if (bb.opIndex == opIndex) { + return bb; + } + } + return null; + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java index 6212a0d6ab..09bbb9f16e 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java @@ -1,88 +1,88 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.awt.image.BufferedImage; -import java.io.IOException; - -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; - -public class HwmfBitmap16 { - final boolean isPartial; - int type; - int width; - int height; - int widthBytes; - int planes; - int bitsPixel; - - public HwmfBitmap16() { - this(false); - } - - public HwmfBitmap16(boolean isPartial) { - this.isPartial = isPartial; - } - - public int init(LittleEndianInputStream leis) throws IOException { - // A 16-bit signed integer that defines the bitmap type. - type = leis.readShort(); - - // A 16-bit signed integer that defines the width of the bitmap in pixels. - width = leis.readShort(); - - // A 16-bit signed integer that defines the height of the bitmap in scan lines. - height = leis.readShort(); - - // A 16-bit signed integer that defines the number of bytes per scan line. - widthBytes = leis.readShort(); - - // An 8-bit unsigned integer that defines the number of color planes in the - // bitmap. The value of this field MUST be 0x01. - planes = leis.readUByte(); - - // An 8-bit unsigned integer that defines the number of adjacent color bits on - // each plane. - bitsPixel = leis.readUByte(); - - int size = 2*LittleEndianConsts.BYTE_SIZE+4*LittleEndianConsts.SHORT_SIZE; - if (isPartial) { - // Bits (4 bytes): This field MUST be ignored. - long skipSize = leis.skip(LittleEndianConsts.INT_SIZE); - assert(skipSize == LittleEndianConsts.INT_SIZE); - // Reserved (18 bytes): This field MUST be ignored. - skipSize = leis.skip(18); - assert(skipSize == 18); - size += 18+LittleEndianConsts.INT_SIZE; - } - - int length = (((width * bitsPixel + 15) >> 4) << 1) * height; - /*byte buf[] =*/ IOUtils.toByteArray(leis, length); - - // TODO: this is not implemented ... please provide a sample, if it - // ever happens to you, to come here ... - - return size; - } - - public BufferedImage getImage() { - return new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.awt.image.BufferedImage; +import java.io.IOException; + +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; + +public class HwmfBitmap16 { + final boolean isPartial; + int type; + int width; + int height; + int widthBytes; + int planes; + int bitsPixel; + + public HwmfBitmap16() { + this(false); + } + + public HwmfBitmap16(boolean isPartial) { + this.isPartial = isPartial; + } + + public int init(LittleEndianInputStream leis) throws IOException { + // A 16-bit signed integer that defines the bitmap type. + type = leis.readShort(); + + // A 16-bit signed integer that defines the width of the bitmap in pixels. + width = leis.readShort(); + + // A 16-bit signed integer that defines the height of the bitmap in scan lines. + height = leis.readShort(); + + // A 16-bit signed integer that defines the number of bytes per scan line. + widthBytes = leis.readShort(); + + // An 8-bit unsigned integer that defines the number of color planes in the + // bitmap. The value of this field MUST be 0x01. + planes = leis.readUByte(); + + // An 8-bit unsigned integer that defines the number of adjacent color bits on + // each plane. + bitsPixel = leis.readUByte(); + + int size = 2*LittleEndianConsts.BYTE_SIZE+4*LittleEndianConsts.SHORT_SIZE; + if (isPartial) { + // Bits (4 bytes): This field MUST be ignored. + long skipSize = leis.skip(LittleEndianConsts.INT_SIZE); + assert(skipSize == LittleEndianConsts.INT_SIZE); + // Reserved (18 bytes): This field MUST be ignored. + skipSize = leis.skip(18); + assert(skipSize == 18); + size += 18+LittleEndianConsts.INT_SIZE; + } + + int length = (((width * bitsPixel + 15) >> 4) << 1) * height; + /*byte buf[] =*/ IOUtils.toByteArray(leis, length); + + // TODO: this is not implemented ... please provide a sample, if it + // ever happens to you, to come here ... + + return size; + } + + public BufferedImage getImage() { + return new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java index da49d2ebd4..7c590b6b1f 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java @@ -1,418 +1,418 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.imageio.ImageIO; - -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.RecordFormatException; - -/** - * The DeviceIndependentBitmap Object defines an image in device-independent bitmap (DIB) format. - */ -public class HwmfBitmapDib { - public static enum BitCount { - /** - * The image SHOULD be in either JPEG or PNG format. <6> Neither of these formats includes - * a color table, so this value specifies that no color table is present. See [JFIF] and [RFC2083] - * for more information concerning JPEG and PNG compression formats. - */ - BI_BITCOUNT_0(0x0000), - /** - * Each pixel in the bitmap is represented by a single bit. If the bit is clear, the pixel is displayed - * with the color of the first entry in the color table; if the bit is set, the pixel has the color of the - * second entry in the table. - */ - BI_BITCOUNT_1(0x0001), - /** - * Each pixel in the bitmap is represented by a 4-bit index into the color table, and each byte - * contains 2 pixels. - */ - BI_BITCOUNT_2(0x0004), - /** - * Each pixel in the bitmap is represented by an 8-bit index into the color table, and each byte - * contains 1 pixel. - */ - BI_BITCOUNT_3(0x0008), - /** - * Each pixel in the bitmap is represented by a 16-bit value. - *
    - * If the Compression field of the BitmapInfoHeader Object is BI_RGB, the Colors field of DIB - * is NULL. Each WORD in the bitmap array represents a single pixel. The relative intensities of - * red, green, and blue are represented with 5 bits for each color component. The value for blue - * is in the least significant 5 bits, followed by 5 bits each for green and red. The most significant - * bit is not used. The color table is used for optimizing colors on palette-based devices, and - * contains the number of entries specified by the ColorUsed field of the BitmapInfoHeader - * Object. - *
    - * If the Compression field of the BitmapInfoHeader Object is BI_BITFIELDS, the Colors field - * contains three DWORD color masks that specify the red, green, and blue components, - * respectively, of each pixel. Each WORD in the bitmap array represents a single pixel. - *
    - * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask MUST be - * contiguous and SHOULD NOT overlap the bits of another mask. - */ - BI_BITCOUNT_4(0x0010), - /** - * The bitmap has a maximum of 2^24 colors, and the Colors field of DIB is - * NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, - * and red, respectively, for a pixel. The Colors color table is used for optimizing colors used on - * palette-based devices, and MUST contain the number of entries specified by the ColorUsed - * field of the BitmapInfoHeader Object. - */ - BI_BITCOUNT_5(0x0018), - /** - * The bitmap has a maximum of 2^24 colors. - *
    - * If the Compression field of the BitmapInfoHeader Object is set to BI_RGB, the Colors field - * of DIB is set to NULL. Each DWORD in the bitmap array represents the relative intensities of - * blue, green, and red, respectively, for a pixel. The high byte in each DWORD is not used. The - * Colors color table is used for optimizing colors used on palette-based devices, and MUST - * contain the number of entries specified by the ColorUsed field of the BitmapInfoHeader - * Object. - *
    - * If the Compression field of the BitmapInfoHeader Object is set to BI_BITFIELDS, the Colors - * field contains three DWORD color masks that specify the red, green, and blue components, - * respectively, of each pixel. Each DWORD in the bitmap array represents a single pixel. - *
    - * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask must be - * contiguous and should not overlap the bits of another mask. All the bits in the pixel do not - * need to be used. - */ - BI_BITCOUNT_6(0x0020); - - int flag; - BitCount(int flag) { - this.flag = flag; - } - static BitCount valueOf(int flag) { - for (BitCount bc : values()) { - if (bc.flag == flag) return bc; - } - return null; - } - } - - public static enum Compression { - /** - * The bitmap is in uncompressed red green blue (RGB) format that is not compressed - * and does not use color masks. - */ - BI_RGB(0x0000), - /** - * An RGB format that uses run-length encoding (RLE) compression for bitmaps - * with 8 bits per pixel. The compression uses a 2-byte format consisting of a count byte - * followed by a byte containing a color index. - */ - BI_RLE8(0x0001), - /** - * An RGB format that uses RLE compression for bitmaps with 4 bits per pixel. The - * compression uses a 2-byte format consisting of a count byte followed by two word-length - * color indexes. - */ - BI_RLE4(0x0002), - /** - * The bitmap is not compressed and the color table consists of three DWORD - * color masks that specify the red, green, and blue components, respectively, of each pixel. - * This is valid when used with 16 and 32-bits per pixel bitmaps. - */ - BI_BITFIELDS(0x0003), - /** - * The image is a JPEG image, as specified in [JFIF]. This value SHOULD only be used in - * certain bitmap operations, such as JPEG pass-through. The application MUST query for the - * pass-through support, since not all devices support JPEG pass-through. Using non-RGB - * bitmaps MAY limit the portability of the metafile to other devices. For instance, display device - * contexts generally do not support this pass-through. - */ - BI_JPEG(0x0004), - /** - * The image is a PNG image, as specified in [RFC2083]. This value SHOULD only be - * used certain bitmap operations, such as JPEG/PNG pass-through. The application MUST query - * for the pass-through support, because not all devices support JPEG/PNG pass-through. Using - * non-RGB bitmaps MAY limit the portability of the metafile to other devices. For instance, - * display device contexts generally do not support this pass-through. - */ - BI_PNG(0x0005), - /** - * The image is an uncompressed CMYK format. - */ - BI_CMYK(0x000B), - /** - * A CMYK format that uses RLE compression for bitmaps with 8 bits per pixel. - * The compression uses a 2-byte format consisting of a count byte followed by a byte containing - * a color index. - */ - BI_CMYKRLE8(0x000C), - /** - * A CMYK format that uses RLE compression for bitmaps with 4 bits per pixel. - * The compression uses a 2-byte format consisting of a count byte followed by two word-length - * color indexes. - */ - BI_CMYKRLE4(0x000D); - - int flag; - Compression(int flag) { - this.flag = flag; - } - static Compression valueOf(int flag) { - for (Compression c : values()) { - if (c.flag == flag) return c; - } - return null; - } - } - - private final static POILogger logger = POILogFactory.getLogger(HwmfBitmapDib.class); - private static final int BMP_HEADER_SIZE = 14; - - private int headerSize; - private int headerWidth; - private int headerHeight; - private int headerPlanes; - private BitCount headerBitCount; - private Compression headerCompression; - private long headerImageSize = -1; - @SuppressWarnings("unused") - private int headerXPelsPerMeter = -1; - @SuppressWarnings("unused") - private int headerYPelsPerMeter = -1; - private long headerColorUsed = -1; - @SuppressWarnings("unused") - private long headerColorImportant = -1; - private Color colorTable[]; - @SuppressWarnings("unused") - private int colorMaskR=0,colorMaskG=0,colorMaskB=0; - - // size of header and color table, for start of image data calculation - private int introSize; - private byte imageData[]; - - public int init(LittleEndianInputStream leis, int recordSize) throws IOException { - leis.mark(10000); - - // need to read the header to calculate start of bitmap data correct - introSize = readHeader(leis); - assert(introSize == headerSize); - introSize += readColors(leis); - assert(introSize < 10000); - - int fileSize = (headerImageSize < headerSize) ? recordSize : (int)Math.min(introSize+headerImageSize,recordSize); - - leis.reset(); - imageData = IOUtils.toByteArray(leis, fileSize); - - assert( headerSize != 0x0C || ((((headerWidth * headerPlanes * headerBitCount.flag + 31) & ~31) / 8) * Math.abs(headerHeight)) == headerImageSize); - - return fileSize; - } - - protected int readHeader(LittleEndianInputStream leis) throws IOException { - int size = 0; - - /** - * DIBHeaderInfo (variable): Either a BitmapCoreHeader Object or a - * BitmapInfoHeader Object that specifies information about the image. - * - * The first 32 bits of this field is the HeaderSize value. - * If it is 0x0000000C, then this is a BitmapCoreHeader; otherwise, this is a BitmapInfoHeader. - */ - headerSize = leis.readInt(); - size += LittleEndianConsts.INT_SIZE; - - if (headerSize == 0x0C) { - // BitmapCoreHeader - // A 16-bit unsigned integer that defines the width of the DIB, in pixels. - headerWidth = leis.readUShort(); - // A 16-bit unsigned integer that defines the height of the DIB, in pixels. - headerHeight = leis.readUShort(); - // A 16-bit unsigned integer that defines the number of planes for the target - // device. This value MUST be 0x0001. - headerPlanes = leis.readUShort(); - // A 16-bit unsigned integer that defines the format of each pixel, and the - // maximum number of colors in the DIB. - headerBitCount = BitCount.valueOf(leis.readUShort()); - size += 4*LittleEndianConsts.SHORT_SIZE; - } else { - // BitmapInfoHeader - // A 32-bit signed integer that defines the width of the DIB, in pixels. - // This value MUST be positive. - // This field SHOULD specify the width of the decompressed image file, - // if the Compression value specifies JPEG or PNG format. - headerWidth = leis.readInt(); - // A 32-bit signed integer that defines the height of the DIB, in pixels. - // This value MUST NOT be zero. - // - If this value is positive, the DIB is a bottom-up bitmap, - // and its origin is the lower-left corner. - // This field SHOULD specify the height of the decompressed image file, - // if the Compression value specifies JPEG or PNG format. - // - If this value is negative, the DIB is a top-down bitmap, - // and its origin is the upper-left corner. Top-down bitmaps do not support compression. - headerHeight = leis.readInt(); - // A 16-bit unsigned integer that defines the number of planes for the target - // device. This value MUST be 0x0001. - headerPlanes = leis.readUShort(); - // A 16-bit unsigned integer that defines the format of each pixel, and the - // maximum number of colors in the DIB. - headerBitCount = BitCount.valueOf(leis.readUShort()); - // A 32-bit unsigned integer that defines the compression mode of the DIB. - // This value MUST NOT specify a compressed format if the DIB is a top-down bitmap, - // as indicated by the Height value. - headerCompression = Compression.valueOf((int)leis.readUInt()); - // A 32-bit unsigned integer that defines the size, in bytes, of the image. - // If the Compression value is BI_RGB, this value SHOULD be zero and MUST be ignored. - // If the Compression value is BI_JPEG or BI_PNG, this value MUST specify the size of the JPEG - // or PNG image buffer, respectively. - headerImageSize = leis.readUInt(); - // A 32-bit signed integer that defines the horizontal resolution, - // in pixels-per-meter, of the target device for the DIB. - headerXPelsPerMeter = leis.readInt(); - // A 32-bit signed integer that defines the vertical resolution, - headerYPelsPerMeter = leis.readInt(); - // A 32-bit unsigned integer that specifies the number of indexes in the - // color table used by the DIB - // in pixelsper-meter, of the target device for the DIB. - headerColorUsed = leis.readUInt(); - // A 32-bit unsigned integer that defines the number of color indexes that are - // required for displaying the DIB. If this value is zero, all color indexes are required. - headerColorImportant = leis.readUInt(); - size += 8*LittleEndianConsts.INT_SIZE+2*LittleEndianConsts.SHORT_SIZE; - } - assert(size == headerSize); - return size; - } - - protected int readColors(LittleEndianInputStream leis) throws IOException { - switch (headerBitCount) { - default: - case BI_BITCOUNT_0: - // no table - return 0; - case BI_BITCOUNT_1: - // 2 colors - return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 2 : Math.min(headerColorUsed,2))); - case BI_BITCOUNT_2: - // 16 colors - return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 16 : Math.min(headerColorUsed,16))); - case BI_BITCOUNT_3: - // 256 colors - return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 256 : Math.min(headerColorUsed,256))); - case BI_BITCOUNT_4: - switch (headerCompression) { - case BI_RGB: - colorMaskB = 0x1F; - colorMaskG = 0x1F<<5; - colorMaskR = 0x1F<<10; - return 0; - case BI_BITFIELDS: - colorMaskB = leis.readInt(); - colorMaskG = leis.readInt(); - colorMaskR = leis.readInt(); - return 3*LittleEndianConsts.INT_SIZE; - default: - throw new IOException("Invalid compression option ("+headerCompression+") for bitcount ("+headerBitCount+")."); - } - case BI_BITCOUNT_5: - case BI_BITCOUNT_6: - switch (headerCompression) { - case BI_RGB: - colorMaskR=0xFF; - colorMaskG=0xFF; - colorMaskB=0xFF; - return 0; - case BI_BITFIELDS: - colorMaskB = leis.readInt(); - colorMaskG = leis.readInt(); - colorMaskR = leis.readInt(); - return 3*LittleEndianConsts.INT_SIZE; - default: - throw new IOException("Invalid compression option ("+headerCompression+") for bitcount ("+headerBitCount+")."); - } - } - } - - protected int readRGBQuad(LittleEndianInputStream leis, int count) throws IOException { - int size = 0; - colorTable = new Color[count]; - for (int i=0; i Neither of these formats includes + * a color table, so this value specifies that no color table is present. See [JFIF] and [RFC2083] + * for more information concerning JPEG and PNG compression formats. + */ + BI_BITCOUNT_0(0x0000), + /** + * Each pixel in the bitmap is represented by a single bit. If the bit is clear, the pixel is displayed + * with the color of the first entry in the color table; if the bit is set, the pixel has the color of the + * second entry in the table. + */ + BI_BITCOUNT_1(0x0001), + /** + * Each pixel in the bitmap is represented by a 4-bit index into the color table, and each byte + * contains 2 pixels. + */ + BI_BITCOUNT_2(0x0004), + /** + * Each pixel in the bitmap is represented by an 8-bit index into the color table, and each byte + * contains 1 pixel. + */ + BI_BITCOUNT_3(0x0008), + /** + * Each pixel in the bitmap is represented by a 16-bit value. + *
    + * If the Compression field of the BitmapInfoHeader Object is BI_RGB, the Colors field of DIB + * is NULL. Each WORD in the bitmap array represents a single pixel. The relative intensities of + * red, green, and blue are represented with 5 bits for each color component. The value for blue + * is in the least significant 5 bits, followed by 5 bits each for green and red. The most significant + * bit is not used. The color table is used for optimizing colors on palette-based devices, and + * contains the number of entries specified by the ColorUsed field of the BitmapInfoHeader + * Object. + *
    + * If the Compression field of the BitmapInfoHeader Object is BI_BITFIELDS, the Colors field + * contains three DWORD color masks that specify the red, green, and blue components, + * respectively, of each pixel. Each WORD in the bitmap array represents a single pixel. + *
    + * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask MUST be + * contiguous and SHOULD NOT overlap the bits of another mask. + */ + BI_BITCOUNT_4(0x0010), + /** + * The bitmap has a maximum of 2^24 colors, and the Colors field of DIB is + * NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, + * and red, respectively, for a pixel. The Colors color table is used for optimizing colors used on + * palette-based devices, and MUST contain the number of entries specified by the ColorUsed + * field of the BitmapInfoHeader Object. + */ + BI_BITCOUNT_5(0x0018), + /** + * The bitmap has a maximum of 2^24 colors. + *
    + * If the Compression field of the BitmapInfoHeader Object is set to BI_RGB, the Colors field + * of DIB is set to NULL. Each DWORD in the bitmap array represents the relative intensities of + * blue, green, and red, respectively, for a pixel. The high byte in each DWORD is not used. The + * Colors color table is used for optimizing colors used on palette-based devices, and MUST + * contain the number of entries specified by the ColorUsed field of the BitmapInfoHeader + * Object. + *
    + * If the Compression field of the BitmapInfoHeader Object is set to BI_BITFIELDS, the Colors + * field contains three DWORD color masks that specify the red, green, and blue components, + * respectively, of each pixel. Each DWORD in the bitmap array represents a single pixel. + *
    + * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask must be + * contiguous and should not overlap the bits of another mask. All the bits in the pixel do not + * need to be used. + */ + BI_BITCOUNT_6(0x0020); + + int flag; + BitCount(int flag) { + this.flag = flag; + } + static BitCount valueOf(int flag) { + for (BitCount bc : values()) { + if (bc.flag == flag) return bc; + } + return null; + } + } + + public static enum Compression { + /** + * The bitmap is in uncompressed red green blue (RGB) format that is not compressed + * and does not use color masks. + */ + BI_RGB(0x0000), + /** + * An RGB format that uses run-length encoding (RLE) compression for bitmaps + * with 8 bits per pixel. The compression uses a 2-byte format consisting of a count byte + * followed by a byte containing a color index. + */ + BI_RLE8(0x0001), + /** + * An RGB format that uses RLE compression for bitmaps with 4 bits per pixel. The + * compression uses a 2-byte format consisting of a count byte followed by two word-length + * color indexes. + */ + BI_RLE4(0x0002), + /** + * The bitmap is not compressed and the color table consists of three DWORD + * color masks that specify the red, green, and blue components, respectively, of each pixel. + * This is valid when used with 16 and 32-bits per pixel bitmaps. + */ + BI_BITFIELDS(0x0003), + /** + * The image is a JPEG image, as specified in [JFIF]. This value SHOULD only be used in + * certain bitmap operations, such as JPEG pass-through. The application MUST query for the + * pass-through support, since not all devices support JPEG pass-through. Using non-RGB + * bitmaps MAY limit the portability of the metafile to other devices. For instance, display device + * contexts generally do not support this pass-through. + */ + BI_JPEG(0x0004), + /** + * The image is a PNG image, as specified in [RFC2083]. This value SHOULD only be + * used certain bitmap operations, such as JPEG/PNG pass-through. The application MUST query + * for the pass-through support, because not all devices support JPEG/PNG pass-through. Using + * non-RGB bitmaps MAY limit the portability of the metafile to other devices. For instance, + * display device contexts generally do not support this pass-through. + */ + BI_PNG(0x0005), + /** + * The image is an uncompressed CMYK format. + */ + BI_CMYK(0x000B), + /** + * A CMYK format that uses RLE compression for bitmaps with 8 bits per pixel. + * The compression uses a 2-byte format consisting of a count byte followed by a byte containing + * a color index. + */ + BI_CMYKRLE8(0x000C), + /** + * A CMYK format that uses RLE compression for bitmaps with 4 bits per pixel. + * The compression uses a 2-byte format consisting of a count byte followed by two word-length + * color indexes. + */ + BI_CMYKRLE4(0x000D); + + int flag; + Compression(int flag) { + this.flag = flag; + } + static Compression valueOf(int flag) { + for (Compression c : values()) { + if (c.flag == flag) return c; + } + return null; + } + } + + private final static POILogger logger = POILogFactory.getLogger(HwmfBitmapDib.class); + private static final int BMP_HEADER_SIZE = 14; + + private int headerSize; + private int headerWidth; + private int headerHeight; + private int headerPlanes; + private BitCount headerBitCount; + private Compression headerCompression; + private long headerImageSize = -1; + @SuppressWarnings("unused") + private int headerXPelsPerMeter = -1; + @SuppressWarnings("unused") + private int headerYPelsPerMeter = -1; + private long headerColorUsed = -1; + @SuppressWarnings("unused") + private long headerColorImportant = -1; + private Color colorTable[]; + @SuppressWarnings("unused") + private int colorMaskR=0,colorMaskG=0,colorMaskB=0; + + // size of header and color table, for start of image data calculation + private int introSize; + private byte imageData[]; + + public int init(LittleEndianInputStream leis, int recordSize) throws IOException { + leis.mark(10000); + + // need to read the header to calculate start of bitmap data correct + introSize = readHeader(leis); + assert(introSize == headerSize); + introSize += readColors(leis); + assert(introSize < 10000); + + int fileSize = (headerImageSize < headerSize) ? recordSize : (int)Math.min(introSize+headerImageSize,recordSize); + + leis.reset(); + imageData = IOUtils.toByteArray(leis, fileSize); + + assert( headerSize != 0x0C || ((((headerWidth * headerPlanes * headerBitCount.flag + 31) & ~31) / 8) * Math.abs(headerHeight)) == headerImageSize); + + return fileSize; + } + + protected int readHeader(LittleEndianInputStream leis) throws IOException { + int size = 0; + + /** + * DIBHeaderInfo (variable): Either a BitmapCoreHeader Object or a + * BitmapInfoHeader Object that specifies information about the image. + * + * The first 32 bits of this field is the HeaderSize value. + * If it is 0x0000000C, then this is a BitmapCoreHeader; otherwise, this is a BitmapInfoHeader. + */ + headerSize = leis.readInt(); + size += LittleEndianConsts.INT_SIZE; + + if (headerSize == 0x0C) { + // BitmapCoreHeader + // A 16-bit unsigned integer that defines the width of the DIB, in pixels. + headerWidth = leis.readUShort(); + // A 16-bit unsigned integer that defines the height of the DIB, in pixels. + headerHeight = leis.readUShort(); + // A 16-bit unsigned integer that defines the number of planes for the target + // device. This value MUST be 0x0001. + headerPlanes = leis.readUShort(); + // A 16-bit unsigned integer that defines the format of each pixel, and the + // maximum number of colors in the DIB. + headerBitCount = BitCount.valueOf(leis.readUShort()); + size += 4*LittleEndianConsts.SHORT_SIZE; + } else { + // BitmapInfoHeader + // A 32-bit signed integer that defines the width of the DIB, in pixels. + // This value MUST be positive. + // This field SHOULD specify the width of the decompressed image file, + // if the Compression value specifies JPEG or PNG format. + headerWidth = leis.readInt(); + // A 32-bit signed integer that defines the height of the DIB, in pixels. + // This value MUST NOT be zero. + // - If this value is positive, the DIB is a bottom-up bitmap, + // and its origin is the lower-left corner. + // This field SHOULD specify the height of the decompressed image file, + // if the Compression value specifies JPEG or PNG format. + // - If this value is negative, the DIB is a top-down bitmap, + // and its origin is the upper-left corner. Top-down bitmaps do not support compression. + headerHeight = leis.readInt(); + // A 16-bit unsigned integer that defines the number of planes for the target + // device. This value MUST be 0x0001. + headerPlanes = leis.readUShort(); + // A 16-bit unsigned integer that defines the format of each pixel, and the + // maximum number of colors in the DIB. + headerBitCount = BitCount.valueOf(leis.readUShort()); + // A 32-bit unsigned integer that defines the compression mode of the DIB. + // This value MUST NOT specify a compressed format if the DIB is a top-down bitmap, + // as indicated by the Height value. + headerCompression = Compression.valueOf((int)leis.readUInt()); + // A 32-bit unsigned integer that defines the size, in bytes, of the image. + // If the Compression value is BI_RGB, this value SHOULD be zero and MUST be ignored. + // If the Compression value is BI_JPEG or BI_PNG, this value MUST specify the size of the JPEG + // or PNG image buffer, respectively. + headerImageSize = leis.readUInt(); + // A 32-bit signed integer that defines the horizontal resolution, + // in pixels-per-meter, of the target device for the DIB. + headerXPelsPerMeter = leis.readInt(); + // A 32-bit signed integer that defines the vertical resolution, + headerYPelsPerMeter = leis.readInt(); + // A 32-bit unsigned integer that specifies the number of indexes in the + // color table used by the DIB + // in pixelsper-meter, of the target device for the DIB. + headerColorUsed = leis.readUInt(); + // A 32-bit unsigned integer that defines the number of color indexes that are + // required for displaying the DIB. If this value is zero, all color indexes are required. + headerColorImportant = leis.readUInt(); + size += 8*LittleEndianConsts.INT_SIZE+2*LittleEndianConsts.SHORT_SIZE; + } + assert(size == headerSize); + return size; + } + + protected int readColors(LittleEndianInputStream leis) throws IOException { + switch (headerBitCount) { + default: + case BI_BITCOUNT_0: + // no table + return 0; + case BI_BITCOUNT_1: + // 2 colors + return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 2 : Math.min(headerColorUsed,2))); + case BI_BITCOUNT_2: + // 16 colors + return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 16 : Math.min(headerColorUsed,16))); + case BI_BITCOUNT_3: + // 256 colors + return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 256 : Math.min(headerColorUsed,256))); + case BI_BITCOUNT_4: + switch (headerCompression) { + case BI_RGB: + colorMaskB = 0x1F; + colorMaskG = 0x1F<<5; + colorMaskR = 0x1F<<10; + return 0; + case BI_BITFIELDS: + colorMaskB = leis.readInt(); + colorMaskG = leis.readInt(); + colorMaskR = leis.readInt(); + return 3*LittleEndianConsts.INT_SIZE; + default: + throw new IOException("Invalid compression option ("+headerCompression+") for bitcount ("+headerBitCount+")."); + } + case BI_BITCOUNT_5: + case BI_BITCOUNT_6: + switch (headerCompression) { + case BI_RGB: + colorMaskR=0xFF; + colorMaskG=0xFF; + colorMaskB=0xFF; + return 0; + case BI_BITFIELDS: + colorMaskB = leis.readInt(); + colorMaskG = leis.readInt(); + colorMaskR = leis.readInt(); + return 3*LittleEndianConsts.INT_SIZE; + default: + throw new IOException("Invalid compression option ("+headerCompression+") for bitcount ("+headerBitCount+")."); + } + } + } + + protected int readRGBQuad(LittleEndianInputStream leis, int count) throws IOException { + int size = 0; + colorTable = new Color[count]; + for (int i=0; i polyList = new ArrayList(); - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.polyPolygon; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - // see http://secunia.com/gfx/pdf/SA31675_BA.pdf ;) - /** - * A 16-bit unsigned integer that defines the number of polygons in the object. - */ - int numberOfPolygons = leis.readUShort(); - /** - * A NumberOfPolygons array of 16-bit unsigned integers that define the number of - * points for each polygon in the object. - */ - int[] pointsPerPolygon = new int[numberOfPolygons]; - - int size = LittleEndianConsts.SHORT_SIZE; - - for (int i=0; i 0 ? 0 : 360); - if (startAngle < 0) { - startAngle += 360; - } - - boolean fillShape; - int arcClosure; - switch (getRecordType()) { - default: - case arc: - arcClosure = Arc2D.OPEN; - fillShape = false; - break; - case chord: - arcClosure = Arc2D.CHORD; - fillShape = true; - break; - case pie: - arcClosure = Arc2D.PIE; - fillShape = true; - break; - } - - Shape s = new Arc2D.Double(x, y, w, h, startAngle, arcAngle, arcClosure); - if (fillShape) { - ctx.fill(s); - } else { - ctx.draw(s); - } - } - } - - /** - * The META_PIE record draws a pie-shaped wedge bounded by the intersection of an ellipse and two - * radials. The pie is outlined by using the pen and filled by using the brush that are defined in the - * playback device context. - */ - public static class WmfPie extends WmfArc { - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.pie; - } - } - - /** - * The META_CHORD record draws a chord, which is defined by a region bounded by the intersection of - * an ellipse with a line segment. The chord is outlined using the pen and filled using the brush - * that are defined in the playback device context. - */ - public static class WmfChord extends WmfArc { - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.chord; - } - } - - - /** - * The META_SELECTOBJECT record specifies a graphics object for the playback device context. The - * new object replaces the previous object of the same type, unless if the previous object is a palette - * object. If the previous object is a palette object, then the META_SELECTPALETTE record must be - * used instead of the META_SELECTOBJECT record, as the META_SELECTOBJECT record does not - * support replacing the palette object type. - */ - public static class WmfSelectObject implements HwmfRecord { - - /** - * A 16-bit unsigned integer used to index into the WMF Object Table to - * get the object to be selected. - */ - private int objectIndex; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.selectObject; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - objectIndex = leis.readUShort(); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.applyObjectTableEntry(objectIndex); - } - } - - private static int getWindingRule(HwmfGraphics ctx) { - return ctx.getProperties().getPolyfillMode().awtFlag; - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.awt.Shape; +import java.awt.geom.Arc2D; +import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Line2D; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.hwmf.draw.HwmfGraphics; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; + +public class HwmfDraw { + /** + * The META_MOVETO record sets the output position in the playback device context to a specified + * point. + */ + public static class WmfMoveTo implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units. + */ + private int y; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units. + */ + private int x; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.moveTo; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + y = leis.readShort(); + x = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setLocation(x, y); + } + } + + /** + * The META_LINETO record draws a line from the drawing position that is defined in the playback + * device context up to, but not including, the specified point. + */ + public static class WmfLineTo implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the vertical component of the drawing + * destination position, in logical units. + */ + private int y; + + /** + * A 16-bit signed integer that defines the horizontal component of the drawing + * destination position, in logical units. + */ + private int x; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.lineTo; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + y = leis.readShort(); + x = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + Point2D start = ctx.getProperties().getLocation(); + Line2D line = new Line2D.Double(start.getX(), start.getY(), x, y); + ctx.draw(line); + ctx.getProperties().setLocation(x, y); + } + } + + /** + * The META_POLYGON record paints a polygon consisting of two or more vertices connected by + * straight lines. The polygon is outlined by using the pen and filled by using the brush and polygon fill + * mode that are defined in the playback device context. + */ + public static class WmfPolygon implements HwmfRecord { + + private Path2D poly = new Path2D.Double(); + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.polygon; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + /** + * A 16-bit signed integer that defines the number of points in the array. + */ + int numberofPoints = leis.readShort(); + + for (int i=0; i polyList = new ArrayList(); + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.polyPolygon; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + // see http://secunia.com/gfx/pdf/SA31675_BA.pdf ;) + /** + * A 16-bit unsigned integer that defines the number of polygons in the object. + */ + int numberOfPolygons = leis.readUShort(); + /** + * A NumberOfPolygons array of 16-bit unsigned integers that define the number of + * points for each polygon in the object. + */ + int[] pointsPerPolygon = new int[numberOfPolygons]; + + int size = LittleEndianConsts.SHORT_SIZE; + + for (int i=0; i 0 ? 0 : 360); + if (startAngle < 0) { + startAngle += 360; + } + + boolean fillShape; + int arcClosure; + switch (getRecordType()) { + default: + case arc: + arcClosure = Arc2D.OPEN; + fillShape = false; + break; + case chord: + arcClosure = Arc2D.CHORD; + fillShape = true; + break; + case pie: + arcClosure = Arc2D.PIE; + fillShape = true; + break; + } + + Shape s = new Arc2D.Double(x, y, w, h, startAngle, arcAngle, arcClosure); + if (fillShape) { + ctx.fill(s); + } else { + ctx.draw(s); + } + } + } + + /** + * The META_PIE record draws a pie-shaped wedge bounded by the intersection of an ellipse and two + * radials. The pie is outlined by using the pen and filled by using the brush that are defined in the + * playback device context. + */ + public static class WmfPie extends WmfArc { + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.pie; + } + } + + /** + * The META_CHORD record draws a chord, which is defined by a region bounded by the intersection of + * an ellipse with a line segment. The chord is outlined using the pen and filled using the brush + * that are defined in the playback device context. + */ + public static class WmfChord extends WmfArc { + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.chord; + } + } + + + /** + * The META_SELECTOBJECT record specifies a graphics object for the playback device context. The + * new object replaces the previous object of the same type, unless if the previous object is a palette + * object. If the previous object is a palette object, then the META_SELECTPALETTE record must be + * used instead of the META_SELECTOBJECT record, as the META_SELECTOBJECT record does not + * support replacing the palette object type. + */ + public static class WmfSelectObject implements HwmfRecord { + + /** + * A 16-bit unsigned integer used to index into the WMF Object Table to + * get the object to be selected. + */ + private int objectIndex; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.selectObject; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + objectIndex = leis.readUShort(); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.applyObjectTableEntry(objectIndex); + } + } + + private static int getWindingRule(HwmfGraphics ctx) { + return ctx.getProperties().getPolyfillMode().awtFlag; + } + } diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java index c1714674a1..6c7ef213b0 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java @@ -1,212 +1,212 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.io.IOException; - -import org.apache.poi.hwmf.draw.HwmfGraphics; -import org.apache.poi.util.HexDump; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; - -/** - * The MetafileEscapes specifies printer driver functionality that - * might not be directly accessible through WMF records - */ -public class HwmfEscape implements HwmfRecord { - - public enum EscapeFunction { - /** Notifies the printer driver that the application has finished writing to a page. */ - NEWFRAME(0x0001), - /** Stops processing the current document. */ - ABORTDOC(0x0002), - /** Notifies the printer driver that the application has finished writing to a band. */ - NEXTBAND(0x0003), - /** Sets color table values. */ - SETCOLORTABLE(0x0004), - /** Gets color table values. */ - GETCOLORTABLE(0x0005), - /** Causes all pending output to be flushed to the output device. */ - FLUSHOUT(0x0006), - /** Indicates that the printer driver SHOULD print text only, and no graphics. */ - DRAFTMODE(0x0007), - /** Queries a printer driver to determine whether a specific escape function is supported on the output device it drives. */ - QUERYESCSUPPORT(0x0008), - /** Sets the application-defined function that allows a print job to be canceled during printing. */ - SETABORTPROC(0x0009), - /** Notifies the printer driver that a new print job is starting. */ - STARTDOC(0x000A), - /** Notifies the printer driver that the current print job is ending. */ - ENDDOC(0x000B), - /** Retrieves the physical page size currently selected on an output device. */ - GETPHYSPAGESIZE(0x000C), - /** Retrieves the offset from the upper-left corner of the physical page where the actual printing or drawing begins. */ - GETPRINTINGOFFSET(0x000D), - /** Retrieves the scaling factors for the x-axis and the y-axis of a printer. */ - GETSCALINGFACTOR(0x000E), - /** Used to embed an enhanced metafile format (EMF) metafile within a WMF metafile. */ - META_ESCAPE_ENHANCED_METAFILE(0x000F), - /** Sets the width of a pen in pixels. */ - SETPENWIDTH(0x0010), - /** Sets the number of copies. */ - SETCOPYCOUNT(0x0011), - /** Sets the source, such as a particular paper tray or bin on a printer, for output forms. */ - SETPAPERSOURCE(0x0012), - /** This record passes through arbitrary data. */ - PASSTHROUGH(0x0013), - /** Gets information concerning graphics technology that is supported on a device. */ - GETTECHNOLOGY(0x0014), - /** Specifies the line-drawing mode to use in output to a device. */ - SETLINECAP(0x0015), - /** Specifies the line-joining mode to use in output to a device. */ - SETLINEJOIN(0x0016), - /** Sets the limit for the length of miter joins to use in output to a device. */ - SETMITERLIMIT(0x0017), - /** Retrieves or specifies settings concerning banding on a device, such as the number of bands. */ - BANDINFO(0x0018), - /** Draws a rectangle with a defined pattern. */ - DRAWPATTERNRECT(0x0019), - /** Retrieves the physical pen size currently defined on a device. */ - GETVECTORPENSIZE(0x001A), - /** Retrieves the physical brush size currently defined on a device. */ - GETVECTORBRUSHSIZE(0x001B), - /** Enables or disables double-sided (duplex) printing on a device. */ - ENABLEDUPLEX(0x001C), - /** Retrieves or specifies the source of output forms on a device. */ - GETSETPAPERBINS(0x001D), - /** Retrieves or specifies the paper orientation on a device. */ - GETSETPRINTORIENT(0x001E), - /** Retrieves information concerning the sources of different forms on an output device. */ - ENUMPAPERBINS(0x001F), - /** Specifies the scaling of device-independent bitmaps (DIBs). */ - SETDIBSCALING(0x0020), - /** Indicates the start and end of an encapsulated PostScript (EPS) section. */ - EPSPRINTING(0x0021), - /** Queries a printer driver for paper dimensions and other forms data. */ - ENUMPAPERMETRICS(0x0022), - /** Retrieves or specifies paper dimensions and other forms data on an output device. */ - GETSETPAPERMETRICS(0x0023), - /** Sends arbitrary PostScript data to an output device. */ - POSTSCRIPT_DATA(0x0025), - /** Notifies an output device to ignore PostScript data. */ - POSTSCRIPT_IGNORE(0x0026), - /** Gets the device units currently configured on an output device. */ - GETDEVICEUNITS(0x002A), - /** Gets extended text metrics currently configured on an output device. */ - GETEXTENDEDTEXTMETRICS(0x0100), - /** Gets the font kern table currently defined on an output device. */ - GETPAIRKERNTABLE(0x0102), - /** Draws text using the currently selected font, background color, and text color. */ - EXTTEXTOUT(0x0200), - /** Gets the font face name currently configured on a device. */ - GETFACENAME(0x0201), - /** Sets the font face name on a device. */ - DOWNLOADFACE(0x0202), - /** Queries a printer driver about the support for metafiles on an output device. */ - METAFILE_DRIVER(0x0801), - /** Queries the printer driver about its support for DIBs on an output device. */ - QUERYDIBSUPPORT(0x0C01), - /** Opens a path. */ - BEGIN_PATH(0x1000), - /** Defines a clip region that is bounded by a path. The input MUST be a 16-bit quantity that defines the action to take. */ - CLIP_TO_PATH(0x1001), - /** Ends a path. */ - END_PATH(0x1002), - /** The same as STARTDOC specified with a NULL document and output filename, data in raw mode, and a type of zero. */ - OPEN_CHANNEL(0x100E), - /** Instructs the printer driver to download sets of PostScript procedures. */ - DOWNLOADHEADER(0x100F), - /** The same as ENDDOC. See OPEN_CHANNEL. */ - CLOSE_CHANNEL(0x1010), - /** Sends arbitrary data directly to a printer driver, which is expected to process this data only when in PostScript mode. */ - POSTSCRIPT_PASSTHROUGH(0x1013), - /** Sends arbitrary data directly to the printer driver. */ - ENCAPSULATED_POSTSCRIPT(0x1014), - /** Sets the printer driver to either PostScript or GDI mode. */ - POSTSCRIPT_IDENTIFY(0x1015), - /** Inserts a block of raw data into a PostScript stream. The input MUST be - a 32-bit quantity specifying the number of bytes to inject, a 16-bit quantity specifying the - injection point, and a 16-bit quantity specifying the page number, followed by the bytes to - inject. */ - POSTSCRIPT_INJECTION(0x1016), - /** Checks whether the printer supports a JPEG image. */ - CHECKJPEGFORMAT(0x1017), - /** Checks whether the printer supports a PNG image */ - CHECKPNGFORMAT(0x1018), - /** Gets information on a specified feature setting for a PostScript printer driver. */ - GET_PS_FEATURESETTING(0x1019), - /** Enables applications to write documents to a file or to a printer in XML Paper Specification (XPS) format. */ - MXDC_ESCAPE(0x101A), - /** Enables applications to include private procedures and other arbitrary data in documents. */ - SPCLPASSTHROUGH2(0x11D8); - - int flag; - EscapeFunction(int flag) { - this.flag = flag; - } - - static EscapeFunction valueOf(int flag) { - for (EscapeFunction hs : values()) { - if (hs.flag == flag) return hs; - } - return null; - } - } - - /** - * A 16-bit unsigned integer that defines the escape function. The - * value MUST be from the MetafileEscapes enumeration. - */ - private EscapeFunction escapeFunction; - /** - * A 16-bit unsigned integer that specifies the size, in bytes, of the - * EscapeData field. - */ - private int byteCount; - /** - * An array of bytes of size ByteCount. - */ - private byte escapeData[]; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.escape; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - escapeFunction = EscapeFunction.valueOf(leis.readUShort()); - byteCount = leis.readUShort(); - escapeData = IOUtils.toByteArray(leis,byteCount); - - return 2*LittleEndianConsts.SHORT_SIZE+byteCount; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("escape - function: "+escapeFunction+"\n"); - sb.append(HexDump.dump(escapeData, 0, 0)); - return sb.toString(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.io.IOException; + +import org.apache.poi.hwmf.draw.HwmfGraphics; +import org.apache.poi.util.HexDump; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; + +/** + * The MetafileEscapes specifies printer driver functionality that + * might not be directly accessible through WMF records + */ +public class HwmfEscape implements HwmfRecord { + + public enum EscapeFunction { + /** Notifies the printer driver that the application has finished writing to a page. */ + NEWFRAME(0x0001), + /** Stops processing the current document. */ + ABORTDOC(0x0002), + /** Notifies the printer driver that the application has finished writing to a band. */ + NEXTBAND(0x0003), + /** Sets color table values. */ + SETCOLORTABLE(0x0004), + /** Gets color table values. */ + GETCOLORTABLE(0x0005), + /** Causes all pending output to be flushed to the output device. */ + FLUSHOUT(0x0006), + /** Indicates that the printer driver SHOULD print text only, and no graphics. */ + DRAFTMODE(0x0007), + /** Queries a printer driver to determine whether a specific escape function is supported on the output device it drives. */ + QUERYESCSUPPORT(0x0008), + /** Sets the application-defined function that allows a print job to be canceled during printing. */ + SETABORTPROC(0x0009), + /** Notifies the printer driver that a new print job is starting. */ + STARTDOC(0x000A), + /** Notifies the printer driver that the current print job is ending. */ + ENDDOC(0x000B), + /** Retrieves the physical page size currently selected on an output device. */ + GETPHYSPAGESIZE(0x000C), + /** Retrieves the offset from the upper-left corner of the physical page where the actual printing or drawing begins. */ + GETPRINTINGOFFSET(0x000D), + /** Retrieves the scaling factors for the x-axis and the y-axis of a printer. */ + GETSCALINGFACTOR(0x000E), + /** Used to embed an enhanced metafile format (EMF) metafile within a WMF metafile. */ + META_ESCAPE_ENHANCED_METAFILE(0x000F), + /** Sets the width of a pen in pixels. */ + SETPENWIDTH(0x0010), + /** Sets the number of copies. */ + SETCOPYCOUNT(0x0011), + /** Sets the source, such as a particular paper tray or bin on a printer, for output forms. */ + SETPAPERSOURCE(0x0012), + /** This record passes through arbitrary data. */ + PASSTHROUGH(0x0013), + /** Gets information concerning graphics technology that is supported on a device. */ + GETTECHNOLOGY(0x0014), + /** Specifies the line-drawing mode to use in output to a device. */ + SETLINECAP(0x0015), + /** Specifies the line-joining mode to use in output to a device. */ + SETLINEJOIN(0x0016), + /** Sets the limit for the length of miter joins to use in output to a device. */ + SETMITERLIMIT(0x0017), + /** Retrieves or specifies settings concerning banding on a device, such as the number of bands. */ + BANDINFO(0x0018), + /** Draws a rectangle with a defined pattern. */ + DRAWPATTERNRECT(0x0019), + /** Retrieves the physical pen size currently defined on a device. */ + GETVECTORPENSIZE(0x001A), + /** Retrieves the physical brush size currently defined on a device. */ + GETVECTORBRUSHSIZE(0x001B), + /** Enables or disables double-sided (duplex) printing on a device. */ + ENABLEDUPLEX(0x001C), + /** Retrieves or specifies the source of output forms on a device. */ + GETSETPAPERBINS(0x001D), + /** Retrieves or specifies the paper orientation on a device. */ + GETSETPRINTORIENT(0x001E), + /** Retrieves information concerning the sources of different forms on an output device. */ + ENUMPAPERBINS(0x001F), + /** Specifies the scaling of device-independent bitmaps (DIBs). */ + SETDIBSCALING(0x0020), + /** Indicates the start and end of an encapsulated PostScript (EPS) section. */ + EPSPRINTING(0x0021), + /** Queries a printer driver for paper dimensions and other forms data. */ + ENUMPAPERMETRICS(0x0022), + /** Retrieves or specifies paper dimensions and other forms data on an output device. */ + GETSETPAPERMETRICS(0x0023), + /** Sends arbitrary PostScript data to an output device. */ + POSTSCRIPT_DATA(0x0025), + /** Notifies an output device to ignore PostScript data. */ + POSTSCRIPT_IGNORE(0x0026), + /** Gets the device units currently configured on an output device. */ + GETDEVICEUNITS(0x002A), + /** Gets extended text metrics currently configured on an output device. */ + GETEXTENDEDTEXTMETRICS(0x0100), + /** Gets the font kern table currently defined on an output device. */ + GETPAIRKERNTABLE(0x0102), + /** Draws text using the currently selected font, background color, and text color. */ + EXTTEXTOUT(0x0200), + /** Gets the font face name currently configured on a device. */ + GETFACENAME(0x0201), + /** Sets the font face name on a device. */ + DOWNLOADFACE(0x0202), + /** Queries a printer driver about the support for metafiles on an output device. */ + METAFILE_DRIVER(0x0801), + /** Queries the printer driver about its support for DIBs on an output device. */ + QUERYDIBSUPPORT(0x0C01), + /** Opens a path. */ + BEGIN_PATH(0x1000), + /** Defines a clip region that is bounded by a path. The input MUST be a 16-bit quantity that defines the action to take. */ + CLIP_TO_PATH(0x1001), + /** Ends a path. */ + END_PATH(0x1002), + /** The same as STARTDOC specified with a NULL document and output filename, data in raw mode, and a type of zero. */ + OPEN_CHANNEL(0x100E), + /** Instructs the printer driver to download sets of PostScript procedures. */ + DOWNLOADHEADER(0x100F), + /** The same as ENDDOC. See OPEN_CHANNEL. */ + CLOSE_CHANNEL(0x1010), + /** Sends arbitrary data directly to a printer driver, which is expected to process this data only when in PostScript mode. */ + POSTSCRIPT_PASSTHROUGH(0x1013), + /** Sends arbitrary data directly to the printer driver. */ + ENCAPSULATED_POSTSCRIPT(0x1014), + /** Sets the printer driver to either PostScript or GDI mode. */ + POSTSCRIPT_IDENTIFY(0x1015), + /** Inserts a block of raw data into a PostScript stream. The input MUST be + a 32-bit quantity specifying the number of bytes to inject, a 16-bit quantity specifying the + injection point, and a 16-bit quantity specifying the page number, followed by the bytes to + inject. */ + POSTSCRIPT_INJECTION(0x1016), + /** Checks whether the printer supports a JPEG image. */ + CHECKJPEGFORMAT(0x1017), + /** Checks whether the printer supports a PNG image */ + CHECKPNGFORMAT(0x1018), + /** Gets information on a specified feature setting for a PostScript printer driver. */ + GET_PS_FEATURESETTING(0x1019), + /** Enables applications to write documents to a file or to a printer in XML Paper Specification (XPS) format. */ + MXDC_ESCAPE(0x101A), + /** Enables applications to include private procedures and other arbitrary data in documents. */ + SPCLPASSTHROUGH2(0x11D8); + + int flag; + EscapeFunction(int flag) { + this.flag = flag; + } + + static EscapeFunction valueOf(int flag) { + for (EscapeFunction hs : values()) { + if (hs.flag == flag) return hs; + } + return null; + } + } + + /** + * A 16-bit unsigned integer that defines the escape function. The + * value MUST be from the MetafileEscapes enumeration. + */ + private EscapeFunction escapeFunction; + /** + * A 16-bit unsigned integer that specifies the size, in bytes, of the + * EscapeData field. + */ + private int byteCount; + /** + * An array of bytes of size ByteCount. + */ + private byte escapeData[]; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.escape; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + escapeFunction = EscapeFunction.valueOf(leis.readUShort()); + byteCount = leis.readUShort(); + escapeData = IOUtils.toByteArray(leis,byteCount); + + return 2*LittleEndianConsts.SHORT_SIZE+byteCount; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("escape - function: "+escapeFunction+"\n"); + sb.append(HexDump.dump(escapeData, 0, 0)); + return sb.toString(); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java index 4b227f7d16..ec4d070540 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java @@ -1,1010 +1,1010 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.awt.Shape; -import java.awt.geom.Path2D; -import java.awt.image.BufferedImage; -import java.io.IOException; - -import org.apache.poi.hwmf.draw.HwmfGraphics; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; - -public class HwmfFill { - /** - * A record which contains an image (to be extracted) - */ - public interface HwmfImageRecord { - BufferedImage getImage(); - } - - /** - * The ColorUsage Enumeration (a 16-bit unsigned integer) specifies whether a color table - * exists in a device-independent bitmap (DIB) and how to interpret its values, - * i.e. if contains explicit RGB values or indexes into a palette. - */ - public enum ColorUsage { - /** - * The color table contains RGB values - */ - DIB_RGB_COLORS(0x0000), - /** - * The color table contains 16-bit indices into the current logical palette in - * the playback device context. - */ - DIB_PAL_COLORS(0x0001), - /** - * No color table exists. The pixels in the DIB are indices into the current - * logical palette in the playback device context. - */ - DIB_PAL_INDICES(0x0002) - ; - - - public final int flag; - ColorUsage(int flag) { - this.flag = flag; - } - - static ColorUsage valueOf(int flag) { - for (ColorUsage bs : values()) { - if (bs.flag == flag) return bs; - } - return null; - } - } - - - /** - * The META_FILLREGION record fills a region using a specified brush. - */ - public static class WmfFillRegion implements HwmfRecord { - - /** - * A 16-bit unsigned integer used to index into the WMF Object Table to get - * the region to be filled. - */ - private int regionIndex; - - /** - * A 16-bit unsigned integer used to index into the WMF Object Table to get the - * brush to use for filling the region. - */ - private int brushIndex; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.fillRegion; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - regionIndex = leis.readUShort(); - brushIndex = leis.readUShort(); - return 2*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.applyObjectTableEntry(regionIndex); - ctx.applyObjectTableEntry(brushIndex); - - Shape region = ctx.getProperties().getRegion(); - if (region != null) { - ctx.fill(region); - } - - } - } - - /** - * The META_PAINTREGION record paints the specified region by using the brush that is - * defined in the playback device context. - */ - public static class WmfPaintRegion implements HwmfRecord { - - /** - * A 16-bit unsigned integer used to index into the WMF Object Table to get - * the region to be painted. - */ - int regionIndex; - - public HwmfRecordType getRecordType() { - return HwmfRecordType.paintRegion; - } - - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - regionIndex = leis.readUShort(); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.applyObjectTableEntry(regionIndex); - - Shape region = ctx.getProperties().getRegion(); - if (region != null) { - ctx.fill(region); - } - } - } - - - /** - * The META_FLOODFILL record fills an area of the output surface with the brush that - * is defined in the playback device context. - */ - public static class WmfFloodFill implements HwmfRecord { - - /** - * A 32-bit ColorRef Object that defines the color value. - */ - private HwmfColorRef colorRef; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the - * point where filling is to start. - */ - private int yStart; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the - * point where filling is to start. - */ - private int xStart; - - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.floodFill; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - colorRef = new HwmfColorRef(); - int size = colorRef.init(leis); - yStart = leis.readShort(); - xStart = leis.readShort(); - return size+2*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_SETPOLYFILLMODE record sets polygon fill mode in the playback device context for - * graphics operations that fill polygons. - */ - public static class WmfSetPolyfillMode implements HwmfRecord { - /** - * A 16-bit unsigned integer that defines polygon fill mode. - * This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002 - */ - public enum HwmfPolyfillMode { - /** - * Selects alternate mode (fills the area between odd-numbered and - * even-numbered polygon sides on each scan line). - */ - ALTERNATE(0x0001, Path2D.WIND_EVEN_ODD), - /** - * Selects winding mode (fills any region with a nonzero winding value). - */ - WINDING(0x0002, Path2D.WIND_NON_ZERO); - - public final int wmfFlag; - public final int awtFlag; - HwmfPolyfillMode(int wmfFlag, int awtFlag) { - this.wmfFlag = wmfFlag; - this.awtFlag = awtFlag; - } - - static HwmfPolyfillMode valueOf(int wmfFlag) { - for (HwmfPolyfillMode pm : values()) { - if (pm.wmfFlag == wmfFlag) return pm; - } - return null; - } - } - - /** - * A 16-bit unsigned integer that defines polygon fill mode. - * This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002 - */ - private HwmfPolyfillMode polyfillMode; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setPolyFillMode; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - polyfillMode = HwmfPolyfillMode.valueOf(leis.readUShort() & 3); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.getProperties().setPolyfillMode(polyfillMode); - } - } - - - /** - * The META_EXTFLOODFILL record fills an area with the brush that is defined in - * the playback device context. - */ - public static class WmfExtFloodFill implements HwmfRecord { - - /** - * A 16-bit unsigned integer that defines the fill operation to be performed. This - * member MUST be one of the values in the FloodFill Enumeration table: - * - * FLOODFILLBORDER = 0x0000: - * The fill area is bounded by the color specified by the Color member. - * This style is identical to the filling performed by the META_FLOODFILL record. - * - * FLOODFILLSURFACE = 0x0001: - * The fill area is bounded by the color that is specified by the Color member. - * Filling continues outward in all directions as long as the color is encountered. - * This style is useful for filling areas with multicolored boundaries. - */ - private int mode; - - /** - * A 32-bit ColorRef Object that defines the color value. - */ - private HwmfColorRef colorRef; - - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the point - * to be set. - */ - private int y; - - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the point - * to be set. - */ - private int x; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.extFloodFill; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - mode = leis.readUShort(); - colorRef = new HwmfColorRef(); - int size = colorRef.init(leis); - y = leis.readShort(); - x = leis.readShort(); - return size+3*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_INVERTREGION record draws a region in which the colors are inverted. - */ - public static class WmfInvertRegion implements HwmfRecord { - - /** - * A 16-bit unsigned integer used to index into the WMF Object Table to get - * the region to be inverted. - */ - private int region; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.invertRegion; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - region = leis.readUShort(); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - - /** - * The META_PATBLT record paints a specified rectangle using the brush that is defined in the playback - * device context. The brush color and the surface color or colors are combined using the specified - * raster operation. - */ - public static class WmfPatBlt implements HwmfRecord { - - /** - * A 32-bit unsigned integer that defines the raster operation code. - * This code MUST be one of the values in the Ternary Raster Operation enumeration table. - */ - private HwmfTernaryRasterOp rasterOperation; - - /** - * A 16-bit signed integer that defines the height, in logical units, of the rectangle. - */ - private int height; - - /** - * A 16-bit signed integer that defines the width, in logical units, of the rectangle. - */ - private int width; - - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the - * upper-left corner of the rectangle to be filled. - */ - private int yLeft; - - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the - * upper-left corner of the rectangle to be filled. - */ - private int xLeft; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.patBlt; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - int rasterOpCode = leis.readUShort(); - int rasterOpIndex = leis.readUShort(); - - rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); - assert(rasterOpCode == rasterOperation.opCode); - - height = leis.readShort(); - width = leis.readShort(); - yLeft = leis.readShort(); - xLeft = leis.readShort(); - - return 6*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_STRETCHBLT record specifies the transfer of a block of pixels according to a raster - * operation, with possible expansion or contraction. - * The destination of the transfer is the current output region in the playback device context. - * There are two forms of META_STRETCHBLT, one which specifies a bitmap as the source, and the other - * which uses the playback device context as the source. Definitions follow for the fields that are the - * same in the two forms of META_STRETCHBLT are defined below. The subsections that follow specify - * the packet structures of the two forms of META_STRETCHBLT. - * The expansion or contraction is performed according to the stretching mode currently set in the - * playback device context, which MUST be a value from the StretchMode. - */ - public static class WmfStretchBlt implements HwmfRecord { - /** - * A 32-bit unsigned integer that defines how the source pixels, the current brush - * in the playback device context, and the destination pixels are to be combined to form the new - * image. This code MUST be one of the values in the Ternary Raster Operation Enumeration - */ - private HwmfTernaryRasterOp rasterOperation; - - /** - * A 16-bit signed integer that defines the height, in logical units, of the source rectangle. - */ - private int srcHeight; - /** - * A 16-bit signed integer that defines the width, in logical units, of the source rectangle. - */ - private int srcWidth; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner - * of the source rectangle. - */ - private int ySrc; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner - * of the source rectangle. - */ - private int xSrc; - /** - * A 16-bit signed integer that defines the height, in logical units, of the destination rectangle. - */ - private int destHeight; - /** - * A 16-bit signed integer that defines the width, in logical units, of the destination rectangle. - */ - private int destWidth; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left - * corner of the destination rectangle. - */ - private int yDest; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left - * corner of the destination rectangle. - */ - private int xDest; - - /** - * A variable-sized Bitmap16 Object that defines source image content. - * This object MUST be specified, even if the raster operation does not require a source. - */ - HwmfBitmap16 target; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.stretchBlt; - } - - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); - - int size = 0; - int rasterOpCode = leis.readUShort(); - int rasterOpIndex = leis.readUShort(); - - rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); - assert(rasterOpCode == rasterOperation.opCode); - - srcHeight = leis.readShort(); - srcWidth = leis.readShort(); - ySrc = leis.readShort(); - xSrc = leis.readShort(); - size = 6*LittleEndianConsts.SHORT_SIZE; - if (!hasBitmap) { - /*int reserved =*/ leis.readShort(); - size += LittleEndianConsts.SHORT_SIZE; - } - destHeight = leis.readShort(); - destWidth = leis.readShort(); - yDest = leis.readShort(); - xDest = leis.readShort(); - size += 4*LittleEndianConsts.SHORT_SIZE; - if (hasBitmap) { - target = new HwmfBitmap16(); - size += target.init(leis); - } - - return size; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_STRETCHDIB record specifies the transfer of color data from a - * block of pixels in device independent format according to a raster operation, - * with possible expansion or contraction. - * The source of the color data is a DIB, and the destination of the transfer is - * the current output region in the playback device context. - */ - public static class WmfStretchDib implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { - /** - * A 32-bit unsigned integer that defines how the source pixels, the current brush in - * the playback device context, and the destination pixels are to be combined to - * form the new image. - */ - private HwmfTernaryRasterOp rasterOperation; - - /** - * A 16-bit unsigned integer that defines whether the Colors field of the - * DIB contains explicit RGB values or indexes into a palette. - */ - private ColorUsage colorUsage; - /** - * A 16-bit signed integer that defines the height, in logical units, of the - * source rectangle. - */ - private int srcHeight; - /** - * A 16-bit signed integer that defines the width, in logical units, of the - * source rectangle. - */ - private int srcWidth; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the - * source rectangle. - */ - private int ySrc; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the - * source rectangle. - */ - private int xSrc; - /** - * A 16-bit signed integer that defines the height, in logical units, of the - * destination rectangle. - */ - private int destHeight; - /** - * A 16-bit signed integer that defines the width, in logical units, of the - * destination rectangle. - */ - private int destWidth; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the - * upper-left corner of the destination rectangle. - */ - private int yDst; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the - * upper-left corner of the destination rectangle. - */ - private int xDst; - /** - * A variable-sized DeviceIndependentBitmap Object (section 2.2.2.9) that is the - * source of the color data. - */ - private HwmfBitmapDib dib; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.stretchDib; - } - - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - int rasterOpCode = leis.readUShort(); - int rasterOpIndex = leis.readUShort(); - - rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); - assert(rasterOpCode == rasterOperation.opCode); - - colorUsage = ColorUsage.valueOf(leis.readUShort()); - srcHeight = leis.readShort(); - srcWidth = leis.readShort(); - ySrc = leis.readShort(); - xSrc = leis.readShort(); - destHeight = leis.readShort(); - destWidth = leis.readShort(); - yDst = leis.readShort(); - xDst = leis.readShort(); - - int size = 11*LittleEndianConsts.SHORT_SIZE; - dib = new HwmfBitmapDib(); - size += dib.init(leis, (int)(recordSize-6-size)); - - return size; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - - } - - @Override - public BufferedImage getImage() { - return dib.getImage(); - } - } - - public static class WmfBitBlt implements HwmfRecord { - - /** - * A 32-bit unsigned integer that defines how the source pixels, the current brush in the playback - * device context, and the destination pixels are to be combined to form the new image. - */ - private HwmfTernaryRasterOp rasterOperation; - - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner - of the source rectangle. - */ - private int ySrc; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner - of the source rectangle. - */ - private int xSrc; - /** - * A 16-bit signed integer that defines the height, in logical units, of the source and - destination rectangles. - */ - private int height; - /** - * A 16-bit signed integer that defines the width, in logical units, of the source and destination - rectangles. - */ - private int width; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left - corner of the destination rectangle. - */ - private int yDest; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left - corner of the destination rectangle. - */ - private int xDest; - - /** - * A variable-sized Bitmap16 Object that defines source image content. - * This object MUST be specified, even if the raster operation does not require a source. - */ - private HwmfBitmap16 target; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.bitBlt; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - boolean hasBitmap = (recordSize/2 != ((recordFunction >> 8) + 3)); - - int size = 0; - int rasterOpCode = leis.readUShort(); - int rasterOpIndex = leis.readUShort(); - - rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); - assert(rasterOpCode == rasterOperation.opCode); - - ySrc = leis.readShort(); - xSrc = leis.readShort(); - - size = 4*LittleEndianConsts.SHORT_SIZE; - - if (!hasBitmap) { - /*int reserved =*/ leis.readShort(); - size += LittleEndianConsts.SHORT_SIZE; - } - - height = leis.readShort(); - width = leis.readShort(); - yDest = leis.readShort(); - xDest = leis.readShort(); - - size += 4*LittleEndianConsts.SHORT_SIZE; - if (hasBitmap) { - target = new HwmfBitmap16(); - size += target.init(leis); - } - - return size; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - - /** - * The META_SETDIBTODEV record sets a block of pixels in the playback device context - * using deviceindependent color data. - * The source of the color data is a DIB - */ - public static class WmfSetDibToDev implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { - - /** - * A 16-bit unsigned integer that defines whether the Colors field of the - * DIB contains explicit RGB values or indexes into a palette. - */ - private ColorUsage colorUsage; - /** - * A 16-bit unsigned integer that defines the number of scan lines in the source. - */ - private int scanCount; - /** - * A 16-bit unsigned integer that defines the starting scan line in the source. - */ - private int startScan; - /** - * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the - * source rectangle. - */ - private int yDib; - /** - * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the - * source rectangle. - */ - private int xDib; - /** - * A 16-bit unsigned integer that defines the height, in logical units, of the - * source and destination rectangles. - */ - private int height; - /** - * A 16-bit unsigned integer that defines the width, in logical units, of the - * source and destination rectangles. - */ - private int width; - /** - * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the - * upper-left corner of the destination rectangle. - */ - private int yDest; - /** - * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the - * upper-left corner of the destination rectangle. - */ - private int xDest; - /** - * A variable-sized DeviceIndependentBitmap Object that is the source of the color data. - */ - private HwmfBitmapDib dib; - - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setDibToDev; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - colorUsage = ColorUsage.valueOf(leis.readUShort()); - scanCount = leis.readUShort(); - startScan = leis.readUShort(); - yDib = leis.readUShort(); - xDib = leis.readUShort(); - height = leis.readUShort(); - width = leis.readUShort(); - yDest = leis.readUShort(); - xDest = leis.readUShort(); - - int size = 9*LittleEndianConsts.SHORT_SIZE; - dib = new HwmfBitmapDib(); - size += dib.init(leis, (int)(recordSize-6-size)); - - return size; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - - } - - @Override - public BufferedImage getImage() { - return dib.getImage(); - } - } - - - public static class WmfDibBitBlt implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { - - /** - * A 32-bit unsigned integer that defines how the source pixels, the current brush - * in the playback device context, and the destination pixels are to be combined to form the - * new image. This code MUST be one of the values in the Ternary Raster Operation Enumeration. - */ - HwmfTernaryRasterOp rasterOperation; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the source rectangle. - */ - private int ySrc; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the source rectangle. - */ - private int xSrc; - /** - * A 16-bit signed integer that defines the height, in logical units, of the source and - * destination rectangles. - */ - private int height; - /** - * A 16-bit signed integer that defines the width, in logical units, of the source and destination - * rectangles. - */ - private int width; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left - * corner of the destination rectangle. - */ - private int yDest; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left - * corner of the destination rectangle. - */ - private int xDest; - - /** - * A variable-sized DeviceIndependentBitmap Object that defines image content. - * This object MUST be specified, even if the raster operation does not require a source. - */ - private HwmfBitmapDib target; - - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.dibBitBlt; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - boolean hasBitmap = (recordSize/2 != ((recordFunction >> 8) + 3)); - - int size = 0; - int rasterOpCode = leis.readUShort(); - int rasterOpIndex = leis.readUShort(); - - rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); - assert(rasterOpCode == rasterOperation.opCode); - - ySrc = leis.readShort(); - xSrc = leis.readShort(); - size = 4*LittleEndianConsts.SHORT_SIZE; - if (!hasBitmap) { - /*int reserved =*/ leis.readShort(); - size += LittleEndianConsts.SHORT_SIZE; - } - height = leis.readShort(); - width = leis.readShort(); - yDest = leis.readShort(); - xDest = leis.readShort(); - - size += 4*LittleEndianConsts.SHORT_SIZE; - if (hasBitmap) { - target = new HwmfBitmapDib(); - size += target.init(leis, (int)(recordSize-6-size)); - } - - return size; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - - } - - @Override - public BufferedImage getImage() { - return (target == null) ? null : target.getImage(); - } - } - - public static class WmfDibStretchBlt implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { - /** - * A 32-bit unsigned integer that defines how the source pixels, the current brush - * in the playback device context, and the destination pixels are to be combined to form the - * new image. This code MUST be one of the values in the Ternary Raster Operation Enumeration. - */ - private HwmfTernaryRasterOp rasterOperation; - /** - * A 16-bit signed integer that defines the height, in logical units, of the source rectangle. - */ - private int srcHeight; - /** - * A 16-bit signed integer that defines the width, in logical units, of the source rectangle. - */ - private int srcWidth; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, of the - * upper-left corner of the source rectangle. - */ - private int ySrc; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, of the - * upper-left corner of the source rectangle. - */ - private int xSrc; - /** - * A 16-bit signed integer that defines the height, in logical units, of the - * destination rectangle. - */ - private int destHeight; - /** - * A 16-bit signed integer that defines the width, in logical units, of the - * destination rectangle. - */ - private int destWidth; - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, - * of the upper-left corner of the destination rectangle. - */ - private int yDest; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, - * of the upper-left corner of the destination rectangle. - */ - private int xDest; - /** - * A variable-sized DeviceIndependentBitmap Object that defines image content. - * This object MUST be specified, even if the raster operation does not require a source. - */ - HwmfBitmapDib target; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.dibStretchBlt; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); - - int size = 0; - int rasterOpCode = leis.readUShort(); - int rasterOpIndex = leis.readUShort(); - - rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); - assert(rasterOpCode == rasterOperation.opCode); - - srcHeight = leis.readShort(); - srcWidth = leis.readShort(); - ySrc = leis.readShort(); - xSrc = leis.readShort(); - size = 6*LittleEndianConsts.SHORT_SIZE; - if (!hasBitmap) { - /*int reserved =*/ leis.readShort(); - size += LittleEndianConsts.SHORT_SIZE; - } - destHeight = leis.readShort(); - destWidth = leis.readShort(); - yDest = leis.readShort(); - xDest = leis.readShort(); - size += 4*LittleEndianConsts.SHORT_SIZE; - if (hasBitmap) { - target = new HwmfBitmapDib(); - size += target.init(leis, (int)(recordSize-6-size)); - } - - return size; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - - } - - @Override - public BufferedImage getImage() { - return target.getImage(); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.awt.Shape; +import java.awt.geom.Path2D; +import java.awt.image.BufferedImage; +import java.io.IOException; + +import org.apache.poi.hwmf.draw.HwmfGraphics; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; + +public class HwmfFill { + /** + * A record which contains an image (to be extracted) + */ + public interface HwmfImageRecord { + BufferedImage getImage(); + } + + /** + * The ColorUsage Enumeration (a 16-bit unsigned integer) specifies whether a color table + * exists in a device-independent bitmap (DIB) and how to interpret its values, + * i.e. if contains explicit RGB values or indexes into a palette. + */ + public enum ColorUsage { + /** + * The color table contains RGB values + */ + DIB_RGB_COLORS(0x0000), + /** + * The color table contains 16-bit indices into the current logical palette in + * the playback device context. + */ + DIB_PAL_COLORS(0x0001), + /** + * No color table exists. The pixels in the DIB are indices into the current + * logical palette in the playback device context. + */ + DIB_PAL_INDICES(0x0002) + ; + + + public final int flag; + ColorUsage(int flag) { + this.flag = flag; + } + + static ColorUsage valueOf(int flag) { + for (ColorUsage bs : values()) { + if (bs.flag == flag) return bs; + } + return null; + } + } + + + /** + * The META_FILLREGION record fills a region using a specified brush. + */ + public static class WmfFillRegion implements HwmfRecord { + + /** + * A 16-bit unsigned integer used to index into the WMF Object Table to get + * the region to be filled. + */ + private int regionIndex; + + /** + * A 16-bit unsigned integer used to index into the WMF Object Table to get the + * brush to use for filling the region. + */ + private int brushIndex; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.fillRegion; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + regionIndex = leis.readUShort(); + brushIndex = leis.readUShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.applyObjectTableEntry(regionIndex); + ctx.applyObjectTableEntry(brushIndex); + + Shape region = ctx.getProperties().getRegion(); + if (region != null) { + ctx.fill(region); + } + + } + } + + /** + * The META_PAINTREGION record paints the specified region by using the brush that is + * defined in the playback device context. + */ + public static class WmfPaintRegion implements HwmfRecord { + + /** + * A 16-bit unsigned integer used to index into the WMF Object Table to get + * the region to be painted. + */ + int regionIndex; + + public HwmfRecordType getRecordType() { + return HwmfRecordType.paintRegion; + } + + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + regionIndex = leis.readUShort(); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.applyObjectTableEntry(regionIndex); + + Shape region = ctx.getProperties().getRegion(); + if (region != null) { + ctx.fill(region); + } + } + } + + + /** + * The META_FLOODFILL record fills an area of the output surface with the brush that + * is defined in the playback device context. + */ + public static class WmfFloodFill implements HwmfRecord { + + /** + * A 32-bit ColorRef Object that defines the color value. + */ + private HwmfColorRef colorRef; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * point where filling is to start. + */ + private int yStart; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * point where filling is to start. + */ + private int xStart; + + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.floodFill; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + colorRef = new HwmfColorRef(); + int size = colorRef.init(leis); + yStart = leis.readShort(); + xStart = leis.readShort(); + return size+2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_SETPOLYFILLMODE record sets polygon fill mode in the playback device context for + * graphics operations that fill polygons. + */ + public static class WmfSetPolyfillMode implements HwmfRecord { + /** + * A 16-bit unsigned integer that defines polygon fill mode. + * This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002 + */ + public enum HwmfPolyfillMode { + /** + * Selects alternate mode (fills the area between odd-numbered and + * even-numbered polygon sides on each scan line). + */ + ALTERNATE(0x0001, Path2D.WIND_EVEN_ODD), + /** + * Selects winding mode (fills any region with a nonzero winding value). + */ + WINDING(0x0002, Path2D.WIND_NON_ZERO); + + public final int wmfFlag; + public final int awtFlag; + HwmfPolyfillMode(int wmfFlag, int awtFlag) { + this.wmfFlag = wmfFlag; + this.awtFlag = awtFlag; + } + + static HwmfPolyfillMode valueOf(int wmfFlag) { + for (HwmfPolyfillMode pm : values()) { + if (pm.wmfFlag == wmfFlag) return pm; + } + return null; + } + } + + /** + * A 16-bit unsigned integer that defines polygon fill mode. + * This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002 + */ + private HwmfPolyfillMode polyfillMode; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setPolyFillMode; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + polyfillMode = HwmfPolyfillMode.valueOf(leis.readUShort() & 3); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setPolyfillMode(polyfillMode); + } + } + + + /** + * The META_EXTFLOODFILL record fills an area with the brush that is defined in + * the playback device context. + */ + public static class WmfExtFloodFill implements HwmfRecord { + + /** + * A 16-bit unsigned integer that defines the fill operation to be performed. This + * member MUST be one of the values in the FloodFill Enumeration table: + * + * FLOODFILLBORDER = 0x0000: + * The fill area is bounded by the color specified by the Color member. + * This style is identical to the filling performed by the META_FLOODFILL record. + * + * FLOODFILLSURFACE = 0x0001: + * The fill area is bounded by the color that is specified by the Color member. + * Filling continues outward in all directions as long as the color is encountered. + * This style is useful for filling areas with multicolored boundaries. + */ + private int mode; + + /** + * A 32-bit ColorRef Object that defines the color value. + */ + private HwmfColorRef colorRef; + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the point + * to be set. + */ + private int y; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the point + * to be set. + */ + private int x; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.extFloodFill; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + mode = leis.readUShort(); + colorRef = new HwmfColorRef(); + int size = colorRef.init(leis); + y = leis.readShort(); + x = leis.readShort(); + return size+3*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_INVERTREGION record draws a region in which the colors are inverted. + */ + public static class WmfInvertRegion implements HwmfRecord { + + /** + * A 16-bit unsigned integer used to index into the WMF Object Table to get + * the region to be inverted. + */ + private int region; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.invertRegion; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + region = leis.readUShort(); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + + /** + * The META_PATBLT record paints a specified rectangle using the brush that is defined in the playback + * device context. The brush color and the surface color or colors are combined using the specified + * raster operation. + */ + public static class WmfPatBlt implements HwmfRecord { + + /** + * A 32-bit unsigned integer that defines the raster operation code. + * This code MUST be one of the values in the Ternary Raster Operation enumeration table. + */ + private HwmfTernaryRasterOp rasterOperation; + + /** + * A 16-bit signed integer that defines the height, in logical units, of the rectangle. + */ + private int height; + + /** + * A 16-bit signed integer that defines the width, in logical units, of the rectangle. + */ + private int width; + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * upper-left corner of the rectangle to be filled. + */ + private int yLeft; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * upper-left corner of the rectangle to be filled. + */ + private int xLeft; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.patBlt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + int rasterOpCode = leis.readUShort(); + int rasterOpIndex = leis.readUShort(); + + rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); + assert(rasterOpCode == rasterOperation.opCode); + + height = leis.readShort(); + width = leis.readShort(); + yLeft = leis.readShort(); + xLeft = leis.readShort(); + + return 6*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_STRETCHBLT record specifies the transfer of a block of pixels according to a raster + * operation, with possible expansion or contraction. + * The destination of the transfer is the current output region in the playback device context. + * There are two forms of META_STRETCHBLT, one which specifies a bitmap as the source, and the other + * which uses the playback device context as the source. Definitions follow for the fields that are the + * same in the two forms of META_STRETCHBLT are defined below. The subsections that follow specify + * the packet structures of the two forms of META_STRETCHBLT. + * The expansion or contraction is performed according to the stretching mode currently set in the + * playback device context, which MUST be a value from the StretchMode. + */ + public static class WmfStretchBlt implements HwmfRecord { + /** + * A 32-bit unsigned integer that defines how the source pixels, the current brush + * in the playback device context, and the destination pixels are to be combined to form the new + * image. This code MUST be one of the values in the Ternary Raster Operation Enumeration + */ + private HwmfTernaryRasterOp rasterOperation; + + /** + * A 16-bit signed integer that defines the height, in logical units, of the source rectangle. + */ + private int srcHeight; + /** + * A 16-bit signed integer that defines the width, in logical units, of the source rectangle. + */ + private int srcWidth; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner + * of the source rectangle. + */ + private int ySrc; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner + * of the source rectangle. + */ + private int xSrc; + /** + * A 16-bit signed integer that defines the height, in logical units, of the destination rectangle. + */ + private int destHeight; + /** + * A 16-bit signed integer that defines the width, in logical units, of the destination rectangle. + */ + private int destWidth; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left + * corner of the destination rectangle. + */ + private int yDest; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left + * corner of the destination rectangle. + */ + private int xDest; + + /** + * A variable-sized Bitmap16 Object that defines source image content. + * This object MUST be specified, even if the raster operation does not require a source. + */ + HwmfBitmap16 target; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.stretchBlt; + } + + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); + + int size = 0; + int rasterOpCode = leis.readUShort(); + int rasterOpIndex = leis.readUShort(); + + rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); + assert(rasterOpCode == rasterOperation.opCode); + + srcHeight = leis.readShort(); + srcWidth = leis.readShort(); + ySrc = leis.readShort(); + xSrc = leis.readShort(); + size = 6*LittleEndianConsts.SHORT_SIZE; + if (!hasBitmap) { + /*int reserved =*/ leis.readShort(); + size += LittleEndianConsts.SHORT_SIZE; + } + destHeight = leis.readShort(); + destWidth = leis.readShort(); + yDest = leis.readShort(); + xDest = leis.readShort(); + size += 4*LittleEndianConsts.SHORT_SIZE; + if (hasBitmap) { + target = new HwmfBitmap16(); + size += target.init(leis); + } + + return size; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_STRETCHDIB record specifies the transfer of color data from a + * block of pixels in device independent format according to a raster operation, + * with possible expansion or contraction. + * The source of the color data is a DIB, and the destination of the transfer is + * the current output region in the playback device context. + */ + public static class WmfStretchDib implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { + /** + * A 32-bit unsigned integer that defines how the source pixels, the current brush in + * the playback device context, and the destination pixels are to be combined to + * form the new image. + */ + private HwmfTernaryRasterOp rasterOperation; + + /** + * A 16-bit unsigned integer that defines whether the Colors field of the + * DIB contains explicit RGB values or indexes into a palette. + */ + private ColorUsage colorUsage; + /** + * A 16-bit signed integer that defines the height, in logical units, of the + * source rectangle. + */ + private int srcHeight; + /** + * A 16-bit signed integer that defines the width, in logical units, of the + * source rectangle. + */ + private int srcWidth; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * source rectangle. + */ + private int ySrc; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * source rectangle. + */ + private int xSrc; + /** + * A 16-bit signed integer that defines the height, in logical units, of the + * destination rectangle. + */ + private int destHeight; + /** + * A 16-bit signed integer that defines the width, in logical units, of the + * destination rectangle. + */ + private int destWidth; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * upper-left corner of the destination rectangle. + */ + private int yDst; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * upper-left corner of the destination rectangle. + */ + private int xDst; + /** + * A variable-sized DeviceIndependentBitmap Object (section 2.2.2.9) that is the + * source of the color data. + */ + private HwmfBitmapDib dib; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.stretchDib; + } + + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + int rasterOpCode = leis.readUShort(); + int rasterOpIndex = leis.readUShort(); + + rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); + assert(rasterOpCode == rasterOperation.opCode); + + colorUsage = ColorUsage.valueOf(leis.readUShort()); + srcHeight = leis.readShort(); + srcWidth = leis.readShort(); + ySrc = leis.readShort(); + xSrc = leis.readShort(); + destHeight = leis.readShort(); + destWidth = leis.readShort(); + yDst = leis.readShort(); + xDst = leis.readShort(); + + int size = 11*LittleEndianConsts.SHORT_SIZE; + dib = new HwmfBitmapDib(); + size += dib.init(leis, (int)(recordSize-6-size)); + + return size; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + + } + + @Override + public BufferedImage getImage() { + return dib.getImage(); + } + } + + public static class WmfBitBlt implements HwmfRecord { + + /** + * A 32-bit unsigned integer that defines how the source pixels, the current brush in the playback + * device context, and the destination pixels are to be combined to form the new image. + */ + private HwmfTernaryRasterOp rasterOperation; + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner + of the source rectangle. + */ + private int ySrc; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner + of the source rectangle. + */ + private int xSrc; + /** + * A 16-bit signed integer that defines the height, in logical units, of the source and + destination rectangles. + */ + private int height; + /** + * A 16-bit signed integer that defines the width, in logical units, of the source and destination + rectangles. + */ + private int width; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left + corner of the destination rectangle. + */ + private int yDest; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left + corner of the destination rectangle. + */ + private int xDest; + + /** + * A variable-sized Bitmap16 Object that defines source image content. + * This object MUST be specified, even if the raster operation does not require a source. + */ + private HwmfBitmap16 target; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.bitBlt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + boolean hasBitmap = (recordSize/2 != ((recordFunction >> 8) + 3)); + + int size = 0; + int rasterOpCode = leis.readUShort(); + int rasterOpIndex = leis.readUShort(); + + rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); + assert(rasterOpCode == rasterOperation.opCode); + + ySrc = leis.readShort(); + xSrc = leis.readShort(); + + size = 4*LittleEndianConsts.SHORT_SIZE; + + if (!hasBitmap) { + /*int reserved =*/ leis.readShort(); + size += LittleEndianConsts.SHORT_SIZE; + } + + height = leis.readShort(); + width = leis.readShort(); + yDest = leis.readShort(); + xDest = leis.readShort(); + + size += 4*LittleEndianConsts.SHORT_SIZE; + if (hasBitmap) { + target = new HwmfBitmap16(); + size += target.init(leis); + } + + return size; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + + /** + * The META_SETDIBTODEV record sets a block of pixels in the playback device context + * using deviceindependent color data. + * The source of the color data is a DIB + */ + public static class WmfSetDibToDev implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { + + /** + * A 16-bit unsigned integer that defines whether the Colors field of the + * DIB contains explicit RGB values or indexes into a palette. + */ + private ColorUsage colorUsage; + /** + * A 16-bit unsigned integer that defines the number of scan lines in the source. + */ + private int scanCount; + /** + * A 16-bit unsigned integer that defines the starting scan line in the source. + */ + private int startScan; + /** + * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the + * source rectangle. + */ + private int yDib; + /** + * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the + * source rectangle. + */ + private int xDib; + /** + * A 16-bit unsigned integer that defines the height, in logical units, of the + * source and destination rectangles. + */ + private int height; + /** + * A 16-bit unsigned integer that defines the width, in logical units, of the + * source and destination rectangles. + */ + private int width; + /** + * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the + * upper-left corner of the destination rectangle. + */ + private int yDest; + /** + * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the + * upper-left corner of the destination rectangle. + */ + private int xDest; + /** + * A variable-sized DeviceIndependentBitmap Object that is the source of the color data. + */ + private HwmfBitmapDib dib; + + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setDibToDev; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + colorUsage = ColorUsage.valueOf(leis.readUShort()); + scanCount = leis.readUShort(); + startScan = leis.readUShort(); + yDib = leis.readUShort(); + xDib = leis.readUShort(); + height = leis.readUShort(); + width = leis.readUShort(); + yDest = leis.readUShort(); + xDest = leis.readUShort(); + + int size = 9*LittleEndianConsts.SHORT_SIZE; + dib = new HwmfBitmapDib(); + size += dib.init(leis, (int)(recordSize-6-size)); + + return size; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + + } + + @Override + public BufferedImage getImage() { + return dib.getImage(); + } + } + + + public static class WmfDibBitBlt implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { + + /** + * A 32-bit unsigned integer that defines how the source pixels, the current brush + * in the playback device context, and the destination pixels are to be combined to form the + * new image. This code MUST be one of the values in the Ternary Raster Operation Enumeration. + */ + HwmfTernaryRasterOp rasterOperation; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the source rectangle. + */ + private int ySrc; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the source rectangle. + */ + private int xSrc; + /** + * A 16-bit signed integer that defines the height, in logical units, of the source and + * destination rectangles. + */ + private int height; + /** + * A 16-bit signed integer that defines the width, in logical units, of the source and destination + * rectangles. + */ + private int width; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left + * corner of the destination rectangle. + */ + private int yDest; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left + * corner of the destination rectangle. + */ + private int xDest; + + /** + * A variable-sized DeviceIndependentBitmap Object that defines image content. + * This object MUST be specified, even if the raster operation does not require a source. + */ + private HwmfBitmapDib target; + + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.dibBitBlt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + boolean hasBitmap = (recordSize/2 != ((recordFunction >> 8) + 3)); + + int size = 0; + int rasterOpCode = leis.readUShort(); + int rasterOpIndex = leis.readUShort(); + + rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); + assert(rasterOpCode == rasterOperation.opCode); + + ySrc = leis.readShort(); + xSrc = leis.readShort(); + size = 4*LittleEndianConsts.SHORT_SIZE; + if (!hasBitmap) { + /*int reserved =*/ leis.readShort(); + size += LittleEndianConsts.SHORT_SIZE; + } + height = leis.readShort(); + width = leis.readShort(); + yDest = leis.readShort(); + xDest = leis.readShort(); + + size += 4*LittleEndianConsts.SHORT_SIZE; + if (hasBitmap) { + target = new HwmfBitmapDib(); + size += target.init(leis, (int)(recordSize-6-size)); + } + + return size; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + + } + + @Override + public BufferedImage getImage() { + return (target == null) ? null : target.getImage(); + } + } + + public static class WmfDibStretchBlt implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { + /** + * A 32-bit unsigned integer that defines how the source pixels, the current brush + * in the playback device context, and the destination pixels are to be combined to form the + * new image. This code MUST be one of the values in the Ternary Raster Operation Enumeration. + */ + private HwmfTernaryRasterOp rasterOperation; + /** + * A 16-bit signed integer that defines the height, in logical units, of the source rectangle. + */ + private int srcHeight; + /** + * A 16-bit signed integer that defines the width, in logical units, of the source rectangle. + */ + private int srcWidth; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * upper-left corner of the source rectangle. + */ + private int ySrc; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * upper-left corner of the source rectangle. + */ + private int xSrc; + /** + * A 16-bit signed integer that defines the height, in logical units, of the + * destination rectangle. + */ + private int destHeight; + /** + * A 16-bit signed integer that defines the width, in logical units, of the + * destination rectangle. + */ + private int destWidth; + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, + * of the upper-left corner of the destination rectangle. + */ + private int yDest; + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, + * of the upper-left corner of the destination rectangle. + */ + private int xDest; + /** + * A variable-sized DeviceIndependentBitmap Object that defines image content. + * This object MUST be specified, even if the raster operation does not require a source. + */ + HwmfBitmapDib target; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.dibStretchBlt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); + + int size = 0; + int rasterOpCode = leis.readUShort(); + int rasterOpIndex = leis.readUShort(); + + rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex); + assert(rasterOpCode == rasterOperation.opCode); + + srcHeight = leis.readShort(); + srcWidth = leis.readShort(); + ySrc = leis.readShort(); + xSrc = leis.readShort(); + size = 6*LittleEndianConsts.SHORT_SIZE; + if (!hasBitmap) { + /*int reserved =*/ leis.readShort(); + size += LittleEndianConsts.SHORT_SIZE; + } + destHeight = leis.readShort(); + destWidth = leis.readShort(); + yDest = leis.readShort(); + xDest = leis.readShort(); + size += 4*LittleEndianConsts.SHORT_SIZE; + if (hasBitmap) { + target = new HwmfBitmapDib(); + size += target.init(leis, (int)(recordSize-6-size)); + } + + return size; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + + } + + @Override + public BufferedImage getImage() { + return target.getImage(); + } + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java index 9225de47ec..703faa153a 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java @@ -1,595 +1,595 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; - -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * The Font object specifies the attributes of a logical font - */ -public class HwmfFont { - - private static final POILogger logger = POILogFactory.getLogger(HwmfFont.class); - - public enum WmfCharset { - /** Specifies the English character set. */ - ANSI_CHARSET(0x00000000, "Cp1252"), - /** - * Specifies a character set based on the current system locale; - * for example, when the system locale is United States English, - * the default character set is ANSI_CHARSET. - */ - DEFAULT_CHARSET(0x00000001, "Cp1252"), - /** Specifies a character set of symbols. */ - SYMBOL_CHARSET(0x00000002, ""), - /** Specifies the Apple Macintosh character set. */ - MAC_CHARSET(0x0000004D, "MacRoman"), - /** Specifies the Japanese character set. */ - SHIFTJIS_CHARSET(0x00000080, "Shift_JIS"), - /** Also spelled "Hangeul". Specifies the Hangul Korean character set. */ - HANGUL_CHARSET(0x00000081, "cp949"), - /** Also spelled "Johap". Specifies the Johab Korean character set. */ - JOHAB_CHARSET(0x00000082, "x-Johab"), - /** Specifies the "simplified" Chinese character set for People's Republic of China. */ - GB2312_CHARSET(0x00000086, "GB2312"), - /** - * Specifies the "traditional" Chinese character set, used mostly in - * Taiwan and in the Hong Kong and Macao Special Administrative Regions. - */ - CHINESEBIG5_CHARSET(0x00000088, "Big5"), - /** Specifies the Greek character set. */ - GREEK_CHARSET(0x000000A1, "Cp1253"), - /** Specifies the Turkish character set. */ - TURKISH_CHARSET(0x000000A2, "Cp1254"), - /** Specifies the Vietnamese character set. */ - VIETNAMESE_CHARSET(0x000000A3, "Cp1258"), - /** Specifies the Hebrew character set. */ - HEBREW_CHARSET(0x000000B1, "Cp1255"), - /** Specifies the Arabic character set. */ - ARABIC_CHARSET(0x000000B2, "Cp1256"), - /** Specifies the Baltic (Northeastern European) character set. */ - BALTIC_CHARSET(0x000000BA, "Cp1257"), - /** Specifies the Russian Cyrillic character set. */ - RUSSIAN_CHARSET(0x000000CC, "Cp1251"), - /** Specifies the Thai character set. */ - THAI_CHARSET(0x000000DE, "x-windows-874"), - /** Specifies a Eastern European character set. */ - EASTEUROPE_CHARSET(0x000000EE, "Cp1250"), - /** - * Specifies a mapping to one of the OEM code pages, - * according to the current system locale setting. - */ - OEM_CHARSET(0x000000FF, "Cp1252"); - - int flag; - Charset charset; - - WmfCharset(int flag, String javaCharsetName) { - this.flag = flag; - if (javaCharsetName.length() > 0) { - try { - charset = Charset.forName(javaCharsetName); - return; - } catch (UnsupportedCharsetException e) { - logger.log(POILogger.WARN, "Unsupported charset: "+javaCharsetName); - } - } - charset = null; - } - - /** - * - * @return charset for the font or null if there is no matching charset or - * if the charset is a "default" - */ - public Charset getCharset() { - return charset; - } - - static WmfCharset valueOf(int flag) { - for (WmfCharset cs : values()) { - if (cs.flag == flag) return cs; - } - return null; - } - } - - /** - * The output precision defines how closely the output must match the requested font's height, - * width, character orientation, escapement, pitch, and font type. - */ - public enum WmfOutPrecision { - /** - * A value that specifies default behavior. - */ - OUT_DEFAULT_PRECIS(0x00000000), - /** - * A value that is returned when rasterized fonts are enumerated. - */ - OUT_STRING_PRECIS(0x00000001), - /** - * A value that is returned when TrueType and other outline fonts, and - * vector fonts are enumerated. - */ - OUT_STROKE_PRECIS(0x00000003), - /** - * A value that specifies the choice of a TrueType font when the system - * contains multiple fonts with the same name. - */ - OUT_TT_PRECIS(0x00000004), - /** - * A value that specifies the choice of a device font when the system - * contains multiple fonts with the same name. - */ - OUT_DEVICE_PRECIS(0x00000005), - /** - * A value that specifies the choice of a rasterized font when the system - * contains multiple fonts with the same name. - */ - OUT_RASTER_PRECIS(0x00000006), - /** - * A value that specifies the requirement for only TrueType fonts. If - * there are no TrueType fonts installed in the system, default behavior is specified. - */ - OUT_TT_ONLY_PRECIS(0x00000007), - /** - * A value that specifies the requirement for TrueType and other outline fonts. - */ - OUT_OUTLINE_PRECIS (0x00000008), - /** - * A value that specifies a preference for TrueType and other outline fonts. - */ - OUT_SCREEN_OUTLINE_PRECIS (0x00000009), - /** - * A value that specifies a requirement for only PostScript fonts. If there - * are no PostScript fonts installed in the system, default behavior is specified. - */ - OUT_PS_ONLY_PRECIS (0x0000000A); - - - int flag; - WmfOutPrecision(int flag) { - this.flag = flag; - } - - static WmfOutPrecision valueOf(int flag) { - for (WmfOutPrecision op : values()) { - if (op.flag == flag) return op; - } - return null; - } - } - - /** - * ClipPrecision Flags specify clipping precision, which defines how to clip characters that are - * partially outside a clipping region. These flags can be combined to specify multiple options. - */ - public enum WmfClipPrecision { - - /** - * Specifies that default clipping MUST be used. - */ - CLIP_DEFAULT_PRECIS (0x00000000), - - /** - * This value SHOULD NOT be used. - */ - CLIP_CHARACTER_PRECIS (0x00000001), - - /** - * This value MAY be returned when enumerating rasterized, TrueType and vector fonts. - */ - CLIP_STROKE_PRECIS (0x00000002), - - /** - * This value is used to control font rotation, as follows: - * If set, the rotation for all fonts SHOULD be determined by the orientation of the coordinate system; - * that is, whether the orientation is left-handed or right-handed. - * - * If clear, device fonts SHOULD rotate counterclockwise, but the rotation of other fonts - * SHOULD be determined by the orientation of the coordinate system. - */ - CLIP_LH_ANGLES (0x00000010), - - /** - * This value SHOULD NOT be used. - */ - CLIP_TT_ALWAYS (0x00000020), - - /** - * This value specifies that font association SHOULD< be turned off. - */ - CLIP_DFA_DISABLE (0x00000040), - - /** - * This value specifies that font embedding MUST be used to render document content; - * embedded fonts are read-only. - */ - CLIP_EMBEDDED (0x00000080); - - - int flag; - WmfClipPrecision(int flag) { - this.flag = flag; - } - - static WmfClipPrecision valueOf(int flag) { - for (WmfClipPrecision cp : values()) { - if (cp.flag == flag) return cp; - } - return null; - } - } - - /** - * The output quality defines how carefully to attempt to match the logical font attributes to those of an actual - * physical font. - */ - public enum WmfFontQuality { - /** - * Specifies that the character quality of the font does not matter, so DRAFT_QUALITY can be used. - */ - DEFAULT_QUALITY (0x00), - - /** - * Specifies that the character quality of the font is less important than the - * matching of logical attribuetes. For rasterized fonts, scaling SHOULD be enabled, which - * means that more font sizes are available. - */ - DRAFT_QUALITY (0x01), - - /** - * Specifies that the character quality of the font is more important than the - * matching of logical attributes. For rasterized fonts, scaling SHOULD be disabled, and the font - * closest in size SHOULD be chosen. - */ - PROOF_QUALITY (0x02), - - /** - * Specifies that anti-aliasing SHOULD NOT be used when rendering text. - */ - NONANTIALIASED_QUALITY (0x03), - - /** - * Specifies that anti-aliasing SHOULD be used when rendering text, if the font supports it. - */ - ANTIALIASED_QUALITY (0x04), - - /** - * Specifies that ClearType anti-aliasing SHOULD be used when rendering text, if the font supports it. - * - * Fonts that do not support ClearType anti-aliasing include type 1 fonts, PostScript fonts, - * OpenType fonts without TrueType outlines, rasterized fonts, vector fonts, and device fonts. - */ - CLEARTYPE_QUALITY (0x05); - - int flag; - WmfFontQuality(int flag) { - this.flag = flag; - } - - static WmfFontQuality valueOf(int flag) { - for (WmfFontQuality fq : values()) { - if (fq.flag == flag) return fq; - } - return null; - } - } - - /** - * A property of a font that describes its general appearance. - */ - public enum WmfFontFamilyClass { - /** - * The default font is specified, which is implementation-dependent. - */ - FF_DONTCARE (0x00), - /** - * Fonts with variable stroke widths, which are proportional to the actual widths of - * the glyphs, and which have serifs. "MS Serif" is an example. - */ - FF_ROMAN (0x01), - /** - * Fonts with variable stroke widths, which are proportional to the actual widths of the - * glyphs, and which do not have serifs. "MS Sans Serif" is an example. - */ - FF_SWISS (0x02), - /** - * Fonts with constant stroke width, with or without serifs. Fixed-width fonts are - * usually modern. "Pica", "Elite", and "Courier New" are examples. - */ - FF_MODERN (0x03), - /** - * Fonts designed to look like handwriting. "Script" and "Cursive" are examples. - */ - FF_SCRIPT (0x04), - /** - * Novelty fonts. "Old English" is an example. - */ - FF_DECORATIVE (0x05); - - int flag; - WmfFontFamilyClass(int flag) { - this.flag = flag; - } - - static WmfFontFamilyClass valueOf(int flag) { - for (WmfFontFamilyClass ff : values()) { - if (ff.flag == flag) return ff; - } - return null; - } - } - - /** - * A property of a font that describes the pitch, of the characters. - */ - public enum WmfFontPitch { - /** - * The default pitch, which is implementation-dependent. - */ - DEFAULT_PITCH (0x00), - /** - * A fixed pitch, which means that all the characters in the font occupy the same - * width when output in a string. - */ - FIXED_PITCH (0x01), - /** - * A variable pitch, which means that the characters in the font occupy widths - * that are proportional to the actual widths of the glyphs when output in a string. For example, - * the "i" and space characters usually have much smaller widths than a "W" or "O" character. - */ - VARIABLE_PITCH (0x02); - - int flag; - WmfFontPitch(int flag) { - this.flag = flag; - } - - static WmfFontPitch valueOf(int flag) { - for (WmfFontPitch fp : values()) { - if (fp.flag == flag) return fp; - } - return null; - } - } - - /** - * A 16-bit signed integer that specifies the height, in logical units, of the font's - * character cell. The character height is computed as the character cell height minus the - * internal leading. The font mapper SHOULD interpret the height as follows. - * - * negative value: - * The font mapper SHOULD transform this value into device units and match its - * absolute value against the character height of available fonts. - * - * zero value: - * A default height value MUST be used when creating a physical font. - * - * positive value: - * The font mapper SHOULD transform this value into device units and match it - * against the cell height of available fonts. - * - * For all height comparisons, the font mapper SHOULD find the largest physical - * font that does not exceed the requested size. - */ - int height; - - /** - * A 16-bit signed integer that defines the average width, in logical units, of - * characters in the font. If Width is 0x0000, the aspect ratio of the device SHOULD be matched - * against the digitization aspect ratio of the available fonts to find the closest match, - * determined by the absolute value of the difference. - */ - int width; - - /** - * A 16-bit signed integer that defines the angle, in tenths of degrees, between the - * escapement vector and the x-axis of the device. The escapement vector is parallel - * to the base line of a row of text. - */ - int escapement; - - /** - * A 16-bit signed integer that defines the angle, in tenths of degrees, - * between each character's base line and the x-axis of the device. - */ - int orientation; - - /** - * A 16-bit signed integer that defines the weight of the font in the range 0 - * through 1000. For example, 400 is normal and 700 is bold. If this value is 0x0000, - * a default weight SHOULD be used. - */ - int weight; - - /** - * A 8-bit Boolean value that specifies the italic attribute of the font. - * 0 = not italic / 1 = italic. - */ - boolean italic; - - /** - * An 8-bit Boolean value that specifies the underline attribute of the font. - * 0 = not underlined / 1 = underlined - */ - boolean underline; - - /** - * An 8-bit Boolean value that specifies the strike out attribute of the font. - * 0 = not striked out / 1 = striked out - */ - boolean strikeOut; - - /** - * An 8-bit unsigned integer that defines the character set. - * It SHOULD be set to a value in the {@link WmfCharset} Enumeration. - * - * The DEFAULT_CHARSET value MAY be used to allow the name and size of a font to fully - * describe the logical font. If the specified font name does not exist, a font in another character - * set MAY be substituted. The DEFAULT_CHARSET value is set to a value based on the current - * system locale. For example, when the system locale is United States, it is set to ANSI_CHARSET. - * If a typeface name in the FaceName field is specified, the CharSet value MUST match the - * character set of that typeface. - */ - WmfCharset charSet; - - /** - * An 8-bit unsigned integer that defines the output precision. - */ - WmfOutPrecision outPrecision; - - /** - * An 8-bit unsigned integer that defines the clipping precision. - * These flags can be combined to specify multiple options. - * - * @see WmfClipPrecision - */ - WmfClipPrecision clipPrecision; - - /** - * An 8-bit unsigned integer that defines the output quality. - */ - WmfFontQuality quality; - - /** - * A PitchAndFamily object that defines the pitch and the family of the font. - * Font families specify the look of fonts in a general way and are intended for - * specifying fonts when the exact typeface wanted is not available. - */ - int pitchAndFamily; - - /** - * Font families specify the look of fonts in a general way and are - * intended for specifying fonts when the exact typeface wanted is not available. - * (LSB 4 bits) - */ - WmfFontFamilyClass family; - - /** - * A property of a font that describes the pitch (MSB 2 bits) - */ - WmfFontPitch pitch; - - /** - * A null-terminated string of 8-bit Latin-1 [ISO/IEC-8859-1] ANSI - * characters that specifies the typeface name of the font. The length of this string MUST NOT - * exceed 32 8-bit characters, including the terminating null. - */ - String facename; - - public int init(LittleEndianInputStream leis) throws IOException { - height = leis.readShort(); - width = leis.readShort(); - escapement = leis.readShort(); - orientation = leis.readShort(); - weight = leis.readShort(); - italic = leis.readByte() != 0; - underline = leis.readByte() != 0; - strikeOut = leis.readByte() != 0; - charSet = WmfCharset.valueOf(leis.readUByte()); - outPrecision = WmfOutPrecision.valueOf(leis.readUByte()); - clipPrecision = WmfClipPrecision.valueOf(leis.readUByte()); - quality = WmfFontQuality.valueOf(leis.readUByte()); - pitchAndFamily = leis.readUByte(); - - byte buf[] = new byte[32], b, readBytes = 0; - do { - if (readBytes == 32) { - throw new IOException("Font facename can't be determined."); - } - - buf[readBytes++] = b = leis.readByte(); - } while (b != 0 && b != -1 && readBytes <= 32); - - facename = new String(buf, 0, readBytes-1, Charset.forName("ISO-8859-1")); - - return 5*LittleEndianConsts.SHORT_SIZE+8*LittleEndianConsts.BYTE_SIZE+readBytes; - } - - public int getHeight() { - return height; - } - - public int getWidth() { - return width; - } - - public int getEscapement() { - return escapement; - } - - public int getOrientation() { - return orientation; - } - - public int getWeight() { - return weight; - } - - public boolean isItalic() { - return italic; - } - - public boolean isUnderline() { - return underline; - } - - public boolean isStrikeOut() { - return strikeOut; - } - - public WmfCharset getCharSet() { - return charSet; - } - - public WmfOutPrecision getOutPrecision() { - return outPrecision; - } - - public WmfClipPrecision getClipPrecision() { - return clipPrecision; - } - - public WmfFontQuality getQuality() { - return quality; - } - - public int getPitchAndFamily() { - return pitchAndFamily; - } - - public WmfFontFamilyClass getFamily() { - return WmfFontFamilyClass.valueOf(pitchAndFamily & 0xF); - } - - public WmfFontPitch getPitch() { - return WmfFontPitch.valueOf((pitchAndFamily >>> 6) & 3); - } - - public String getFacename() { - return facename; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; + +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * The Font object specifies the attributes of a logical font + */ +public class HwmfFont { + + private static final POILogger logger = POILogFactory.getLogger(HwmfFont.class); + + public enum WmfCharset { + /** Specifies the English character set. */ + ANSI_CHARSET(0x00000000, "Cp1252"), + /** + * Specifies a character set based on the current system locale; + * for example, when the system locale is United States English, + * the default character set is ANSI_CHARSET. + */ + DEFAULT_CHARSET(0x00000001, "Cp1252"), + /** Specifies a character set of symbols. */ + SYMBOL_CHARSET(0x00000002, ""), + /** Specifies the Apple Macintosh character set. */ + MAC_CHARSET(0x0000004D, "MacRoman"), + /** Specifies the Japanese character set. */ + SHIFTJIS_CHARSET(0x00000080, "Shift_JIS"), + /** Also spelled "Hangeul". Specifies the Hangul Korean character set. */ + HANGUL_CHARSET(0x00000081, "cp949"), + /** Also spelled "Johap". Specifies the Johab Korean character set. */ + JOHAB_CHARSET(0x00000082, "x-Johab"), + /** Specifies the "simplified" Chinese character set for People's Republic of China. */ + GB2312_CHARSET(0x00000086, "GB2312"), + /** + * Specifies the "traditional" Chinese character set, used mostly in + * Taiwan and in the Hong Kong and Macao Special Administrative Regions. + */ + CHINESEBIG5_CHARSET(0x00000088, "Big5"), + /** Specifies the Greek character set. */ + GREEK_CHARSET(0x000000A1, "Cp1253"), + /** Specifies the Turkish character set. */ + TURKISH_CHARSET(0x000000A2, "Cp1254"), + /** Specifies the Vietnamese character set. */ + VIETNAMESE_CHARSET(0x000000A3, "Cp1258"), + /** Specifies the Hebrew character set. */ + HEBREW_CHARSET(0x000000B1, "Cp1255"), + /** Specifies the Arabic character set. */ + ARABIC_CHARSET(0x000000B2, "Cp1256"), + /** Specifies the Baltic (Northeastern European) character set. */ + BALTIC_CHARSET(0x000000BA, "Cp1257"), + /** Specifies the Russian Cyrillic character set. */ + RUSSIAN_CHARSET(0x000000CC, "Cp1251"), + /** Specifies the Thai character set. */ + THAI_CHARSET(0x000000DE, "x-windows-874"), + /** Specifies a Eastern European character set. */ + EASTEUROPE_CHARSET(0x000000EE, "Cp1250"), + /** + * Specifies a mapping to one of the OEM code pages, + * according to the current system locale setting. + */ + OEM_CHARSET(0x000000FF, "Cp1252"); + + int flag; + Charset charset; + + WmfCharset(int flag, String javaCharsetName) { + this.flag = flag; + if (javaCharsetName.length() > 0) { + try { + charset = Charset.forName(javaCharsetName); + return; + } catch (UnsupportedCharsetException e) { + logger.log(POILogger.WARN, "Unsupported charset: "+javaCharsetName); + } + } + charset = null; + } + + /** + * + * @return charset for the font or null if there is no matching charset or + * if the charset is a "default" + */ + public Charset getCharset() { + return charset; + } + + static WmfCharset valueOf(int flag) { + for (WmfCharset cs : values()) { + if (cs.flag == flag) return cs; + } + return null; + } + } + + /** + * The output precision defines how closely the output must match the requested font's height, + * width, character orientation, escapement, pitch, and font type. + */ + public enum WmfOutPrecision { + /** + * A value that specifies default behavior. + */ + OUT_DEFAULT_PRECIS(0x00000000), + /** + * A value that is returned when rasterized fonts are enumerated. + */ + OUT_STRING_PRECIS(0x00000001), + /** + * A value that is returned when TrueType and other outline fonts, and + * vector fonts are enumerated. + */ + OUT_STROKE_PRECIS(0x00000003), + /** + * A value that specifies the choice of a TrueType font when the system + * contains multiple fonts with the same name. + */ + OUT_TT_PRECIS(0x00000004), + /** + * A value that specifies the choice of a device font when the system + * contains multiple fonts with the same name. + */ + OUT_DEVICE_PRECIS(0x00000005), + /** + * A value that specifies the choice of a rasterized font when the system + * contains multiple fonts with the same name. + */ + OUT_RASTER_PRECIS(0x00000006), + /** + * A value that specifies the requirement for only TrueType fonts. If + * there are no TrueType fonts installed in the system, default behavior is specified. + */ + OUT_TT_ONLY_PRECIS(0x00000007), + /** + * A value that specifies the requirement for TrueType and other outline fonts. + */ + OUT_OUTLINE_PRECIS (0x00000008), + /** + * A value that specifies a preference for TrueType and other outline fonts. + */ + OUT_SCREEN_OUTLINE_PRECIS (0x00000009), + /** + * A value that specifies a requirement for only PostScript fonts. If there + * are no PostScript fonts installed in the system, default behavior is specified. + */ + OUT_PS_ONLY_PRECIS (0x0000000A); + + + int flag; + WmfOutPrecision(int flag) { + this.flag = flag; + } + + static WmfOutPrecision valueOf(int flag) { + for (WmfOutPrecision op : values()) { + if (op.flag == flag) return op; + } + return null; + } + } + + /** + * ClipPrecision Flags specify clipping precision, which defines how to clip characters that are + * partially outside a clipping region. These flags can be combined to specify multiple options. + */ + public enum WmfClipPrecision { + + /** + * Specifies that default clipping MUST be used. + */ + CLIP_DEFAULT_PRECIS (0x00000000), + + /** + * This value SHOULD NOT be used. + */ + CLIP_CHARACTER_PRECIS (0x00000001), + + /** + * This value MAY be returned when enumerating rasterized, TrueType and vector fonts. + */ + CLIP_STROKE_PRECIS (0x00000002), + + /** + * This value is used to control font rotation, as follows: + * If set, the rotation for all fonts SHOULD be determined by the orientation of the coordinate system; + * that is, whether the orientation is left-handed or right-handed. + * + * If clear, device fonts SHOULD rotate counterclockwise, but the rotation of other fonts + * SHOULD be determined by the orientation of the coordinate system. + */ + CLIP_LH_ANGLES (0x00000010), + + /** + * This value SHOULD NOT be used. + */ + CLIP_TT_ALWAYS (0x00000020), + + /** + * This value specifies that font association SHOULD< be turned off. + */ + CLIP_DFA_DISABLE (0x00000040), + + /** + * This value specifies that font embedding MUST be used to render document content; + * embedded fonts are read-only. + */ + CLIP_EMBEDDED (0x00000080); + + + int flag; + WmfClipPrecision(int flag) { + this.flag = flag; + } + + static WmfClipPrecision valueOf(int flag) { + for (WmfClipPrecision cp : values()) { + if (cp.flag == flag) return cp; + } + return null; + } + } + + /** + * The output quality defines how carefully to attempt to match the logical font attributes to those of an actual + * physical font. + */ + public enum WmfFontQuality { + /** + * Specifies that the character quality of the font does not matter, so DRAFT_QUALITY can be used. + */ + DEFAULT_QUALITY (0x00), + + /** + * Specifies that the character quality of the font is less important than the + * matching of logical attribuetes. For rasterized fonts, scaling SHOULD be enabled, which + * means that more font sizes are available. + */ + DRAFT_QUALITY (0x01), + + /** + * Specifies that the character quality of the font is more important than the + * matching of logical attributes. For rasterized fonts, scaling SHOULD be disabled, and the font + * closest in size SHOULD be chosen. + */ + PROOF_QUALITY (0x02), + + /** + * Specifies that anti-aliasing SHOULD NOT be used when rendering text. + */ + NONANTIALIASED_QUALITY (0x03), + + /** + * Specifies that anti-aliasing SHOULD be used when rendering text, if the font supports it. + */ + ANTIALIASED_QUALITY (0x04), + + /** + * Specifies that ClearType anti-aliasing SHOULD be used when rendering text, if the font supports it. + * + * Fonts that do not support ClearType anti-aliasing include type 1 fonts, PostScript fonts, + * OpenType fonts without TrueType outlines, rasterized fonts, vector fonts, and device fonts. + */ + CLEARTYPE_QUALITY (0x05); + + int flag; + WmfFontQuality(int flag) { + this.flag = flag; + } + + static WmfFontQuality valueOf(int flag) { + for (WmfFontQuality fq : values()) { + if (fq.flag == flag) return fq; + } + return null; + } + } + + /** + * A property of a font that describes its general appearance. + */ + public enum WmfFontFamilyClass { + /** + * The default font is specified, which is implementation-dependent. + */ + FF_DONTCARE (0x00), + /** + * Fonts with variable stroke widths, which are proportional to the actual widths of + * the glyphs, and which have serifs. "MS Serif" is an example. + */ + FF_ROMAN (0x01), + /** + * Fonts with variable stroke widths, which are proportional to the actual widths of the + * glyphs, and which do not have serifs. "MS Sans Serif" is an example. + */ + FF_SWISS (0x02), + /** + * Fonts with constant stroke width, with or without serifs. Fixed-width fonts are + * usually modern. "Pica", "Elite", and "Courier New" are examples. + */ + FF_MODERN (0x03), + /** + * Fonts designed to look like handwriting. "Script" and "Cursive" are examples. + */ + FF_SCRIPT (0x04), + /** + * Novelty fonts. "Old English" is an example. + */ + FF_DECORATIVE (0x05); + + int flag; + WmfFontFamilyClass(int flag) { + this.flag = flag; + } + + static WmfFontFamilyClass valueOf(int flag) { + for (WmfFontFamilyClass ff : values()) { + if (ff.flag == flag) return ff; + } + return null; + } + } + + /** + * A property of a font that describes the pitch, of the characters. + */ + public enum WmfFontPitch { + /** + * The default pitch, which is implementation-dependent. + */ + DEFAULT_PITCH (0x00), + /** + * A fixed pitch, which means that all the characters in the font occupy the same + * width when output in a string. + */ + FIXED_PITCH (0x01), + /** + * A variable pitch, which means that the characters in the font occupy widths + * that are proportional to the actual widths of the glyphs when output in a string. For example, + * the "i" and space characters usually have much smaller widths than a "W" or "O" character. + */ + VARIABLE_PITCH (0x02); + + int flag; + WmfFontPitch(int flag) { + this.flag = flag; + } + + static WmfFontPitch valueOf(int flag) { + for (WmfFontPitch fp : values()) { + if (fp.flag == flag) return fp; + } + return null; + } + } + + /** + * A 16-bit signed integer that specifies the height, in logical units, of the font's + * character cell. The character height is computed as the character cell height minus the + * internal leading. The font mapper SHOULD interpret the height as follows. + * + * negative value: + * The font mapper SHOULD transform this value into device units and match its + * absolute value against the character height of available fonts. + * + * zero value: + * A default height value MUST be used when creating a physical font. + * + * positive value: + * The font mapper SHOULD transform this value into device units and match it + * against the cell height of available fonts. + * + * For all height comparisons, the font mapper SHOULD find the largest physical + * font that does not exceed the requested size. + */ + int height; + + /** + * A 16-bit signed integer that defines the average width, in logical units, of + * characters in the font. If Width is 0x0000, the aspect ratio of the device SHOULD be matched + * against the digitization aspect ratio of the available fonts to find the closest match, + * determined by the absolute value of the difference. + */ + int width; + + /** + * A 16-bit signed integer that defines the angle, in tenths of degrees, between the + * escapement vector and the x-axis of the device. The escapement vector is parallel + * to the base line of a row of text. + */ + int escapement; + + /** + * A 16-bit signed integer that defines the angle, in tenths of degrees, + * between each character's base line and the x-axis of the device. + */ + int orientation; + + /** + * A 16-bit signed integer that defines the weight of the font in the range 0 + * through 1000. For example, 400 is normal and 700 is bold. If this value is 0x0000, + * a default weight SHOULD be used. + */ + int weight; + + /** + * A 8-bit Boolean value that specifies the italic attribute of the font. + * 0 = not italic / 1 = italic. + */ + boolean italic; + + /** + * An 8-bit Boolean value that specifies the underline attribute of the font. + * 0 = not underlined / 1 = underlined + */ + boolean underline; + + /** + * An 8-bit Boolean value that specifies the strike out attribute of the font. + * 0 = not striked out / 1 = striked out + */ + boolean strikeOut; + + /** + * An 8-bit unsigned integer that defines the character set. + * It SHOULD be set to a value in the {@link WmfCharset} Enumeration. + * + * The DEFAULT_CHARSET value MAY be used to allow the name and size of a font to fully + * describe the logical font. If the specified font name does not exist, a font in another character + * set MAY be substituted. The DEFAULT_CHARSET value is set to a value based on the current + * system locale. For example, when the system locale is United States, it is set to ANSI_CHARSET. + * If a typeface name in the FaceName field is specified, the CharSet value MUST match the + * character set of that typeface. + */ + WmfCharset charSet; + + /** + * An 8-bit unsigned integer that defines the output precision. + */ + WmfOutPrecision outPrecision; + + /** + * An 8-bit unsigned integer that defines the clipping precision. + * These flags can be combined to specify multiple options. + * + * @see WmfClipPrecision + */ + WmfClipPrecision clipPrecision; + + /** + * An 8-bit unsigned integer that defines the output quality. + */ + WmfFontQuality quality; + + /** + * A PitchAndFamily object that defines the pitch and the family of the font. + * Font families specify the look of fonts in a general way and are intended for + * specifying fonts when the exact typeface wanted is not available. + */ + int pitchAndFamily; + + /** + * Font families specify the look of fonts in a general way and are + * intended for specifying fonts when the exact typeface wanted is not available. + * (LSB 4 bits) + */ + WmfFontFamilyClass family; + + /** + * A property of a font that describes the pitch (MSB 2 bits) + */ + WmfFontPitch pitch; + + /** + * A null-terminated string of 8-bit Latin-1 [ISO/IEC-8859-1] ANSI + * characters that specifies the typeface name of the font. The length of this string MUST NOT + * exceed 32 8-bit characters, including the terminating null. + */ + String facename; + + public int init(LittleEndianInputStream leis) throws IOException { + height = leis.readShort(); + width = leis.readShort(); + escapement = leis.readShort(); + orientation = leis.readShort(); + weight = leis.readShort(); + italic = leis.readByte() != 0; + underline = leis.readByte() != 0; + strikeOut = leis.readByte() != 0; + charSet = WmfCharset.valueOf(leis.readUByte()); + outPrecision = WmfOutPrecision.valueOf(leis.readUByte()); + clipPrecision = WmfClipPrecision.valueOf(leis.readUByte()); + quality = WmfFontQuality.valueOf(leis.readUByte()); + pitchAndFamily = leis.readUByte(); + + byte buf[] = new byte[32], b, readBytes = 0; + do { + if (readBytes == 32) { + throw new IOException("Font facename can't be determined."); + } + + buf[readBytes++] = b = leis.readByte(); + } while (b != 0 && b != -1 && readBytes <= 32); + + facename = new String(buf, 0, readBytes-1, Charset.forName("ISO-8859-1")); + + return 5*LittleEndianConsts.SHORT_SIZE+8*LittleEndianConsts.BYTE_SIZE+readBytes; + } + + public int getHeight() { + return height; + } + + public int getWidth() { + return width; + } + + public int getEscapement() { + return escapement; + } + + public int getOrientation() { + return orientation; + } + + public int getWeight() { + return weight; + } + + public boolean isItalic() { + return italic; + } + + public boolean isUnderline() { + return underline; + } + + public boolean isStrikeOut() { + return strikeOut; + } + + public WmfCharset getCharSet() { + return charSet; + } + + public WmfOutPrecision getOutPrecision() { + return outPrecision; + } + + public WmfClipPrecision getClipPrecision() { + return clipPrecision; + } + + public WmfFontQuality getQuality() { + return quality; + } + + public int getPitchAndFamily() { + return pitchAndFamily; + } + + public WmfFontFamilyClass getFamily() { + return WmfFontFamilyClass.valueOf(pitchAndFamily & 0xF); + } + + public WmfFontPitch getPitch() { + return WmfFontPitch.valueOf((pitchAndFamily >>> 6) & 3); + } + + public String getFacename() { + return facename; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java index 00108c4ac8..02f896849a 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java @@ -1,48 +1,48 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -/** - * The HatchStyle Enumeration specifies the hatch pattern. - */ -public enum HwmfHatchStyle { - /** ----- - A horizontal hatch */ - HS_HORIZONTAL(0x0000), - /** ||||| - A vertical hatch */ - HS_VERTICAL(0x0001), - /** \\\\\ - A 45-degree downward, left-to-right hatch. */ - HS_FDIAGONAL(0x0002), - /** ///// - A 45-degree upward, left-to-right hatch. */ - HS_BDIAGONAL(0x0003), - /** +++++ - A horizontal and vertical cross-hatch. */ - HS_CROSS(0x0004), - /** xxxxx - A 45-degree crosshatch. */ - HS_DIAGCROSS(0x0005); - - int flag; - HwmfHatchStyle(int flag) { - this.flag = flag; - } - - static HwmfHatchStyle valueOf(int flag) { - for (HwmfHatchStyle hs : values()) { - if (hs.flag == flag) return hs; - } - return null; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +/** + * The HatchStyle Enumeration specifies the hatch pattern. + */ +public enum HwmfHatchStyle { + /** ----- - A horizontal hatch */ + HS_HORIZONTAL(0x0000), + /** ||||| - A vertical hatch */ + HS_VERTICAL(0x0001), + /** \\\\\ - A 45-degree downward, left-to-right hatch. */ + HS_FDIAGONAL(0x0002), + /** ///// - A 45-degree upward, left-to-right hatch. */ + HS_BDIAGONAL(0x0003), + /** +++++ - A horizontal and vertical cross-hatch. */ + HS_CROSS(0x0004), + /** xxxxx - A 45-degree crosshatch. */ + HS_DIAGCROSS(0x0005); + + int flag; + HwmfHatchStyle(int flag) { + this.flag = flag; + } + + static HwmfHatchStyle valueOf(int flag) { + for (HwmfHatchStyle hs : values()) { + if (hs.flag == flag) return hs; + } + return null; + } } \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHeader.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHeader.java index 247f22bd86..811caa0d20 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHeader.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHeader.java @@ -1,77 +1,77 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.io.IOException; - -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; - -public class HwmfHeader { - private int type; - private int recordSize; - private int version; - private int filesize; - private int numberOfObjects; - private long maxRecord; - private int numberOfMembers; - - public HwmfHeader(LittleEndianInputStream leis) throws IOException { - // Type (2 bytes): A 16-bit unsigned integer that defines the type of metafile - // MEMORYMETAFILE = 0x0001, DISKMETAFILE = 0x0002 - type = leis.readUShort(); - - // HeaderSize (2 bytes): A 16-bit unsigned integer that defines the number - // of 16-bit words in the header. - recordSize = leis.readUShort(); - int bytesLeft = recordSize*LittleEndianConsts.SHORT_SIZE-4; - - // Version (2 bytes): A 16-bit unsigned integer that defines the metafile version. - // METAVERSION100 = 0x0100, METAVERSION300 = 0x0300 - version = leis.readUShort(); - bytesLeft -= LittleEndianConsts.SHORT_SIZE; - - // SizeLow (2 bytes): A 16-bit unsigned integer that defines the low-order word - // of the number of 16-bit words in the entire metafile. - // SizeHigh (2 bytes): A 16-bit unsigned integer that defines the high-order word - // of the number of 16-bit words in the entire metafile. - filesize = leis.readInt(); - bytesLeft -= LittleEndianConsts.INT_SIZE; - - // NumberOfObjects (2 bytes): A 16-bit unsigned integer that specifies the number - // of graphics objects that are defined in the entire metafile. These objects include - // brushes, pens, and the other objects - numberOfObjects = leis.readUShort(); - bytesLeft -= LittleEndianConsts.SHORT_SIZE; - - // MaxRecord (4 bytes): A 32-bit unsigned integer that specifies the size of the - // largest record used in the metafile (in 16-bit elements). - maxRecord = leis.readUInt(); - bytesLeft -= LittleEndianConsts.INT_SIZE; - - // NumberOfMembers (2 bytes): A 16-bit unsigned integer that is not used. - // It SHOULD be 0x0000. - numberOfMembers = leis.readUShort(); - bytesLeft -= LittleEndianConsts.SHORT_SIZE; - - if (bytesLeft > 0) { - long len = leis.skip(bytesLeft); - assert(len == bytesLeft); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.io.IOException; + +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; + +public class HwmfHeader { + private int type; + private int recordSize; + private int version; + private int filesize; + private int numberOfObjects; + private long maxRecord; + private int numberOfMembers; + + public HwmfHeader(LittleEndianInputStream leis) throws IOException { + // Type (2 bytes): A 16-bit unsigned integer that defines the type of metafile + // MEMORYMETAFILE = 0x0001, DISKMETAFILE = 0x0002 + type = leis.readUShort(); + + // HeaderSize (2 bytes): A 16-bit unsigned integer that defines the number + // of 16-bit words in the header. + recordSize = leis.readUShort(); + int bytesLeft = recordSize*LittleEndianConsts.SHORT_SIZE-4; + + // Version (2 bytes): A 16-bit unsigned integer that defines the metafile version. + // METAVERSION100 = 0x0100, METAVERSION300 = 0x0300 + version = leis.readUShort(); + bytesLeft -= LittleEndianConsts.SHORT_SIZE; + + // SizeLow (2 bytes): A 16-bit unsigned integer that defines the low-order word + // of the number of 16-bit words in the entire metafile. + // SizeHigh (2 bytes): A 16-bit unsigned integer that defines the high-order word + // of the number of 16-bit words in the entire metafile. + filesize = leis.readInt(); + bytesLeft -= LittleEndianConsts.INT_SIZE; + + // NumberOfObjects (2 bytes): A 16-bit unsigned integer that specifies the number + // of graphics objects that are defined in the entire metafile. These objects include + // brushes, pens, and the other objects + numberOfObjects = leis.readUShort(); + bytesLeft -= LittleEndianConsts.SHORT_SIZE; + + // MaxRecord (4 bytes): A 32-bit unsigned integer that specifies the size of the + // largest record used in the metafile (in 16-bit elements). + maxRecord = leis.readUInt(); + bytesLeft -= LittleEndianConsts.INT_SIZE; + + // NumberOfMembers (2 bytes): A 16-bit unsigned integer that is not used. + // It SHOULD be 0x0000. + numberOfMembers = leis.readUShort(); + bytesLeft -= LittleEndianConsts.SHORT_SIZE; + + if (bytesLeft > 0) { + long len = leis.skip(bytesLeft); + assert(len == bytesLeft); + } + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java index cae700e6dc..f4f9a65c27 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java @@ -1,114 +1,114 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -/** - * A 16-bit unsigned integer that defines the mapping mode. - * - * The MapMode defines how logical units are mapped to physical units; - * that is, assuming that the origins in both the logical and physical coordinate systems - * are at the same point on the drawing surface, what is the physical coordinate (x',y') - * that corresponds to logical coordinate (x,y). - * - * For example, suppose the mapping mode is MM_TEXT. Given the following definition of that - * mapping mode, and an origin (0,0) at the top left corner of the drawing surface, logical - * coordinate (4,5) would map to physical coordinate (4,5) in pixels. - * - * Now suppose the mapping mode is MM_LOENGLISH, with the same origin as the previous - * example. Given the following definition of that mapping mode, logical coordinate (4,-5) - * would map to physical coordinate (0.04,0.05) in inches. - */ -public enum HwmfMapMode { - /** - * Each logical unit is mapped to one device pixel. - * Positive x is to the right; positive y is down. - */ - MM_TEXT(0x0001, 0), - - /** - * Each logical unit is mapped to 0.1 millimeter. - * Positive x is to the right; positive y is up. - */ - MM_LOMETRIC(0x0002, 254), - - /** - * Each logical unit is mapped to 0.01 millimeter. - * Positive x is to the right; positive y is up. - */ - MM_HIMETRIC(0x0003, 2540), - - /** - * Each logical unit is mapped to 0.01 inch. - * Positive x is to the right; positive y is up. - */ - MM_LOENGLISH(0x0004, 100), - - /** - * Each logical unit is mapped to 0.001 inch. - * Positive x is to the right; positive y is up. - */ - MM_HIENGLISH(0x0005, 1000), - - /** - * Each logical unit is mapped to one twentieth (1/20) of a point. - * In printing, a point is 1/72 of an inch; therefore, 1/20 of a point is 1/1440 of an inch. - * This unit is also known as a "twip". - * Positive x is to the right; positive y is up. - */ - MM_TWIPS(0x0006, 1440), - - /** - * Logical units are mapped to arbitrary device units with equally scaled axes; - * that is, one unit along the x-axis is equal to one unit along the y-axis. - * The META_SETWINDOWEXT and META_SETVIEWPORTEXT records specify the units and the - * orientation of the axes. - * The processing application SHOULD make adjustments as necessary to ensure the x and y - * units remain the same size. For example, when the window extent is set, the viewport - * SHOULD be adjusted to keep the units isotropic. - */ - MM_ISOTROPIC(0x0007, -1), - - /** - * Logical units are mapped to arbitrary units with arbitrarily scaled axes. - */ - MM_ANISOTROPIC(0x0008, -1); - - /** - * native flag - */ - public final int flag; - - /** - * transformation units - usually scale relative to current dpi. - * when scale == 0, then don't scale - * when scale == -1, then scale relative to window dimension. - */ - public final int scale; - - HwmfMapMode(int flag, int scale) { - this.flag = flag; - this.scale = scale; - } - - static HwmfMapMode valueOf(int flag) { - for (HwmfMapMode mm : values()) { - if (mm.flag == flag) return mm; - } - return MM_ISOTROPIC; - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +/** + * A 16-bit unsigned integer that defines the mapping mode. + * + * The MapMode defines how logical units are mapped to physical units; + * that is, assuming that the origins in both the logical and physical coordinate systems + * are at the same point on the drawing surface, what is the physical coordinate (x',y') + * that corresponds to logical coordinate (x,y). + * + * For example, suppose the mapping mode is MM_TEXT. Given the following definition of that + * mapping mode, and an origin (0,0) at the top left corner of the drawing surface, logical + * coordinate (4,5) would map to physical coordinate (4,5) in pixels. + * + * Now suppose the mapping mode is MM_LOENGLISH, with the same origin as the previous + * example. Given the following definition of that mapping mode, logical coordinate (4,-5) + * would map to physical coordinate (0.04,0.05) in inches. + */ +public enum HwmfMapMode { + /** + * Each logical unit is mapped to one device pixel. + * Positive x is to the right; positive y is down. + */ + MM_TEXT(0x0001, 0), + + /** + * Each logical unit is mapped to 0.1 millimeter. + * Positive x is to the right; positive y is up. + */ + MM_LOMETRIC(0x0002, 254), + + /** + * Each logical unit is mapped to 0.01 millimeter. + * Positive x is to the right; positive y is up. + */ + MM_HIMETRIC(0x0003, 2540), + + /** + * Each logical unit is mapped to 0.01 inch. + * Positive x is to the right; positive y is up. + */ + MM_LOENGLISH(0x0004, 100), + + /** + * Each logical unit is mapped to 0.001 inch. + * Positive x is to the right; positive y is up. + */ + MM_HIENGLISH(0x0005, 1000), + + /** + * Each logical unit is mapped to one twentieth (1/20) of a point. + * In printing, a point is 1/72 of an inch; therefore, 1/20 of a point is 1/1440 of an inch. + * This unit is also known as a "twip". + * Positive x is to the right; positive y is up. + */ + MM_TWIPS(0x0006, 1440), + + /** + * Logical units are mapped to arbitrary device units with equally scaled axes; + * that is, one unit along the x-axis is equal to one unit along the y-axis. + * The META_SETWINDOWEXT and META_SETVIEWPORTEXT records specify the units and the + * orientation of the axes. + * The processing application SHOULD make adjustments as necessary to ensure the x and y + * units remain the same size. For example, when the window extent is set, the viewport + * SHOULD be adjusted to keep the units isotropic. + */ + MM_ISOTROPIC(0x0007, -1), + + /** + * Logical units are mapped to arbitrary units with arbitrarily scaled axes. + */ + MM_ANISOTROPIC(0x0008, -1); + + /** + * native flag + */ + public final int flag; + + /** + * transformation units - usually scale relative to current dpi. + * when scale == 0, then don't scale + * when scale == -1, then scale relative to window dimension. + */ + public final int scale; + + HwmfMapMode(int flag, int scale) { + this.flag = flag; + this.scale = scale; + } + + static HwmfMapMode valueOf(int flag) { + for (HwmfMapMode mm : values()) { + if (mm.flag == flag) return mm; + } + return MM_ISOTROPIC; + } } \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java index c8f280ecdd..f5ab077d22 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java @@ -1,581 +1,581 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.awt.image.BufferedImage; -import java.io.IOException; - -import org.apache.poi.hwmf.draw.HwmfDrawProperties; -import org.apache.poi.hwmf.draw.HwmfGraphics; -import org.apache.poi.hwmf.record.HwmfFill.ColorUsage; -import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; - -public class HwmfMisc { - - /** - * The META_SAVEDC record saves the playback device context for later retrieval. - */ - public static class WmfSaveDc implements HwmfRecord { - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.saveDc; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - return 0; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.saveProperties(); - } - } - - /** - * The META_SETRELABS record is reserved and not supported. - */ - public static class WmfSetRelabs implements HwmfRecord { - public HwmfRecordType getRecordType() { - return HwmfRecordType.setRelabs; - } - - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - return 0; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_RESTOREDC record restores the playback device context from a previously saved device - * context. - */ - public static class WmfRestoreDc implements HwmfRecord { - - /** - * nSavedDC (2 bytes): A 16-bit signed integer that defines the saved state to be restored. If this - * member is positive, nSavedDC represents a specific instance of the state to be restored. If - * this member is negative, nSavedDC represents an instance relative to the current state. - */ - private int nSavedDC; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.restoreDc; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - nSavedDC = leis.readShort(); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.restoreProperties(nSavedDC); - } - } - - /** - * The META_SETBKCOLOR record sets the background color in the playback device context to a - * specified color, or to the nearest physical color if the device cannot represent the specified color. - */ - public static class WmfSetBkColor implements HwmfRecord { - - private HwmfColorRef colorRef; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setBkColor; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - colorRef = new HwmfColorRef(); - return colorRef.init(leis); - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.getProperties().setBackgroundColor(colorRef); - } - } - - /** - * The META_SETBKMODE record defines the background raster operation mix mode in the playback - * device context. The background mix mode is the mode for combining pens, text, hatched brushes, - * and interiors of filled objects with background colors on the output surface. - */ - public static class WmfSetBkMode implements HwmfRecord { - - /** - * A 16-bit unsigned integer that defines background mix mode. - */ - public enum HwmfBkMode { - TRANSPARENT(0x0001), OPAQUE(0x0002); - - int flag; - HwmfBkMode(int flag) { - this.flag = flag; - } - - static HwmfBkMode valueOf(int flag) { - for (HwmfBkMode bs : values()) { - if (bs.flag == flag) return bs; - } - return null; - } - } - - private HwmfBkMode bkMode; - - public HwmfRecordType getRecordType() { - return HwmfRecordType.setBkMode; - } - - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - bkMode = HwmfBkMode.valueOf(leis.readUShort()); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.getProperties().setBkMode(bkMode); - } - } - - /** - * The META_SETLAYOUT record defines the layout orientation in the playback device context. - * The layout orientation determines the direction in which text and graphics are drawn - */ - public static class WmfSetLayout implements HwmfRecord { - - /** - * A 16-bit unsigned integer that defines the layout of text and graphics. - * LAYOUT_LTR = 0x0000 - * LAYOUT_RTL = 0x0001 - * LAYOUT_BITMAPORIENTATIONPRESERVED = 0x0008 - */ - private int layout; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setLayout; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - layout = leis.readUShort(); - // A 16-bit field that MUST be ignored. - /*int reserved =*/ leis.readShort(); - return 2*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_SETMAPMODE record defines the mapping mode in the playback device context. - * The mapping mode defines the unit of measure used to transform page-space units into - * device-space units, and also defines the orientation of the device's x and y axes. - */ - public static class WmfSetMapMode implements HwmfRecord { - - private HwmfMapMode mapMode; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setMapMode; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - mapMode = HwmfMapMode.valueOf(leis.readUShort()); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.getProperties().setMapMode(mapMode); - ctx.updateWindowMapMode(); - } - } - - /** - * The META_SETMAPPERFLAGS record defines the algorithm that the font mapper uses when it maps - * logical fonts to physical fonts. - */ - public static class WmfSetMapperFlags implements HwmfRecord { - - /** - * A 32-bit unsigned integer that defines whether the font mapper should attempt to - * match a font's aspect ratio to the current device's aspect ratio. If bit 0 is - * set, the mapper selects only matching fonts. - */ - private long mapperValues; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setMapperFlags; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - mapperValues = leis.readUInt(); - return LittleEndianConsts.INT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_SETROP2 record defines the foreground raster operation mix mode in the playback device - * context. The foreground mix mode is the mode for combining pens and interiors of filled objects with - * foreground colors on the output surface. - */ - public static class WmfSetRop2 implements HwmfRecord { - - /** - * A 16-bit unsigned integer that defines the foreground binary raster - * operation mixing mode - */ - private HwmfBinaryRasterOp drawMode; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setRop2; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - drawMode = HwmfBinaryRasterOp.valueOf(leis.readUShort()); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_SETSTRETCHBLTMODE record defines the bitmap stretching mode in the playback device - * context. - */ - public static class WmfSetStretchBltMode implements HwmfRecord { - - /** - * A 16-bit unsigned integer that defines bitmap stretching mode. - * This MUST be one of the values: - * BLACKONWHITE = 0x0001, - * WHITEONBLACK = 0x0002, - * COLORONCOLOR = 0x0003, - * HALFTONE = 0x0004 - */ - private int setStretchBltMode; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setStretchBltMode; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - setStretchBltMode = leis.readUShort(); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_DIBCREATEPATTERNBRUSH record creates a Brush Object with a - * pattern specified by a DeviceIndependentBitmap (DIB) Object - */ - public static class WmfDibCreatePatternBrush implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { - - private HwmfBrushStyle style; - - /** - * A 16-bit unsigned integer that defines whether the Colors field of a DIB - * Object contains explicit RGB values, or indexes into a palette. - * - * If the Style field specifies BS_PATTERN, a ColorUsage value of DIB_RGB_COLORS MUST be - * used regardless of the contents of this field. - * - * If the Style field specified anything but BS_PATTERN, this field MUST be one of the ColorUsage values. - */ - private ColorUsage colorUsage; - - private HwmfBitmapDib patternDib; - private HwmfBitmap16 pattern16; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.dibCreatePatternBrush; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - style = HwmfBrushStyle.valueOf(leis.readUShort()); - colorUsage = ColorUsage.valueOf(leis.readUShort()); - int size = 2*LittleEndianConsts.SHORT_SIZE; - switch (style) { - case BS_SOLID: - case BS_NULL: - case BS_DIBPATTERN: - case BS_DIBPATTERNPT: - case BS_HATCHED: - case BS_PATTERN: - patternDib = new HwmfBitmapDib(); - size += patternDib.init(leis, (int)(recordSize-6-size)); - break; - case BS_INDEXED: - case BS_DIBPATTERN8X8: - case BS_MONOPATTERN: - case BS_PATTERN8X8: - throw new RuntimeException("pattern not supported"); - } - return size; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - HwmfDrawProperties prop = ctx.getProperties(); - prop.setBrushStyle(style); - prop.setBrushBitmap(getImage()); - } - - @Override - public BufferedImage getImage() { - if (patternDib != null) { - return patternDib.getImage(); - } else if (pattern16 != null) { - return pattern16.getImage(); - } else { - return null; - } - } - } - - /** - * The META_DELETEOBJECT record deletes an object, including Bitmap16, Brush, - * DeviceIndependentBitmap, Font, Palette, Pen, and Region. After the object is deleted, - * its index in the WMF Object Table is no longer valid but is available to be reused. - */ - public static class WmfDeleteObject implements HwmfRecord { - /** - * A 16-bit unsigned integer used to index into the WMF Object Table to - * get the object to be deleted. - */ - private int objectIndex; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.deleteObject; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - objectIndex = leis.readUShort(); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.unsetObjectTableEntry(objectIndex); - } - } - - public static class WmfCreatePatternBrush implements HwmfRecord, HwmfObjectTableEntry { - - private HwmfBitmap16 pattern; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.createPatternBrush; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - pattern = new HwmfBitmap16(true); - return pattern.init(leis); - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - HwmfDrawProperties dp = ctx.getProperties(); - dp.setBrushBitmap(pattern.getImage()); - dp.setBrushStyle(HwmfBrushStyle.BS_PATTERN); - } - } - - public static class WmfCreatePenIndirect implements HwmfRecord, HwmfObjectTableEntry { - - private HwmfPenStyle penStyle; - /** - * A 32-bit PointS Object that specifies a point for the object dimensions. - * The x-coordinate is the pen width. The y-coordinate is ignored. - */ - private int xWidth; - @SuppressWarnings("unused") - private int yWidth; - /** - * A 32-bit ColorRef Object that specifies the pen color value. - */ - private HwmfColorRef colorRef; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.createPenIndirect; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - penStyle = HwmfPenStyle.valueOf(leis.readUShort()); - xWidth = leis.readShort(); - yWidth = leis.readShort(); - colorRef = new HwmfColorRef(); - int size = colorRef.init(leis); - return size+3*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - HwmfDrawProperties p = ctx.getProperties(); - p.setPenStyle(penStyle); - p.setPenColor(colorRef); - p.setPenWidth(xWidth); - } - } - - /** - * The META_CREATEBRUSHINDIRECT record creates a Brush Object - * from a LogBrush Object. - * - * The following table shows the relationship between values in the BrushStyle, - * ColorRef and BrushHatch fields in a LogBrush Object. Only supported brush styles are listed. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    BrushStyleColorRefBrushHatch
    BS_SOLIDSHOULD be a ColorRef Object, which determines the color of the brush.Not used, and SHOULD be ignored.
    BS_NULLNot used, and SHOULD be ignored.Not used, and SHOULD be ignored.
    BS_PATTERNNot used, and SHOULD be ignored.Not used. A default object, such as a solidcolor black Brush Object, MAY be created.
    BS_DIBPATTERNNot used, and SHOULD be ignored.Not used. A default object, such as a solidcolor black Brush Object, MAY be created
    BS_DIBPATTERNPTNot used, and SHOULD be ignored.Not used. A default object, such as a solidcolor black Brush Object, MAY be created.
    BS_HATCHEDSHOULD be a ColorRef Object, which determines the foreground color of the hatch pattern.A value from the {@link HwmfHatchStyle} Enumeration that specifies the orientation of lines used to create the hatch.
    - */ - public static class WmfCreateBrushIndirect implements HwmfRecord, HwmfObjectTableEntry { - private HwmfBrushStyle brushStyle; - - private HwmfColorRef colorRef; - - /** - * A 16-bit field that specifies the brush hatch type. - * Its interpretation depends on the value of BrushStyle. - * - */ - private HwmfHatchStyle brushHatch; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.createBrushIndirect; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - brushStyle = HwmfBrushStyle.valueOf(leis.readUShort()); - colorRef = new HwmfColorRef(); - int size = colorRef.init(leis); - brushHatch = HwmfHatchStyle.valueOf(leis.readUShort()); - return size+2*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.addObjectTableEntry(this); - } - - @Override - public void applyObject(HwmfGraphics ctx) { - HwmfDrawProperties p = ctx.getProperties(); - p.setBrushStyle(brushStyle); - p.setBrushColor(colorRef); - p.setBrushHatch(brushHatch); - } - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.awt.image.BufferedImage; +import java.io.IOException; + +import org.apache.poi.hwmf.draw.HwmfDrawProperties; +import org.apache.poi.hwmf.draw.HwmfGraphics; +import org.apache.poi.hwmf.record.HwmfFill.ColorUsage; +import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; + +public class HwmfMisc { + + /** + * The META_SAVEDC record saves the playback device context for later retrieval. + */ + public static class WmfSaveDc implements HwmfRecord { + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.saveDc; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + return 0; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.saveProperties(); + } + } + + /** + * The META_SETRELABS record is reserved and not supported. + */ + public static class WmfSetRelabs implements HwmfRecord { + public HwmfRecordType getRecordType() { + return HwmfRecordType.setRelabs; + } + + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + return 0; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_RESTOREDC record restores the playback device context from a previously saved device + * context. + */ + public static class WmfRestoreDc implements HwmfRecord { + + /** + * nSavedDC (2 bytes): A 16-bit signed integer that defines the saved state to be restored. If this + * member is positive, nSavedDC represents a specific instance of the state to be restored. If + * this member is negative, nSavedDC represents an instance relative to the current state. + */ + private int nSavedDC; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.restoreDc; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + nSavedDC = leis.readShort(); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.restoreProperties(nSavedDC); + } + } + + /** + * The META_SETBKCOLOR record sets the background color in the playback device context to a + * specified color, or to the nearest physical color if the device cannot represent the specified color. + */ + public static class WmfSetBkColor implements HwmfRecord { + + private HwmfColorRef colorRef; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setBkColor; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + colorRef = new HwmfColorRef(); + return colorRef.init(leis); + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setBackgroundColor(colorRef); + } + } + + /** + * The META_SETBKMODE record defines the background raster operation mix mode in the playback + * device context. The background mix mode is the mode for combining pens, text, hatched brushes, + * and interiors of filled objects with background colors on the output surface. + */ + public static class WmfSetBkMode implements HwmfRecord { + + /** + * A 16-bit unsigned integer that defines background mix mode. + */ + public enum HwmfBkMode { + TRANSPARENT(0x0001), OPAQUE(0x0002); + + int flag; + HwmfBkMode(int flag) { + this.flag = flag; + } + + static HwmfBkMode valueOf(int flag) { + for (HwmfBkMode bs : values()) { + if (bs.flag == flag) return bs; + } + return null; + } + } + + private HwmfBkMode bkMode; + + public HwmfRecordType getRecordType() { + return HwmfRecordType.setBkMode; + } + + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + bkMode = HwmfBkMode.valueOf(leis.readUShort()); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setBkMode(bkMode); + } + } + + /** + * The META_SETLAYOUT record defines the layout orientation in the playback device context. + * The layout orientation determines the direction in which text and graphics are drawn + */ + public static class WmfSetLayout implements HwmfRecord { + + /** + * A 16-bit unsigned integer that defines the layout of text and graphics. + * LAYOUT_LTR = 0x0000 + * LAYOUT_RTL = 0x0001 + * LAYOUT_BITMAPORIENTATIONPRESERVED = 0x0008 + */ + private int layout; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setLayout; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + layout = leis.readUShort(); + // A 16-bit field that MUST be ignored. + /*int reserved =*/ leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_SETMAPMODE record defines the mapping mode in the playback device context. + * The mapping mode defines the unit of measure used to transform page-space units into + * device-space units, and also defines the orientation of the device's x and y axes. + */ + public static class WmfSetMapMode implements HwmfRecord { + + private HwmfMapMode mapMode; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setMapMode; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + mapMode = HwmfMapMode.valueOf(leis.readUShort()); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setMapMode(mapMode); + ctx.updateWindowMapMode(); + } + } + + /** + * The META_SETMAPPERFLAGS record defines the algorithm that the font mapper uses when it maps + * logical fonts to physical fonts. + */ + public static class WmfSetMapperFlags implements HwmfRecord { + + /** + * A 32-bit unsigned integer that defines whether the font mapper should attempt to + * match a font's aspect ratio to the current device's aspect ratio. If bit 0 is + * set, the mapper selects only matching fonts. + */ + private long mapperValues; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setMapperFlags; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + mapperValues = leis.readUInt(); + return LittleEndianConsts.INT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_SETROP2 record defines the foreground raster operation mix mode in the playback device + * context. The foreground mix mode is the mode for combining pens and interiors of filled objects with + * foreground colors on the output surface. + */ + public static class WmfSetRop2 implements HwmfRecord { + + /** + * A 16-bit unsigned integer that defines the foreground binary raster + * operation mixing mode + */ + private HwmfBinaryRasterOp drawMode; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setRop2; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + drawMode = HwmfBinaryRasterOp.valueOf(leis.readUShort()); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_SETSTRETCHBLTMODE record defines the bitmap stretching mode in the playback device + * context. + */ + public static class WmfSetStretchBltMode implements HwmfRecord { + + /** + * A 16-bit unsigned integer that defines bitmap stretching mode. + * This MUST be one of the values: + * BLACKONWHITE = 0x0001, + * WHITEONBLACK = 0x0002, + * COLORONCOLOR = 0x0003, + * HALFTONE = 0x0004 + */ + private int setStretchBltMode; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setStretchBltMode; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + setStretchBltMode = leis.readUShort(); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + /** + * The META_DIBCREATEPATTERNBRUSH record creates a Brush Object with a + * pattern specified by a DeviceIndependentBitmap (DIB) Object + */ + public static class WmfDibCreatePatternBrush implements HwmfRecord, HwmfImageRecord, HwmfObjectTableEntry { + + private HwmfBrushStyle style; + + /** + * A 16-bit unsigned integer that defines whether the Colors field of a DIB + * Object contains explicit RGB values, or indexes into a palette. + * + * If the Style field specifies BS_PATTERN, a ColorUsage value of DIB_RGB_COLORS MUST be + * used regardless of the contents of this field. + * + * If the Style field specified anything but BS_PATTERN, this field MUST be one of the ColorUsage values. + */ + private ColorUsage colorUsage; + + private HwmfBitmapDib patternDib; + private HwmfBitmap16 pattern16; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.dibCreatePatternBrush; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + style = HwmfBrushStyle.valueOf(leis.readUShort()); + colorUsage = ColorUsage.valueOf(leis.readUShort()); + int size = 2*LittleEndianConsts.SHORT_SIZE; + switch (style) { + case BS_SOLID: + case BS_NULL: + case BS_DIBPATTERN: + case BS_DIBPATTERNPT: + case BS_HATCHED: + case BS_PATTERN: + patternDib = new HwmfBitmapDib(); + size += patternDib.init(leis, (int)(recordSize-6-size)); + break; + case BS_INDEXED: + case BS_DIBPATTERN8X8: + case BS_MONOPATTERN: + case BS_PATTERN8X8: + throw new RuntimeException("pattern not supported"); + } + return size; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + HwmfDrawProperties prop = ctx.getProperties(); + prop.setBrushStyle(style); + prop.setBrushBitmap(getImage()); + } + + @Override + public BufferedImage getImage() { + if (patternDib != null) { + return patternDib.getImage(); + } else if (pattern16 != null) { + return pattern16.getImage(); + } else { + return null; + } + } + } + + /** + * The META_DELETEOBJECT record deletes an object, including Bitmap16, Brush, + * DeviceIndependentBitmap, Font, Palette, Pen, and Region. After the object is deleted, + * its index in the WMF Object Table is no longer valid but is available to be reused. + */ + public static class WmfDeleteObject implements HwmfRecord { + /** + * A 16-bit unsigned integer used to index into the WMF Object Table to + * get the object to be deleted. + */ + private int objectIndex; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.deleteObject; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + objectIndex = leis.readUShort(); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.unsetObjectTableEntry(objectIndex); + } + } + + public static class WmfCreatePatternBrush implements HwmfRecord, HwmfObjectTableEntry { + + private HwmfBitmap16 pattern; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.createPatternBrush; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + pattern = new HwmfBitmap16(true); + return pattern.init(leis); + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + HwmfDrawProperties dp = ctx.getProperties(); + dp.setBrushBitmap(pattern.getImage()); + dp.setBrushStyle(HwmfBrushStyle.BS_PATTERN); + } + } + + public static class WmfCreatePenIndirect implements HwmfRecord, HwmfObjectTableEntry { + + private HwmfPenStyle penStyle; + /** + * A 32-bit PointS Object that specifies a point for the object dimensions. + * The x-coordinate is the pen width. The y-coordinate is ignored. + */ + private int xWidth; + @SuppressWarnings("unused") + private int yWidth; + /** + * A 32-bit ColorRef Object that specifies the pen color value. + */ + private HwmfColorRef colorRef; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.createPenIndirect; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + penStyle = HwmfPenStyle.valueOf(leis.readUShort()); + xWidth = leis.readShort(); + yWidth = leis.readShort(); + colorRef = new HwmfColorRef(); + int size = colorRef.init(leis); + return size+3*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + HwmfDrawProperties p = ctx.getProperties(); + p.setPenStyle(penStyle); + p.setPenColor(colorRef); + p.setPenWidth(xWidth); + } + } + + /** + * The META_CREATEBRUSHINDIRECT record creates a Brush Object + * from a LogBrush Object. + * + * The following table shows the relationship between values in the BrushStyle, + * ColorRef and BrushHatch fields in a LogBrush Object. Only supported brush styles are listed. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    BrushStyleColorRefBrushHatch
    BS_SOLIDSHOULD be a ColorRef Object, which determines the color of the brush.Not used, and SHOULD be ignored.
    BS_NULLNot used, and SHOULD be ignored.Not used, and SHOULD be ignored.
    BS_PATTERNNot used, and SHOULD be ignored.Not used. A default object, such as a solidcolor black Brush Object, MAY be created.
    BS_DIBPATTERNNot used, and SHOULD be ignored.Not used. A default object, such as a solidcolor black Brush Object, MAY be created
    BS_DIBPATTERNPTNot used, and SHOULD be ignored.Not used. A default object, such as a solidcolor black Brush Object, MAY be created.
    BS_HATCHEDSHOULD be a ColorRef Object, which determines the foreground color of the hatch pattern.A value from the {@link HwmfHatchStyle} Enumeration that specifies the orientation of lines used to create the hatch.
    + */ + public static class WmfCreateBrushIndirect implements HwmfRecord, HwmfObjectTableEntry { + private HwmfBrushStyle brushStyle; + + private HwmfColorRef colorRef; + + /** + * A 16-bit field that specifies the brush hatch type. + * Its interpretation depends on the value of BrushStyle. + * + */ + private HwmfHatchStyle brushHatch; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.createBrushIndirect; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + brushStyle = HwmfBrushStyle.valueOf(leis.readUShort()); + colorRef = new HwmfColorRef(); + int size = colorRef.init(leis); + brushHatch = HwmfHatchStyle.valueOf(leis.readUShort()); + return size+2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + HwmfDrawProperties p = ctx.getProperties(); + p.setBrushStyle(brushStyle); + p.setBrushColor(colorRef); + p.setBrushHatch(brushHatch); + } + } } \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfObjectTableEntry.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfObjectTableEntry.java index f05e6907c7..0aad3d6d16 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfObjectTableEntry.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfObjectTableEntry.java @@ -1,28 +1,28 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import org.apache.poi.hwmf.draw.HwmfGraphics; - -/** - * Marker interface for Records, which should be added to the - * WMF object table for further selection - */ -public interface HwmfObjectTableEntry { - public void applyObject(HwmfGraphics ctx); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import org.apache.poi.hwmf.draw.HwmfGraphics; + +/** + * Marker interface for Records, which should be added to the + * WMF object table for further selection + */ +public interface HwmfObjectTableEntry { + public void applyObject(HwmfGraphics ctx); +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java index eb6139c217..c280988ce4 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java @@ -1,325 +1,325 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.awt.Color; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.poi.hwmf.draw.HwmfDrawProperties; -import org.apache.poi.hwmf.draw.HwmfGraphics; -import org.apache.poi.util.BitField; -import org.apache.poi.util.BitFieldFactory; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; - -public class HwmfPalette { - - public static class PaletteEntry { - private static final BitField PC_RESERVED = BitFieldFactory.getInstance(0x01); - private static final BitField PC_EXPLICIT = BitFieldFactory.getInstance(0x02); - private static final BitField PC_NOCOLLAPSE = BitFieldFactory.getInstance(0x04); - - private int values; - private Color colorRef; - - private PaletteEntry() { - this.values = PC_RESERVED.set(0); - this.colorRef = Color.BLACK; - } - - private PaletteEntry(PaletteEntry other) { - this.values = other.values; - this.colorRef = other.colorRef; - } - - public int init(LittleEndianInputStream leis) throws IOException { - // Values (1 byte): An 8-bit unsigned integer that defines how the palette entry is to be used. - // The Values field MUST be 0x00 or one of the values in the PaletteEntryFlag Enumeration table. - values = leis.readUByte(); - // Blue (1 byte): An 8-bit unsigned integer that defines the blue intensity value for the palette entry. - int blue = leis.readUByte(); - // Green (1 byte): An 8-bit unsigned integer that defines the green intensity value for the palette entry. - int green = leis.readUByte(); - // Red (1 byte): An 8-bit unsigned integer that defines the red intensity value for the palette entry. - int red = leis.readUByte(); - colorRef = new Color(red, green, blue); - - return 4*LittleEndianConsts.BYTE_SIZE; - } - - /** - * Specifies that the logical palette entry be used for palette animation. This value - * prevents other windows from matching colors to the palette entry because the color frequently - * changes. If an unused system-palette entry is available, the color is placed in that entry. - * Otherwise, the color is not available for animation. - */ - public boolean isReserved() { - return PC_RESERVED.isSet(values); - } - - /** - * Specifies that the low-order word of the logical palette entry designates a hardware - * palette index. This value allows the application to show the contents of the display device palette. - */ - public boolean isExplicit() { - return PC_EXPLICIT.isSet(values); - } - - /** - * Specifies that the color be placed in an unused entry in the system palette - * instead of being matched to an existing color in the system palette. If there are no unused entries - * in the system palette, the color is matched normally. Once this color is in the system palette, - * colors in other logical palettes can be matched to this color. - */ - public boolean isNoCollapse() { - return PC_NOCOLLAPSE.isSet(values); - } - } - - public static abstract class WmfPaletteParent implements HwmfRecord, HwmfObjectTableEntry { - - /** - * Start (2 bytes): A 16-bit unsigned integer that defines the offset into the Palette Object when - * used with the META_SETPALENTRIES and META_ANIMATEPALETTE record types. - * When used with META_CREATEPALETTE, it MUST be 0x0300 - */ - private int start; - - private List palette = new ArrayList(); - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - start = leis.readUShort(); - /** - * NumberOfEntries (2 bytes): A 16-bit unsigned integer that defines the number of objects in - * aPaletteEntries. - */ - int numberOfEntries = leis.readUShort(); - int size = 2*LittleEndianConsts.SHORT_SIZE; - for (int i=0; i getPaletteCopy() { - List newPalette = new ArrayList(); - for (PaletteEntry et : palette) { - newPalette.add(new PaletteEntry(et)); - } - return newPalette; - } - - protected int getPaletteStart() { - return start; - } - } - - /** - * The META_CREATEPALETTE record creates a Palette Object - */ - public static class WmfCreatePalette extends WmfPaletteParent implements HwmfObjectTableEntry { - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.createPalette; - } - - @Override - public void applyObject(HwmfGraphics ctx) { - ctx.getProperties().setPalette(getPaletteCopy()); - } - } - - /** - * The META_SETPALENTRIES record defines RGB color values in a range of entries in the logical - * palette that is defined in the playback device context. - */ - public static class WmfSetPaletteEntries extends WmfPaletteParent { - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setPalEntries; - } - - @Override - public void applyObject(HwmfGraphics ctx) { - HwmfDrawProperties props = ctx.getProperties(); - List palette = props.getPalette(); - if (palette == null) { - palette = new ArrayList(); - } - int start = getPaletteStart(); - for (int i=palette.size(); i palette = props.getPalette(); - if (palette == null) { - palette = new ArrayList(); - } - for (int i=palette.size(); i dest = props.getPalette(); - List src = getPaletteCopy(); - int start = getPaletteStart(); - if (dest == null) { - dest = new ArrayList(); - } - for (int i=dest.size(); i palette = new ArrayList(); + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + start = leis.readUShort(); + /** + * NumberOfEntries (2 bytes): A 16-bit unsigned integer that defines the number of objects in + * aPaletteEntries. + */ + int numberOfEntries = leis.readUShort(); + int size = 2*LittleEndianConsts.SHORT_SIZE; + for (int i=0; i getPaletteCopy() { + List newPalette = new ArrayList(); + for (PaletteEntry et : palette) { + newPalette.add(new PaletteEntry(et)); + } + return newPalette; + } + + protected int getPaletteStart() { + return start; + } + } + + /** + * The META_CREATEPALETTE record creates a Palette Object + */ + public static class WmfCreatePalette extends WmfPaletteParent implements HwmfObjectTableEntry { + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.createPalette; + } + + @Override + public void applyObject(HwmfGraphics ctx) { + ctx.getProperties().setPalette(getPaletteCopy()); + } + } + + /** + * The META_SETPALENTRIES record defines RGB color values in a range of entries in the logical + * palette that is defined in the playback device context. + */ + public static class WmfSetPaletteEntries extends WmfPaletteParent { + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setPalEntries; + } + + @Override + public void applyObject(HwmfGraphics ctx) { + HwmfDrawProperties props = ctx.getProperties(); + List palette = props.getPalette(); + if (palette == null) { + palette = new ArrayList(); + } + int start = getPaletteStart(); + for (int i=palette.size(); i palette = props.getPalette(); + if (palette == null) { + palette = new ArrayList(); + } + for (int i=palette.size(); i dest = props.getPalette(); + List src = getPaletteCopy(); + int start = getPaletteStart(); + if (dest == null) { + dest = new ArrayList(); + } + for (int i=dest.size(); iInside the Windows Meta File Format - */ -public enum HwmfRecordType { - eof(0x0000, null) - ,animatePalette(0x0436, HwmfPalette.WmfAnimatePalette.class) - ,arc(0x0817, HwmfDraw.WmfArc.class) - ,bitBlt(0x0922, HwmfFill.WmfBitBlt.class) - ,chord(0x0830, HwmfDraw.WmfChord.class) - ,createBrushIndirect(0x02fc, HwmfMisc.WmfCreateBrushIndirect.class) - ,createFontIndirect(0x02fb, HwmfText.WmfCreateFontIndirect.class) - ,createPalette(0x00f7, HwmfPalette.WmfCreatePalette.class) - ,createPatternBrush(0x01f9, HwmfMisc.WmfCreatePatternBrush.class) - ,createPenIndirect(0x02fa, HwmfMisc.WmfCreatePenIndirect.class) - ,createRegion(0x06ff, HwmfWindowing.WmfCreateRegion.class) - ,deleteObject(0x01f0, HwmfMisc.WmfDeleteObject.class) - ,dibBitBlt(0x0940, HwmfFill.WmfDibBitBlt.class) - ,dibCreatePatternBrush(0x0142, HwmfMisc.WmfDibCreatePatternBrush.class) - ,dibStretchBlt(0x0b41, HwmfFill.WmfDibStretchBlt.class) - ,ellipse(0x0418, HwmfDraw.WmfEllipse.class) - ,escape(0x0626, HwmfEscape.class) - ,excludeClipRect(0x0415, HwmfWindowing.WmfExcludeClipRect.class) - ,extFloodFill(0x0548, HwmfFill.WmfExtFloodFill.class) - ,extTextOut(0x0a32, HwmfText.WmfExtTextOut.class) - ,fillRegion(0x0228, HwmfFill.WmfFillRegion.class) - ,floodFill(0x0419, HwmfFill.WmfFloodFill.class) - ,frameRegion(0x0429, HwmfDraw.WmfFrameRegion.class) - ,intersectClipRect(0x0416, HwmfWindowing.WmfIntersectClipRect.class) - ,invertRegion(0x012a, HwmfFill.WmfInvertRegion.class) - ,lineTo(0x0213, HwmfDraw.WmfLineTo.class) - ,moveTo(0x0214, HwmfDraw.WmfMoveTo.class) - ,offsetClipRgn(0x0220, HwmfWindowing.WmfOffsetClipRgn.class) - ,offsetViewportOrg(0x0211, HwmfWindowing.WmfOffsetViewportOrg.class) - ,offsetWindowOrg(0x020f, HwmfWindowing.WmfOffsetWindowOrg.class) - ,paintRegion(0x012b, HwmfFill.WmfPaintRegion.class) - ,patBlt(0x061d, HwmfFill.WmfPatBlt.class) - ,pie(0x081a, HwmfDraw.WmfPie.class) - ,polygon(0x0324, HwmfDraw.WmfPolygon.class) - ,polyline(0x0325, HwmfDraw.WmfPolyline.class) - ,polyPolygon(0x0538, HwmfDraw.WmfPolyPolygon.class) - ,realizePalette(0x0035, HwmfPalette.WmfRealizePalette.class) - ,rectangle(0x041b, HwmfDraw.WmfRectangle.class) - ,resizePalette(0x0139, HwmfPalette.WmfResizePalette.class) - ,restoreDc(0x0127, HwmfMisc.WmfRestoreDc.class) - ,roundRect(0x061c, HwmfDraw.WmfRoundRect.class) - ,saveDc(0x001e, HwmfMisc.WmfSaveDc.class) - ,scaleViewportExt(0x0412, HwmfWindowing.WmfScaleViewportExt.class) - ,scaleWindowExt(0x0410, HwmfWindowing.WmfScaleWindowExt.class) - ,selectClipRegion(0x012c, HwmfWindowing.WmfSelectClipRegion.class) - ,selectObject(0x012d, HwmfDraw.WmfSelectObject.class) - ,selectPalette(0x0234, HwmfPalette.WmfSelectPalette.class) - ,setBkColor(0x0201, HwmfMisc.WmfSetBkColor.class) - ,setBkMode(0x0102, HwmfMisc.WmfSetBkMode.class) - ,setDibToDev(0x0d33, HwmfFill.WmfSetDibToDev.class) - ,setLayout(0x0149, HwmfMisc.WmfSetLayout.class) - ,setMapMode(0x0103, HwmfMisc.WmfSetMapMode.class) - ,setMapperFlags(0x0231, HwmfMisc.WmfSetMapperFlags.class) - ,setPalEntries(0x0037, HwmfPalette.WmfSetPaletteEntries.class) - ,setPixel(0x041f, HwmfDraw.WmfSetPixel.class) - ,setPolyFillMode(0x0106, HwmfFill.WmfSetPolyfillMode.class) - ,setRelabs(0x0105, HwmfMisc.WmfSetRelabs.class) - ,setRop2(0x0104, HwmfMisc.WmfSetRop2.class) - ,setStretchBltMode(0x0107, HwmfMisc.WmfSetStretchBltMode.class) - ,setTextAlign(0x012e, HwmfText.WmfSetTextAlign.class) - ,setTextCharExtra(0x0108, HwmfText.WmfSetTextCharExtra.class) - ,setTextColor(0x0209, HwmfText.WmfSetTextColor.class) - ,setTextJustification(0x020a, HwmfText.WmfSetTextJustification.class) - ,setViewportExt(0x020e, HwmfWindowing.WmfSetViewportExt.class) - ,setViewportOrg(0x020d, HwmfWindowing.WmfSetViewportOrg.class) - ,setWindowExt(0x020c, HwmfWindowing.WmfSetWindowExt.class) - ,setWindowOrg(0x020b, HwmfWindowing.WmfSetWindowOrg.class) - ,stretchBlt(0x0b23, HwmfFill.WmfStretchBlt.class) - ,stretchDib(0x0f43, HwmfFill.WmfStretchDib.class) - ,textOut(0x0521, HwmfText.WmfTextOut.class) - ; - - public final int id; - public final Class clazz; - - HwmfRecordType(int id, Class clazz) { - this.id = id; - this.clazz = clazz; - } - - public static HwmfRecordType getById(int id) { - for (HwmfRecordType wrt : values()) { - if (wrt.id == id) return wrt; - } - return null; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +/** + * Available record types for WMF + * + * @see Inside the Windows Meta File Format + */ +public enum HwmfRecordType { + eof(0x0000, null) + ,animatePalette(0x0436, HwmfPalette.WmfAnimatePalette.class) + ,arc(0x0817, HwmfDraw.WmfArc.class) + ,bitBlt(0x0922, HwmfFill.WmfBitBlt.class) + ,chord(0x0830, HwmfDraw.WmfChord.class) + ,createBrushIndirect(0x02fc, HwmfMisc.WmfCreateBrushIndirect.class) + ,createFontIndirect(0x02fb, HwmfText.WmfCreateFontIndirect.class) + ,createPalette(0x00f7, HwmfPalette.WmfCreatePalette.class) + ,createPatternBrush(0x01f9, HwmfMisc.WmfCreatePatternBrush.class) + ,createPenIndirect(0x02fa, HwmfMisc.WmfCreatePenIndirect.class) + ,createRegion(0x06ff, HwmfWindowing.WmfCreateRegion.class) + ,deleteObject(0x01f0, HwmfMisc.WmfDeleteObject.class) + ,dibBitBlt(0x0940, HwmfFill.WmfDibBitBlt.class) + ,dibCreatePatternBrush(0x0142, HwmfMisc.WmfDibCreatePatternBrush.class) + ,dibStretchBlt(0x0b41, HwmfFill.WmfDibStretchBlt.class) + ,ellipse(0x0418, HwmfDraw.WmfEllipse.class) + ,escape(0x0626, HwmfEscape.class) + ,excludeClipRect(0x0415, HwmfWindowing.WmfExcludeClipRect.class) + ,extFloodFill(0x0548, HwmfFill.WmfExtFloodFill.class) + ,extTextOut(0x0a32, HwmfText.WmfExtTextOut.class) + ,fillRegion(0x0228, HwmfFill.WmfFillRegion.class) + ,floodFill(0x0419, HwmfFill.WmfFloodFill.class) + ,frameRegion(0x0429, HwmfDraw.WmfFrameRegion.class) + ,intersectClipRect(0x0416, HwmfWindowing.WmfIntersectClipRect.class) + ,invertRegion(0x012a, HwmfFill.WmfInvertRegion.class) + ,lineTo(0x0213, HwmfDraw.WmfLineTo.class) + ,moveTo(0x0214, HwmfDraw.WmfMoveTo.class) + ,offsetClipRgn(0x0220, HwmfWindowing.WmfOffsetClipRgn.class) + ,offsetViewportOrg(0x0211, HwmfWindowing.WmfOffsetViewportOrg.class) + ,offsetWindowOrg(0x020f, HwmfWindowing.WmfOffsetWindowOrg.class) + ,paintRegion(0x012b, HwmfFill.WmfPaintRegion.class) + ,patBlt(0x061d, HwmfFill.WmfPatBlt.class) + ,pie(0x081a, HwmfDraw.WmfPie.class) + ,polygon(0x0324, HwmfDraw.WmfPolygon.class) + ,polyline(0x0325, HwmfDraw.WmfPolyline.class) + ,polyPolygon(0x0538, HwmfDraw.WmfPolyPolygon.class) + ,realizePalette(0x0035, HwmfPalette.WmfRealizePalette.class) + ,rectangle(0x041b, HwmfDraw.WmfRectangle.class) + ,resizePalette(0x0139, HwmfPalette.WmfResizePalette.class) + ,restoreDc(0x0127, HwmfMisc.WmfRestoreDc.class) + ,roundRect(0x061c, HwmfDraw.WmfRoundRect.class) + ,saveDc(0x001e, HwmfMisc.WmfSaveDc.class) + ,scaleViewportExt(0x0412, HwmfWindowing.WmfScaleViewportExt.class) + ,scaleWindowExt(0x0410, HwmfWindowing.WmfScaleWindowExt.class) + ,selectClipRegion(0x012c, HwmfWindowing.WmfSelectClipRegion.class) + ,selectObject(0x012d, HwmfDraw.WmfSelectObject.class) + ,selectPalette(0x0234, HwmfPalette.WmfSelectPalette.class) + ,setBkColor(0x0201, HwmfMisc.WmfSetBkColor.class) + ,setBkMode(0x0102, HwmfMisc.WmfSetBkMode.class) + ,setDibToDev(0x0d33, HwmfFill.WmfSetDibToDev.class) + ,setLayout(0x0149, HwmfMisc.WmfSetLayout.class) + ,setMapMode(0x0103, HwmfMisc.WmfSetMapMode.class) + ,setMapperFlags(0x0231, HwmfMisc.WmfSetMapperFlags.class) + ,setPalEntries(0x0037, HwmfPalette.WmfSetPaletteEntries.class) + ,setPixel(0x041f, HwmfDraw.WmfSetPixel.class) + ,setPolyFillMode(0x0106, HwmfFill.WmfSetPolyfillMode.class) + ,setRelabs(0x0105, HwmfMisc.WmfSetRelabs.class) + ,setRop2(0x0104, HwmfMisc.WmfSetRop2.class) + ,setStretchBltMode(0x0107, HwmfMisc.WmfSetStretchBltMode.class) + ,setTextAlign(0x012e, HwmfText.WmfSetTextAlign.class) + ,setTextCharExtra(0x0108, HwmfText.WmfSetTextCharExtra.class) + ,setTextColor(0x0209, HwmfText.WmfSetTextColor.class) + ,setTextJustification(0x020a, HwmfText.WmfSetTextJustification.class) + ,setViewportExt(0x020e, HwmfWindowing.WmfSetViewportExt.class) + ,setViewportOrg(0x020d, HwmfWindowing.WmfSetViewportOrg.class) + ,setWindowExt(0x020c, HwmfWindowing.WmfSetWindowExt.class) + ,setWindowOrg(0x020b, HwmfWindowing.WmfSetWindowOrg.class) + ,stretchBlt(0x0b23, HwmfFill.WmfStretchBlt.class) + ,stretchDib(0x0f43, HwmfFill.WmfStretchDib.class) + ,textOut(0x0521, HwmfText.WmfTextOut.class) + ; + + public final int id; + public final Class clazz; + + HwmfRecordType(int id, Class clazz) { + this.id = id; + this.clazz = clazz; + } + + public static HwmfRecordType getById(int id) { + for (HwmfRecordType wrt : values()) { + if (wrt.id == id) return wrt; + } + return null; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java index 9cd9b1e81c..4ae792293f 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java @@ -1,398 +1,398 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -/** - * Each ternary raster operation code represents a Boolean operation in which the values of the pixels in - * the source, the selected brush, and the destination are combined. Following are the three operands - * used in these operations. - * - * - * - * - * - * - *
    OperandMeaning
    DDestination bitmap
    PSelected brush (also called pattern)
    SSource bitmap
    - * - * Following are the Boolean operators used in these operations. - * - * - * - * - * - * - *
    OperandMeaning
    aBitwise AND
    nBitwise NOT (inverse)
    oBitwise OR
    xBitwise exclusive OR (XOR)
    - * - * All Boolean operations are presented in reverse Polish notation. For example, the following operation - * replaces the values of the pixels in the destination bitmap with a combination of the pixel values of the - * source and brush: PSo. - * - * The following operation combines the values of the pixels in the source and brush with the pixel values - * of the destination bitmap: DPSoo (there are alternative spellings of some functions, so although a - * particular spelling MAY NOT be listed in the enumeration, an equivalent form SHOULD be). - * - * Each raster operation code is a 32-bit integer whose high-order word is a Boolean operation index and - * whose low-order word is the operation code. The 16-bit operation index is a zero-extended, 8-bit - * value that represents the result of the Boolean operation on predefined brush, source, and destination - * values. For example, the operation indexes for the PSo and DPSoo operations are shown in the - * following list. - * - * - * - * - * - * - * - * - * - * - * - *
    PSDDPoDPan
    00000
    00101
    01011
    01111
    10011
    10111
    11011
    11111
    - * - * The operation indexes are determined by reading the binary values in a column of the table from the - * bottom up. For example, in the PSo column, the binary value is 11111100, which is equivalent to 00FC - * (hexadecimal is implicit for these values), which is the operation index for PSo. - * - * Using this method, DPSoo can be seen to have the operation index 00FE. Operation indexes define the - * locations of corresponding raster operation codes in the preceding enumeration. The PSo operation is - * in line 252 (0x00FC) of the enumeration; DPSoo is in line 254 (0x00FE). - * - * The most commonly used raster operations have been given explicit enumeration names, which - * SHOULD be used; examples are PATCOPY and WHITENESS. - * - * When the source and destination bitmaps are monochrome, a bit value of 0 represents a black pixel - * and a bit value of 1 represents a white pixel. When the source and the destination bitmaps are color, - * those colors are represented with red green blue (RGB) values. - */ -public enum HwmfTernaryRasterOp { - BLACKNESS(0x0000,0x0042,"0"), - DPSOON(0x0001,0x0289,"DPSoon"), - DPSONA(0x0002,0x0C89,"DPSona"), - PSON(0x0003,0x00AA,"PSon"), - SDPONA(0x0004,0x0C88,"SDPona"), - DPON(0x0005,0x00A9,"DPon"), - PDSXNON(0x0006,0x0865,"PDSxnon"), - PDSAON(0x0007,0x02C5,"PDSaon"), - SDPNAA(0x0008,0x0F08,"SDPnaa"), - PDSXON(0x0009,0x0245,"PDSxon"), - DPNA(0x000A,0x0329,"DPna"), - PSDNAON(0x000B,0x0B2A,"PSDnaon"), - SPNA(0x000C,0x0324,"SPna"), - PDSNAON(0x000D,0x0B25,"PDSnaon"), - PDSONON(0x000E,0x08A5,"PDSonon"), - PN(0x000F,0x0001,"Pn"), - PDSONA(0x0010,0x0C85,"PDSona"), - NOTSRCERASE(0x0011,0x00A6,"DSon"), - SDPXNON(0x0012,0x0868,"SDPxnon"), - SDPAON(0x0013,0x02C8,"SDPaon"), - DPSXNON(0x0014,0x0869,"DPSxnon"), - DPSAON(0x0015,0x02C9,"DPSaon"), - PSDPSANAXX(0x0016,0x5CCA,"PSDPSanaxx"), - SSPXDSXAXN(0x0017,0x1D54,"SSPxDSxaxn"), - SPXPDXA(0x0018,0x0D59,"SPxPDxa"), - SDPSANAXN(0x0019,0x1CC8,"SDPSanaxn"), - PDSPAOX(0x001A,0x06C5,"PDSPaox"), - SDPSXAXN(0x001B,0x0768,"SDPSxaxn"), - PSDPAOX(0x001C,0x06CA,"PSDPaox"), - DSPDXAXN(0x001D,0x0766,"DSPDxaxn"), - PDSOX(0x001E,0x01A5,"PDSox"), - PDSOAN(0x001F,0x0385,"PDSoan"), - DPSNAA(0x0020,0x0F09,"DPSnaa"), - SDPXON(0x0021,0x0248,"SDPxon"), - DSNA(0x0022,0x0326,"DSna"), - SPDNAON(0x0023,0x0B24,"SPDnaon"), - SPXDSXA(0x0024,0x0D55,"SPxDSxa"), - PDSPANAXN(0x0025,0x1CC5,"PDSPanaxn"), - SDPSAOX(0x0026,0x06C8,"SDPSaox"), - SDPSXNOX(0x0027,0x1868,"SDPSxnox"), - DPSXA(0x0028,0x0369,"DPSxa"), - PSDPSAOXXN(0x0029,0x16CA,"PSDPSaoxxn"), - DPSANA(0x002A,0x0CC9,"DPSana"), - SSPXPDXAXN(0x002B,0x1D58,"SSPxPDxaxn"), - SPDSOAX(0x002C,0x0784,"SPDSoax"), - PSDNOX(0x002D,0x060A,"PSDnox"), - PSDPXOX(0x002E,0x064A,"PSDPxox"), - PSDNOAN(0x002F,0x0E2A,"PSDnoan"), - PSNA(0x0030,0x032A,"PSna"), - SDPNAON(0x0031,0x0B28,"SDPnaon"), - SDPSOOX(0x0032,0x0688,"SDPSoox"), - NOTSRCCOPY(0x0033,0x0008,"Sn"), - SPDSAOX(0x0034,0x06C4,"SPDSaox"), - SPDSXNOX(0x0035,0x1864,"SPDSxnox"), - SDPOX(0x0036,0x01A8,"SDPox"), - SDPOAN(0x0037,0x0388,"SDPoan"), - PSDPOAX(0x0038,0x078A,"PSDPoax"), - SPDNOX(0x0390,0x604,"SPDnox"), - SPDSXOX(0x003A,0x0644,"SPDSxox"), - SPDNOAN(0x003B,0x0E24,"SPDnoan"), - PSX(0x003C,0x004A,"PSx"), - SPDSONOX(0x003D,0x18A4,"SPDSonox"), - SPDSNAOX(0x003E,0x1B24,"SPDSnaox"), - PSAN(0x003F,0x00EA,"PSan"), - PSDNAA(0x0040,0x0F0A,"PSDnaa"), - DPSXON(0x0041,0x0249,"DPSxon"), - SDXPDXA(0x0042,0x0D5D,"SDxPDxa"), - SPDSANAXN(0x0043,0x1CC4,"SPDSanaxn"), - SRCERASE(0x0044,0x0328,"SDna"), - DPSNAON(0x0045,0x0B29,"DPSnaon"), - DSPDAOX(0x0046,0x06C6,"DSPDaox"), - PSDPXAXN(0x0047,0x076A,"PSDPxaxn"), - SDPXA(0x0048,0x0368,"SDPxa"), - PDSPDAOXXN(0x0049,0x16C5,"PDSPDaoxxn"), - DPSDOAX(0x004A,0x0789,"DPSDoax"), - PDSNOX(0x004B,0x0605,"PDSnox"), - SDPANA(0x004C,0x0CC8,"SDPana"), - SSPXDSXOXN(0x004D,0x1954,"SSPxDSxoxn"), - PDSPXOX(0x004E,0x0645,"PDSPxox"), - PDSNOAN(0x004F,0x0E25,"PDSnoan"), - PDNA(0x0050,0x0325,"PDna"), - DSPNAON(0x0051,0x0B26,"DSPnaon"), - DPSDAOX(0x0052,0x06C9,"DPSDaox"), - SPDSXAXN(0x0053,0x0764,"SPDSxaxn"), - DPSONON(0x0054,0x08A9,"DPSonon"), - DSTINVERT(0x0055,0x0009,"Dn"), - DPSOX(0x0056,0x01A9,"DPSox"), - DPSOAN(0x0005,0x70389,"DPSoan"), - PDSPOAX(0x0058,0x0785,"PDSPoax"), - DPSNOX(0x0059,0x0609,"DPSnox"), - PATINVERT(0x005A,0x0049,"DPx"), - DPSDONOX(0x005B,0x18A9,"DPSDonox"), - DPSDXOX(0x005C,0x0649,"DPSDxox"), - DPSNOAN(0x005D,0x0E29,"DPSnoan"), - DPSDNAOX(0x005E,0x1B29,"DPSDnaox"), - DPAN(0x005F,0x00E9,"DPan"), - PDSXA(0x0060,0x0365,"PDSxa"), - DSPDSAOXXN(0x0061,0x16C6,"DSPDSaoxxn"), - DSPDOAX(0x0062,0x0786,"DSPDoax"), - SDPNOX(0x0063,0x0608,"SDPnox"), - SDPSOAX(0x0064,0x0788,"SDPSoax"), - DSPNOX(0x0065,0x0606,"DSPnox"), - SRCINVERT(0x0066,0x0046,"DSx"), - SDPSONOX(0x0067,0x18A8,"SDPSonox"), - DSPDSONOXXN(0x0068,0x58A6,"DSPDSonoxxn"), - PDSXXN(0x0069,0x0145,"PDSxxn"), - DPSAX(0x006A,0x01E9,"DPSax"), - PSDPSOAXXN(0x006B,0x178A,"PSDPSoaxxn"), - SDPAX(0x006C,0x01E8,"SDPax"), - PDSPDOAXXN(0x006D,0x1785,"PDSPDoaxxn"), - SDPSNOAX(0x006E,0x1E28,"SDPSnoax"), - // PDXNAN(0x006F,0x0C65,"PDXnan"), // invalid combo - PDSANA(0x0070,0x0CC5,"PDSana"), - SSDXPDXAXN(0x0071,0x1D5C,"SSDxPDxaxn"), - SDPSXOX(0x0072,0x0648,"SDPSxox"), - SDPNOAN(0x0073,0x0E28,"SDPnoan"), - DSPDXOX(0x0074,0x0646,"DSPDxox"), - DSPNOAN(0x0075,0x0E26,"DSPnoan"), - SDPSNAOX(0x0076,0x1B28,"SDPSnaox"), - DSAN(0x0077,0x00E6,"DSan"), - PDSAX(0x0078,0x01E5,"PDSax"), - DSPDSOAXXN(0x0079,0x1786,"DSPDSoaxxn"), - DPSDNOAX(0x007A,0x1E29,"DPSDnoax"), - SDPXNAN(0x007B,0x0C68,"SDPxnan"), - SPDSNOAX(0x007C,0x1E24,"SPDSnoax"), - DPSXNAN(0x007D,0x0C69,"DPSxnan"), - SPXDSXO(0x007E,0x0955,"SPxDSxo"), - DPSAAN(0x007F,0x03C9,"DPSaan"), - DPSAA(0x0080,0x03E9,"DPSaa"), - SPXDSXON(0x0081,0x0975,"SPxDSxon"), - DPSXNA(0x0082,0x0C49,"DPSxna"), - SPDSNOAXN(0x0083,0x1E04,"SPDSnoaxn"), - SDPXNA(0x0084,0x0C48,"SDPxna"), - PDSPNOAXN(0x0085,0x1E05,"PDSPnoaxn"), - DSPDSOAXX(0x0086,0x17A6,"DSPDSoaxx"), - PDSAXN(0x0087,0x01C5,"PDSaxn"), - SRCAND(0x0088,0x00C6,"DSa"), - SDPSNAOXN(0x0089,0x1B08,"SDPSnaoxn"), - DSPNOA(0x008A,0x0E06,"DSPnoa"), - DSPDXOXN(0x008B,0x0666,"DSPDxoxn"), - SDPNOA(0x008C,0x0E08,"SDPnoa"), - SDPSXOXN(0x008D,0x0668,"SDPSxoxn"), - SSDXPDXAX(0x008E,0x1D7C,"SSDxPDxax"), - PDSANAN(0x008F,0x0CE5,"PDSanan"), - PDSXNA(0x0090,0x0C45,"PDSxna"), - SDPSNOAXN(0x0091,0x1E08,"SDPSnoaxn"), - DPSDPOAXX(0x0092,0x17A9,"DPSDPoaxx"), - SPDAXN(0x0093,0x01C4,"SPDaxn"), - PSDPSOAXX(0x0094,0x17AA,"PSDPSoaxx"), - DPSAXN(0x0095,0x01C9,"DPSaxn"), - DPSXX(0x0096,0x0169,"DPSxx"), - PSDPSONOXX(0x0097,0x588A,"PSDPSonoxx"), - SDPSONOXN(0x0098,0x1888,"SDPSonoxn"), - DSXN(0x0099,0x0066,"DSxn"), - DPSNAX(0x009A,0x0709,"DPSnax"), - SDPSOAXN(0x009B,0x07A8,"SDPSoaxn"), - SPDNAX(0x009C,0x0704,"SPDnax"), - DSPDOAXN(0x009D,0x07A6,"DSPDoaxn"), - DSPDSAOXX(0x009E,0x16E6,"DSPDSaoxx"), - PDSXAN(0x009F,0x0345,"PDSxan"), - DPA(0x00A0,0x00C9,"DPa"), - PDSPNAOXN(0x00A1,0x1B05,"PDSPnaoxn"), - DPSNOA(0x00A2,0x0E09,"DPSnoa"), - DPSDXOXN(0x00A3,0x0669,"DPSDxoxn"), - PDSPONOXN(0x00A4,0x1885,"PDSPonoxn"), - PDXN(0x00A5,0x0065,"PDxn"), - DSPNAX(0x00A6,0x0706,"DSPnax"), - PDSPOAXN(0x00A7,0x07A5,"PDSPoaxn"), - DPSOA(0x00A8,0x03A9,"DPSoa"), - DPSOXN(0x00A9,0x0189,"DPSoxn"), - D(0x00AA,0x0029,"D"), - DPSONO(0x00AB,0x0889,"DPSono"), - SPDSXAX(0x00AC,0x0744,"SPDSxax"), - DPSDAOXN(0x00AD,0x06E9,"DPSDaoxn"), - DSPNAO(0x00AE,0x0B06,"DSPnao"), - DPNO(0x00AF,0x0229,"DPno"), - PDSNOA(0x00B0,0x0E05,"PDSnoa"), - PDSPXOXN(0x00B1,0x0665,"PDSPxoxn"), - SSPXDSXOX(0x00B2,0x1974,"SSPxDSxox"), - SDPANAN(0x00B3,0x0CE8,"SDPanan"), - PSDNAX(0x00B4,0x070A,"PSDnax"), - DPSDOAXN(0x00B5,0x07A9,"DPSDoaxn"), - DPSDPAOXX(0x00B6,0x16E9,"DPSDPaoxx"), - SDPXAN(0x00B7,0x0348,"SDPxan"), - PSDPXAX(0x00B8,0x074A,"PSDPxax"), - DSPDAOXN(0x00B9,0x06E6,"DSPDaoxn"), - DPSNAO(0x00BA,0x0B09,"DPSnao"), - MERGEPAINT(0x00BB,0x0226,"DSno"), - SPDSANAX(0x00BC,0x1CE4,"SPDSanax"), - SDXPDXAN(0x00BD,0x0D7D,"SDxPDxan"), - DPSXO(0x00BE,0x0269,"DPSxo"), - DPSANO(0x00BF,0x08C9,"DPSano"), - MERGECOPY(0x00C0,0x00CA,"PSa"), - SPDSNAOXN(0x00C1,0x1B04,"SPDSnaoxn"), - SPDSONOXN(0x00C2,0x1884,"SPDSonoxn"), - PSXN(0x00C3,0x006A,"PSxn"), - SPDNOA(0x00C4,0x0E04,"SPDnoa"), - SPDSXOXN(0x00C5,0x0664,"SPDSxoxn"), - SDPNAX(0x00C6,0x0708,"SDPnax"), - PSDPOAXN(0x00C7,0x07AA,"PSDPoaxn"), - SDPOA(0x00C8,0x03A8,"SDPoa"), - SPDOXN(0x00C9,0x0184,"SPDoxn"), - DPSDXAX(0x00CA,0x0749,"DPSDxax"), - SPDSAOXN(0x00CB,0x06E4,"SPDSaoxn"), - SRCCOPY(0x00CC,0x0020,"S"), - SDPONO(0x00CD,0x0888,"SDPono"), - SDPNAO(0x00CE,0x0B08,"SDPnao"), - SPNO(0x00CF,0x0224,"SPno"), - PSDNOA(0x00D0,0x0E0A,"PSDnoa"), - PSDPXOXN(0x00D1,0x066A,"PSDPxoxn"), - PDSNAX(0x00D2,0x0705,"PDSnax"), - SPDSOAXN(0x00D3,0x07A4,"SPDSoaxn"), - SSPXPDXAX(0x00D4,0x1D78,"SSPxPDxax"), - DPSANAN(0x00D5,0x0CE9,"DPSanan"), - PSDPSAOXX(0x00D6,0x16EA,"PSDPSaoxx"), - DPSXAN(0x00D7,0x0349,"DPSxan"), - PDSPXAX(0x00D8,0x0745,"PDSPxax"), - SDPSAOXN(0x00D9,0x06E8,"SDPSaoxn"), - DPSDANAX(0x00DA,0x1CE9,"DPSDanax"), - SPXDSXAN(0x00DB,0x0D75,"SPxDSxan"), - SPDNAO(0x00DC,0x0B04,"SPDnao"), - SDNO(0x00DD,0x0228,"SDno"), - SDPXO(0x00DE,0x0268,"SDPxo"), - SDPANO(0x00DF,0x08C8,"SDPano"), - PDSOA(0x00E0,0x03A5,"PDSoa"), - PDSOXN(0x00E1,0x0185,"PDSoxn"), - DSPDXAX(0x00E2,0x0746,"DSPDxax"), - PSDPAOXN(0x00E3,0x06EA,"PSDPaoxn"), - SDPSXAX(0x00E4,0x0748,"SDPSxax"), - PDSPAOXN(0x00E5,0x06E5,"PDSPaoxn"), - SDPSANAX(0x00E6,0x1CE8,"SDPSanax"), - SPXPDXAN(0x00E7,0x0D79,"SPxPDxan"), - SSPXDSXAX(0x00E8,0x1D74,"SSPxDSxax"), - DSPDSANAXXN(0x00E9,0x5CE6,"DSPDSanaxxn"), - DPSAO(0x00EA,0x02E9,"DPSao"), - DPSXNO(0x00EB,0x0849,"DPSxno"), - SDPAO(0x00EC,0x02E8,"SDPao"), - SDPXNO(0x00ED,0x0848,"SDPxno"), - SRCPAINT(0x00EE,0x0086,"DSo"), - SDPNOO(0x00EF,0x0A08,"SDPnoo"), - PATCOPY(0x00F0,0x0021,"P"), - PDSONO(0x00F1,0x0885,"PDSono"), - PDSNAO(0x00F2,0x0B05,"PDSnao"), - PSNO(0x00F3,0x022A,"PSno"), - PSDNAO(0x00F4,0x0B0A,"PSDnao"), - PDNO(0x00F5,0x0225,"PDno"), - PDSXO(0x00F6,0x0265,"PDSxo"), - PDSANO(0x00F7,0x08C5,"PDSano"), - PDSAO(0x00F8,0x02E5,"PDSao"), - PDSXNO(0x00F9,0x0845,"PDSxno"), - DPO(0x00FA,0x0089,"DPo"), - PATPAINT(0x00FB,0x0A09,"DPSnoo"), - PSO(0x00FC,0x008A,"PSo"), - PSDNOO(0x00FD,0x0A0A,"PSDnoo"), - DPSOO(0x00FE,0x02A9,"DPSoo"), - WHITENESS(0x00FF,0x0062,"1"); - - int opIndex; - int opCode; - String opCmd; - - HwmfTernaryRasterOp(int opIndex, int opCode, String opCmd) { - this.opIndex=opIndex; - this.opCode=opCode; - this.opCmd=opCmd; - } - - public static HwmfTernaryRasterOp valueOf(int opIndex) { - for (HwmfTernaryRasterOp bb : HwmfTernaryRasterOp.values()) { - if (bb.opIndex == opIndex) { - return bb; - } - } - return null; - } - - public String describeCmd() { - String stack[] = new String[10]; - int stackPnt = 0; - - for (char c : opCmd.toCharArray()) { - switch (c) { - case 'S': - case 'D': - case 'P': - stack[stackPnt++] = ""+c; - break; - case 'n': - stack[stackPnt-1] = "not("+stack[stackPnt-1]+")"; - break; - case 'a': - stack[stackPnt-2] = "("+stack[stackPnt-1]+" and "+stack[stackPnt-2]+")"; - stackPnt--; - break; - case 'o': - stack[stackPnt-2] = "("+stack[stackPnt-1]+" or "+stack[stackPnt-2]+")"; - stackPnt--; - break; - case 'x': - stack[stackPnt-2] = "("+stack[stackPnt-1]+" xor "+stack[stackPnt-2]+")"; - stackPnt--; - break; - case '1': - stack[stackPnt++] = "all white"; - break; - case '0': - stack[stackPnt++] = "all black"; - break; - default: - throw new RuntimeException("unknown cmd '"+c+"'."); - } - } - - return stack[--stackPnt]; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +/** + * Each ternary raster operation code represents a Boolean operation in which the values of the pixels in + * the source, the selected brush, and the destination are combined. Following are the three operands + * used in these operations. + * + * + * + * + * + * + *
    OperandMeaning
    DDestination bitmap
    PSelected brush (also called pattern)
    SSource bitmap
    + * + * Following are the Boolean operators used in these operations. + * + * + * + * + * + * + *
    OperandMeaning
    aBitwise AND
    nBitwise NOT (inverse)
    oBitwise OR
    xBitwise exclusive OR (XOR)
    + * + * All Boolean operations are presented in reverse Polish notation. For example, the following operation + * replaces the values of the pixels in the destination bitmap with a combination of the pixel values of the + * source and brush: PSo. + * + * The following operation combines the values of the pixels in the source and brush with the pixel values + * of the destination bitmap: DPSoo (there are alternative spellings of some functions, so although a + * particular spelling MAY NOT be listed in the enumeration, an equivalent form SHOULD be). + * + * Each raster operation code is a 32-bit integer whose high-order word is a Boolean operation index and + * whose low-order word is the operation code. The 16-bit operation index is a zero-extended, 8-bit + * value that represents the result of the Boolean operation on predefined brush, source, and destination + * values. For example, the operation indexes for the PSo and DPSoo operations are shown in the + * following list. + * + * + * + * + * + * + * + * + * + * + * + *
    PSDDPoDPan
    00000
    00101
    01011
    01111
    10011
    10111
    11011
    11111
    + * + * The operation indexes are determined by reading the binary values in a column of the table from the + * bottom up. For example, in the PSo column, the binary value is 11111100, which is equivalent to 00FC + * (hexadecimal is implicit for these values), which is the operation index for PSo. + * + * Using this method, DPSoo can be seen to have the operation index 00FE. Operation indexes define the + * locations of corresponding raster operation codes in the preceding enumeration. The PSo operation is + * in line 252 (0x00FC) of the enumeration; DPSoo is in line 254 (0x00FE). + * + * The most commonly used raster operations have been given explicit enumeration names, which + * SHOULD be used; examples are PATCOPY and WHITENESS. + * + * When the source and destination bitmaps are monochrome, a bit value of 0 represents a black pixel + * and a bit value of 1 represents a white pixel. When the source and the destination bitmaps are color, + * those colors are represented with red green blue (RGB) values. + */ +public enum HwmfTernaryRasterOp { + BLACKNESS(0x0000,0x0042,"0"), + DPSOON(0x0001,0x0289,"DPSoon"), + DPSONA(0x0002,0x0C89,"DPSona"), + PSON(0x0003,0x00AA,"PSon"), + SDPONA(0x0004,0x0C88,"SDPona"), + DPON(0x0005,0x00A9,"DPon"), + PDSXNON(0x0006,0x0865,"PDSxnon"), + PDSAON(0x0007,0x02C5,"PDSaon"), + SDPNAA(0x0008,0x0F08,"SDPnaa"), + PDSXON(0x0009,0x0245,"PDSxon"), + DPNA(0x000A,0x0329,"DPna"), + PSDNAON(0x000B,0x0B2A,"PSDnaon"), + SPNA(0x000C,0x0324,"SPna"), + PDSNAON(0x000D,0x0B25,"PDSnaon"), + PDSONON(0x000E,0x08A5,"PDSonon"), + PN(0x000F,0x0001,"Pn"), + PDSONA(0x0010,0x0C85,"PDSona"), + NOTSRCERASE(0x0011,0x00A6,"DSon"), + SDPXNON(0x0012,0x0868,"SDPxnon"), + SDPAON(0x0013,0x02C8,"SDPaon"), + DPSXNON(0x0014,0x0869,"DPSxnon"), + DPSAON(0x0015,0x02C9,"DPSaon"), + PSDPSANAXX(0x0016,0x5CCA,"PSDPSanaxx"), + SSPXDSXAXN(0x0017,0x1D54,"SSPxDSxaxn"), + SPXPDXA(0x0018,0x0D59,"SPxPDxa"), + SDPSANAXN(0x0019,0x1CC8,"SDPSanaxn"), + PDSPAOX(0x001A,0x06C5,"PDSPaox"), + SDPSXAXN(0x001B,0x0768,"SDPSxaxn"), + PSDPAOX(0x001C,0x06CA,"PSDPaox"), + DSPDXAXN(0x001D,0x0766,"DSPDxaxn"), + PDSOX(0x001E,0x01A5,"PDSox"), + PDSOAN(0x001F,0x0385,"PDSoan"), + DPSNAA(0x0020,0x0F09,"DPSnaa"), + SDPXON(0x0021,0x0248,"SDPxon"), + DSNA(0x0022,0x0326,"DSna"), + SPDNAON(0x0023,0x0B24,"SPDnaon"), + SPXDSXA(0x0024,0x0D55,"SPxDSxa"), + PDSPANAXN(0x0025,0x1CC5,"PDSPanaxn"), + SDPSAOX(0x0026,0x06C8,"SDPSaox"), + SDPSXNOX(0x0027,0x1868,"SDPSxnox"), + DPSXA(0x0028,0x0369,"DPSxa"), + PSDPSAOXXN(0x0029,0x16CA,"PSDPSaoxxn"), + DPSANA(0x002A,0x0CC9,"DPSana"), + SSPXPDXAXN(0x002B,0x1D58,"SSPxPDxaxn"), + SPDSOAX(0x002C,0x0784,"SPDSoax"), + PSDNOX(0x002D,0x060A,"PSDnox"), + PSDPXOX(0x002E,0x064A,"PSDPxox"), + PSDNOAN(0x002F,0x0E2A,"PSDnoan"), + PSNA(0x0030,0x032A,"PSna"), + SDPNAON(0x0031,0x0B28,"SDPnaon"), + SDPSOOX(0x0032,0x0688,"SDPSoox"), + NOTSRCCOPY(0x0033,0x0008,"Sn"), + SPDSAOX(0x0034,0x06C4,"SPDSaox"), + SPDSXNOX(0x0035,0x1864,"SPDSxnox"), + SDPOX(0x0036,0x01A8,"SDPox"), + SDPOAN(0x0037,0x0388,"SDPoan"), + PSDPOAX(0x0038,0x078A,"PSDPoax"), + SPDNOX(0x0390,0x604,"SPDnox"), + SPDSXOX(0x003A,0x0644,"SPDSxox"), + SPDNOAN(0x003B,0x0E24,"SPDnoan"), + PSX(0x003C,0x004A,"PSx"), + SPDSONOX(0x003D,0x18A4,"SPDSonox"), + SPDSNAOX(0x003E,0x1B24,"SPDSnaox"), + PSAN(0x003F,0x00EA,"PSan"), + PSDNAA(0x0040,0x0F0A,"PSDnaa"), + DPSXON(0x0041,0x0249,"DPSxon"), + SDXPDXA(0x0042,0x0D5D,"SDxPDxa"), + SPDSANAXN(0x0043,0x1CC4,"SPDSanaxn"), + SRCERASE(0x0044,0x0328,"SDna"), + DPSNAON(0x0045,0x0B29,"DPSnaon"), + DSPDAOX(0x0046,0x06C6,"DSPDaox"), + PSDPXAXN(0x0047,0x076A,"PSDPxaxn"), + SDPXA(0x0048,0x0368,"SDPxa"), + PDSPDAOXXN(0x0049,0x16C5,"PDSPDaoxxn"), + DPSDOAX(0x004A,0x0789,"DPSDoax"), + PDSNOX(0x004B,0x0605,"PDSnox"), + SDPANA(0x004C,0x0CC8,"SDPana"), + SSPXDSXOXN(0x004D,0x1954,"SSPxDSxoxn"), + PDSPXOX(0x004E,0x0645,"PDSPxox"), + PDSNOAN(0x004F,0x0E25,"PDSnoan"), + PDNA(0x0050,0x0325,"PDna"), + DSPNAON(0x0051,0x0B26,"DSPnaon"), + DPSDAOX(0x0052,0x06C9,"DPSDaox"), + SPDSXAXN(0x0053,0x0764,"SPDSxaxn"), + DPSONON(0x0054,0x08A9,"DPSonon"), + DSTINVERT(0x0055,0x0009,"Dn"), + DPSOX(0x0056,0x01A9,"DPSox"), + DPSOAN(0x0005,0x70389,"DPSoan"), + PDSPOAX(0x0058,0x0785,"PDSPoax"), + DPSNOX(0x0059,0x0609,"DPSnox"), + PATINVERT(0x005A,0x0049,"DPx"), + DPSDONOX(0x005B,0x18A9,"DPSDonox"), + DPSDXOX(0x005C,0x0649,"DPSDxox"), + DPSNOAN(0x005D,0x0E29,"DPSnoan"), + DPSDNAOX(0x005E,0x1B29,"DPSDnaox"), + DPAN(0x005F,0x00E9,"DPan"), + PDSXA(0x0060,0x0365,"PDSxa"), + DSPDSAOXXN(0x0061,0x16C6,"DSPDSaoxxn"), + DSPDOAX(0x0062,0x0786,"DSPDoax"), + SDPNOX(0x0063,0x0608,"SDPnox"), + SDPSOAX(0x0064,0x0788,"SDPSoax"), + DSPNOX(0x0065,0x0606,"DSPnox"), + SRCINVERT(0x0066,0x0046,"DSx"), + SDPSONOX(0x0067,0x18A8,"SDPSonox"), + DSPDSONOXXN(0x0068,0x58A6,"DSPDSonoxxn"), + PDSXXN(0x0069,0x0145,"PDSxxn"), + DPSAX(0x006A,0x01E9,"DPSax"), + PSDPSOAXXN(0x006B,0x178A,"PSDPSoaxxn"), + SDPAX(0x006C,0x01E8,"SDPax"), + PDSPDOAXXN(0x006D,0x1785,"PDSPDoaxxn"), + SDPSNOAX(0x006E,0x1E28,"SDPSnoax"), + // PDXNAN(0x006F,0x0C65,"PDXnan"), // invalid combo + PDSANA(0x0070,0x0CC5,"PDSana"), + SSDXPDXAXN(0x0071,0x1D5C,"SSDxPDxaxn"), + SDPSXOX(0x0072,0x0648,"SDPSxox"), + SDPNOAN(0x0073,0x0E28,"SDPnoan"), + DSPDXOX(0x0074,0x0646,"DSPDxox"), + DSPNOAN(0x0075,0x0E26,"DSPnoan"), + SDPSNAOX(0x0076,0x1B28,"SDPSnaox"), + DSAN(0x0077,0x00E6,"DSan"), + PDSAX(0x0078,0x01E5,"PDSax"), + DSPDSOAXXN(0x0079,0x1786,"DSPDSoaxxn"), + DPSDNOAX(0x007A,0x1E29,"DPSDnoax"), + SDPXNAN(0x007B,0x0C68,"SDPxnan"), + SPDSNOAX(0x007C,0x1E24,"SPDSnoax"), + DPSXNAN(0x007D,0x0C69,"DPSxnan"), + SPXDSXO(0x007E,0x0955,"SPxDSxo"), + DPSAAN(0x007F,0x03C9,"DPSaan"), + DPSAA(0x0080,0x03E9,"DPSaa"), + SPXDSXON(0x0081,0x0975,"SPxDSxon"), + DPSXNA(0x0082,0x0C49,"DPSxna"), + SPDSNOAXN(0x0083,0x1E04,"SPDSnoaxn"), + SDPXNA(0x0084,0x0C48,"SDPxna"), + PDSPNOAXN(0x0085,0x1E05,"PDSPnoaxn"), + DSPDSOAXX(0x0086,0x17A6,"DSPDSoaxx"), + PDSAXN(0x0087,0x01C5,"PDSaxn"), + SRCAND(0x0088,0x00C6,"DSa"), + SDPSNAOXN(0x0089,0x1B08,"SDPSnaoxn"), + DSPNOA(0x008A,0x0E06,"DSPnoa"), + DSPDXOXN(0x008B,0x0666,"DSPDxoxn"), + SDPNOA(0x008C,0x0E08,"SDPnoa"), + SDPSXOXN(0x008D,0x0668,"SDPSxoxn"), + SSDXPDXAX(0x008E,0x1D7C,"SSDxPDxax"), + PDSANAN(0x008F,0x0CE5,"PDSanan"), + PDSXNA(0x0090,0x0C45,"PDSxna"), + SDPSNOAXN(0x0091,0x1E08,"SDPSnoaxn"), + DPSDPOAXX(0x0092,0x17A9,"DPSDPoaxx"), + SPDAXN(0x0093,0x01C4,"SPDaxn"), + PSDPSOAXX(0x0094,0x17AA,"PSDPSoaxx"), + DPSAXN(0x0095,0x01C9,"DPSaxn"), + DPSXX(0x0096,0x0169,"DPSxx"), + PSDPSONOXX(0x0097,0x588A,"PSDPSonoxx"), + SDPSONOXN(0x0098,0x1888,"SDPSonoxn"), + DSXN(0x0099,0x0066,"DSxn"), + DPSNAX(0x009A,0x0709,"DPSnax"), + SDPSOAXN(0x009B,0x07A8,"SDPSoaxn"), + SPDNAX(0x009C,0x0704,"SPDnax"), + DSPDOAXN(0x009D,0x07A6,"DSPDoaxn"), + DSPDSAOXX(0x009E,0x16E6,"DSPDSaoxx"), + PDSXAN(0x009F,0x0345,"PDSxan"), + DPA(0x00A0,0x00C9,"DPa"), + PDSPNAOXN(0x00A1,0x1B05,"PDSPnaoxn"), + DPSNOA(0x00A2,0x0E09,"DPSnoa"), + DPSDXOXN(0x00A3,0x0669,"DPSDxoxn"), + PDSPONOXN(0x00A4,0x1885,"PDSPonoxn"), + PDXN(0x00A5,0x0065,"PDxn"), + DSPNAX(0x00A6,0x0706,"DSPnax"), + PDSPOAXN(0x00A7,0x07A5,"PDSPoaxn"), + DPSOA(0x00A8,0x03A9,"DPSoa"), + DPSOXN(0x00A9,0x0189,"DPSoxn"), + D(0x00AA,0x0029,"D"), + DPSONO(0x00AB,0x0889,"DPSono"), + SPDSXAX(0x00AC,0x0744,"SPDSxax"), + DPSDAOXN(0x00AD,0x06E9,"DPSDaoxn"), + DSPNAO(0x00AE,0x0B06,"DSPnao"), + DPNO(0x00AF,0x0229,"DPno"), + PDSNOA(0x00B0,0x0E05,"PDSnoa"), + PDSPXOXN(0x00B1,0x0665,"PDSPxoxn"), + SSPXDSXOX(0x00B2,0x1974,"SSPxDSxox"), + SDPANAN(0x00B3,0x0CE8,"SDPanan"), + PSDNAX(0x00B4,0x070A,"PSDnax"), + DPSDOAXN(0x00B5,0x07A9,"DPSDoaxn"), + DPSDPAOXX(0x00B6,0x16E9,"DPSDPaoxx"), + SDPXAN(0x00B7,0x0348,"SDPxan"), + PSDPXAX(0x00B8,0x074A,"PSDPxax"), + DSPDAOXN(0x00B9,0x06E6,"DSPDaoxn"), + DPSNAO(0x00BA,0x0B09,"DPSnao"), + MERGEPAINT(0x00BB,0x0226,"DSno"), + SPDSANAX(0x00BC,0x1CE4,"SPDSanax"), + SDXPDXAN(0x00BD,0x0D7D,"SDxPDxan"), + DPSXO(0x00BE,0x0269,"DPSxo"), + DPSANO(0x00BF,0x08C9,"DPSano"), + MERGECOPY(0x00C0,0x00CA,"PSa"), + SPDSNAOXN(0x00C1,0x1B04,"SPDSnaoxn"), + SPDSONOXN(0x00C2,0x1884,"SPDSonoxn"), + PSXN(0x00C3,0x006A,"PSxn"), + SPDNOA(0x00C4,0x0E04,"SPDnoa"), + SPDSXOXN(0x00C5,0x0664,"SPDSxoxn"), + SDPNAX(0x00C6,0x0708,"SDPnax"), + PSDPOAXN(0x00C7,0x07AA,"PSDPoaxn"), + SDPOA(0x00C8,0x03A8,"SDPoa"), + SPDOXN(0x00C9,0x0184,"SPDoxn"), + DPSDXAX(0x00CA,0x0749,"DPSDxax"), + SPDSAOXN(0x00CB,0x06E4,"SPDSaoxn"), + SRCCOPY(0x00CC,0x0020,"S"), + SDPONO(0x00CD,0x0888,"SDPono"), + SDPNAO(0x00CE,0x0B08,"SDPnao"), + SPNO(0x00CF,0x0224,"SPno"), + PSDNOA(0x00D0,0x0E0A,"PSDnoa"), + PSDPXOXN(0x00D1,0x066A,"PSDPxoxn"), + PDSNAX(0x00D2,0x0705,"PDSnax"), + SPDSOAXN(0x00D3,0x07A4,"SPDSoaxn"), + SSPXPDXAX(0x00D4,0x1D78,"SSPxPDxax"), + DPSANAN(0x00D5,0x0CE9,"DPSanan"), + PSDPSAOXX(0x00D6,0x16EA,"PSDPSaoxx"), + DPSXAN(0x00D7,0x0349,"DPSxan"), + PDSPXAX(0x00D8,0x0745,"PDSPxax"), + SDPSAOXN(0x00D9,0x06E8,"SDPSaoxn"), + DPSDANAX(0x00DA,0x1CE9,"DPSDanax"), + SPXDSXAN(0x00DB,0x0D75,"SPxDSxan"), + SPDNAO(0x00DC,0x0B04,"SPDnao"), + SDNO(0x00DD,0x0228,"SDno"), + SDPXO(0x00DE,0x0268,"SDPxo"), + SDPANO(0x00DF,0x08C8,"SDPano"), + PDSOA(0x00E0,0x03A5,"PDSoa"), + PDSOXN(0x00E1,0x0185,"PDSoxn"), + DSPDXAX(0x00E2,0x0746,"DSPDxax"), + PSDPAOXN(0x00E3,0x06EA,"PSDPaoxn"), + SDPSXAX(0x00E4,0x0748,"SDPSxax"), + PDSPAOXN(0x00E5,0x06E5,"PDSPaoxn"), + SDPSANAX(0x00E6,0x1CE8,"SDPSanax"), + SPXPDXAN(0x00E7,0x0D79,"SPxPDxan"), + SSPXDSXAX(0x00E8,0x1D74,"SSPxDSxax"), + DSPDSANAXXN(0x00E9,0x5CE6,"DSPDSanaxxn"), + DPSAO(0x00EA,0x02E9,"DPSao"), + DPSXNO(0x00EB,0x0849,"DPSxno"), + SDPAO(0x00EC,0x02E8,"SDPao"), + SDPXNO(0x00ED,0x0848,"SDPxno"), + SRCPAINT(0x00EE,0x0086,"DSo"), + SDPNOO(0x00EF,0x0A08,"SDPnoo"), + PATCOPY(0x00F0,0x0021,"P"), + PDSONO(0x00F1,0x0885,"PDSono"), + PDSNAO(0x00F2,0x0B05,"PDSnao"), + PSNO(0x00F3,0x022A,"PSno"), + PSDNAO(0x00F4,0x0B0A,"PSDnao"), + PDNO(0x00F5,0x0225,"PDno"), + PDSXO(0x00F6,0x0265,"PDSxo"), + PDSANO(0x00F7,0x08C5,"PDSano"), + PDSAO(0x00F8,0x02E5,"PDSao"), + PDSXNO(0x00F9,0x0845,"PDSxno"), + DPO(0x00FA,0x0089,"DPo"), + PATPAINT(0x00FB,0x0A09,"DPSnoo"), + PSO(0x00FC,0x008A,"PSo"), + PSDNOO(0x00FD,0x0A0A,"PSDnoo"), + DPSOO(0x00FE,0x02A9,"DPSoo"), + WHITENESS(0x00FF,0x0062,"1"); + + int opIndex; + int opCode; + String opCmd; + + HwmfTernaryRasterOp(int opIndex, int opCode, String opCmd) { + this.opIndex=opIndex; + this.opCode=opCode; + this.opCmd=opCmd; + } + + public static HwmfTernaryRasterOp valueOf(int opIndex) { + for (HwmfTernaryRasterOp bb : HwmfTernaryRasterOp.values()) { + if (bb.opIndex == opIndex) { + return bb; + } + } + return null; + } + + public String describeCmd() { + String stack[] = new String[10]; + int stackPnt = 0; + + for (char c : opCmd.toCharArray()) { + switch (c) { + case 'S': + case 'D': + case 'P': + stack[stackPnt++] = ""+c; + break; + case 'n': + stack[stackPnt-1] = "not("+stack[stackPnt-1]+")"; + break; + case 'a': + stack[stackPnt-2] = "("+stack[stackPnt-1]+" and "+stack[stackPnt-2]+")"; + stackPnt--; + break; + case 'o': + stack[stackPnt-2] = "("+stack[stackPnt-1]+" or "+stack[stackPnt-2]+")"; + stackPnt--; + break; + case 'x': + stack[stackPnt-2] = "("+stack[stackPnt-1]+" xor "+stack[stackPnt-2]+")"; + stackPnt--; + break; + case '1': + stack[stackPnt++] = "all white"; + break; + case '0': + stack[stackPnt++] = "all black"; + break; + default: + throw new RuntimeException("unknown cmd '"+c+"'."); + } + } + + return stack[--stackPnt]; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java index 108970d761..9bcac30d06 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java @@ -1,561 +1,561 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.record; - -import java.awt.geom.Rectangle2D; -import java.io.IOException; -import java.nio.charset.Charset; - -import org.apache.poi.hwmf.draw.HwmfDrawProperties; -import org.apache.poi.hwmf.draw.HwmfGraphics; -import org.apache.poi.hwmf.record.HwmfMisc.WmfSetMapMode; -import org.apache.poi.util.BitField; -import org.apache.poi.util.BitFieldFactory; -import org.apache.poi.util.LittleEndianConsts; -import org.apache.poi.util.LittleEndianInputStream; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -public class HwmfText { - private static final POILogger logger = POILogFactory.getLogger(HwmfText.class); - - /** - * The META_SETTEXTCHAREXTRA record defines inter-character spacing for text justification in the - * playback device context. Spacing is added to the white space between each character, including - * break characters, when a line of justified text is output. - */ - public static class WmfSetTextCharExtra implements HwmfRecord { - - /** - * A 16-bit unsigned integer that defines the amount of extra space, in - * logical units, to be added to each character. If the current mapping mode is not MM_TEXT, - * this value is transformed and rounded to the nearest pixel. For details about setting the - * mapping mode, see META_SETMAPMODE - */ - private int charExtra; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setTextCharExtra; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - charExtra = leis.readUShort(); - return LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_SETTEXTCOLOR record defines the text foreground color in the playback device context. - */ - public static class WmfSetTextColor implements HwmfRecord { - - private HwmfColorRef colorRef; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setTextColor; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - colorRef = new HwmfColorRef(); - return colorRef.init(leis); - } - - @Override - public void draw(HwmfGraphics ctx) { - ctx.getProperties().setTextColor(colorRef); - } - } - - /** - * The META_SETTEXTJUSTIFICATION record defines the amount of space to add to break characters - * in a string of justified text. - */ - public static class WmfSetTextJustification implements HwmfRecord { - - /** - * A 16-bit unsigned integer that specifies the number of space characters in the line. - */ - private int breakCount; - - /** - * A 16-bit unsigned integer that specifies the total extra space, in logical - * units, to be added to the line of text. If the current mapping mode is not MM_TEXT, the value - * identified by the BreakExtra member is transformed and rounded to the nearest pixel. For - * details about setting the mapping mode, see {@link WmfSetMapMode}. - */ - private int breakExtra; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.setBkColor; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - breakCount = leis.readUShort(); - breakExtra = leis.readUShort(); - return 2*LittleEndianConsts.SHORT_SIZE; - } - - @Override - public void draw(HwmfGraphics ctx) { - - } - } - - /** - * The META_TEXTOUT record outputs a character string at the specified location by using the font, - * background color, and text color that are defined in the playback device context. - */ - public static class WmfTextOut implements HwmfRecord { - /** - * A 16-bit signed integer that defines the length of the string, in bytes, pointed to by String. - */ - private int stringLength; - /** - * The size of this field MUST be a multiple of two. If StringLength is an odd - * number, then this field MUST be of a size greater than or equal to StringLength + 1. - * A variable-length string that specifies the text to be drawn. - * The string does not need to be null-terminated, because StringLength specifies the - * length of the string. - * The string is written at the location specified by the XStart and YStart fields. - */ - private byte[] rawTextBytes; - /** - * A 16-bit signed integer that defines the vertical (y-axis) coordinate, in logical - * units, of the point where drawing is to start. - */ - private int yStart; - /** - * A 16-bit signed integer that defines the horizontal (x-axis) coordinate, in - * logical units, of the point where drawing is to start. - */ - private int xStart; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.textOut; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - stringLength = leis.readShort(); - rawTextBytes = new byte[stringLength+(stringLength&1)]; - leis.readFully(rawTextBytes); - yStart = leis.readShort(); - xStart = leis.readShort(); - return 3*LittleEndianConsts.SHORT_SIZE+rawTextBytes.length; - } - - @Override - public void draw(HwmfGraphics ctx) { - Rectangle2D bounds = new Rectangle2D.Double(xStart, yStart, 0, 0); - ctx.drawString(getTextBytes(), bounds); - } - - public String getText(Charset charset) { - return new String(getTextBytes(), charset); - } - - /** - * - * @return a copy of a trimmed byte array of rawTextBytes bytes. - * This includes only the bytes from 0..stringLength. - * This does not include the extra optional padding on the byte array. - */ - private byte[] getTextBytes() { - byte[] ret = new byte[stringLength]; - System.arraycopy(rawTextBytes, 0, ret, 0, stringLength); - return ret; - } - } - - /** - * The META_EXTTEXTOUT record outputs text by using the font, background color, and text color that - * are defined in the playback device context. Optionally, dimensions can be provided for clipping, - * opaquing, or both. - */ - public static class WmfExtTextOut implements HwmfRecord { - - /** - * Indicates that the background color that is defined in the playback device context - * SHOULD be used to fill the rectangle. - */ - private static final BitField ETO_OPAQUE = BitFieldFactory.getInstance(0x0002); - - /** - * Indicates that the text SHOULD be clipped to the rectangle. - */ - private static final BitField ETO_CLIPPED = BitFieldFactory.getInstance(0x0004); - - /** - * Indicates that the string to be output SHOULD NOT require further processing - * with respect to the placement of the characters, and an array of character - * placement values SHOULD be provided. This character placement process is - * useful for fonts in which diacritical characters affect character spacing. - */ - private static final BitField ETO_GLYPH_INDEX = BitFieldFactory.getInstance(0x0010); - - /** - * Indicates that the text MUST be laid out in right-to-left reading order, instead of - * the default left-to-right order. This SHOULD be applied only when the font that is - * defined in the playback device context is either Hebrew or Arabic. - */ - private static final BitField ETO_RTLREADING = BitFieldFactory.getInstance(0x0080); - - /** - * Indicates that to display numbers, digits appropriate to the locale SHOULD be used. - */ - private static final BitField ETO_NUMERICSLOCAL = BitFieldFactory.getInstance(0x0400); - - /** - * Indicates that to display numbers, European digits SHOULD be used. - */ - private static final BitField ETO_NUMERICSLATIN = BitFieldFactory.getInstance(0x0800); - - /** - * Indicates that both horizontal and vertical character displacement values - * SHOULD be provided. - */ - private static final BitField ETO_PDY = BitFieldFactory.getInstance(0x2000); - - /** - * A 16-bit signed integer that defines the y-coordinate, in logical units, where the - text string is to be located. - */ - private int y; - /** - * A 16-bit signed integer that defines the x-coordinate, in logical units, where the - text string is to be located. - */ - private int x; - /** - * A 16-bit signed integer that defines the length of the string. - */ - private int stringLength; - - /** - * A 16-bit unsigned integer that defines the use of the application-defined - * rectangle. This member can be a combination of one or more values in the - * ExtTextOutOptions Flags (ETO_*) - */ - private int fwOpts; - /** - * An optional 8-byte Rect Object (section 2.2.2.18) that defines the - * dimensions, in logical coordinates, of a rectangle that is used for clipping, opaquing, or both. - * - * The corners are given in the order left, top, right, bottom. - * Each value is a 16-bit signed integer that defines the coordinate, in logical coordinates, of - * the upper-left corner of the rectangle - */ - private int left,top,right,bottom; - /** - * A variable-length string that specifies the text to be drawn. The string does - * not need to be null-terminated, because StringLength specifies the length of the string. If - * the length is odd, an extra byte is placed after it so that the following member (optional Dx) is - * aligned on a 16-bit boundary. - */ - private byte[] rawTextBytes; - /** - * An optional array of 16-bit signed integers that indicate the distance between - * origins of adjacent character cells. For example, Dx[i] logical units separate the origins of - * character cell i and character cell i + 1. If this field is present, there MUST be the same - * number of values as there are characters in the string. - */ - private int dx[]; - - @Override - public HwmfRecordType getRecordType() { - return HwmfRecordType.extTextOut; - } - - @Override - public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { - // -6 bytes of record function and length header - final int remainingRecordSize = (int)(recordSize-6); - - y = leis.readShort(); - x = leis.readShort(); - stringLength = leis.readShort(); - fwOpts = leis.readUShort(); - - int size = 4*LittleEndianConsts.SHORT_SIZE; - - // Check if we have a rectangle - if ((ETO_OPAQUE.isSet(fwOpts) || ETO_CLIPPED.isSet(fwOpts)) && size+8<=remainingRecordSize) { - // the bounding rectangle is optional and only read when fwOpts are given - left = leis.readShort(); - top = leis.readShort(); - right = leis.readShort(); - bottom = leis.readShort(); - size += 4*LittleEndianConsts.SHORT_SIZE; - } - - rawTextBytes = new byte[stringLength+(stringLength&1)]; - leis.readFully(rawTextBytes); - size += rawTextBytes.length; - - if (size >= remainingRecordSize) { - logger.log(POILogger.INFO, "META_EXTTEXTOUT doesn't contain character tracking info"); - return size; - } - - int dxLen = Math.min(stringLength, (remainingRecordSize-size)/LittleEndianConsts.SHORT_SIZE); - if (dxLen < stringLength) { - logger.log(POILogger.WARN, "META_EXTTEXTOUT tracking info doesn't cover all characters"); - } - - dx = new int[stringLength]; - for (int i=0; i= remainingRecordSize) { + logger.log(POILogger.INFO, "META_EXTTEXTOUT doesn't contain character tracking info"); + return size; + } + + int dxLen = Math.min(stringLength, (remainingRecordSize-size)/LittleEndianConsts.SHORT_SIZE); + if (dxLen < stringLength) { + logger.log(POILogger.WARN, "META_EXTTEXTOUT tracking info doesn't cover all characters"); + } + + dx = new int[stringLength]; + for (int i=0; i 0) { - region = (count == 1) ? lastRect : scanLines; - } - - ctx.getProperties().setRegion(region); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.record; + +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.apache.poi.hwmf.draw.HwmfGraphics; +import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndianInputStream; + +public class HwmfWindowing { + + /** + * The META_SETVIEWPORTORG record defines the viewport origin in the playback device context. + */ + public static class WmfSetViewportOrg implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the vertical offset, in device units. + */ + private int y; + + /** + * A 16-bit signed integer that defines the horizontal offset, in device units. + */ + private int x; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setViewportOrg; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + y = leis.readShort(); + x = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setViewportOrg(x, y); + } + } + + /** + * The META_SETVIEWPORTEXT record sets the horizontal and vertical extents + * of the viewport in the playback device context. + */ + public static class WmfSetViewportExt implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the vertical extent + * of the viewport in device units. + */ + private int height; + + /** + * A 16-bit signed integer that defines the horizontal extent + * of the viewport in device units. + */ + private int width; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setViewportExt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + height = leis.readShort(); + width = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setViewportExt(width, height); + } + } + + /** + * The META_OFFSETVIEWPORTORG record moves the viewport origin in the playback device context + * by specified horizontal and vertical offsets. + */ + public static class WmfOffsetViewportOrg implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the vertical offset, in device units. + */ + private int yOffset; + + /** + * A 16-bit signed integer that defines the horizontal offset, in device units. + */ + private int xOffset; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.offsetViewportOrg; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + yOffset = leis.readShort(); + xOffset = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + Rectangle2D viewport = ctx.getProperties().getViewport(); + double x = (viewport == null) ? 0 : viewport.getX(); + double y = (viewport == null) ? 0 : viewport.getY(); + ctx.getProperties().setViewportOrg(x+xOffset, y+yOffset); + } + } + + /** + * The META_SETWINDOWORG record defines the output window origin in the playback device context. + */ + public static class WmfSetWindowOrg implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units. + */ + private int y; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units. + */ + private int x; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setWindowOrg; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + y = leis.readShort(); + x = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setWindowOrg(x, y); + ctx.updateWindowMapMode(); + } + + public int getY() { + return y; + } + + public int getX() { + return x; + } + } + + /** + * The META_SETWINDOWEXT record defines the horizontal and vertical extents + * of the output window in the playback device context. + */ + public static class WmfSetWindowExt implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the vertical extent of + * the window in logical units. + */ + private int height; + + /** + * A 16-bit signed integer that defines the horizontal extent of + * the window in logical units. + */ + private int width; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.setWindowExt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + height = leis.readShort(); + width = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.getProperties().setWindowExt(width, height); + ctx.updateWindowMapMode(); + } + + public int getHeight() { + return height; + } + + public int getWidth() { + return width; + } + } + + /** + * The META_OFFSETWINDOWORG record moves the output window origin in the + * playback device context by specified horizontal and vertical offsets. + */ + public static class WmfOffsetWindowOrg implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the vertical offset, in device units. + */ + private int yOffset; + + /** + * A 16-bit signed integer that defines the horizontal offset, in device units. + */ + private int xOffset; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.offsetWindowOrg; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + yOffset = leis.readShort(); + xOffset = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + Rectangle2D window = ctx.getProperties().getWindow(); + ctx.getProperties().setWindowOrg(window.getX()+xOffset, window.getY()+yOffset); + ctx.updateWindowMapMode(); + } + } + + /** + * The META_OFFSETWINDOWORG record moves the output window origin in the + * playback device context by specified horizontal and vertical offsets. + */ + public static class WmfScaleWindowExt implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the amount by which to divide the + * result of multiplying the current y-extent by the value of the yNum member. + */ + private int yDenom; + + /** + * A 16-bit signed integer that defines the amount by which to multiply the + * current y-extent. + */ + private int yNum; + + /** + * A 16-bit signed integer that defines the amount by which to divide the + * result of multiplying the current x-extent by the value of the xNum member. + */ + private int xDenom; + + /** + * A 16-bit signed integer that defines the amount by which to multiply the + * current x-extent. + */ + private int xNum; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.scaleWindowExt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + yDenom = leis.readShort(); + yNum = leis.readShort(); + xDenom = leis.readShort(); + xNum = leis.readShort(); + return 4*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + Rectangle2D window = ctx.getProperties().getWindow(); + double width = window.getWidth() * xNum / xDenom; + double height = window.getHeight() * yNum / yDenom; + ctx.getProperties().setWindowExt(width, height); + ctx.updateWindowMapMode(); + } + } + + + /** + * The META_SCALEVIEWPORTEXT record scales the horizontal and vertical extents of the viewport + * that is defined in the playback device context by using the ratios formed by the specified + * multiplicands and divisors. + */ + public static class WmfScaleViewportExt implements HwmfRecord { + + /** + * A 16-bit signed integer that defines the amount by which to divide the + * result of multiplying the current y-extent by the value of the yNum member. + */ + private int yDenom; + + /** + * A 16-bit signed integer that defines the amount by which to multiply the + * current y-extent. + */ + private int yNum; + + /** + * A 16-bit signed integer that defines the amount by which to divide the + * result of multiplying the current x-extent by the value of the xNum member. + */ + private int xDenom; + + /** + * A 16-bit signed integer that defines the amount by which to multiply the + * current x-extent. + */ + private int xNum; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.scaleViewportExt; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + yDenom = leis.readShort(); + yNum = leis.readShort(); + xDenom = leis.readShort(); + xNum = leis.readShort(); + return 4*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + Rectangle2D viewport = ctx.getProperties().getViewport(); + if (viewport == null) { + viewport = ctx.getProperties().getWindow(); + } + double width = viewport.getWidth() * xNum / xDenom; + double height = viewport.getHeight() * yNum / yDenom; + ctx.getProperties().setViewportExt(width, height); + } + } + + /** + * The META_OFFSETCLIPRGN record moves the clipping region in the playback device context by the + * specified offsets. + */ + public static class WmfOffsetClipRgn implements HwmfRecord, HwmfObjectTableEntry { + + /** + * A 16-bit signed integer that defines the number of logical units to move up or down. + */ + private int yOffset; + + /** + * A 16-bit signed integer that defines the number of logical units to move left or right. + */ + private int xOffset; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.offsetClipRgn; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + yOffset = leis.readShort(); + xOffset = leis.readShort(); + return 2*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + } + } + + /** + * The META_EXCLUDECLIPRECT record sets the clipping region in the playback device context to the + * existing clipping region minus the specified rectangle. + */ + public static class WmfExcludeClipRect implements HwmfRecord, HwmfObjectTableEntry { + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * lower-right corner of the rectangle. + */ + private int bottom; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * lower-right corner of the rectangle. + */ + private int right; + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * upper-left corner of the rectangle. + */ + private int top; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * upper-left corner of the rectangle. + */ + private int left; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.excludeClipRect; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + bottom = leis.readShort(); + right = leis.readShort(); + top = leis.readShort(); + left = leis.readShort(); + return 4*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + } + } + + + /** + * The META_INTERSECTCLIPRECT record sets the clipping region in the playback device context to the + * intersection of the existing clipping region and the specified rectangle. + */ + public static class WmfIntersectClipRect implements HwmfRecord, HwmfObjectTableEntry { + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * lower-right corner of the rectangle. + */ + private int bottom; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * lower-right corner of the rectangle. + */ + private int right; + + /** + * A 16-bit signed integer that defines the y-coordinate, in logical units, of the + * upper-left corner of the rectangle. + */ + private int top; + + /** + * A 16-bit signed integer that defines the x-coordinate, in logical units, of the + * upper-left corner of the rectangle. + */ + private int left; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.intersectClipRect; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + bottom = leis.readShort(); + right = leis.readShort(); + top = leis.readShort(); + left = leis.readShort(); + return 4*LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + ctx.addObjectTableEntry(this); + } + + @Override + public void applyObject(HwmfGraphics ctx) { + } + } + + /** + * The META_SELECTCLIPREGION record specifies a Region Object to be the current clipping region. + */ + public static class WmfSelectClipRegion implements HwmfRecord { + + /** + * A 16-bit unsigned integer used to index into the WMF Object Table to get + * the region to be clipped. + */ + private int region; + + @Override + public HwmfRecordType getRecordType() { + return HwmfRecordType.selectClipRegion; + } + + @Override + public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { + region = leis.readShort(); + return LittleEndianConsts.SHORT_SIZE; + } + + @Override + public void draw(HwmfGraphics ctx) { + + } + } + + public static class WmfScanObject { + /** + * A 16-bit unsigned integer that specifies the number of horizontal (x-axis) + * coordinates in the ScanLines array. This value MUST be a multiple of 2, since left and right + * endpoints are required to specify each scanline. + */ + private int count; + /** + * A 16-bit unsigned integer that defines the vertical (y-axis) coordinate, in logical units, of the top scanline. + */ + private int top; + /** + * A 16-bit unsigned integer that defines the vertical (y-axis) coordinate, in logical units, of the bottom scanline. + */ + private int bottom; + /** + * A 16-bit unsigned integer that defines the horizontal (x-axis) coordinate, + * in logical units, of the left endpoint of the scanline. + */ + private int left_scanline[]; + /** + * A 16-bit unsigned integer that defines the horizontal (x-axis) coordinate, + * in logical units, of the right endpoint of the scanline. + */ + private int right_scanline[]; + /** + * A 16-bit unsigned integer that MUST be the same as the value of the Count + * field; it is present to allow upward travel in the structure. + */ + private int count2; + + public int init(LittleEndianInputStream leis) { + count = leis.readUShort(); + top = leis.readUShort(); + bottom = leis.readUShort(); + int size = 3*LittleEndianConsts.SHORT_SIZE; + left_scanline = new int[count/2]; + right_scanline = new int[count/2]; + for (int i=0; i 0) { + region = (count == 1) ? lastRect : scanLines; + } + + ctx.getProperties().setRegion(region); + } + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java b/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java index 5b7601f7a3..78aca4241b 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java @@ -1,172 +1,172 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf.usermodel; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.apache.poi.hwmf.draw.HwmfGraphics; -import org.apache.poi.hwmf.record.HwmfHeader; -import org.apache.poi.hwmf.record.HwmfPlaceableHeader; -import org.apache.poi.hwmf.record.HwmfRecord; -import org.apache.poi.hwmf.record.HwmfRecordType; -import org.apache.poi.hwmf.record.HwmfWindowing.WmfSetWindowExt; -import org.apache.poi.hwmf.record.HwmfWindowing.WmfSetWindowOrg; -import org.apache.poi.util.LittleEndianInputStream; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.Units; - -public class HwmfPicture { - private static final POILogger logger = POILogFactory.getLogger(HwmfPicture.class); - - final List records = new ArrayList(); - final HwmfPlaceableHeader placeableHeader; - final HwmfHeader header; - - public HwmfPicture(InputStream inputStream) throws IOException { - BufferedInputStream bis = new BufferedInputStream(inputStream, 10000); - LittleEndianInputStream leis = new LittleEndianInputStream(bis); - placeableHeader = HwmfPlaceableHeader.readHeader(leis); - header = new HwmfHeader(leis); - - for (;;) { - if (leis.available() < 6) { - logger.log(POILogger.ERROR, "unexpected eof - wmf file was truncated"); - break; - } - // recordSize in DWORDs - long recordSize = leis.readUInt()*2; - int recordFunction = leis.readShort(); - // 4 bytes (recordSize) + 2 bytes (recordFunction) - int consumedSize = 6; - HwmfRecordType wrt = HwmfRecordType.getById(recordFunction); - if (wrt == null) { - throw new IOException("unexpected record type: "+recordFunction); - } - if (wrt == HwmfRecordType.eof) break; - if (wrt.clazz == null) { - throw new IOException("unsupported record type: "+recordFunction); - } - - HwmfRecord wr; - try { - wr = wrt.clazz.newInstance(); - records.add(wr); - } catch (Exception e) { - throw (IOException)new IOException("can't create wmf record").initCause(e); - } - - consumedSize += wr.init(leis, recordSize, recordFunction); - int remainingSize = (int)(recordSize - consumedSize); - assert(remainingSize >= 0); - if (remainingSize > 0) { - // skip size in loops, because not always all bytes are skipped in one call - for (int i=remainingSize; i>0; i-=leis.skip(i)); - } - } - } - - public List getRecords() { - return Collections.unmodifiableList(records); - } - - public void draw(Graphics2D ctx) { - Dimension dim = getSize(); - int width = Units.pointsToPixel(dim.getWidth()); - // keep aspect ratio for height - int height = Units.pointsToPixel(dim.getHeight()); - Rectangle2D bounds = new Rectangle2D.Double(0,0,width,height); - draw(ctx, bounds); - } - - public void draw(Graphics2D ctx, Rectangle2D graphicsBounds) { - AffineTransform at = ctx.getTransform(); - try { - Rectangle2D wmfBounds = getBounds(); - // scale output bounds to image bounds - ctx.translate(graphicsBounds.getX(), graphicsBounds.getY()); - ctx.scale(graphicsBounds.getWidth()/wmfBounds.getWidth(), graphicsBounds.getHeight()/wmfBounds.getHeight()); - - HwmfGraphics g = new HwmfGraphics(ctx, wmfBounds); - for (HwmfRecord r : records) { - r.draw(g); - } - } finally { - ctx.setTransform(at); - } - } - - /** - * Returns the bounding box in device-independent units. Usually this is taken from the placeable header. - * - * @return the bounding box - */ - public Rectangle2D getBounds() { - if (placeableHeader != null) { - return placeableHeader.getBounds(); - } else { - WmfSetWindowOrg wOrg = null; - WmfSetWindowExt wExt = null; - for (HwmfRecord r : getRecords()) { - if (wOrg != null && wExt != null) { - break; - } - if (r instanceof WmfSetWindowOrg) { - wOrg = (WmfSetWindowOrg)r; - } else if (r instanceof WmfSetWindowExt) { - wExt = (WmfSetWindowExt)r; - } - } - if (wOrg == null || wExt == null) { - throw new RuntimeException("invalid wmf file - window records are incomplete."); - } - return new Rectangle2D.Double(wOrg.getX(), wOrg.getY(), wExt.getWidth(), wExt.getHeight()); - } - } - - public HwmfPlaceableHeader getPlaceableHeader() { - return placeableHeader; - } - - public HwmfHeader getHeader() { - return header; - } - - /** - * Return the image size in points - * - * @return the image size in points - */ - public Dimension getSize() { - double inch = (placeableHeader == null) ? 1440 : placeableHeader.getUnitsPerInch(); - Rectangle2D bounds = getBounds(); - - //coefficient to translate from WMF dpi to 72dpi - double coeff = Units.POINT_DPI/inch; - return new Dimension((int)Math.round(bounds.getWidth()*coeff), (int)Math.round(bounds.getHeight()*coeff)); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf.usermodel; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.poi.hwmf.draw.HwmfGraphics; +import org.apache.poi.hwmf.record.HwmfHeader; +import org.apache.poi.hwmf.record.HwmfPlaceableHeader; +import org.apache.poi.hwmf.record.HwmfRecord; +import org.apache.poi.hwmf.record.HwmfRecordType; +import org.apache.poi.hwmf.record.HwmfWindowing.WmfSetWindowExt; +import org.apache.poi.hwmf.record.HwmfWindowing.WmfSetWindowOrg; +import org.apache.poi.util.LittleEndianInputStream; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.Units; + +public class HwmfPicture { + private static final POILogger logger = POILogFactory.getLogger(HwmfPicture.class); + + final List records = new ArrayList(); + final HwmfPlaceableHeader placeableHeader; + final HwmfHeader header; + + public HwmfPicture(InputStream inputStream) throws IOException { + BufferedInputStream bis = new BufferedInputStream(inputStream, 10000); + LittleEndianInputStream leis = new LittleEndianInputStream(bis); + placeableHeader = HwmfPlaceableHeader.readHeader(leis); + header = new HwmfHeader(leis); + + for (;;) { + if (leis.available() < 6) { + logger.log(POILogger.ERROR, "unexpected eof - wmf file was truncated"); + break; + } + // recordSize in DWORDs + long recordSize = leis.readUInt()*2; + int recordFunction = leis.readShort(); + // 4 bytes (recordSize) + 2 bytes (recordFunction) + int consumedSize = 6; + HwmfRecordType wrt = HwmfRecordType.getById(recordFunction); + if (wrt == null) { + throw new IOException("unexpected record type: "+recordFunction); + } + if (wrt == HwmfRecordType.eof) break; + if (wrt.clazz == null) { + throw new IOException("unsupported record type: "+recordFunction); + } + + HwmfRecord wr; + try { + wr = wrt.clazz.newInstance(); + records.add(wr); + } catch (Exception e) { + throw (IOException)new IOException("can't create wmf record").initCause(e); + } + + consumedSize += wr.init(leis, recordSize, recordFunction); + int remainingSize = (int)(recordSize - consumedSize); + assert(remainingSize >= 0); + if (remainingSize > 0) { + // skip size in loops, because not always all bytes are skipped in one call + for (int i=remainingSize; i>0; i-=leis.skip(i)); + } + } + } + + public List getRecords() { + return Collections.unmodifiableList(records); + } + + public void draw(Graphics2D ctx) { + Dimension dim = getSize(); + int width = Units.pointsToPixel(dim.getWidth()); + // keep aspect ratio for height + int height = Units.pointsToPixel(dim.getHeight()); + Rectangle2D bounds = new Rectangle2D.Double(0,0,width,height); + draw(ctx, bounds); + } + + public void draw(Graphics2D ctx, Rectangle2D graphicsBounds) { + AffineTransform at = ctx.getTransform(); + try { + Rectangle2D wmfBounds = getBounds(); + // scale output bounds to image bounds + ctx.translate(graphicsBounds.getX(), graphicsBounds.getY()); + ctx.scale(graphicsBounds.getWidth()/wmfBounds.getWidth(), graphicsBounds.getHeight()/wmfBounds.getHeight()); + + HwmfGraphics g = new HwmfGraphics(ctx, wmfBounds); + for (HwmfRecord r : records) { + r.draw(g); + } + } finally { + ctx.setTransform(at); + } + } + + /** + * Returns the bounding box in device-independent units. Usually this is taken from the placeable header. + * + * @return the bounding box + */ + public Rectangle2D getBounds() { + if (placeableHeader != null) { + return placeableHeader.getBounds(); + } else { + WmfSetWindowOrg wOrg = null; + WmfSetWindowExt wExt = null; + for (HwmfRecord r : getRecords()) { + if (wOrg != null && wExt != null) { + break; + } + if (r instanceof WmfSetWindowOrg) { + wOrg = (WmfSetWindowOrg)r; + } else if (r instanceof WmfSetWindowExt) { + wExt = (WmfSetWindowExt)r; + } + } + if (wOrg == null || wExt == null) { + throw new RuntimeException("invalid wmf file - window records are incomplete."); + } + return new Rectangle2D.Double(wOrg.getX(), wOrg.getY(), wExt.getWidth(), wExt.getHeight()); + } + } + + public HwmfPlaceableHeader getPlaceableHeader() { + return placeableHeader; + } + + public HwmfHeader getHeader() { + return header; + } + + /** + * Return the image size in points + * + * @return the image size in points + */ + public Dimension getSize() { + double inch = (placeableHeader == null) ? 1440 : placeableHeader.getUnitsPerInch(); + Rectangle2D bounds = getBounds(); + + //coefficient to translate from WMF dpi to 72dpi + double coeff = Units.POINT_DPI/inch; + return new Dimension((int)Math.round(bounds.getWidth()*coeff), (int)Math.round(bounds.getHeight()*coeff)); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/CharIndexTranslator.java b/src/scratchpad/src/org/apache/poi/hwpf/model/CharIndexTranslator.java index 29cd5d6231..f59da4f0e0 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/CharIndexTranslator.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/CharIndexTranslator.java @@ -1,94 +1,94 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model; - -import org.apache.poi.util.Internal; - -@Internal -public interface CharIndexTranslator { - /** - * Calculates the byte index of the given char index. - * - * @param charPos - * The char position - * @return The byte index - */ - int getByteIndex( int charPos ); - - /** - * Calculates the char index of the given byte index. Look forward if index - * is not in table - * - * @param bytePos - * The character offset to check - * @return the char index - * @deprecated This API were based on incorrect assumption that single byte - * offset corresponds to single char offset - */ - @Deprecated - int getCharIndex(int bytePos); - - /** - * Calculates the char index of the given byte index. - * Look forward if index is not in table - * - * @param bytePos The character offset to check - * @param startCP look from this characted position - * @return the char index - * @deprecated This API were based on incorrect assumption that single byte - * offset corresponds to single char offset - */ - @Deprecated - int getCharIndex(int bytePos, int startCP); - - /** - * Finds character ranges that includes specified byte range. - * - * @param startBytePosInclusive - * start byte range - * @param endBytePosExclusive - * end byte range - */ - int[][] getCharIndexRanges( int startBytePosInclusive, - int endBytePosExclusive ); - - /** - * Check if index is in table - * - * @param bytePos - * @return true if index in table, false if not - */ - boolean isIndexInTable(int bytePos); - - /** - * Return first index >= bytePos that is in table - * - * @param bytePos - * @return first index greater or equal to bytePos that is in table - */ - int lookIndexForward(int bytePos); - - /** - * Return last index <= bytePos that is in table - * - * @param bytePos - * @return last index less of equal to bytePos that is in table - */ - int lookIndexBackward(int bytePos); - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.model; + +import org.apache.poi.util.Internal; + +@Internal +public interface CharIndexTranslator { + /** + * Calculates the byte index of the given char index. + * + * @param charPos + * The char position + * @return The byte index + */ + int getByteIndex( int charPos ); + + /** + * Calculates the char index of the given byte index. Look forward if index + * is not in table + * + * @param bytePos + * The character offset to check + * @return the char index + * @deprecated This API were based on incorrect assumption that single byte + * offset corresponds to single char offset + */ + @Deprecated + int getCharIndex(int bytePos); + + /** + * Calculates the char index of the given byte index. + * Look forward if index is not in table + * + * @param bytePos The character offset to check + * @param startCP look from this characted position + * @return the char index + * @deprecated This API were based on incorrect assumption that single byte + * offset corresponds to single char offset + */ + @Deprecated + int getCharIndex(int bytePos, int startCP); + + /** + * Finds character ranges that includes specified byte range. + * + * @param startBytePosInclusive + * start byte range + * @param endBytePosExclusive + * end byte range + */ + int[][] getCharIndexRanges( int startBytePosInclusive, + int endBytePosExclusive ); + + /** + * Check if index is in table + * + * @param bytePos + * @return true if index in table, false if not + */ + boolean isIndexInTable(int bytePos); + + /** + * Return first index >= bytePos that is in table + * + * @param bytePos + * @return first index greater or equal to bytePos that is in table + */ + int lookIndexForward(int bytePos); + + /** + * Return last index <= bytePos that is in table + * + * @param bytePos + * @return last index less of equal to bytePos that is in table + */ + int lookIndexBackward(int bytePos); + +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FFData.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FFData.java index 1ed09aa683..325fd5b974 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FFData.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FFData.java @@ -1,230 +1,230 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model; - -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * The FFData structure specifies form field data for a text box, check box, or - * drop-down list box. - *

    - * Class and fields descriptions are quoted from [MS-DOC] -- v20121003 Word - * (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; Release: - * October 8, 2012 - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - * - * @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word (.doc) - * Binary File Format; Copyright (c) 2012 Microsoft Corporation; - * Release: October 8, 2012 - */ -@Internal -public class FFData -{ - private FFDataBase _base; - - /** - * An optional STTB that specifies the entries in the dropdown list box. - * This MUST exist if and only if bits.iType is iTypeDrop (2). The entries - * are Unicode strings and do not have extra data. This MUST NOT exceed 25 - * elements. - */ - private Sttb _hsttbDropList; - - /** - * An optional unsigned integer that specifies the default state of the - * checkbox or dropdown list box. This value MUST exist if and only if - * bits.iType is iTypeChck (1) or iTypeDrop (2). If bits.iType is iTypeChck - * (1), wDef MUST be 0 or 1 and specify the default state of the checkbox as - * unchecked or checked, respectively. If bits.iType is iTypeDrop (2), wDef - * MUST be less than the number of items in the dropdown list box and - * specify the default item selected (zero-based index). - */ - private Integer _wDef; - - private Xstz _xstzEntryMcr; - - private Xstz _xstzExitMcr; - - private Xstz _xstzHelpText; - - /** - * An Xstz that specifies the name of this form field. xstzName.cch MUST NOT - * exceed 20. - */ - private Xstz _xstzName; - - private Xstz _xstzStatText; - - /** - * An optional Xstz that specifies the default text of this textbox. This - * structure MUST exist if and only if bits.iType is iTypeTxt (0). - * xstzTextDef.cch MUST NOT exceed 255. If bits.iTypeTxt is either - * iTypeTxtCurDate (3) or iTypeTxtCurTime (4), xstzTextDef MUST be an empty - * string. If bits.iTypeTxt is iTypeTxtCalc (5), xstzTextDef specifies an - * expression to calculate. - */ - private Xstz _xstzTextDef; - - private Xstz _xstzTextFormat; - - public FFData( byte[] std, int offset ) - { - fillFields( std, offset ); - } - - public void fillFields( final byte[] std, final int startOffset ) // NOSONAR - { - int offset = startOffset; - - this._base = new FFDataBase( std, offset ); - offset += FFDataBase.getSize(); - - this._xstzName = new Xstz( std, offset ); - offset += this._xstzName.getSize(); - - if ( _base.getIType() == FFDataBase.ITYPE_TEXT ) - { - _xstzTextDef = new Xstz( std, offset ); - offset += this._xstzTextDef.getSize(); - } - else - { - this._xstzTextDef = null; - } - - if ( _base.getIType() == FFDataBase.ITYPE_CHCK - || _base.getIType() == FFDataBase.ITYPE_DROP ) - { - this._wDef = Integer - .valueOf( LittleEndian.getUShort( std, offset ) ); - offset += LittleEndian.SHORT_SIZE; - } - else - { - this._wDef = null; - } - - _xstzTextFormat = new Xstz( std, offset ); - offset += this._xstzTextFormat.getSize(); - - _xstzHelpText = new Xstz( std, offset ); - offset += this._xstzHelpText.getSize(); - - _xstzStatText = new Xstz( std, offset ); - offset += this._xstzStatText.getSize(); - - _xstzEntryMcr = new Xstz( std, offset ); - offset += this._xstzEntryMcr.getSize(); - - _xstzExitMcr = new Xstz( std, offset ); - offset += this._xstzExitMcr.getSize(); - - if ( _base.getIType() == FFDataBase.ITYPE_DROP ) - { - _hsttbDropList = new Sttb( std, offset ); - offset += _hsttbDropList.getSize(); - } - } - - /** - * specify the default item selected (zero-based index). - */ - public int getDefaultDropDownItemIndex() - { - return _wDef.intValue(); - } - - public String[] getDropList() - { - return _hsttbDropList.getData(); - } - - public int getSize() - { - int size = FFDataBase.getSize(); - - size += _xstzName.getSize(); - - if ( _base.getIType() == FFDataBase.ITYPE_TEXT ) - { - size += _xstzTextDef.getSize(); - } - - if ( _base.getIType() == FFDataBase.ITYPE_CHCK - || _base.getIType() == FFDataBase.ITYPE_DROP ) - { - size += LittleEndian.SHORT_SIZE; - } - - size += _xstzTextFormat.getSize(); - size += _xstzHelpText.getSize(); - size += _xstzStatText.getSize(); - size += _xstzEntryMcr.getSize(); - size += _xstzExitMcr.getSize(); - - if ( _base.getIType() == FFDataBase.ITYPE_DROP ) - { - size += _hsttbDropList.getSize(); - } - - return size; - } - - public String getTextDef() - { - return _xstzTextDef.getAsJavaString(); - } - - public byte[] serialize() - { - byte[] buffer = new byte[getSize()]; - int offset = 0; - - _base.serialize( buffer, offset ); - offset += FFDataBase.getSize(); - - offset += _xstzName.serialize( buffer, offset ); - - if ( _base.getIType() == FFDataBase.ITYPE_TEXT ) - { - offset += _xstzTextDef.serialize( buffer, offset ); - } - - if ( _base.getIType() == FFDataBase.ITYPE_CHCK - || _base.getIType() == FFDataBase.ITYPE_DROP ) - { - LittleEndian.putUShort( buffer, offset, _wDef ); - offset += LittleEndian.SHORT_SIZE; - } - - offset += _xstzTextFormat.serialize( buffer, offset ); - offset += _xstzHelpText.serialize( buffer, offset ); - offset += _xstzStatText.serialize( buffer, offset ); - offset += _xstzEntryMcr.serialize( buffer, offset ); - offset += _xstzExitMcr.serialize( buffer, offset ); - - if ( _base.getIType() == FFDataBase.ITYPE_DROP ) - { - offset += _hsttbDropList.serialize( buffer, offset ); - } - - return buffer; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model; + +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * The FFData structure specifies form field data for a text box, check box, or + * drop-down list box. + *

    + * Class and fields descriptions are quoted from [MS-DOC] -- v20121003 Word + * (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; Release: + * October 8, 2012 + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + * + * @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word (.doc) + * Binary File Format; Copyright (c) 2012 Microsoft Corporation; + * Release: October 8, 2012 + */ +@Internal +public class FFData +{ + private FFDataBase _base; + + /** + * An optional STTB that specifies the entries in the dropdown list box. + * This MUST exist if and only if bits.iType is iTypeDrop (2). The entries + * are Unicode strings and do not have extra data. This MUST NOT exceed 25 + * elements. + */ + private Sttb _hsttbDropList; + + /** + * An optional unsigned integer that specifies the default state of the + * checkbox or dropdown list box. This value MUST exist if and only if + * bits.iType is iTypeChck (1) or iTypeDrop (2). If bits.iType is iTypeChck + * (1), wDef MUST be 0 or 1 and specify the default state of the checkbox as + * unchecked or checked, respectively. If bits.iType is iTypeDrop (2), wDef + * MUST be less than the number of items in the dropdown list box and + * specify the default item selected (zero-based index). + */ + private Integer _wDef; + + private Xstz _xstzEntryMcr; + + private Xstz _xstzExitMcr; + + private Xstz _xstzHelpText; + + /** + * An Xstz that specifies the name of this form field. xstzName.cch MUST NOT + * exceed 20. + */ + private Xstz _xstzName; + + private Xstz _xstzStatText; + + /** + * An optional Xstz that specifies the default text of this textbox. This + * structure MUST exist if and only if bits.iType is iTypeTxt (0). + * xstzTextDef.cch MUST NOT exceed 255. If bits.iTypeTxt is either + * iTypeTxtCurDate (3) or iTypeTxtCurTime (4), xstzTextDef MUST be an empty + * string. If bits.iTypeTxt is iTypeTxtCalc (5), xstzTextDef specifies an + * expression to calculate. + */ + private Xstz _xstzTextDef; + + private Xstz _xstzTextFormat; + + public FFData( byte[] std, int offset ) + { + fillFields( std, offset ); + } + + public void fillFields( final byte[] std, final int startOffset ) // NOSONAR + { + int offset = startOffset; + + this._base = new FFDataBase( std, offset ); + offset += FFDataBase.getSize(); + + this._xstzName = new Xstz( std, offset ); + offset += this._xstzName.getSize(); + + if ( _base.getIType() == FFDataBase.ITYPE_TEXT ) + { + _xstzTextDef = new Xstz( std, offset ); + offset += this._xstzTextDef.getSize(); + } + else + { + this._xstzTextDef = null; + } + + if ( _base.getIType() == FFDataBase.ITYPE_CHCK + || _base.getIType() == FFDataBase.ITYPE_DROP ) + { + this._wDef = Integer + .valueOf( LittleEndian.getUShort( std, offset ) ); + offset += LittleEndian.SHORT_SIZE; + } + else + { + this._wDef = null; + } + + _xstzTextFormat = new Xstz( std, offset ); + offset += this._xstzTextFormat.getSize(); + + _xstzHelpText = new Xstz( std, offset ); + offset += this._xstzHelpText.getSize(); + + _xstzStatText = new Xstz( std, offset ); + offset += this._xstzStatText.getSize(); + + _xstzEntryMcr = new Xstz( std, offset ); + offset += this._xstzEntryMcr.getSize(); + + _xstzExitMcr = new Xstz( std, offset ); + offset += this._xstzExitMcr.getSize(); + + if ( _base.getIType() == FFDataBase.ITYPE_DROP ) + { + _hsttbDropList = new Sttb( std, offset ); + offset += _hsttbDropList.getSize(); + } + } + + /** + * specify the default item selected (zero-based index). + */ + public int getDefaultDropDownItemIndex() + { + return _wDef.intValue(); + } + + public String[] getDropList() + { + return _hsttbDropList.getData(); + } + + public int getSize() + { + int size = FFDataBase.getSize(); + + size += _xstzName.getSize(); + + if ( _base.getIType() == FFDataBase.ITYPE_TEXT ) + { + size += _xstzTextDef.getSize(); + } + + if ( _base.getIType() == FFDataBase.ITYPE_CHCK + || _base.getIType() == FFDataBase.ITYPE_DROP ) + { + size += LittleEndian.SHORT_SIZE; + } + + size += _xstzTextFormat.getSize(); + size += _xstzHelpText.getSize(); + size += _xstzStatText.getSize(); + size += _xstzEntryMcr.getSize(); + size += _xstzExitMcr.getSize(); + + if ( _base.getIType() == FFDataBase.ITYPE_DROP ) + { + size += _hsttbDropList.getSize(); + } + + return size; + } + + public String getTextDef() + { + return _xstzTextDef.getAsJavaString(); + } + + public byte[] serialize() + { + byte[] buffer = new byte[getSize()]; + int offset = 0; + + _base.serialize( buffer, offset ); + offset += FFDataBase.getSize(); + + offset += _xstzName.serialize( buffer, offset ); + + if ( _base.getIType() == FFDataBase.ITYPE_TEXT ) + { + offset += _xstzTextDef.serialize( buffer, offset ); + } + + if ( _base.getIType() == FFDataBase.ITYPE_CHCK + || _base.getIType() == FFDataBase.ITYPE_DROP ) + { + LittleEndian.putUShort( buffer, offset, _wDef ); + offset += LittleEndian.SHORT_SIZE; + } + + offset += _xstzTextFormat.serialize( buffer, offset ); + offset += _xstzHelpText.serialize( buffer, offset ); + offset += _xstzStatText.serialize( buffer, offset ); + offset += _xstzEntryMcr.serialize( buffer, offset ); + offset += _xstzExitMcr.serialize( buffer, offset ); + + if ( _base.getIType() == FFDataBase.ITYPE_DROP ) + { + offset += _hsttbDropList.serialize( buffer, offset ); + } + + return buffer; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FFDataBase.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FFDataBase.java index d0e542fe01..b12fe40691 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FFDataBase.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FFDataBase.java @@ -1,49 +1,49 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model; - -import org.apache.poi.hwpf.model.types.FFDataBaseAbstractType; -import org.apache.poi.util.Internal; - -/** - * The FFData structure specifies form field data for a text box, check box, or - * drop-down list box. - *

    - * Class and fields descriptions are quoted from [MS-DOC] -- v20121003 Word - * (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; Release: - * October 8, 2012 - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - * - * @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word (.doc) - * Binary File Format; Copyright (c) 2012 Microsoft Corporation; - * Release: October 8, 2012 - */ -@Internal -public class FFDataBase extends FFDataBaseAbstractType -{ - public FFDataBase() - { - super(); - } - - public FFDataBase( byte[] std, int offset ) - { - fillFields( std, offset ); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model; + +import org.apache.poi.hwpf.model.types.FFDataBaseAbstractType; +import org.apache.poi.util.Internal; + +/** + * The FFData structure specifies form field data for a text box, check box, or + * drop-down list box. + *

    + * Class and fields descriptions are quoted from [MS-DOC] -- v20121003 Word + * (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; Release: + * October 8, 2012 + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + * + * @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word (.doc) + * Binary File Format; Copyright (c) 2012 Microsoft Corporation; + * Release: October 8, 2012 + */ +@Internal +public class FFDataBase extends FFDataBaseAbstractType +{ + public FFDataBase() + { + super(); + } + + public FFDataBase( byte[] std, int offset ) + { + fillFields( std, offset ); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/NilPICFAndBinData.java b/src/scratchpad/src/org/apache/poi/hwpf/model/NilPICFAndBinData.java index 918afdb3c8..c2f1ab387a 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/NilPICFAndBinData.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/NilPICFAndBinData.java @@ -1,79 +1,79 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model; - -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -import java.util.Arrays; - -public class NilPICFAndBinData -{ - - private static final POILogger log = POILogFactory - .getLogger( NilPICFAndBinData.class ); - - private byte[] _binData; - - public NilPICFAndBinData( byte[] data, int offset ) - { - fillFields( data, offset ); - } - - public void fillFields( byte[] data, int offset ) - { - int lcb = LittleEndian.getInt( data, offset ); - int cbHeader = LittleEndian.getUShort( data, offset - + LittleEndian.INT_SIZE ); - - if ( cbHeader != 0x44 ) - { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "NilPICFAndBinData at offset ", offset, - " cbHeader 0x" + Integer.toHexString(cbHeader) - + " != 0x44" - ); - } - } - - // skip the 62 ignored bytes - int binaryLength = lcb - cbHeader; - this._binData = Arrays.copyOfRange(data, offset + cbHeader, - offset + cbHeader + binaryLength); - } - - public byte[] getBinData() - { - return _binData; - } - - public byte[] serialize() - { - byte[] bs = new byte[_binData.length + 0x44]; - LittleEndian.putInt( bs, 0, _binData.length + 0x44 ); - System.arraycopy( _binData, 0, bs, 0x44, _binData.length ); - return bs; - } - - public int serialize( byte[] data, int offset ) - { - LittleEndian.putInt( data, offset, _binData.length + 0x44 ); - System.arraycopy( _binData, 0, data, offset + 0x44, _binData.length ); - return 0x44 + _binData.length; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +import java.util.Arrays; + +public class NilPICFAndBinData +{ + + private static final POILogger log = POILogFactory + .getLogger( NilPICFAndBinData.class ); + + private byte[] _binData; + + public NilPICFAndBinData( byte[] data, int offset ) + { + fillFields( data, offset ); + } + + public void fillFields( byte[] data, int offset ) + { + int lcb = LittleEndian.getInt( data, offset ); + int cbHeader = LittleEndian.getUShort( data, offset + + LittleEndian.INT_SIZE ); + + if ( cbHeader != 0x44 ) + { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "NilPICFAndBinData at offset ", offset, + " cbHeader 0x" + Integer.toHexString(cbHeader) + + " != 0x44" + ); + } + } + + // skip the 62 ignored bytes + int binaryLength = lcb - cbHeader; + this._binData = Arrays.copyOfRange(data, offset + cbHeader, + offset + cbHeader + binaryLength); + } + + public byte[] getBinData() + { + return _binData; + } + + public byte[] serialize() + { + byte[] bs = new byte[_binData.length + 0x44]; + LittleEndian.putInt( bs, 0, _binData.length + 0x44 ); + System.arraycopy( _binData, 0, bs, 0x44, _binData.length ); + return bs; + } + + public int serialize( byte[] data, int offset ) + { + LittleEndian.putInt( data, offset, _binData.length + 0x44 ); + System.arraycopy( _binData, 0, data, offset + 0x44, _binData.length ); + return 0x44 + _binData.length; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/Xstz.java b/src/scratchpad/src/org/apache/poi/hwpf/model/Xstz.java index 4aef0171fa..f7aeb10dd1 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/Xstz.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/Xstz.java @@ -1,87 +1,87 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model; - -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -@Internal -public class Xstz -{ - private static final POILogger log = POILogFactory.getLogger( Xstz.class ); - - private final short _chTerm = 0; - private Xst _xst; - - public Xstz() - { - _xst = new Xst(); - } - - public Xstz( byte[] data, int startOffset ) - { - fillFields( data, startOffset ); - } - - public void fillFields( byte[] data, int startOffset ) - { - int offset = startOffset; - - _xst = new Xst( data, offset ); - offset += _xst.getSize(); - - short term = LittleEndian.getShort( data, offset ); - if ( term != 0 ) - { - if (log.check(POILogger.WARN)) { - log.log(POILogger.WARN, "chTerm at the end of Xstz at offset ", - offset, " is not 0"); - } - } - } - - public String getAsJavaString() - { - return _xst.getAsJavaString(); - } - - public int getSize() - { - return _xst.getSize() + LittleEndian.SHORT_SIZE; - } - - public int serialize( byte[] data, int startOffset ) - { - int offset = startOffset; - - _xst.serialize( data, offset ); - offset += _xst.getSize(); - - LittleEndian.putUShort( data, offset, _chTerm ); - offset += LittleEndian.SHORT_SIZE; - - return offset - startOffset; - } - - @Override - public String toString() - { - return "[Xstz]" + _xst.getAsJavaString() + "[/Xstz]"; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model; + +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +@Internal +public class Xstz +{ + private static final POILogger log = POILogFactory.getLogger( Xstz.class ); + + private final short _chTerm = 0; + private Xst _xst; + + public Xstz() + { + _xst = new Xst(); + } + + public Xstz( byte[] data, int startOffset ) + { + fillFields( data, startOffset ); + } + + public void fillFields( byte[] data, int startOffset ) + { + int offset = startOffset; + + _xst = new Xst( data, offset ); + offset += _xst.getSize(); + + short term = LittleEndian.getShort( data, offset ); + if ( term != 0 ) + { + if (log.check(POILogger.WARN)) { + log.log(POILogger.WARN, "chTerm at the end of Xstz at offset ", + offset, " is not 0"); + } + } + } + + public String getAsJavaString() + { + return _xst.getAsJavaString(); + } + + public int getSize() + { + return _xst.getSize() + LittleEndian.SHORT_SIZE; + } + + public int serialize( byte[] data, int startOffset ) + { + int offset = startOffset; + + _xst.serialize( data, offset ); + offset += _xst.getSize(); + + LittleEndian.putUShort( data, offset, _chTerm ); + offset += LittleEndian.SHORT_SIZE; + + return offset - startOffset; + } + + @Override + public String toString() + { + return "[Xstz]" + _xst.getAsJavaString() + "[/Xstz]"; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/BKFAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/BKFAbstractType.java index fb62447460..20ab5ecb89 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/BKFAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/BKFAbstractType.java @@ -1,192 +1,192 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * BooKmark First descriptor (BKF). - *

    - * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 - * Binary File Format (.doc) Specification - * - * NOTE: This source is automatically generated please do not modify this file. - * Either subclass or remove the record in src/types/definitions. - * - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary - * File Format (.doc) Specification - */ -@Internal -public abstract class BKFAbstractType -{ - - protected short field_1_ibkl; - protected short field_2_bkf_flags; - /**/private static BitField itcFirst = new BitField( 0x007F ); - /**/private static BitField fPub = new BitField( 0x0080 ); - /**/private static BitField itcLim = new BitField( 0x7F00 ); - /**/private static BitField fCol = new BitField( 0x8000 ); - - protected BKFAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_ibkl = LittleEndian.getShort(data, 0x0 + offset); - field_2_bkf_flags = LittleEndian.getShort(data, 0x2 + offset); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putShort(data, 0x0 + offset, field_1_ibkl); - LittleEndian.putShort(data, 0x2 + offset, field_2_bkf_flags); - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 2 + 2; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[BKF]\n"); - builder.append(" .ibkl = "); - builder.append(" (").append(getIbkl()).append(" )\n"); - builder.append(" .bkf_flags = "); - builder.append(" (").append(getBkf_flags()).append(" )\n"); - builder.append(" .itcFirst = ").append(getItcFirst()).append('\n'); - builder.append(" .fPub = ").append(isFPub()).append('\n'); - builder.append(" .itcLim = ").append(getItcLim()).append('\n'); - builder.append(" .fCol = ").append(isFCol()).append('\n'); - - builder.append("[/BKF]\n"); - return builder.toString(); - } - - /** - * Index to BKL entry in plcfbkl that describes the ending position of this bookmark in the CP stream. - */ - public short getIbkl() - { - return field_1_ibkl; - } - - /** - * Index to BKL entry in plcfbkl that describes the ending position of this bookmark in the CP stream. - */ - public void setIbkl( short field_1_ibkl ) - { - this.field_1_ibkl = field_1_ibkl; - } - - /** - * Get the bkf_flags field for the BKF record. - */ - public short getBkf_flags() - { - return field_2_bkf_flags; - } - - /** - * Set the bkf_flags field for the BKF record. - */ - public void setBkf_flags( short field_2_bkf_flags ) - { - this.field_2_bkf_flags = field_2_bkf_flags; - } - - /** - * Sets the itcFirst field value. - * When bkf.fCol==1, this is the index to the first column of a table column bookmark - */ - public void setItcFirst( byte value ) - { - field_2_bkf_flags = (short)itcFirst.setValue(field_2_bkf_flags, value); - } - - /** - * When bkf.fCol==1, this is the index to the first column of a table column bookmark - * @return the itcFirst field value. - */ - public byte getItcFirst() - { - return ( byte )itcFirst.getValue(field_2_bkf_flags); - } - - /** - * Sets the fPub field value. - * When 1, this indicates that this bookmark is marking the range of a Macintosh Publisher section - */ - public void setFPub( boolean value ) - { - field_2_bkf_flags = (short)fPub.setBoolean(field_2_bkf_flags, value); - } - - /** - * When 1, this indicates that this bookmark is marking the range of a Macintosh Publisher section - * @return the fPub field value. - */ - public boolean isFPub() - { - return fPub.isSet(field_2_bkf_flags); - } - - /** - * Sets the itcLim field value. - * When bkf.fCol==1, this is the index to limit column of a table column bookmark - */ - public void setItcLim( byte value ) - { - field_2_bkf_flags = (short)itcLim.setValue(field_2_bkf_flags, value); - } - - /** - * When bkf.fCol==1, this is the index to limit column of a table column bookmark - * @return the itcLim field value. - */ - public byte getItcLim() - { - return ( byte )itcLim.getValue(field_2_bkf_flags); - } - - /** - * Sets the fCol field value. - * When 1, this bookmark marks a range of columns in a table specified by (bkf.itcFirst, bkf.itcLim) - */ - public void setFCol( boolean value ) - { - field_2_bkf_flags = (short)fCol.setBoolean(field_2_bkf_flags, value); - } - - /** - * When 1, this bookmark marks a range of columns in a table specified by (bkf.itcFirst, bkf.itcLim) - * @return the fCol field value. - */ - public boolean isFCol() - { - return fCol.isSet(field_2_bkf_flags); - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * BooKmark First descriptor (BKF). + *

    + * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 + * Binary File Format (.doc) Specification + * + * NOTE: This source is automatically generated please do not modify this file. + * Either subclass or remove the record in src/types/definitions. + * + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary + * File Format (.doc) Specification + */ +@Internal +public abstract class BKFAbstractType +{ + + protected short field_1_ibkl; + protected short field_2_bkf_flags; + /**/private static BitField itcFirst = new BitField( 0x007F ); + /**/private static BitField fPub = new BitField( 0x0080 ); + /**/private static BitField itcLim = new BitField( 0x7F00 ); + /**/private static BitField fCol = new BitField( 0x8000 ); + + protected BKFAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_ibkl = LittleEndian.getShort(data, 0x0 + offset); + field_2_bkf_flags = LittleEndian.getShort(data, 0x2 + offset); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putShort(data, 0x0 + offset, field_1_ibkl); + LittleEndian.putShort(data, 0x2 + offset, field_2_bkf_flags); + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 2 + 2; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[BKF]\n"); + builder.append(" .ibkl = "); + builder.append(" (").append(getIbkl()).append(" )\n"); + builder.append(" .bkf_flags = "); + builder.append(" (").append(getBkf_flags()).append(" )\n"); + builder.append(" .itcFirst = ").append(getItcFirst()).append('\n'); + builder.append(" .fPub = ").append(isFPub()).append('\n'); + builder.append(" .itcLim = ").append(getItcLim()).append('\n'); + builder.append(" .fCol = ").append(isFCol()).append('\n'); + + builder.append("[/BKF]\n"); + return builder.toString(); + } + + /** + * Index to BKL entry in plcfbkl that describes the ending position of this bookmark in the CP stream. + */ + public short getIbkl() + { + return field_1_ibkl; + } + + /** + * Index to BKL entry in plcfbkl that describes the ending position of this bookmark in the CP stream. + */ + public void setIbkl( short field_1_ibkl ) + { + this.field_1_ibkl = field_1_ibkl; + } + + /** + * Get the bkf_flags field for the BKF record. + */ + public short getBkf_flags() + { + return field_2_bkf_flags; + } + + /** + * Set the bkf_flags field for the BKF record. + */ + public void setBkf_flags( short field_2_bkf_flags ) + { + this.field_2_bkf_flags = field_2_bkf_flags; + } + + /** + * Sets the itcFirst field value. + * When bkf.fCol==1, this is the index to the first column of a table column bookmark + */ + public void setItcFirst( byte value ) + { + field_2_bkf_flags = (short)itcFirst.setValue(field_2_bkf_flags, value); + } + + /** + * When bkf.fCol==1, this is the index to the first column of a table column bookmark + * @return the itcFirst field value. + */ + public byte getItcFirst() + { + return ( byte )itcFirst.getValue(field_2_bkf_flags); + } + + /** + * Sets the fPub field value. + * When 1, this indicates that this bookmark is marking the range of a Macintosh Publisher section + */ + public void setFPub( boolean value ) + { + field_2_bkf_flags = (short)fPub.setBoolean(field_2_bkf_flags, value); + } + + /** + * When 1, this indicates that this bookmark is marking the range of a Macintosh Publisher section + * @return the fPub field value. + */ + public boolean isFPub() + { + return fPub.isSet(field_2_bkf_flags); + } + + /** + * Sets the itcLim field value. + * When bkf.fCol==1, this is the index to limit column of a table column bookmark + */ + public void setItcLim( byte value ) + { + field_2_bkf_flags = (short)itcLim.setValue(field_2_bkf_flags, value); + } + + /** + * When bkf.fCol==1, this is the index to limit column of a table column bookmark + * @return the itcLim field value. + */ + public byte getItcLim() + { + return ( byte )itcLim.getValue(field_2_bkf_flags); + } + + /** + * Sets the fCol field value. + * When 1, this bookmark marks a range of columns in a table specified by (bkf.itcFirst, bkf.itcLim) + */ + public void setFCol( boolean value ) + { + field_2_bkf_flags = (short)fCol.setBoolean(field_2_bkf_flags, value); + } + + /** + * When 1, this bookmark marks a range of columns in a table specified by (bkf.itcFirst, bkf.itcLim) + * @return the fCol field value. + */ + public boolean isFCol() + { + return fCol.isSet(field_2_bkf_flags); + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FFDataBaseAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FFDataBaseAbstractType.java index f582018b28..20c4106142 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FFDataBaseAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FFDataBaseAbstractType.java @@ -1,428 +1,428 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model.types; - - -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * The FFData structure specifies form field data for a text - box, check box, or drop-down list box.

    Class and fields - descriptions are quoted from [MS-DOC] -- v20121003 Word (.doc) Binary - File Format; Copyright (c) 2012 Microsoft Corporation; Release: - October 8, 2012 - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word - (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; - Release: October 8, 2012 - - */ -@Internal -public abstract class FFDataBaseAbstractType -{ - - protected long field_1_version; - protected short field_2_bits; - /**/private static final BitField iType = new BitField(0x0003); - /** Specifies that the form field is a textbox. */ - /* */public final static byte ITYPE_TEXT = 0; - /** Specifies that the form field is a checkbox. */ - /* */public final static byte ITYPE_CHCK = 1; - /** Specifies that the form field is a dropdown list box. */ - /* */public final static byte ITYPE_DROP = 2; - /**/private static final BitField iRes = new BitField(0x007C); - /**/private static final BitField fOwnHelp = new BitField(0x0080); - /**/private static final BitField fOwnStat = new BitField(0x0100); - /**/private static final BitField fProt = new BitField(0x0200); - /**/private static final BitField iSize = new BitField(0x0400); - /**/private static final BitField iTypeTxt = new BitField(0x3800); - /** Specifies that the textbox value is regular text. */ - /* */public final static byte ITYPETXT_REG = 0; - /** Specifies that the textbox value is a number. */ - /* */public final static byte ITYPETXT_NUM = 0; - /** Specifies that the textbox value is a date or time. */ - /* */public final static byte ITYPETXT_DATE = 0; - /** Specifies that the textbox value is the current date. */ - /* */public final static byte ITYPETXT_CURDATE = 0; - /** Specifies that the textbox value is the current time. */ - /* */public final static byte ITYPETXT_CURTIME = 0; - /** Specifies that the textbox value is calculated from an expression. The expression is given by FFData.xstzTextDef. */ - /* */protected final static byte ITYPETXT_CALC = 0; - /**/private static final BitField fRecalc = new BitField(0x4000); - /**/private static final BitField fHasListBox = new BitField(0x8000); - protected int field_3_cch; - protected int field_4_hps; - - protected FFDataBaseAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_version = LittleEndian.getUInt( data, 0x0 + offset ); - field_2_bits = LittleEndian.getShort( data, 0x4 + offset ); - field_3_cch = LittleEndian.getShort( data, 0x6 + offset ); - field_4_hps = LittleEndian.getShort( data, 0x8 + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putUInt( data, 0x0 + offset, field_1_version ); - LittleEndian.putShort( data, 0x4 + offset, field_2_bits ); - LittleEndian.putUShort( data, 0x6 + offset, field_3_cch ); - LittleEndian.putUShort( data, 0x8 + offset, field_4_hps ); - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 4 + 2 + 2 + 2; - } - - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - FFDataBaseAbstractType other = (FFDataBaseAbstractType) obj; - if ( field_1_version != other.field_1_version ) - return false; - if ( field_2_bits != other.field_2_bits ) - return false; - if ( field_3_cch != other.field_3_cch ) - return false; - if ( field_4_hps != other.field_4_hps ) - return false; - return true; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + (int) ( field_1_version ^ ( field_1_version >>> 32 ) ); - result = prime * result + field_2_bits; - result = prime * result + field_3_cch; - result = prime * result + field_4_hps; - return result; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - - builder.append("[FFDataBase]\n"); - builder.append( " .version = " ); - builder.append(" ( ").append( field_1_version ).append( " )\n" ); - builder.append( " .bits = " ); - builder.append(" ( ").append( field_2_bits ).append( " )\n" ); - builder.append(" .iType = ").append(getIType()).append('\n'); - builder.append(" .iRes = ").append(getIRes()).append('\n'); - builder.append(" .fOwnHelp = ").append(isFOwnHelp()).append('\n'); - builder.append(" .fOwnStat = ").append(isFOwnStat()).append('\n'); - builder.append(" .fProt = ").append(isFProt()).append('\n'); - builder.append(" .iSize = ").append(isISize()).append('\n'); - builder.append(" .iTypeTxt = ").append(getITypeTxt()).append('\n'); - builder.append(" .fRecalc = ").append(isFRecalc()).append('\n'); - builder.append(" .fHasListBox = ").append(isFHasListBox()).append('\n'); - builder.append( " .cch = " ); - builder.append(" ( ").append( field_3_cch ).append( " )\n" ); - builder.append( " .hps = " ); - builder.append(" ( ").append( field_4_hps ).append( " )\n" ); - - builder.append("[/FFDataBase]"); - return builder.toString(); - } - - /** - * An unsigned integer that MUST be 0xFFFFFFFF. - */ - @Internal - public long getVersion() - { - return field_1_version; - } - - /** - * An unsigned integer that MUST be 0xFFFFFFFF. - */ - @Internal - public void setVersion( long field_1_version ) - { - this.field_1_version = field_1_version; - } - - /** - * An FFDataBits that specifies the type and state of this form field. - */ - @Internal - public short getBits() - { - return field_2_bits; - } - - /** - * An FFDataBits that specifies the type and state of this form field. - */ - @Internal - public void setBits( short field_2_bits ) - { - this.field_2_bits = field_2_bits; - } - - /** - * An unsigned integer that specifies the maximum length, in characters, of the value of the textbox. This value MUST NOT exceed 32767. A value of 0 means there is no maximum length of the value of the textbox. If bits.iType is not iTypeText (0), this value MUST be 0.. - */ - @Internal - public int getCch() - { - return field_3_cch; - } - - /** - * An unsigned integer that specifies the maximum length, in characters, of the value of the textbox. This value MUST NOT exceed 32767. A value of 0 means there is no maximum length of the value of the textbox. If bits.iType is not iTypeText (0), this value MUST be 0.. - */ - @Internal - public void setCch( int field_3_cch ) - { - this.field_3_cch = field_3_cch; - } - - /** - * An unsigned integer. If bits.iType is iTypeChck (1), hps specifies the size, in half-points, of the checkbox and MUST be between 2 and 3168, inclusive. If bits.iType is not iTypeChck (1), hps is undefined and MUST be ignored.. - */ - @Internal - public int getHps() - { - return field_4_hps; - } - - /** - * An unsigned integer. If bits.iType is iTypeChck (1), hps specifies the size, in half-points, of the checkbox and MUST be between 2 and 3168, inclusive. If bits.iType is not iTypeChck (1), hps is undefined and MUST be ignored.. - */ - @Internal - public void setHps( int field_4_hps ) - { - this.field_4_hps = field_4_hps; - } - - /** - * Sets the iType field value. - * An unsigned integer that specifies the type of the form field. - */ - @Internal - public void setIType( byte value ) - { - field_2_bits = (short)iType.setValue(field_2_bits, value); - } - - /** - * An unsigned integer that specifies the type of the form field. - * @return the iType field value. - */ - @Internal - public byte getIType() - { - return ( byte )iType.getValue(field_2_bits); - } - - /** - * Sets the iRes field value. - * An unsigned integer. If iType is iTypeText (0), then iRes MUST be 0. If iType is iTypeChck (1), iRes specifies the state of the checkbox and MUST be 0 (unchecked), 1 (checked), or 25 (undefined). Undefined checkboxes are treated as unchecked. If iType is iTypeDrop (2), iRes specifies the current selected list box item. A value of 25 specifies the selection is undefined. Otherwise, iRes is a zero-based index into FFData.hsttbDropList. - */ - @Internal - public void setIRes( byte value ) - { - field_2_bits = (short)iRes.setValue(field_2_bits, value); - } - - /** - * An unsigned integer. If iType is iTypeText (0), then iRes MUST be 0. If iType is iTypeChck (1), iRes specifies the state of the checkbox and MUST be 0 (unchecked), 1 (checked), or 25 (undefined). Undefined checkboxes are treated as unchecked. If iType is iTypeDrop (2), iRes specifies the current selected list box item. A value of 25 specifies the selection is undefined. Otherwise, iRes is a zero-based index into FFData.hsttbDropList. - * @return the iRes field value. - */ - @Internal - public byte getIRes() - { - return ( byte )iRes.getValue(field_2_bits); - } - - /** - * Sets the fOwnHelp field value. - * A bit that specifies whether the form field has custom help text in FFData.xstzHelpText. If fOwnHelp is 0, FFData.xstzHelpText contains an empty or auto-generated string. - */ - @Internal - public void setFOwnHelp( boolean value ) - { - field_2_bits = (short)fOwnHelp.setBoolean(field_2_bits, value); - } - - /** - * A bit that specifies whether the form field has custom help text in FFData.xstzHelpText. If fOwnHelp is 0, FFData.xstzHelpText contains an empty or auto-generated string. - * @return the fOwnHelp field value. - */ - @Internal - public boolean isFOwnHelp() - { - return fOwnHelp.isSet(field_2_bits); - } - - /** - * Sets the fOwnStat field value. - * A bit that specifies whether the form field has custom status bar text in FFData.xstzStatText. If fOwnStat is 0, FFData.xstzStatText contains an empty or auto-generated string. - */ - @Internal - public void setFOwnStat( boolean value ) - { - field_2_bits = (short)fOwnStat.setBoolean(field_2_bits, value); - } - - /** - * A bit that specifies whether the form field has custom status bar text in FFData.xstzStatText. If fOwnStat is 0, FFData.xstzStatText contains an empty or auto-generated string. - * @return the fOwnStat field value. - */ - @Internal - public boolean isFOwnStat() - { - return fOwnStat.isSet(field_2_bits); - } - - /** - * Sets the fProt field value. - * A bit that specifies whether the form field is protected and its value cannot be changed. - */ - @Internal - public void setFProt( boolean value ) - { - field_2_bits = (short)fProt.setBoolean(field_2_bits, value); - } - - /** - * A bit that specifies whether the form field is protected and its value cannot be changed. - * @return the fProt field value. - */ - @Internal - public boolean isFProt() - { - return fProt.isSet(field_2_bits); - } - - /** - * Sets the iSize field value. - * A bit that specifies whether the size of a checkbox is automatically determined by the text size where the checkbox is located. This value MUST be 0 if iType is not iTypeChck (1). - */ - @Internal - public void setISize( boolean value ) - { - field_2_bits = (short)iSize.setBoolean(field_2_bits, value); - } - - /** - * A bit that specifies whether the size of a checkbox is automatically determined by the text size where the checkbox is located. This value MUST be 0 if iType is not iTypeChck (1). - * @return the iSize field value. - */ - @Internal - public boolean isISize() - { - return iSize.isSet(field_2_bits); - } - - /** - * Sets the iTypeTxt field value. - * An unsigned integer that specifies the type of the textbox. If iType is not iTypeText (0), iTypeTxt MUST be 0 and MUST be ignored. - */ - @Internal - public void setITypeTxt( byte value ) - { - field_2_bits = (short)iTypeTxt.setValue(field_2_bits, value); - } - - /** - * An unsigned integer that specifies the type of the textbox. If iType is not iTypeText (0), iTypeTxt MUST be 0 and MUST be ignored. - * @return the iTypeTxt field value. - */ - @Internal - public byte getITypeTxt() - { - return ( byte )iTypeTxt.getValue(field_2_bits); - } - - /** - * Sets the fRecalc field value. - * A bit that specifies whether the value of the field is automatically calculated after the field is modified. - */ - @Internal - public void setFRecalc( boolean value ) - { - field_2_bits = (short)fRecalc.setBoolean(field_2_bits, value); - } - - /** - * A bit that specifies whether the value of the field is automatically calculated after the field is modified. - * @return the fRecalc field value. - */ - @Internal - public boolean isFRecalc() - { - return fRecalc.isSet(field_2_bits); - } - - /** - * Sets the fHasListBox field value. - * A bit that specifies that the form field has a list box. This value MUST be 1 if iType is iTypeDrop (2). Otherwise, this value MUST be 0. - */ - @Internal - public void setFHasListBox( boolean value ) - { - field_2_bits = (short)fHasListBox.setBoolean(field_2_bits, value); - } - - /** - * A bit that specifies that the form field has a list box. This value MUST be 1 if iType is iTypeDrop (2). Otherwise, this value MUST be 0. - * @return the fHasListBox field value. - */ - @Internal - public boolean isFHasListBox() - { - return fHasListBox.isSet(field_2_bits); - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.model.types; + + +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * The FFData structure specifies form field data for a text + box, check box, or drop-down list box.

    Class and fields + descriptions are quoted from [MS-DOC] -- v20121003 Word (.doc) Binary + File Format; Copyright (c) 2012 Microsoft Corporation; Release: + October 8, 2012 + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov; according to [MS-DOC] -- v20121003 Word + (.doc) Binary File Format; Copyright (c) 2012 Microsoft Corporation; + Release: October 8, 2012 + + */ +@Internal +public abstract class FFDataBaseAbstractType +{ + + protected long field_1_version; + protected short field_2_bits; + /**/private static final BitField iType = new BitField(0x0003); + /** Specifies that the form field is a textbox. */ + /* */public final static byte ITYPE_TEXT = 0; + /** Specifies that the form field is a checkbox. */ + /* */public final static byte ITYPE_CHCK = 1; + /** Specifies that the form field is a dropdown list box. */ + /* */public final static byte ITYPE_DROP = 2; + /**/private static final BitField iRes = new BitField(0x007C); + /**/private static final BitField fOwnHelp = new BitField(0x0080); + /**/private static final BitField fOwnStat = new BitField(0x0100); + /**/private static final BitField fProt = new BitField(0x0200); + /**/private static final BitField iSize = new BitField(0x0400); + /**/private static final BitField iTypeTxt = new BitField(0x3800); + /** Specifies that the textbox value is regular text. */ + /* */public final static byte ITYPETXT_REG = 0; + /** Specifies that the textbox value is a number. */ + /* */public final static byte ITYPETXT_NUM = 0; + /** Specifies that the textbox value is a date or time. */ + /* */public final static byte ITYPETXT_DATE = 0; + /** Specifies that the textbox value is the current date. */ + /* */public final static byte ITYPETXT_CURDATE = 0; + /** Specifies that the textbox value is the current time. */ + /* */public final static byte ITYPETXT_CURTIME = 0; + /** Specifies that the textbox value is calculated from an expression. The expression is given by FFData.xstzTextDef. */ + /* */protected final static byte ITYPETXT_CALC = 0; + /**/private static final BitField fRecalc = new BitField(0x4000); + /**/private static final BitField fHasListBox = new BitField(0x8000); + protected int field_3_cch; + protected int field_4_hps; + + protected FFDataBaseAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_version = LittleEndian.getUInt( data, 0x0 + offset ); + field_2_bits = LittleEndian.getShort( data, 0x4 + offset ); + field_3_cch = LittleEndian.getShort( data, 0x6 + offset ); + field_4_hps = LittleEndian.getShort( data, 0x8 + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putUInt( data, 0x0 + offset, field_1_version ); + LittleEndian.putShort( data, 0x4 + offset, field_2_bits ); + LittleEndian.putUShort( data, 0x6 + offset, field_3_cch ); + LittleEndian.putUShort( data, 0x8 + offset, field_4_hps ); + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 4 + 2 + 2 + 2; + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + return true; + if ( obj == null ) + return false; + if ( getClass() != obj.getClass() ) + return false; + FFDataBaseAbstractType other = (FFDataBaseAbstractType) obj; + if ( field_1_version != other.field_1_version ) + return false; + if ( field_2_bits != other.field_2_bits ) + return false; + if ( field_3_cch != other.field_3_cch ) + return false; + if ( field_4_hps != other.field_4_hps ) + return false; + return true; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + (int) ( field_1_version ^ ( field_1_version >>> 32 ) ); + result = prime * result + field_2_bits; + result = prime * result + field_3_cch; + result = prime * result + field_4_hps; + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + + builder.append("[FFDataBase]\n"); + builder.append( " .version = " ); + builder.append(" ( ").append( field_1_version ).append( " )\n" ); + builder.append( " .bits = " ); + builder.append(" ( ").append( field_2_bits ).append( " )\n" ); + builder.append(" .iType = ").append(getIType()).append('\n'); + builder.append(" .iRes = ").append(getIRes()).append('\n'); + builder.append(" .fOwnHelp = ").append(isFOwnHelp()).append('\n'); + builder.append(" .fOwnStat = ").append(isFOwnStat()).append('\n'); + builder.append(" .fProt = ").append(isFProt()).append('\n'); + builder.append(" .iSize = ").append(isISize()).append('\n'); + builder.append(" .iTypeTxt = ").append(getITypeTxt()).append('\n'); + builder.append(" .fRecalc = ").append(isFRecalc()).append('\n'); + builder.append(" .fHasListBox = ").append(isFHasListBox()).append('\n'); + builder.append( " .cch = " ); + builder.append(" ( ").append( field_3_cch ).append( " )\n" ); + builder.append( " .hps = " ); + builder.append(" ( ").append( field_4_hps ).append( " )\n" ); + + builder.append("[/FFDataBase]"); + return builder.toString(); + } + + /** + * An unsigned integer that MUST be 0xFFFFFFFF. + */ + @Internal + public long getVersion() + { + return field_1_version; + } + + /** + * An unsigned integer that MUST be 0xFFFFFFFF. + */ + @Internal + public void setVersion( long field_1_version ) + { + this.field_1_version = field_1_version; + } + + /** + * An FFDataBits that specifies the type and state of this form field. + */ + @Internal + public short getBits() + { + return field_2_bits; + } + + /** + * An FFDataBits that specifies the type and state of this form field. + */ + @Internal + public void setBits( short field_2_bits ) + { + this.field_2_bits = field_2_bits; + } + + /** + * An unsigned integer that specifies the maximum length, in characters, of the value of the textbox. This value MUST NOT exceed 32767. A value of 0 means there is no maximum length of the value of the textbox. If bits.iType is not iTypeText (0), this value MUST be 0.. + */ + @Internal + public int getCch() + { + return field_3_cch; + } + + /** + * An unsigned integer that specifies the maximum length, in characters, of the value of the textbox. This value MUST NOT exceed 32767. A value of 0 means there is no maximum length of the value of the textbox. If bits.iType is not iTypeText (0), this value MUST be 0.. + */ + @Internal + public void setCch( int field_3_cch ) + { + this.field_3_cch = field_3_cch; + } + + /** + * An unsigned integer. If bits.iType is iTypeChck (1), hps specifies the size, in half-points, of the checkbox and MUST be between 2 and 3168, inclusive. If bits.iType is not iTypeChck (1), hps is undefined and MUST be ignored.. + */ + @Internal + public int getHps() + { + return field_4_hps; + } + + /** + * An unsigned integer. If bits.iType is iTypeChck (1), hps specifies the size, in half-points, of the checkbox and MUST be between 2 and 3168, inclusive. If bits.iType is not iTypeChck (1), hps is undefined and MUST be ignored.. + */ + @Internal + public void setHps( int field_4_hps ) + { + this.field_4_hps = field_4_hps; + } + + /** + * Sets the iType field value. + * An unsigned integer that specifies the type of the form field. + */ + @Internal + public void setIType( byte value ) + { + field_2_bits = (short)iType.setValue(field_2_bits, value); + } + + /** + * An unsigned integer that specifies the type of the form field. + * @return the iType field value. + */ + @Internal + public byte getIType() + { + return ( byte )iType.getValue(field_2_bits); + } + + /** + * Sets the iRes field value. + * An unsigned integer. If iType is iTypeText (0), then iRes MUST be 0. If iType is iTypeChck (1), iRes specifies the state of the checkbox and MUST be 0 (unchecked), 1 (checked), or 25 (undefined). Undefined checkboxes are treated as unchecked. If iType is iTypeDrop (2), iRes specifies the current selected list box item. A value of 25 specifies the selection is undefined. Otherwise, iRes is a zero-based index into FFData.hsttbDropList. + */ + @Internal + public void setIRes( byte value ) + { + field_2_bits = (short)iRes.setValue(field_2_bits, value); + } + + /** + * An unsigned integer. If iType is iTypeText (0), then iRes MUST be 0. If iType is iTypeChck (1), iRes specifies the state of the checkbox and MUST be 0 (unchecked), 1 (checked), or 25 (undefined). Undefined checkboxes are treated as unchecked. If iType is iTypeDrop (2), iRes specifies the current selected list box item. A value of 25 specifies the selection is undefined. Otherwise, iRes is a zero-based index into FFData.hsttbDropList. + * @return the iRes field value. + */ + @Internal + public byte getIRes() + { + return ( byte )iRes.getValue(field_2_bits); + } + + /** + * Sets the fOwnHelp field value. + * A bit that specifies whether the form field has custom help text in FFData.xstzHelpText. If fOwnHelp is 0, FFData.xstzHelpText contains an empty or auto-generated string. + */ + @Internal + public void setFOwnHelp( boolean value ) + { + field_2_bits = (short)fOwnHelp.setBoolean(field_2_bits, value); + } + + /** + * A bit that specifies whether the form field has custom help text in FFData.xstzHelpText. If fOwnHelp is 0, FFData.xstzHelpText contains an empty or auto-generated string. + * @return the fOwnHelp field value. + */ + @Internal + public boolean isFOwnHelp() + { + return fOwnHelp.isSet(field_2_bits); + } + + /** + * Sets the fOwnStat field value. + * A bit that specifies whether the form field has custom status bar text in FFData.xstzStatText. If fOwnStat is 0, FFData.xstzStatText contains an empty or auto-generated string. + */ + @Internal + public void setFOwnStat( boolean value ) + { + field_2_bits = (short)fOwnStat.setBoolean(field_2_bits, value); + } + + /** + * A bit that specifies whether the form field has custom status bar text in FFData.xstzStatText. If fOwnStat is 0, FFData.xstzStatText contains an empty or auto-generated string. + * @return the fOwnStat field value. + */ + @Internal + public boolean isFOwnStat() + { + return fOwnStat.isSet(field_2_bits); + } + + /** + * Sets the fProt field value. + * A bit that specifies whether the form field is protected and its value cannot be changed. + */ + @Internal + public void setFProt( boolean value ) + { + field_2_bits = (short)fProt.setBoolean(field_2_bits, value); + } + + /** + * A bit that specifies whether the form field is protected and its value cannot be changed. + * @return the fProt field value. + */ + @Internal + public boolean isFProt() + { + return fProt.isSet(field_2_bits); + } + + /** + * Sets the iSize field value. + * A bit that specifies whether the size of a checkbox is automatically determined by the text size where the checkbox is located. This value MUST be 0 if iType is not iTypeChck (1). + */ + @Internal + public void setISize( boolean value ) + { + field_2_bits = (short)iSize.setBoolean(field_2_bits, value); + } + + /** + * A bit that specifies whether the size of a checkbox is automatically determined by the text size where the checkbox is located. This value MUST be 0 if iType is not iTypeChck (1). + * @return the iSize field value. + */ + @Internal + public boolean isISize() + { + return iSize.isSet(field_2_bits); + } + + /** + * Sets the iTypeTxt field value. + * An unsigned integer that specifies the type of the textbox. If iType is not iTypeText (0), iTypeTxt MUST be 0 and MUST be ignored. + */ + @Internal + public void setITypeTxt( byte value ) + { + field_2_bits = (short)iTypeTxt.setValue(field_2_bits, value); + } + + /** + * An unsigned integer that specifies the type of the textbox. If iType is not iTypeText (0), iTypeTxt MUST be 0 and MUST be ignored. + * @return the iTypeTxt field value. + */ + @Internal + public byte getITypeTxt() + { + return ( byte )iTypeTxt.getValue(field_2_bits); + } + + /** + * Sets the fRecalc field value. + * A bit that specifies whether the value of the field is automatically calculated after the field is modified. + */ + @Internal + public void setFRecalc( boolean value ) + { + field_2_bits = (short)fRecalc.setBoolean(field_2_bits, value); + } + + /** + * A bit that specifies whether the value of the field is automatically calculated after the field is modified. + * @return the fRecalc field value. + */ + @Internal + public boolean isFRecalc() + { + return fRecalc.isSet(field_2_bits); + } + + /** + * Sets the fHasListBox field value. + * A bit that specifies that the form field has a list box. This value MUST be 1 if iType is iTypeDrop (2). Otherwise, this value MUST be 0. + */ + @Internal + public void setFHasListBox( boolean value ) + { + field_2_bits = (short)fHasListBox.setBoolean(field_2_bits, value); + } + + /** + * A bit that specifies that the form field has a list box. This value MUST be 1 if iType is iTypeDrop (2). Otherwise, this value MUST be 0. + * @return the fHasListBox field value. + */ + @Internal + public boolean isFHasListBox() + { + return fHasListBox.isSet(field_2_bits); + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FRDAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FRDAbstractType.java index 9923fe64e9..8ebaab7667 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FRDAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FRDAbstractType.java @@ -1,91 +1,91 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * Footnote Reference Descriptor (FRD). - *

    - * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 - * Binary File Format (.doc) Specification - * - * NOTE: This source is automatically generated please do not modify this file. - * Either subclass or remove the record in src/types/definitions. - * - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary - * File Format (.doc) Specification - */ -@Internal -public abstract class FRDAbstractType -{ - - protected short field_1_nAuto; - - protected FRDAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_nAuto = LittleEndian.getShort( data, 0x0 + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putShort( data, 0x0 + offset, field_1_nAuto ); - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 2; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append( "[FRD]\n" ); - builder.append( " .nAuto = " ); - builder.append( " (" ).append( getNAuto() ).append( " )\n" ); - - builder.append( "[/FRD]\n" ); - return builder.toString(); - } - - /** - * If > 0, the note is an automatically numbered note, otherwise it has a - * custom mark. - */ - public short getNAuto() - { - return field_1_nAuto; - } - - /** - * If > 0, the note is an automatically numbered note, otherwise it has a - * custom mark. - */ - public void setNAuto( short field_1_nAuto ) - { - this.field_1_nAuto = field_1_nAuto; - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * Footnote Reference Descriptor (FRD). + *

    + * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 + * Binary File Format (.doc) Specification + * + * NOTE: This source is automatically generated please do not modify this file. + * Either subclass or remove the record in src/types/definitions. + * + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary + * File Format (.doc) Specification + */ +@Internal +public abstract class FRDAbstractType +{ + + protected short field_1_nAuto; + + protected FRDAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_nAuto = LittleEndian.getShort( data, 0x0 + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putShort( data, 0x0 + offset, field_1_nAuto ); + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 2; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append( "[FRD]\n" ); + builder.append( " .nAuto = " ); + builder.append( " (" ).append( getNAuto() ).append( " )\n" ); + + builder.append( "[/FRD]\n" ); + return builder.toString(); + } + + /** + * If > 0, the note is an automatically numbered note, otherwise it has a + * custom mark. + */ + public short getNAuto() + { + return field_1_nAuto; + } + + /** + * If > 0, the note is an automatically numbered note, otherwise it has a + * custom mark. + */ + public void setNAuto( short field_1_nAuto ) + { + this.field_1_nAuto = field_1_nAuto; + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FSPAAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FSPAAbstractType.java index ee71c2bab7..8d7df40e36 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FSPAAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FSPAAbstractType.java @@ -1,411 +1,411 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model.types; - - -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * File Shape Address (FSPA). - *

    - * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 - * Binary File Format - * - *

    - * NOTE: This source is automatically generated please do not modify this file. - * Either subclass or remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - * - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary - * File Format Specification [*.doc] - */ -@Internal -public abstract class FSPAAbstractType -{ - - protected int field_1_spid; - protected int field_2_xaLeft; - protected int field_3_yaTop; - protected int field_4_xaRight; - protected int field_5_yaBottom; - protected short field_6_flags; - /**/private static BitField fHdr = new BitField(0x0001); - /**/private static BitField bx = new BitField(0x0006); - /**/private static BitField by = new BitField(0x0018); - /**/private static BitField wr = new BitField(0x01E0); - /**/private static BitField wrk = new BitField(0x1E00); - /**/private static BitField fRcaSimple = new BitField(0x2000); - /**/private static BitField fBelowText = new BitField(0x4000); - /**/private static BitField fAnchorLock = new BitField(0x8000); - protected int field_7_cTxbx; - - protected FSPAAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_spid = LittleEndian.getInt(data, 0x0 + offset); - field_2_xaLeft = LittleEndian.getInt(data, 0x4 + offset); - field_3_yaTop = LittleEndian.getInt(data, 0x8 + offset); - field_4_xaRight = LittleEndian.getInt(data, 0xc + offset); - field_5_yaBottom = LittleEndian.getInt(data, 0x10 + offset); - field_6_flags = LittleEndian.getShort(data, 0x14 + offset); - field_7_cTxbx = LittleEndian.getInt(data, 0x16 + offset); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putInt(data, 0x0 + offset, field_1_spid); - LittleEndian.putInt(data, 0x4 + offset, field_2_xaLeft); - LittleEndian.putInt(data, 0x8 + offset, field_3_yaTop); - LittleEndian.putInt(data, 0xc + offset, field_4_xaRight); - LittleEndian.putInt(data, 0x10 + offset, field_5_yaBottom); - LittleEndian.putShort(data, 0x14 + offset, field_6_flags); - LittleEndian.putInt(data, 0x16 + offset, field_7_cTxbx); - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 4 + 4 + 4 + 4 + 4 + 2 + 4; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[FSPA]\n"); - builder.append(" .spid = "); - builder.append(" (").append(getSpid()).append(" )\n"); - builder.append(" .xaLeft = "); - builder.append(" (").append(getXaLeft()).append(" )\n"); - builder.append(" .yaTop = "); - builder.append(" (").append(getYaTop()).append(" )\n"); - builder.append(" .xaRight = "); - builder.append(" (").append(getXaRight()).append(" )\n"); - builder.append(" .yaBottom = "); - builder.append(" (").append(getYaBottom()).append(" )\n"); - builder.append(" .flags = "); - builder.append(" (").append(getFlags()).append(" )\n"); - builder.append(" .fHdr = ").append(isFHdr()).append('\n'); - builder.append(" .bx = ").append(getBx()).append('\n'); - builder.append(" .by = ").append(getBy()).append('\n'); - builder.append(" .wr = ").append(getWr()).append('\n'); - builder.append(" .wrk = ").append(getWrk()).append('\n'); - builder.append(" .fRcaSimple = ").append(isFRcaSimple()).append('\n'); - builder.append(" .fBelowText = ").append(isFBelowText()).append('\n'); - builder.append(" .fAnchorLock = ").append(isFAnchorLock()).append('\n'); - builder.append(" .cTxbx = "); - builder.append(" (").append(getCTxbx()).append(" )\n"); - - builder.append("[/FSPA]\n"); - return builder.toString(); - } - - /** - * Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape. - */ - @Internal - public int getSpid() - { - return field_1_spid; - } - - /** - * Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape. - */ - @Internal - public void setSpid( int field_1_spid ) - { - this.field_1_spid = field_1_spid; - } - - /** - * Left of rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public int getXaLeft() - { - return field_2_xaLeft; - } - - /** - * Left of rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public void setXaLeft( int field_2_xaLeft ) - { - this.field_2_xaLeft = field_2_xaLeft; - } - - /** - * Top of rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public int getYaTop() - { - return field_3_yaTop; - } - - /** - * Top of rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public void setYaTop( int field_3_yaTop ) - { - this.field_3_yaTop = field_3_yaTop; - } - - /** - * Right of rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public int getXaRight() - { - return field_4_xaRight; - } - - /** - * Right of rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public void setXaRight( int field_4_xaRight ) - { - this.field_4_xaRight = field_4_xaRight; - } - - /** - * Bottom of the rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public int getYaBottom() - { - return field_5_yaBottom; - } - - /** - * Bottom of the rectangle enclosing shape relative to the origin of the shape. - */ - @Internal - public void setYaBottom( int field_5_yaBottom ) - { - this.field_5_yaBottom = field_5_yaBottom; - } - - /** - * Get the flags field for the FSPA record. - */ - @Internal - public short getFlags() - { - return field_6_flags; - } - - /** - * Set the flags field for the FSPA record. - */ - @Internal - public void setFlags( short field_6_flags ) - { - this.field_6_flags = field_6_flags; - } - - /** - * Count of textboxes in shape (undo doc only). - */ - @Internal - public int getCTxbx() - { - return field_7_cTxbx; - } - - /** - * Count of textboxes in shape (undo doc only). - */ - @Internal - public void setCTxbx( int field_7_cTxbx ) - { - this.field_7_cTxbx = field_7_cTxbx; - } - - /** - * Sets the fHdr field value. - * 1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc) - */ - @Internal - public void setFHdr( boolean value ) - { - field_6_flags = (short)fHdr.setBoolean(field_6_flags, value); - } - - /** - * 1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc) - * @return the fHdr field value. - */ - @Internal - public boolean isFHdr() - { - return fHdr.isSet(field_6_flags); - } - - /** - * Sets the bx field value. - * X position of shape relative to anchor CP - */ - @Internal - public void setBx( byte value ) - { - field_6_flags = (short)bx.setValue(field_6_flags, value); - } - - /** - * X position of shape relative to anchor CP - * @return the bx field value. - */ - @Internal - public byte getBx() - { - return ( byte )bx.getValue(field_6_flags); - } - - /** - * Sets the by field value. - * Y position of shape relative to anchor CP - */ - @Internal - public void setBy( byte value ) - { - field_6_flags = (short)by.setValue(field_6_flags, value); - } - - /** - * Y position of shape relative to anchor CP - * @return the by field value. - */ - @Internal - public byte getBy() - { - return ( byte )by.getValue(field_6_flags); - } - - /** - * Sets the wr field value. - * Text wrapping mode - */ - @Internal - public void setWr( byte value ) - { - field_6_flags = (short)wr.setValue(field_6_flags, value); - } - - /** - * Text wrapping mode - * @return the wr field value. - */ - @Internal - public byte getWr() - { - return ( byte )wr.getValue(field_6_flags); - } - - /** - * Sets the wrk field value. - * Text wrapping mode type (valid only for wrapping modes 2 and 4 - */ - @Internal - public void setWrk( byte value ) - { - field_6_flags = (short)wrk.setValue(field_6_flags, value); - } - - /** - * Text wrapping mode type (valid only for wrapping modes 2 and 4 - * @return the wrk field value. - */ - @Internal - public byte getWrk() - { - return ( byte )wrk.getValue(field_6_flags); - } - - /** - * Sets the fRcaSimple field value. - * When set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative. - */ - @Internal - public void setFRcaSimple( boolean value ) - { - field_6_flags = (short)fRcaSimple.setBoolean(field_6_flags, value); - } - - /** - * When set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative. - * @return the fRcaSimple field value. - */ - @Internal - public boolean isFRcaSimple() - { - return fRcaSimple.isSet(field_6_flags); - } - - /** - * Sets the fBelowText field value. - * - */ - @Internal - public void setFBelowText( boolean value ) - { - field_6_flags = (short)fBelowText.setBoolean(field_6_flags, value); - } - - /** - * - * @return the fBelowText field value. - */ - @Internal - public boolean isFBelowText() - { - return fBelowText.isSet(field_6_flags); - } - - /** - * Sets the fAnchorLock field value. - * - */ - @Internal - public void setFAnchorLock( boolean value ) - { - field_6_flags = (short)fAnchorLock.setBoolean(field_6_flags, value); - } - - /** - * - * @return the fAnchorLock field value. - */ - @Internal - public boolean isFAnchorLock() - { - return fAnchorLock.isSet(field_6_flags); - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model.types; + + +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * File Shape Address (FSPA). + *

    + * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 + * Binary File Format + * + *

    + * NOTE: This source is automatically generated please do not modify this file. + * Either subclass or remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + * + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary + * File Format Specification [*.doc] + */ +@Internal +public abstract class FSPAAbstractType +{ + + protected int field_1_spid; + protected int field_2_xaLeft; + protected int field_3_yaTop; + protected int field_4_xaRight; + protected int field_5_yaBottom; + protected short field_6_flags; + /**/private static BitField fHdr = new BitField(0x0001); + /**/private static BitField bx = new BitField(0x0006); + /**/private static BitField by = new BitField(0x0018); + /**/private static BitField wr = new BitField(0x01E0); + /**/private static BitField wrk = new BitField(0x1E00); + /**/private static BitField fRcaSimple = new BitField(0x2000); + /**/private static BitField fBelowText = new BitField(0x4000); + /**/private static BitField fAnchorLock = new BitField(0x8000); + protected int field_7_cTxbx; + + protected FSPAAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_spid = LittleEndian.getInt(data, 0x0 + offset); + field_2_xaLeft = LittleEndian.getInt(data, 0x4 + offset); + field_3_yaTop = LittleEndian.getInt(data, 0x8 + offset); + field_4_xaRight = LittleEndian.getInt(data, 0xc + offset); + field_5_yaBottom = LittleEndian.getInt(data, 0x10 + offset); + field_6_flags = LittleEndian.getShort(data, 0x14 + offset); + field_7_cTxbx = LittleEndian.getInt(data, 0x16 + offset); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putInt(data, 0x0 + offset, field_1_spid); + LittleEndian.putInt(data, 0x4 + offset, field_2_xaLeft); + LittleEndian.putInt(data, 0x8 + offset, field_3_yaTop); + LittleEndian.putInt(data, 0xc + offset, field_4_xaRight); + LittleEndian.putInt(data, 0x10 + offset, field_5_yaBottom); + LittleEndian.putShort(data, 0x14 + offset, field_6_flags); + LittleEndian.putInt(data, 0x16 + offset, field_7_cTxbx); + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 4 + 4 + 4 + 4 + 4 + 2 + 4; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[FSPA]\n"); + builder.append(" .spid = "); + builder.append(" (").append(getSpid()).append(" )\n"); + builder.append(" .xaLeft = "); + builder.append(" (").append(getXaLeft()).append(" )\n"); + builder.append(" .yaTop = "); + builder.append(" (").append(getYaTop()).append(" )\n"); + builder.append(" .xaRight = "); + builder.append(" (").append(getXaRight()).append(" )\n"); + builder.append(" .yaBottom = "); + builder.append(" (").append(getYaBottom()).append(" )\n"); + builder.append(" .flags = "); + builder.append(" (").append(getFlags()).append(" )\n"); + builder.append(" .fHdr = ").append(isFHdr()).append('\n'); + builder.append(" .bx = ").append(getBx()).append('\n'); + builder.append(" .by = ").append(getBy()).append('\n'); + builder.append(" .wr = ").append(getWr()).append('\n'); + builder.append(" .wrk = ").append(getWrk()).append('\n'); + builder.append(" .fRcaSimple = ").append(isFRcaSimple()).append('\n'); + builder.append(" .fBelowText = ").append(isFBelowText()).append('\n'); + builder.append(" .fAnchorLock = ").append(isFAnchorLock()).append('\n'); + builder.append(" .cTxbx = "); + builder.append(" (").append(getCTxbx()).append(" )\n"); + + builder.append("[/FSPA]\n"); + return builder.toString(); + } + + /** + * Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape. + */ + @Internal + public int getSpid() + { + return field_1_spid; + } + + /** + * Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape. + */ + @Internal + public void setSpid( int field_1_spid ) + { + this.field_1_spid = field_1_spid; + } + + /** + * Left of rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public int getXaLeft() + { + return field_2_xaLeft; + } + + /** + * Left of rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public void setXaLeft( int field_2_xaLeft ) + { + this.field_2_xaLeft = field_2_xaLeft; + } + + /** + * Top of rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public int getYaTop() + { + return field_3_yaTop; + } + + /** + * Top of rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public void setYaTop( int field_3_yaTop ) + { + this.field_3_yaTop = field_3_yaTop; + } + + /** + * Right of rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public int getXaRight() + { + return field_4_xaRight; + } + + /** + * Right of rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public void setXaRight( int field_4_xaRight ) + { + this.field_4_xaRight = field_4_xaRight; + } + + /** + * Bottom of the rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public int getYaBottom() + { + return field_5_yaBottom; + } + + /** + * Bottom of the rectangle enclosing shape relative to the origin of the shape. + */ + @Internal + public void setYaBottom( int field_5_yaBottom ) + { + this.field_5_yaBottom = field_5_yaBottom; + } + + /** + * Get the flags field for the FSPA record. + */ + @Internal + public short getFlags() + { + return field_6_flags; + } + + /** + * Set the flags field for the FSPA record. + */ + @Internal + public void setFlags( short field_6_flags ) + { + this.field_6_flags = field_6_flags; + } + + /** + * Count of textboxes in shape (undo doc only). + */ + @Internal + public int getCTxbx() + { + return field_7_cTxbx; + } + + /** + * Count of textboxes in shape (undo doc only). + */ + @Internal + public void setCTxbx( int field_7_cTxbx ) + { + this.field_7_cTxbx = field_7_cTxbx; + } + + /** + * Sets the fHdr field value. + * 1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc) + */ + @Internal + public void setFHdr( boolean value ) + { + field_6_flags = (short)fHdr.setBoolean(field_6_flags, value); + } + + /** + * 1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc) + * @return the fHdr field value. + */ + @Internal + public boolean isFHdr() + { + return fHdr.isSet(field_6_flags); + } + + /** + * Sets the bx field value. + * X position of shape relative to anchor CP + */ + @Internal + public void setBx( byte value ) + { + field_6_flags = (short)bx.setValue(field_6_flags, value); + } + + /** + * X position of shape relative to anchor CP + * @return the bx field value. + */ + @Internal + public byte getBx() + { + return ( byte )bx.getValue(field_6_flags); + } + + /** + * Sets the by field value. + * Y position of shape relative to anchor CP + */ + @Internal + public void setBy( byte value ) + { + field_6_flags = (short)by.setValue(field_6_flags, value); + } + + /** + * Y position of shape relative to anchor CP + * @return the by field value. + */ + @Internal + public byte getBy() + { + return ( byte )by.getValue(field_6_flags); + } + + /** + * Sets the wr field value. + * Text wrapping mode + */ + @Internal + public void setWr( byte value ) + { + field_6_flags = (short)wr.setValue(field_6_flags, value); + } + + /** + * Text wrapping mode + * @return the wr field value. + */ + @Internal + public byte getWr() + { + return ( byte )wr.getValue(field_6_flags); + } + + /** + * Sets the wrk field value. + * Text wrapping mode type (valid only for wrapping modes 2 and 4 + */ + @Internal + public void setWrk( byte value ) + { + field_6_flags = (short)wrk.setValue(field_6_flags, value); + } + + /** + * Text wrapping mode type (valid only for wrapping modes 2 and 4 + * @return the wrk field value. + */ + @Internal + public byte getWrk() + { + return ( byte )wrk.getValue(field_6_flags); + } + + /** + * Sets the fRcaSimple field value. + * When set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative. + */ + @Internal + public void setFRcaSimple( boolean value ) + { + field_6_flags = (short)fRcaSimple.setBoolean(field_6_flags, value); + } + + /** + * When set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative. + * @return the fRcaSimple field value. + */ + @Internal + public boolean isFRcaSimple() + { + return fRcaSimple.isSet(field_6_flags); + } + + /** + * Sets the fBelowText field value. + * + */ + @Internal + public void setFBelowText( boolean value ) + { + field_6_flags = (short)fBelowText.setBoolean(field_6_flags, value); + } + + /** + * + * @return the fBelowText field value. + */ + @Internal + public boolean isFBelowText() + { + return fBelowText.isSet(field_6_flags); + } + + /** + * Sets the fAnchorLock field value. + * + */ + @Internal + public void setFAnchorLock( boolean value ) + { + field_6_flags = (short)fAnchorLock.setBoolean(field_6_flags, value); + } + + /** + * + * @return the fAnchorLock field value. + */ + @Internal + public boolean isFAnchorLock() + { + return fAnchorLock.isSet(field_6_flags); + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibBaseAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibBaseAbstractType.java index 7ef107883e..de588af3d9 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibBaseAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibBaseAbstractType.java @@ -1,837 +1,837 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * Base part of the File information Block (FibBase). Holds the core part of the FIB, - from the first 32 bytes.

    Class and fields descriptions are quoted from Microsoft - Office Word 97-2007 Binary File Format and [MS-DOC] - v20110608 Word (.doc) Binary File - Format - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Andrew C. Oliver; Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary - File Format Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format - - */ -@Internal -public abstract class FibBaseAbstractType -{ - - protected int field_1_wIdent; - protected int field_2_nFib; - protected int field_3_unused; - protected int field_4_lid; - protected int field_5_pnNext; - protected short field_6_flags1; - /**/private static final BitField fDot = new BitField(0x0001); - /**/private static final BitField fGlsy = new BitField(0x0002); - /**/private static final BitField fComplex = new BitField(0x0004); - /**/private static final BitField fHasPic = new BitField(0x0008); - /**/private static final BitField cQuickSaves = new BitField(0x00F0); - /**/private static final BitField fEncrypted = new BitField(0x0100); - /**/private static final BitField fWhichTblStm = new BitField(0x0200); - /**/private static final BitField fReadOnlyRecommended = new BitField(0x0400); - /**/private static final BitField fWriteReservation = new BitField(0x0800); - /**/private static final BitField fExtChar = new BitField(0x1000); - /**/private static final BitField fLoadOverride = new BitField(0x2000); - /**/private static final BitField fFarEast = new BitField(0x4000); - /**/private static final BitField fObfuscated = new BitField(0x8000); - protected int field_7_nFibBack; - protected int field_8_lKey; - @Deprecated - protected byte field_9_envr; - protected byte field_10_flags2; - /**/private static final BitField fMac = new BitField(0x01); - /**/private static final BitField fEmptySpecial = new BitField(0x02); - /**/private static final BitField fLoadOverridePage = new BitField(0x04); - /**/private static final BitField reserved1 = new BitField(0x08); - /**/private static final BitField reserved2 = new BitField(0x10); - /**/private static final BitField fSpare0 = new BitField(0xFE); - @Deprecated - protected short field_11_Chs; - @Deprecated - protected short field_12_chsTables; - @Deprecated - protected int field_13_fcMin; - @Deprecated - protected int field_14_fcMac; - - protected FibBaseAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_wIdent = LittleEndian.getShort( data, 0x0 + offset ); - field_2_nFib = LittleEndian.getShort( data, 0x2 + offset ); - field_3_unused = LittleEndian.getShort( data, 0x4 + offset ); - field_4_lid = LittleEndian.getShort( data, 0x6 + offset ); - field_5_pnNext = LittleEndian.getShort( data, 0x8 + offset ); - field_6_flags1 = LittleEndian.getShort( data, 0xa + offset ); - field_7_nFibBack = LittleEndian.getShort( data, 0xc + offset ); - field_8_lKey = LittleEndian.getInt( data, 0xe + offset ); - field_9_envr = data[ 0x12 + offset ]; - field_10_flags2 = data[ 0x13 + offset ]; - field_11_Chs = LittleEndian.getShort( data, 0x14 + offset ); - field_12_chsTables = LittleEndian.getShort( data, 0x16 + offset ); - field_13_fcMin = LittleEndian.getInt( data, 0x18 + offset ); - field_14_fcMac = LittleEndian.getInt( data, 0x1c + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putUShort( data, 0x0 + offset, field_1_wIdent ); - LittleEndian.putUShort( data, 0x2 + offset, field_2_nFib ); - LittleEndian.putUShort( data, 0x4 + offset, field_3_unused ); - LittleEndian.putUShort( data, 0x6 + offset, field_4_lid ); - LittleEndian.putUShort( data, 0x8 + offset, field_5_pnNext ); - LittleEndian.putShort( data, 0xa + offset, field_6_flags1 ); - LittleEndian.putUShort( data, 0xc + offset, field_7_nFibBack ); - LittleEndian.putInt( data, 0xe + offset, field_8_lKey ); - data[ 0x12 + offset ] = field_9_envr; - data[ 0x13 + offset ] = field_10_flags2; - LittleEndian.putShort( data, 0x14 + offset, field_11_Chs ); - LittleEndian.putShort( data, 0x16 + offset, field_12_chsTables ); - LittleEndian.putInt( data, 0x18 + offset, field_13_fcMin ); - LittleEndian.putInt( data, 0x1c + offset, field_14_fcMac ); - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 4 + 1 + 1 + 2 + 2 + 4 + 4; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[FibBase]\n"); - builder.append(" .wIdent = "); - builder.append(" (").append(getWIdent()).append(" )\n"); - builder.append(" .nFib = "); - builder.append(" (").append(getNFib()).append(" )\n"); - builder.append(" .unused = "); - builder.append(" (").append(getUnused()).append(" )\n"); - builder.append(" .lid = "); - builder.append(" (").append(getLid()).append(" )\n"); - builder.append(" .pnNext = "); - builder.append(" (").append(getPnNext()).append(" )\n"); - builder.append(" .flags1 = "); - builder.append(" (").append(getFlags1()).append(" )\n"); - builder.append(" .fDot = ").append(isFDot()).append('\n'); - builder.append(" .fGlsy = ").append(isFGlsy()).append('\n'); - builder.append(" .fComplex = ").append(isFComplex()).append('\n'); - builder.append(" .fHasPic = ").append(isFHasPic()).append('\n'); - builder.append(" .cQuickSaves = ").append(getCQuickSaves()).append('\n'); - builder.append(" .fEncrypted = ").append(isFEncrypted()).append('\n'); - builder.append(" .fWhichTblStm = ").append(isFWhichTblStm()).append('\n'); - builder.append(" .fReadOnlyRecommended = ").append(isFReadOnlyRecommended()).append('\n'); - builder.append(" .fWriteReservation = ").append(isFWriteReservation()).append('\n'); - builder.append(" .fExtChar = ").append(isFExtChar()).append('\n'); - builder.append(" .fLoadOverride = ").append(isFLoadOverride()).append('\n'); - builder.append(" .fFarEast = ").append(isFFarEast()).append('\n'); - builder.append(" .fObfuscated = ").append(isFObfuscated()).append('\n'); - builder.append(" .nFibBack = "); - builder.append(" (").append(getNFibBack()).append(" )\n"); - builder.append(" .lKey = "); - builder.append(" (").append(getLKey()).append(" )\n"); - builder.append(" .envr = "); - builder.append(" (").append(getEnvr()).append(" )\n"); - builder.append(" .flags2 = "); - builder.append(" (").append(getFlags2()).append(" )\n"); - builder.append(" .fMac = ").append(isFMac()).append('\n'); - builder.append(" .fEmptySpecial = ").append(isFEmptySpecial()).append('\n'); - builder.append(" .fLoadOverridePage = ").append(isFLoadOverridePage()).append('\n'); - builder.append(" .reserved1 = ").append(isReserved1()).append('\n'); - builder.append(" .reserved2 = ").append(isReserved2()).append('\n'); - builder.append(" .fSpare0 = ").append(getFSpare0()).append('\n'); - builder.append(" .Chs = "); - builder.append(" (").append(getChs()).append(" )\n"); - builder.append(" .chsTables = "); - builder.append(" (").append(getChsTables()).append(" )\n"); - builder.append(" .fcMin = "); - builder.append(" (").append(getFcMin()).append(" )\n"); - builder.append(" .fcMac = "); - builder.append(" (").append(getFcMac()).append(" )\n"); - - builder.append("[/FibBase]\n"); - return builder.toString(); - } - - /** - * An unsigned integer that specifies that this is a Word Binary File. This value MUST be 0xA5EC. - */ - @Internal - public int getWIdent() - { - return field_1_wIdent; - } - - /** - * An unsigned integer that specifies that this is a Word Binary File. This value MUST be 0xA5EC. - */ - @Internal - public void setWIdent( int field_1_wIdent ) - { - this.field_1_wIdent = field_1_wIdent; - } - - /** - * An unsigned integer that specifies the version number of the file format used. Superseded by FibRgCswNew.nFibNew if it is present. This value SHOULD be 0x00C1. - */ - @Internal - public int getNFib() - { - return field_2_nFib; - } - - /** - * An unsigned integer that specifies the version number of the file format used. Superseded by FibRgCswNew.nFibNew if it is present. This value SHOULD be 0x00C1. - */ - @Internal - public void setNFib( int field_2_nFib ) - { - this.field_2_nFib = field_2_nFib; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getUnused() - { - return field_3_unused; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setUnused( int field_3_unused ) - { - this.field_3_unused = field_3_unused; - } - - /** - * A LID that specifies the install language of the application that is producing the document. If nFib is 0x00D9 or greater, then any East Asian install lid or any install lid with a base language of Spanish, German or French MUST be recorded as lidAmerican. If the nFib is 0x0101 or greater, then any install lid with a base language of Vietnamese, Thai, or Hindi MUST be recorded as lidAmerican.. - */ - @Internal - public int getLid() - { - return field_4_lid; - } - - /** - * A LID that specifies the install language of the application that is producing the document. If nFib is 0x00D9 or greater, then any East Asian install lid or any install lid with a base language of Spanish, German or French MUST be recorded as lidAmerican. If the nFib is 0x0101 or greater, then any install lid with a base language of Vietnamese, Thai, or Hindi MUST be recorded as lidAmerican.. - */ - @Internal - public void setLid( int field_4_lid ) - { - this.field_4_lid = field_4_lid; - } - - /** - * An unsigned integer that specifies the offset in the WordDocument stream of the FIB for the document which contains all the AutoText items. - */ - @Internal - public int getPnNext() - { - return field_5_pnNext; - } - - /** - * An unsigned integer that specifies the offset in the WordDocument stream of the FIB for the document which contains all the AutoText items. - */ - @Internal - public void setPnNext( int field_5_pnNext ) - { - this.field_5_pnNext = field_5_pnNext; - } - - /** - * Get the flags1 field for the FibBase record. - */ - @Internal - public short getFlags1() - { - return field_6_flags1; - } - - /** - * Set the flags1 field for the FibBase record. - */ - @Internal - public void setFlags1( short field_6_flags1 ) - { - this.field_6_flags1 = field_6_flags1; - } - - /** - * This value SHOULD be 0x00BF. This value MUST be 0x00BF or 0x00C1. - */ - @Internal - public int getNFibBack() - { - return field_7_nFibBack; - } - - /** - * This value SHOULD be 0x00BF. This value MUST be 0x00BF or 0x00C1. - */ - @Internal - public void setNFibBack( int field_7_nFibBack ) - { - this.field_7_nFibBack = field_7_nFibBack; - } - - /** - * If fEncryption is 1 and fObfuscation is 1, this value specifies the XOR obfuscation password verifier. If fEncryption is 1 and fObfuscation is 0, this value specifies the size of the EncryptionHeader that is stored at the beginning of the Table stream as described in Encryption and Obfuscation. Otherwise, this value MUST be 0. - */ - @Internal - public int getLKey() - { - return field_8_lKey; - } - - /** - * If fEncryption is 1 and fObfuscation is 1, this value specifies the XOR obfuscation password verifier. If fEncryption is 1 and fObfuscation is 0, this value specifies the size of the EncryptionHeader that is stored at the beginning of the Table stream as described in Encryption and Obfuscation. Otherwise, this value MUST be 0. - */ - @Internal - public void setLKey( int field_8_lKey ) - { - this.field_8_lKey = field_8_lKey; - } - - /** - * This value MUST be 0, and MUST be ignored. - */ - @Internal - public byte getEnvr() - { - return field_9_envr; - } - - /** - * This value MUST be 0, and MUST be ignored. - */ - @Internal - public void setEnvr( byte field_9_envr ) - { - this.field_9_envr = field_9_envr; - } - - /** - * Get the flags2 field for the FibBase record. - */ - @Internal - public byte getFlags2() - { - return field_10_flags2; - } - - /** - * Set the flags2 field for the FibBase record. - */ - @Internal - public void setFlags2( byte field_10_flags2 ) - { - this.field_10_flags2 = field_10_flags2; - } - - /** - * This value MUST be 0 and MUST be ignored. - */ - @Internal - public short getChs() - { - return field_11_Chs; - } - - /** - * This value MUST be 0 and MUST be ignored. - */ - @Internal - public void setChs( short field_11_Chs ) - { - this.field_11_Chs = field_11_Chs; - } - - /** - * This value MUST be 0 and MUST be ignored. - */ - @Internal - public short getChsTables() - { - return field_12_chsTables; - } - - /** - * This value MUST be 0 and MUST be ignored. - */ - @Internal - public void setChsTables( short field_12_chsTables ) - { - this.field_12_chsTables = field_12_chsTables; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getFcMin() - { - return field_13_fcMin; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setFcMin( int field_13_fcMin ) - { - this.field_13_fcMin = field_13_fcMin; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getFcMac() - { - return field_14_fcMac; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setFcMac( int field_14_fcMac ) - { - this.field_14_fcMac = field_14_fcMac; - } - - /** - * Sets the fDot field value. - * Specifies whether this is a document template - */ - @Internal - public void setFDot( boolean value ) - { - field_6_flags1 = (short)fDot.setBoolean(field_6_flags1, value); - } - - /** - * Specifies whether this is a document template - * @return the fDot field value. - */ - @Internal - public boolean isFDot() - { - return fDot.isSet(field_6_flags1); - } - - /** - * Sets the fGlsy field value. - * Specifies whether this is a document that contains only AutoText items - */ - @Internal - public void setFGlsy( boolean value ) - { - field_6_flags1 = (short)fGlsy.setBoolean(field_6_flags1, value); - } - - /** - * Specifies whether this is a document that contains only AutoText items - * @return the fGlsy field value. - */ - @Internal - public boolean isFGlsy() - { - return fGlsy.isSet(field_6_flags1); - } - - /** - * Sets the fComplex field value. - * Specifies that the last save operation that was performed on this document was an incremental save operation - */ - @Internal - public void setFComplex( boolean value ) - { - field_6_flags1 = (short)fComplex.setBoolean(field_6_flags1, value); - } - - /** - * Specifies that the last save operation that was performed on this document was an incremental save operation - * @return the fComplex field value. - */ - @Internal - public boolean isFComplex() - { - return fComplex.isSet(field_6_flags1); - } - - /** - * Sets the fHasPic field value. - * When set to 0, there SHOULD be no pictures in the document - */ - @Internal - public void setFHasPic( boolean value ) - { - field_6_flags1 = (short)fHasPic.setBoolean(field_6_flags1, value); - } - - /** - * When set to 0, there SHOULD be no pictures in the document - * @return the fHasPic field value. - */ - @Internal - public boolean isFHasPic() - { - return fHasPic.isSet(field_6_flags1); - } - - /** - * Sets the cQuickSaves field value. - * An unsigned integer. If nFib is less than 0x00D9, then cQuickSaves specifies the number of consecutive times this document was incrementally saved. If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF - */ - @Internal - public void setCQuickSaves( byte value ) - { - field_6_flags1 = (short)cQuickSaves.setValue(field_6_flags1, value); - } - - /** - * An unsigned integer. If nFib is less than 0x00D9, then cQuickSaves specifies the number of consecutive times this document was incrementally saved. If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF - * @return the cQuickSaves field value. - */ - @Internal - public byte getCQuickSaves() - { - return ( byte )cQuickSaves.getValue(field_6_flags1); - } - - /** - * Sets the fEncrypted field value. - * Specifies whether the document is encrypted or obfuscated as specified in Encryption and Obfuscation - */ - @Internal - public void setFEncrypted( boolean value ) - { - field_6_flags1 = (short)fEncrypted.setBoolean(field_6_flags1, value); - } - - /** - * Specifies whether the document is encrypted or obfuscated as specified in Encryption and Obfuscation - * @return the fEncrypted field value. - */ - @Internal - public boolean isFEncrypted() - { - return fEncrypted.isSet(field_6_flags1); - } - - /** - * Sets the fWhichTblStm field value. - * Specifies the Table stream to which the FIB refers. When this value is set to 1, use 1Table; when this value is set to 0, use 0Table. - */ - @Internal - public void setFWhichTblStm( boolean value ) - { - field_6_flags1 = (short)fWhichTblStm.setBoolean(field_6_flags1, value); - } - - /** - * Specifies the Table stream to which the FIB refers. When this value is set to 1, use 1Table; when this value is set to 0, use 0Table. - * @return the fWhichTblStm field value. - */ - @Internal - public boolean isFWhichTblStm() - { - return fWhichTblStm.isSet(field_6_flags1); - } - - /** - * Sets the fReadOnlyRecommended field value. - * Specifies whether the document author recommended that the document be opened in read-only mode - */ - @Internal - public void setFReadOnlyRecommended( boolean value ) - { - field_6_flags1 = (short)fReadOnlyRecommended.setBoolean(field_6_flags1, value); - } - - /** - * Specifies whether the document author recommended that the document be opened in read-only mode - * @return the fReadOnlyRecommended field value. - */ - @Internal - public boolean isFReadOnlyRecommended() - { - return fReadOnlyRecommended.isSet(field_6_flags1); - } - - /** - * Sets the fWriteReservation field value. - * Specifies whether the document has a write-reservation password - */ - @Internal - public void setFWriteReservation( boolean value ) - { - field_6_flags1 = (short)fWriteReservation.setBoolean(field_6_flags1, value); - } - - /** - * Specifies whether the document has a write-reservation password - * @return the fWriteReservation field value. - */ - @Internal - public boolean isFWriteReservation() - { - return fWriteReservation.isSet(field_6_flags1); - } - - /** - * Sets the fExtChar field value. - * This value MUST be 1 - */ - @Internal - public void setFExtChar( boolean value ) - { - field_6_flags1 = (short)fExtChar.setBoolean(field_6_flags1, value); - } - - /** - * This value MUST be 1 - * @return the fExtChar field value. - */ - @Internal - public boolean isFExtChar() - { - return fExtChar.isSet(field_6_flags1); - } - - /** - * Sets the fLoadOverride field value. - * Specifies whether to override the language information and font that are specified in the paragraph style at istd 0 (the normal style) with the defaults that are appropriate for the installation language of the application - */ - @Internal - public void setFLoadOverride( boolean value ) - { - field_6_flags1 = (short)fLoadOverride.setBoolean(field_6_flags1, value); - } - - /** - * Specifies whether to override the language information and font that are specified in the paragraph style at istd 0 (the normal style) with the defaults that are appropriate for the installation language of the application - * @return the fLoadOverride field value. - */ - @Internal - public boolean isFLoadOverride() - { - return fLoadOverride.isSet(field_6_flags1); - } - - /** - * Sets the fFarEast field value. - * Specifies whether the installation language of the application that created the document was an East Asian language - */ - @Internal - public void setFFarEast( boolean value ) - { - field_6_flags1 = (short)fFarEast.setBoolean(field_6_flags1, value); - } - - /** - * Specifies whether the installation language of the application that created the document was an East Asian language - * @return the fFarEast field value. - */ - @Internal - public boolean isFFarEast() - { - return fFarEast.isSet(field_6_flags1); - } - - /** - * Sets the fObfuscated field value. - * If fEncrypted is 1, this bit specifies whether the document is obfuscated by using XOR obfuscation; otherwise, this bit MUST be ignored - */ - @Internal - public void setFObfuscated( boolean value ) - { - field_6_flags1 = (short)fObfuscated.setBoolean(field_6_flags1, value); - } - - /** - * If fEncrypted is 1, this bit specifies whether the document is obfuscated by using XOR obfuscation; otherwise, this bit MUST be ignored - * @return the fObfuscated field value. - */ - @Internal - public boolean isFObfuscated() - { - return fObfuscated.isSet(field_6_flags1); - } - - /** - * Sets the fMac field value. - * This value MUST be 0, and MUST be ignored - */ - @Internal - public void setFMac( boolean value ) - { - field_10_flags2 = (byte)fMac.setBoolean(field_10_flags2, value); - } - - /** - * This value MUST be 0, and MUST be ignored - * @return the fMac field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public boolean isFMac() - { - return fMac.isSet(field_10_flags2); - } - - /** - * Sets the fEmptySpecial field value. - * This value SHOULD be 0 and SHOULD be ignored - */ - @Internal - public void setFEmptySpecial( boolean value ) - { - field_10_flags2 = (byte)fEmptySpecial.setBoolean(field_10_flags2, value); - } - - /** - * This value SHOULD be 0 and SHOULD be ignored - * @return the fEmptySpecial field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public boolean isFEmptySpecial() - { - return fEmptySpecial.isSet(field_10_flags2); - } - - /** - * Sets the fLoadOverridePage field value. - * Specifies whether to override the section properties for page size, orientation, and margins with the defaults that are appropriate for the installation language of the application - */ - @Internal - public void setFLoadOverridePage( boolean value ) - { - field_10_flags2 = (byte)fLoadOverridePage.setBoolean(field_10_flags2, value); - } - - /** - * Specifies whether to override the section properties for page size, orientation, and margins with the defaults that are appropriate for the installation language of the application - * @return the fLoadOverridePage field value. - */ - @Internal - public boolean isFLoadOverridePage() - { - return fLoadOverridePage.isSet(field_10_flags2); - } - - /** - * Sets the reserved1 field value. - * This value is undefined and MUST be ignored - */ - @Internal - public void setReserved1( boolean value ) - { - field_10_flags2 = (byte)reserved1.setBoolean(field_10_flags2, value); - } - - /** - * This value is undefined and MUST be ignored - * @return the reserved1 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public boolean isReserved1() - { - return reserved1.isSet(field_10_flags2); - } - - /** - * Sets the reserved2 field value. - * This value is undefined and MUST be ignored - */ - @Internal - public void setReserved2( boolean value ) - { - field_10_flags2 = (byte)reserved2.setBoolean(field_10_flags2, value); - } - - /** - * This value is undefined and MUST be ignored - * @return the reserved2 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public boolean isReserved2() - { - return reserved2.isSet(field_10_flags2); - } - - /** - * Sets the fSpare0 field value. - * This value is undefined and MUST be ignored - */ - @Internal - public void setFSpare0( byte value ) - { - field_10_flags2 = (byte)fSpare0.setValue(field_10_flags2, value); - } - - /** - * This value is undefined and MUST be ignored - * @return the fSpare0 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public byte getFSpare0() - { - return ( byte )fSpare0.getValue(field_10_flags2); - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * Base part of the File information Block (FibBase). Holds the core part of the FIB, + from the first 32 bytes.

    Class and fields descriptions are quoted from Microsoft + Office Word 97-2007 Binary File Format and [MS-DOC] - v20110608 Word (.doc) Binary File + Format + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Andrew C. Oliver; Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary + File Format Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format + + */ +@Internal +public abstract class FibBaseAbstractType +{ + + protected int field_1_wIdent; + protected int field_2_nFib; + protected int field_3_unused; + protected int field_4_lid; + protected int field_5_pnNext; + protected short field_6_flags1; + /**/private static final BitField fDot = new BitField(0x0001); + /**/private static final BitField fGlsy = new BitField(0x0002); + /**/private static final BitField fComplex = new BitField(0x0004); + /**/private static final BitField fHasPic = new BitField(0x0008); + /**/private static final BitField cQuickSaves = new BitField(0x00F0); + /**/private static final BitField fEncrypted = new BitField(0x0100); + /**/private static final BitField fWhichTblStm = new BitField(0x0200); + /**/private static final BitField fReadOnlyRecommended = new BitField(0x0400); + /**/private static final BitField fWriteReservation = new BitField(0x0800); + /**/private static final BitField fExtChar = new BitField(0x1000); + /**/private static final BitField fLoadOverride = new BitField(0x2000); + /**/private static final BitField fFarEast = new BitField(0x4000); + /**/private static final BitField fObfuscated = new BitField(0x8000); + protected int field_7_nFibBack; + protected int field_8_lKey; + @Deprecated + protected byte field_9_envr; + protected byte field_10_flags2; + /**/private static final BitField fMac = new BitField(0x01); + /**/private static final BitField fEmptySpecial = new BitField(0x02); + /**/private static final BitField fLoadOverridePage = new BitField(0x04); + /**/private static final BitField reserved1 = new BitField(0x08); + /**/private static final BitField reserved2 = new BitField(0x10); + /**/private static final BitField fSpare0 = new BitField(0xFE); + @Deprecated + protected short field_11_Chs; + @Deprecated + protected short field_12_chsTables; + @Deprecated + protected int field_13_fcMin; + @Deprecated + protected int field_14_fcMac; + + protected FibBaseAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_wIdent = LittleEndian.getShort( data, 0x0 + offset ); + field_2_nFib = LittleEndian.getShort( data, 0x2 + offset ); + field_3_unused = LittleEndian.getShort( data, 0x4 + offset ); + field_4_lid = LittleEndian.getShort( data, 0x6 + offset ); + field_5_pnNext = LittleEndian.getShort( data, 0x8 + offset ); + field_6_flags1 = LittleEndian.getShort( data, 0xa + offset ); + field_7_nFibBack = LittleEndian.getShort( data, 0xc + offset ); + field_8_lKey = LittleEndian.getInt( data, 0xe + offset ); + field_9_envr = data[ 0x12 + offset ]; + field_10_flags2 = data[ 0x13 + offset ]; + field_11_Chs = LittleEndian.getShort( data, 0x14 + offset ); + field_12_chsTables = LittleEndian.getShort( data, 0x16 + offset ); + field_13_fcMin = LittleEndian.getInt( data, 0x18 + offset ); + field_14_fcMac = LittleEndian.getInt( data, 0x1c + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putUShort( data, 0x0 + offset, field_1_wIdent ); + LittleEndian.putUShort( data, 0x2 + offset, field_2_nFib ); + LittleEndian.putUShort( data, 0x4 + offset, field_3_unused ); + LittleEndian.putUShort( data, 0x6 + offset, field_4_lid ); + LittleEndian.putUShort( data, 0x8 + offset, field_5_pnNext ); + LittleEndian.putShort( data, 0xa + offset, field_6_flags1 ); + LittleEndian.putUShort( data, 0xc + offset, field_7_nFibBack ); + LittleEndian.putInt( data, 0xe + offset, field_8_lKey ); + data[ 0x12 + offset ] = field_9_envr; + data[ 0x13 + offset ] = field_10_flags2; + LittleEndian.putShort( data, 0x14 + offset, field_11_Chs ); + LittleEndian.putShort( data, 0x16 + offset, field_12_chsTables ); + LittleEndian.putInt( data, 0x18 + offset, field_13_fcMin ); + LittleEndian.putInt( data, 0x1c + offset, field_14_fcMac ); + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 4 + 1 + 1 + 2 + 2 + 4 + 4; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[FibBase]\n"); + builder.append(" .wIdent = "); + builder.append(" (").append(getWIdent()).append(" )\n"); + builder.append(" .nFib = "); + builder.append(" (").append(getNFib()).append(" )\n"); + builder.append(" .unused = "); + builder.append(" (").append(getUnused()).append(" )\n"); + builder.append(" .lid = "); + builder.append(" (").append(getLid()).append(" )\n"); + builder.append(" .pnNext = "); + builder.append(" (").append(getPnNext()).append(" )\n"); + builder.append(" .flags1 = "); + builder.append(" (").append(getFlags1()).append(" )\n"); + builder.append(" .fDot = ").append(isFDot()).append('\n'); + builder.append(" .fGlsy = ").append(isFGlsy()).append('\n'); + builder.append(" .fComplex = ").append(isFComplex()).append('\n'); + builder.append(" .fHasPic = ").append(isFHasPic()).append('\n'); + builder.append(" .cQuickSaves = ").append(getCQuickSaves()).append('\n'); + builder.append(" .fEncrypted = ").append(isFEncrypted()).append('\n'); + builder.append(" .fWhichTblStm = ").append(isFWhichTblStm()).append('\n'); + builder.append(" .fReadOnlyRecommended = ").append(isFReadOnlyRecommended()).append('\n'); + builder.append(" .fWriteReservation = ").append(isFWriteReservation()).append('\n'); + builder.append(" .fExtChar = ").append(isFExtChar()).append('\n'); + builder.append(" .fLoadOverride = ").append(isFLoadOverride()).append('\n'); + builder.append(" .fFarEast = ").append(isFFarEast()).append('\n'); + builder.append(" .fObfuscated = ").append(isFObfuscated()).append('\n'); + builder.append(" .nFibBack = "); + builder.append(" (").append(getNFibBack()).append(" )\n"); + builder.append(" .lKey = "); + builder.append(" (").append(getLKey()).append(" )\n"); + builder.append(" .envr = "); + builder.append(" (").append(getEnvr()).append(" )\n"); + builder.append(" .flags2 = "); + builder.append(" (").append(getFlags2()).append(" )\n"); + builder.append(" .fMac = ").append(isFMac()).append('\n'); + builder.append(" .fEmptySpecial = ").append(isFEmptySpecial()).append('\n'); + builder.append(" .fLoadOverridePage = ").append(isFLoadOverridePage()).append('\n'); + builder.append(" .reserved1 = ").append(isReserved1()).append('\n'); + builder.append(" .reserved2 = ").append(isReserved2()).append('\n'); + builder.append(" .fSpare0 = ").append(getFSpare0()).append('\n'); + builder.append(" .Chs = "); + builder.append(" (").append(getChs()).append(" )\n"); + builder.append(" .chsTables = "); + builder.append(" (").append(getChsTables()).append(" )\n"); + builder.append(" .fcMin = "); + builder.append(" (").append(getFcMin()).append(" )\n"); + builder.append(" .fcMac = "); + builder.append(" (").append(getFcMac()).append(" )\n"); + + builder.append("[/FibBase]\n"); + return builder.toString(); + } + + /** + * An unsigned integer that specifies that this is a Word Binary File. This value MUST be 0xA5EC. + */ + @Internal + public int getWIdent() + { + return field_1_wIdent; + } + + /** + * An unsigned integer that specifies that this is a Word Binary File. This value MUST be 0xA5EC. + */ + @Internal + public void setWIdent( int field_1_wIdent ) + { + this.field_1_wIdent = field_1_wIdent; + } + + /** + * An unsigned integer that specifies the version number of the file format used. Superseded by FibRgCswNew.nFibNew if it is present. This value SHOULD be 0x00C1. + */ + @Internal + public int getNFib() + { + return field_2_nFib; + } + + /** + * An unsigned integer that specifies the version number of the file format used. Superseded by FibRgCswNew.nFibNew if it is present. This value SHOULD be 0x00C1. + */ + @Internal + public void setNFib( int field_2_nFib ) + { + this.field_2_nFib = field_2_nFib; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getUnused() + { + return field_3_unused; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setUnused( int field_3_unused ) + { + this.field_3_unused = field_3_unused; + } + + /** + * A LID that specifies the install language of the application that is producing the document. If nFib is 0x00D9 or greater, then any East Asian install lid or any install lid with a base language of Spanish, German or French MUST be recorded as lidAmerican. If the nFib is 0x0101 or greater, then any install lid with a base language of Vietnamese, Thai, or Hindi MUST be recorded as lidAmerican.. + */ + @Internal + public int getLid() + { + return field_4_lid; + } + + /** + * A LID that specifies the install language of the application that is producing the document. If nFib is 0x00D9 or greater, then any East Asian install lid or any install lid with a base language of Spanish, German or French MUST be recorded as lidAmerican. If the nFib is 0x0101 or greater, then any install lid with a base language of Vietnamese, Thai, or Hindi MUST be recorded as lidAmerican.. + */ + @Internal + public void setLid( int field_4_lid ) + { + this.field_4_lid = field_4_lid; + } + + /** + * An unsigned integer that specifies the offset in the WordDocument stream of the FIB for the document which contains all the AutoText items. + */ + @Internal + public int getPnNext() + { + return field_5_pnNext; + } + + /** + * An unsigned integer that specifies the offset in the WordDocument stream of the FIB for the document which contains all the AutoText items. + */ + @Internal + public void setPnNext( int field_5_pnNext ) + { + this.field_5_pnNext = field_5_pnNext; + } + + /** + * Get the flags1 field for the FibBase record. + */ + @Internal + public short getFlags1() + { + return field_6_flags1; + } + + /** + * Set the flags1 field for the FibBase record. + */ + @Internal + public void setFlags1( short field_6_flags1 ) + { + this.field_6_flags1 = field_6_flags1; + } + + /** + * This value SHOULD be 0x00BF. This value MUST be 0x00BF or 0x00C1. + */ + @Internal + public int getNFibBack() + { + return field_7_nFibBack; + } + + /** + * This value SHOULD be 0x00BF. This value MUST be 0x00BF or 0x00C1. + */ + @Internal + public void setNFibBack( int field_7_nFibBack ) + { + this.field_7_nFibBack = field_7_nFibBack; + } + + /** + * If fEncryption is 1 and fObfuscation is 1, this value specifies the XOR obfuscation password verifier. If fEncryption is 1 and fObfuscation is 0, this value specifies the size of the EncryptionHeader that is stored at the beginning of the Table stream as described in Encryption and Obfuscation. Otherwise, this value MUST be 0. + */ + @Internal + public int getLKey() + { + return field_8_lKey; + } + + /** + * If fEncryption is 1 and fObfuscation is 1, this value specifies the XOR obfuscation password verifier. If fEncryption is 1 and fObfuscation is 0, this value specifies the size of the EncryptionHeader that is stored at the beginning of the Table stream as described in Encryption and Obfuscation. Otherwise, this value MUST be 0. + */ + @Internal + public void setLKey( int field_8_lKey ) + { + this.field_8_lKey = field_8_lKey; + } + + /** + * This value MUST be 0, and MUST be ignored. + */ + @Internal + public byte getEnvr() + { + return field_9_envr; + } + + /** + * This value MUST be 0, and MUST be ignored. + */ + @Internal + public void setEnvr( byte field_9_envr ) + { + this.field_9_envr = field_9_envr; + } + + /** + * Get the flags2 field for the FibBase record. + */ + @Internal + public byte getFlags2() + { + return field_10_flags2; + } + + /** + * Set the flags2 field for the FibBase record. + */ + @Internal + public void setFlags2( byte field_10_flags2 ) + { + this.field_10_flags2 = field_10_flags2; + } + + /** + * This value MUST be 0 and MUST be ignored. + */ + @Internal + public short getChs() + { + return field_11_Chs; + } + + /** + * This value MUST be 0 and MUST be ignored. + */ + @Internal + public void setChs( short field_11_Chs ) + { + this.field_11_Chs = field_11_Chs; + } + + /** + * This value MUST be 0 and MUST be ignored. + */ + @Internal + public short getChsTables() + { + return field_12_chsTables; + } + + /** + * This value MUST be 0 and MUST be ignored. + */ + @Internal + public void setChsTables( short field_12_chsTables ) + { + this.field_12_chsTables = field_12_chsTables; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getFcMin() + { + return field_13_fcMin; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setFcMin( int field_13_fcMin ) + { + this.field_13_fcMin = field_13_fcMin; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getFcMac() + { + return field_14_fcMac; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setFcMac( int field_14_fcMac ) + { + this.field_14_fcMac = field_14_fcMac; + } + + /** + * Sets the fDot field value. + * Specifies whether this is a document template + */ + @Internal + public void setFDot( boolean value ) + { + field_6_flags1 = (short)fDot.setBoolean(field_6_flags1, value); + } + + /** + * Specifies whether this is a document template + * @return the fDot field value. + */ + @Internal + public boolean isFDot() + { + return fDot.isSet(field_6_flags1); + } + + /** + * Sets the fGlsy field value. + * Specifies whether this is a document that contains only AutoText items + */ + @Internal + public void setFGlsy( boolean value ) + { + field_6_flags1 = (short)fGlsy.setBoolean(field_6_flags1, value); + } + + /** + * Specifies whether this is a document that contains only AutoText items + * @return the fGlsy field value. + */ + @Internal + public boolean isFGlsy() + { + return fGlsy.isSet(field_6_flags1); + } + + /** + * Sets the fComplex field value. + * Specifies that the last save operation that was performed on this document was an incremental save operation + */ + @Internal + public void setFComplex( boolean value ) + { + field_6_flags1 = (short)fComplex.setBoolean(field_6_flags1, value); + } + + /** + * Specifies that the last save operation that was performed on this document was an incremental save operation + * @return the fComplex field value. + */ + @Internal + public boolean isFComplex() + { + return fComplex.isSet(field_6_flags1); + } + + /** + * Sets the fHasPic field value. + * When set to 0, there SHOULD be no pictures in the document + */ + @Internal + public void setFHasPic( boolean value ) + { + field_6_flags1 = (short)fHasPic.setBoolean(field_6_flags1, value); + } + + /** + * When set to 0, there SHOULD be no pictures in the document + * @return the fHasPic field value. + */ + @Internal + public boolean isFHasPic() + { + return fHasPic.isSet(field_6_flags1); + } + + /** + * Sets the cQuickSaves field value. + * An unsigned integer. If nFib is less than 0x00D9, then cQuickSaves specifies the number of consecutive times this document was incrementally saved. If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF + */ + @Internal + public void setCQuickSaves( byte value ) + { + field_6_flags1 = (short)cQuickSaves.setValue(field_6_flags1, value); + } + + /** + * An unsigned integer. If nFib is less than 0x00D9, then cQuickSaves specifies the number of consecutive times this document was incrementally saved. If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF + * @return the cQuickSaves field value. + */ + @Internal + public byte getCQuickSaves() + { + return ( byte )cQuickSaves.getValue(field_6_flags1); + } + + /** + * Sets the fEncrypted field value. + * Specifies whether the document is encrypted or obfuscated as specified in Encryption and Obfuscation + */ + @Internal + public void setFEncrypted( boolean value ) + { + field_6_flags1 = (short)fEncrypted.setBoolean(field_6_flags1, value); + } + + /** + * Specifies whether the document is encrypted or obfuscated as specified in Encryption and Obfuscation + * @return the fEncrypted field value. + */ + @Internal + public boolean isFEncrypted() + { + return fEncrypted.isSet(field_6_flags1); + } + + /** + * Sets the fWhichTblStm field value. + * Specifies the Table stream to which the FIB refers. When this value is set to 1, use 1Table; when this value is set to 0, use 0Table. + */ + @Internal + public void setFWhichTblStm( boolean value ) + { + field_6_flags1 = (short)fWhichTblStm.setBoolean(field_6_flags1, value); + } + + /** + * Specifies the Table stream to which the FIB refers. When this value is set to 1, use 1Table; when this value is set to 0, use 0Table. + * @return the fWhichTblStm field value. + */ + @Internal + public boolean isFWhichTblStm() + { + return fWhichTblStm.isSet(field_6_flags1); + } + + /** + * Sets the fReadOnlyRecommended field value. + * Specifies whether the document author recommended that the document be opened in read-only mode + */ + @Internal + public void setFReadOnlyRecommended( boolean value ) + { + field_6_flags1 = (short)fReadOnlyRecommended.setBoolean(field_6_flags1, value); + } + + /** + * Specifies whether the document author recommended that the document be opened in read-only mode + * @return the fReadOnlyRecommended field value. + */ + @Internal + public boolean isFReadOnlyRecommended() + { + return fReadOnlyRecommended.isSet(field_6_flags1); + } + + /** + * Sets the fWriteReservation field value. + * Specifies whether the document has a write-reservation password + */ + @Internal + public void setFWriteReservation( boolean value ) + { + field_6_flags1 = (short)fWriteReservation.setBoolean(field_6_flags1, value); + } + + /** + * Specifies whether the document has a write-reservation password + * @return the fWriteReservation field value. + */ + @Internal + public boolean isFWriteReservation() + { + return fWriteReservation.isSet(field_6_flags1); + } + + /** + * Sets the fExtChar field value. + * This value MUST be 1 + */ + @Internal + public void setFExtChar( boolean value ) + { + field_6_flags1 = (short)fExtChar.setBoolean(field_6_flags1, value); + } + + /** + * This value MUST be 1 + * @return the fExtChar field value. + */ + @Internal + public boolean isFExtChar() + { + return fExtChar.isSet(field_6_flags1); + } + + /** + * Sets the fLoadOverride field value. + * Specifies whether to override the language information and font that are specified in the paragraph style at istd 0 (the normal style) with the defaults that are appropriate for the installation language of the application + */ + @Internal + public void setFLoadOverride( boolean value ) + { + field_6_flags1 = (short)fLoadOverride.setBoolean(field_6_flags1, value); + } + + /** + * Specifies whether to override the language information and font that are specified in the paragraph style at istd 0 (the normal style) with the defaults that are appropriate for the installation language of the application + * @return the fLoadOverride field value. + */ + @Internal + public boolean isFLoadOverride() + { + return fLoadOverride.isSet(field_6_flags1); + } + + /** + * Sets the fFarEast field value. + * Specifies whether the installation language of the application that created the document was an East Asian language + */ + @Internal + public void setFFarEast( boolean value ) + { + field_6_flags1 = (short)fFarEast.setBoolean(field_6_flags1, value); + } + + /** + * Specifies whether the installation language of the application that created the document was an East Asian language + * @return the fFarEast field value. + */ + @Internal + public boolean isFFarEast() + { + return fFarEast.isSet(field_6_flags1); + } + + /** + * Sets the fObfuscated field value. + * If fEncrypted is 1, this bit specifies whether the document is obfuscated by using XOR obfuscation; otherwise, this bit MUST be ignored + */ + @Internal + public void setFObfuscated( boolean value ) + { + field_6_flags1 = (short)fObfuscated.setBoolean(field_6_flags1, value); + } + + /** + * If fEncrypted is 1, this bit specifies whether the document is obfuscated by using XOR obfuscation; otherwise, this bit MUST be ignored + * @return the fObfuscated field value. + */ + @Internal + public boolean isFObfuscated() + { + return fObfuscated.isSet(field_6_flags1); + } + + /** + * Sets the fMac field value. + * This value MUST be 0, and MUST be ignored + */ + @Internal + public void setFMac( boolean value ) + { + field_10_flags2 = (byte)fMac.setBoolean(field_10_flags2, value); + } + + /** + * This value MUST be 0, and MUST be ignored + * @return the fMac field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public boolean isFMac() + { + return fMac.isSet(field_10_flags2); + } + + /** + * Sets the fEmptySpecial field value. + * This value SHOULD be 0 and SHOULD be ignored + */ + @Internal + public void setFEmptySpecial( boolean value ) + { + field_10_flags2 = (byte)fEmptySpecial.setBoolean(field_10_flags2, value); + } + + /** + * This value SHOULD be 0 and SHOULD be ignored + * @return the fEmptySpecial field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public boolean isFEmptySpecial() + { + return fEmptySpecial.isSet(field_10_flags2); + } + + /** + * Sets the fLoadOverridePage field value. + * Specifies whether to override the section properties for page size, orientation, and margins with the defaults that are appropriate for the installation language of the application + */ + @Internal + public void setFLoadOverridePage( boolean value ) + { + field_10_flags2 = (byte)fLoadOverridePage.setBoolean(field_10_flags2, value); + } + + /** + * Specifies whether to override the section properties for page size, orientation, and margins with the defaults that are appropriate for the installation language of the application + * @return the fLoadOverridePage field value. + */ + @Internal + public boolean isFLoadOverridePage() + { + return fLoadOverridePage.isSet(field_10_flags2); + } + + /** + * Sets the reserved1 field value. + * This value is undefined and MUST be ignored + */ + @Internal + public void setReserved1( boolean value ) + { + field_10_flags2 = (byte)reserved1.setBoolean(field_10_flags2, value); + } + + /** + * This value is undefined and MUST be ignored + * @return the reserved1 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public boolean isReserved1() + { + return reserved1.isSet(field_10_flags2); + } + + /** + * Sets the reserved2 field value. + * This value is undefined and MUST be ignored + */ + @Internal + public void setReserved2( boolean value ) + { + field_10_flags2 = (byte)reserved2.setBoolean(field_10_flags2, value); + } + + /** + * This value is undefined and MUST be ignored + * @return the reserved2 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public boolean isReserved2() + { + return reserved2.isSet(field_10_flags2); + } + + /** + * Sets the fSpare0 field value. + * This value is undefined and MUST be ignored + */ + @Internal + public void setFSpare0( byte value ) + { + field_10_flags2 = (byte)fSpare0.setValue(field_10_flags2, value); + } + + /** + * This value is undefined and MUST be ignored + * @return the fSpare0 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public byte getFSpare0() + { + return ( byte )fSpare0.getValue(field_10_flags2); + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw95AbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw95AbstractType.java index a67069b4d0..d1a03a6b85 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw95AbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw95AbstractType.java @@ -1,468 +1,468 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - - -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * The FibRgLw95 structure is the third section of the FIB for Word95. - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov - - */ -@Internal -public abstract class FibRgLw95AbstractType -{ - - protected int field_1_cbMac; - @Deprecated - protected int field_2_reserved1; - @Deprecated - protected int field_3_reserved2; - @Deprecated - protected int field_4_reserved3; - @Deprecated - protected int field_5_reserved4; - protected int field_6_ccpText; - protected int field_7_ccpFtn; - protected int field_8_ccpHdd; - protected int field_9_ccpMcr; - protected int field_10_ccpAtn; - protected int field_11_ccpEdn; - protected int field_12_ccpTxbx; - protected int field_13_ccpHdrTxbx; - @Deprecated - protected int field_14_reserved5; - - protected FibRgLw95AbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_cbMac = LittleEndian.getInt( data, 0x0 + offset ); - field_2_reserved1 = LittleEndian.getInt( data, 0x4 + offset ); - field_3_reserved2 = LittleEndian.getInt( data, 0x8 + offset ); - field_4_reserved3 = LittleEndian.getInt( data, 0xc + offset ); - field_5_reserved4 = LittleEndian.getInt( data, 0x10 + offset ); - field_6_ccpText = LittleEndian.getInt( data, 0x14 + offset ); - field_7_ccpFtn = LittleEndian.getInt( data, 0x18 + offset ); - field_8_ccpHdd = LittleEndian.getInt( data, 0x1c + offset ); - field_9_ccpMcr = LittleEndian.getInt( data, 0x20 + offset ); - field_10_ccpAtn = LittleEndian.getInt( data, 0x24 + offset ); - field_11_ccpEdn = LittleEndian.getInt( data, 0x28 + offset ); - field_12_ccpTxbx = LittleEndian.getInt( data, 0x2c + offset ); - field_13_ccpHdrTxbx = LittleEndian.getInt( data, 0x30 + offset ); - field_14_reserved5 = LittleEndian.getInt( data, 0x34 + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putInt( data, 0x0 + offset, field_1_cbMac ); - LittleEndian.putInt( data, 0x4 + offset, field_2_reserved1 ); - LittleEndian.putInt( data, 0x8 + offset, field_3_reserved2 ); - LittleEndian.putInt( data, 0xc + offset, field_4_reserved3 ); - LittleEndian.putInt( data, 0x10 + offset, field_5_reserved4 ); - LittleEndian.putInt( data, 0x14 + offset, field_6_ccpText ); - LittleEndian.putInt( data, 0x18 + offset, field_7_ccpFtn ); - LittleEndian.putInt( data, 0x1c + offset, field_8_ccpHdd ); - LittleEndian.putInt( data, 0x20 + offset, field_9_ccpMcr ); - LittleEndian.putInt( data, 0x24 + offset, field_10_ccpAtn ); - LittleEndian.putInt( data, 0x28 + offset, field_11_ccpEdn ); - LittleEndian.putInt( data, 0x2c + offset, field_12_ccpTxbx ); - LittleEndian.putInt( data, 0x30 + offset, field_13_ccpHdrTxbx ); - LittleEndian.putInt( data, 0x34 + offset, field_14_reserved5 ); - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4; - } - - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - FibRgLw95AbstractType other = (FibRgLw95AbstractType) obj; - if ( field_1_cbMac != other.field_1_cbMac ) - return false; - if ( field_2_reserved1 != other.field_2_reserved1 ) - return false; - if ( field_3_reserved2 != other.field_3_reserved2 ) - return false; - if ( field_4_reserved3 != other.field_4_reserved3 ) - return false; - if ( field_5_reserved4 != other.field_5_reserved4 ) - return false; - if ( field_6_ccpText != other.field_6_ccpText ) - return false; - if ( field_7_ccpFtn != other.field_7_ccpFtn ) - return false; - if ( field_8_ccpHdd != other.field_8_ccpHdd ) - return false; - if ( field_9_ccpMcr != other.field_9_ccpMcr ) - return false; - if ( field_10_ccpAtn != other.field_10_ccpAtn ) - return false; - if ( field_11_ccpEdn != other.field_11_ccpEdn ) - return false; - if ( field_12_ccpTxbx != other.field_12_ccpTxbx ) - return false; - if ( field_13_ccpHdrTxbx != other.field_13_ccpHdrTxbx ) - return false; - if ( field_14_reserved5 != other.field_14_reserved5 ) - return false; - return true; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + field_1_cbMac; - result = prime * result + field_2_reserved1; - result = prime * result + field_3_reserved2; - result = prime * result + field_4_reserved3; - result = prime * result + field_5_reserved4; - result = prime * result + field_6_ccpText; - result = prime * result + field_7_ccpFtn; - result = prime * result + field_8_ccpHdd; - result = prime * result + field_9_ccpMcr; - result = prime * result + field_10_ccpAtn; - result = prime * result + field_11_ccpEdn; - result = prime * result + field_12_ccpTxbx; - result = prime * result + field_13_ccpHdrTxbx; - result = prime * result + field_14_reserved5; - return result; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[FibRgLw95]\n"); - builder.append(" .cbMac = "); - builder.append(" (").append(getCbMac()).append(" )\n"); - builder.append(" .reserved1 = "); - builder.append(" (").append(getReserved1()).append(" )\n"); - builder.append(" .reserved2 = "); - builder.append(" (").append(getReserved2()).append(" )\n"); - builder.append(" .reserved3 = "); - builder.append(" (").append(getReserved3()).append(" )\n"); - builder.append(" .reserved4 = "); - builder.append(" (").append(getReserved4()).append(" )\n"); - builder.append(" .ccpText = "); - builder.append(" (").append(getCcpText()).append(" )\n"); - builder.append(" .ccpFtn = "); - builder.append(" (").append(getCcpFtn()).append(" )\n"); - builder.append(" .ccpHdd = "); - builder.append(" (").append(getCcpHdd()).append(" )\n"); - builder.append(" .ccpMcr = "); - builder.append(" (").append(getCcpMcr()).append(" )\n"); - builder.append(" .ccpAtn = "); - builder.append(" (").append(getCcpAtn()).append(" )\n"); - builder.append(" .ccpEdn = "); - builder.append(" (").append(getCcpEdn()).append(" )\n"); - builder.append(" .ccpTxbx = "); - builder.append(" (").append(getCcpTxbx()).append(" )\n"); - builder.append(" .ccpHdrTxbx = "); - builder.append(" (").append(getCcpHdrTxbx()).append(" )\n"); - builder.append(" .reserved5 = "); - builder.append(" (").append(getReserved5()).append(" )\n"); - - builder.append("[/FibRgLw95]\n"); - return builder.toString(); - } - - /** - * Get the cbMac field for the FibRgLw95 record. - */ - @Internal - public int getCbMac() - { - return field_1_cbMac; - } - - /** - * Set the cbMac field for the FibRgLw95 record. - */ - @Internal - public void setCbMac( int field_1_cbMac ) - { - this.field_1_cbMac = field_1_cbMac; - } - - /** - * Get the reserved1 field for the FibRgLw95 record. - */ - @Internal - public int getReserved1() - { - return field_2_reserved1; - } - - /** - * Set the reserved1 field for the FibRgLw95 record. - */ - @Internal - public void setReserved1( int field_2_reserved1 ) - { - this.field_2_reserved1 = field_2_reserved1; - } - - /** - * Get the reserved2 field for the FibRgLw95 record. - */ - @Internal - public int getReserved2() - { - return field_3_reserved2; - } - - /** - * Set the reserved2 field for the FibRgLw95 record. - */ - @Internal - public void setReserved2( int field_3_reserved2 ) - { - this.field_3_reserved2 = field_3_reserved2; - } - - /** - * Get the reserved3 field for the FibRgLw95 record. - */ - @Internal - public int getReserved3() - { - return field_4_reserved3; - } - - /** - * Set the reserved3 field for the FibRgLw95 record. - */ - @Internal - public void setReserved3( int field_4_reserved3 ) - { - this.field_4_reserved3 = field_4_reserved3; - } - - /** - * Get the reserved4 field for the FibRgLw95 record. - */ - @Internal - public int getReserved4() - { - return field_5_reserved4; - } - - /** - * Set the reserved4 field for the FibRgLw95 record. - */ - @Internal - public void setReserved4( int field_5_reserved4 ) - { - this.field_5_reserved4 = field_5_reserved4; - } - - /** - * Get the ccpText field for the FibRgLw95 record. - */ - @Internal - public int getCcpText() - { - return field_6_ccpText; - } - - /** - * Set the ccpText field for the FibRgLw95 record. - */ - @Internal - public void setCcpText( int field_6_ccpText ) - { - this.field_6_ccpText = field_6_ccpText; - } - - /** - * Get the ccpFtn field for the FibRgLw95 record. - */ - @Internal - public int getCcpFtn() - { - return field_7_ccpFtn; - } - - /** - * Set the ccpFtn field for the FibRgLw95 record. - */ - @Internal - public void setCcpFtn( int field_7_ccpFtn ) - { - this.field_7_ccpFtn = field_7_ccpFtn; - } - - /** - * Get the ccpHdd field for the FibRgLw95 record. - */ - @Internal - public int getCcpHdd() - { - return field_8_ccpHdd; - } - - /** - * Set the ccpHdd field for the FibRgLw95 record. - */ - @Internal - public void setCcpHdd( int field_8_ccpHdd ) - { - this.field_8_ccpHdd = field_8_ccpHdd; - } - - /** - * Get the ccpMcr field for the FibRgLw95 record. - */ - @Internal - public int getCcpMcr() - { - return field_9_ccpMcr; - } - - /** - * Set the ccpMcr field for the FibRgLw95 record. - */ - @Internal - public void setCcpMcr( int field_9_ccpMcr ) - { - this.field_9_ccpMcr = field_9_ccpMcr; - } - - /** - * Get the ccpAtn field for the FibRgLw95 record. - */ - @Internal - public int getCcpAtn() - { - return field_10_ccpAtn; - } - - /** - * Set the ccpAtn field for the FibRgLw95 record. - */ - @Internal - public void setCcpAtn( int field_10_ccpAtn ) - { - this.field_10_ccpAtn = field_10_ccpAtn; - } - - /** - * Get the ccpEdn field for the FibRgLw95 record. - */ - @Internal - public int getCcpEdn() - { - return field_11_ccpEdn; - } - - /** - * Set the ccpEdn field for the FibRgLw95 record. - */ - @Internal - public void setCcpEdn( int field_11_ccpEdn ) - { - this.field_11_ccpEdn = field_11_ccpEdn; - } - - /** - * Get the ccpTxbx field for the FibRgLw95 record. - */ - @Internal - public int getCcpTxbx() - { - return field_12_ccpTxbx; - } - - /** - * Set the ccpTxbx field for the FibRgLw95 record. - */ - @Internal - public void setCcpTxbx( int field_12_ccpTxbx ) - { - this.field_12_ccpTxbx = field_12_ccpTxbx; - } - - /** - * Get the ccpHdrTxbx field for the FibRgLw95 record. - */ - @Internal - public int getCcpHdrTxbx() - { - return field_13_ccpHdrTxbx; - } - - /** - * Set the ccpHdrTxbx field for the FibRgLw95 record. - */ - @Internal - public void setCcpHdrTxbx( int field_13_ccpHdrTxbx ) - { - this.field_13_ccpHdrTxbx = field_13_ccpHdrTxbx; - } - - /** - * Get the reserved5 field for the FibRgLw95 record. - */ - @Internal - public int getReserved5() - { - return field_14_reserved5; - } - - /** - * Set the reserved5 field for the FibRgLw95 record. - */ - @Internal - public void setReserved5( int field_14_reserved5 ) - { - this.field_14_reserved5 = field_14_reserved5; - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * The FibRgLw95 structure is the third section of the FIB for Word95. + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov + + */ +@Internal +public abstract class FibRgLw95AbstractType +{ + + protected int field_1_cbMac; + @Deprecated + protected int field_2_reserved1; + @Deprecated + protected int field_3_reserved2; + @Deprecated + protected int field_4_reserved3; + @Deprecated + protected int field_5_reserved4; + protected int field_6_ccpText; + protected int field_7_ccpFtn; + protected int field_8_ccpHdd; + protected int field_9_ccpMcr; + protected int field_10_ccpAtn; + protected int field_11_ccpEdn; + protected int field_12_ccpTxbx; + protected int field_13_ccpHdrTxbx; + @Deprecated + protected int field_14_reserved5; + + protected FibRgLw95AbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_cbMac = LittleEndian.getInt( data, 0x0 + offset ); + field_2_reserved1 = LittleEndian.getInt( data, 0x4 + offset ); + field_3_reserved2 = LittleEndian.getInt( data, 0x8 + offset ); + field_4_reserved3 = LittleEndian.getInt( data, 0xc + offset ); + field_5_reserved4 = LittleEndian.getInt( data, 0x10 + offset ); + field_6_ccpText = LittleEndian.getInt( data, 0x14 + offset ); + field_7_ccpFtn = LittleEndian.getInt( data, 0x18 + offset ); + field_8_ccpHdd = LittleEndian.getInt( data, 0x1c + offset ); + field_9_ccpMcr = LittleEndian.getInt( data, 0x20 + offset ); + field_10_ccpAtn = LittleEndian.getInt( data, 0x24 + offset ); + field_11_ccpEdn = LittleEndian.getInt( data, 0x28 + offset ); + field_12_ccpTxbx = LittleEndian.getInt( data, 0x2c + offset ); + field_13_ccpHdrTxbx = LittleEndian.getInt( data, 0x30 + offset ); + field_14_reserved5 = LittleEndian.getInt( data, 0x34 + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putInt( data, 0x0 + offset, field_1_cbMac ); + LittleEndian.putInt( data, 0x4 + offset, field_2_reserved1 ); + LittleEndian.putInt( data, 0x8 + offset, field_3_reserved2 ); + LittleEndian.putInt( data, 0xc + offset, field_4_reserved3 ); + LittleEndian.putInt( data, 0x10 + offset, field_5_reserved4 ); + LittleEndian.putInt( data, 0x14 + offset, field_6_ccpText ); + LittleEndian.putInt( data, 0x18 + offset, field_7_ccpFtn ); + LittleEndian.putInt( data, 0x1c + offset, field_8_ccpHdd ); + LittleEndian.putInt( data, 0x20 + offset, field_9_ccpMcr ); + LittleEndian.putInt( data, 0x24 + offset, field_10_ccpAtn ); + LittleEndian.putInt( data, 0x28 + offset, field_11_ccpEdn ); + LittleEndian.putInt( data, 0x2c + offset, field_12_ccpTxbx ); + LittleEndian.putInt( data, 0x30 + offset, field_13_ccpHdrTxbx ); + LittleEndian.putInt( data, 0x34 + offset, field_14_reserved5 ); + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4; + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + return true; + if ( obj == null ) + return false; + if ( getClass() != obj.getClass() ) + return false; + FibRgLw95AbstractType other = (FibRgLw95AbstractType) obj; + if ( field_1_cbMac != other.field_1_cbMac ) + return false; + if ( field_2_reserved1 != other.field_2_reserved1 ) + return false; + if ( field_3_reserved2 != other.field_3_reserved2 ) + return false; + if ( field_4_reserved3 != other.field_4_reserved3 ) + return false; + if ( field_5_reserved4 != other.field_5_reserved4 ) + return false; + if ( field_6_ccpText != other.field_6_ccpText ) + return false; + if ( field_7_ccpFtn != other.field_7_ccpFtn ) + return false; + if ( field_8_ccpHdd != other.field_8_ccpHdd ) + return false; + if ( field_9_ccpMcr != other.field_9_ccpMcr ) + return false; + if ( field_10_ccpAtn != other.field_10_ccpAtn ) + return false; + if ( field_11_ccpEdn != other.field_11_ccpEdn ) + return false; + if ( field_12_ccpTxbx != other.field_12_ccpTxbx ) + return false; + if ( field_13_ccpHdrTxbx != other.field_13_ccpHdrTxbx ) + return false; + if ( field_14_reserved5 != other.field_14_reserved5 ) + return false; + return true; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + field_1_cbMac; + result = prime * result + field_2_reserved1; + result = prime * result + field_3_reserved2; + result = prime * result + field_4_reserved3; + result = prime * result + field_5_reserved4; + result = prime * result + field_6_ccpText; + result = prime * result + field_7_ccpFtn; + result = prime * result + field_8_ccpHdd; + result = prime * result + field_9_ccpMcr; + result = prime * result + field_10_ccpAtn; + result = prime * result + field_11_ccpEdn; + result = prime * result + field_12_ccpTxbx; + result = prime * result + field_13_ccpHdrTxbx; + result = prime * result + field_14_reserved5; + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[FibRgLw95]\n"); + builder.append(" .cbMac = "); + builder.append(" (").append(getCbMac()).append(" )\n"); + builder.append(" .reserved1 = "); + builder.append(" (").append(getReserved1()).append(" )\n"); + builder.append(" .reserved2 = "); + builder.append(" (").append(getReserved2()).append(" )\n"); + builder.append(" .reserved3 = "); + builder.append(" (").append(getReserved3()).append(" )\n"); + builder.append(" .reserved4 = "); + builder.append(" (").append(getReserved4()).append(" )\n"); + builder.append(" .ccpText = "); + builder.append(" (").append(getCcpText()).append(" )\n"); + builder.append(" .ccpFtn = "); + builder.append(" (").append(getCcpFtn()).append(" )\n"); + builder.append(" .ccpHdd = "); + builder.append(" (").append(getCcpHdd()).append(" )\n"); + builder.append(" .ccpMcr = "); + builder.append(" (").append(getCcpMcr()).append(" )\n"); + builder.append(" .ccpAtn = "); + builder.append(" (").append(getCcpAtn()).append(" )\n"); + builder.append(" .ccpEdn = "); + builder.append(" (").append(getCcpEdn()).append(" )\n"); + builder.append(" .ccpTxbx = "); + builder.append(" (").append(getCcpTxbx()).append(" )\n"); + builder.append(" .ccpHdrTxbx = "); + builder.append(" (").append(getCcpHdrTxbx()).append(" )\n"); + builder.append(" .reserved5 = "); + builder.append(" (").append(getReserved5()).append(" )\n"); + + builder.append("[/FibRgLw95]\n"); + return builder.toString(); + } + + /** + * Get the cbMac field for the FibRgLw95 record. + */ + @Internal + public int getCbMac() + { + return field_1_cbMac; + } + + /** + * Set the cbMac field for the FibRgLw95 record. + */ + @Internal + public void setCbMac( int field_1_cbMac ) + { + this.field_1_cbMac = field_1_cbMac; + } + + /** + * Get the reserved1 field for the FibRgLw95 record. + */ + @Internal + public int getReserved1() + { + return field_2_reserved1; + } + + /** + * Set the reserved1 field for the FibRgLw95 record. + */ + @Internal + public void setReserved1( int field_2_reserved1 ) + { + this.field_2_reserved1 = field_2_reserved1; + } + + /** + * Get the reserved2 field for the FibRgLw95 record. + */ + @Internal + public int getReserved2() + { + return field_3_reserved2; + } + + /** + * Set the reserved2 field for the FibRgLw95 record. + */ + @Internal + public void setReserved2( int field_3_reserved2 ) + { + this.field_3_reserved2 = field_3_reserved2; + } + + /** + * Get the reserved3 field for the FibRgLw95 record. + */ + @Internal + public int getReserved3() + { + return field_4_reserved3; + } + + /** + * Set the reserved3 field for the FibRgLw95 record. + */ + @Internal + public void setReserved3( int field_4_reserved3 ) + { + this.field_4_reserved3 = field_4_reserved3; + } + + /** + * Get the reserved4 field for the FibRgLw95 record. + */ + @Internal + public int getReserved4() + { + return field_5_reserved4; + } + + /** + * Set the reserved4 field for the FibRgLw95 record. + */ + @Internal + public void setReserved4( int field_5_reserved4 ) + { + this.field_5_reserved4 = field_5_reserved4; + } + + /** + * Get the ccpText field for the FibRgLw95 record. + */ + @Internal + public int getCcpText() + { + return field_6_ccpText; + } + + /** + * Set the ccpText field for the FibRgLw95 record. + */ + @Internal + public void setCcpText( int field_6_ccpText ) + { + this.field_6_ccpText = field_6_ccpText; + } + + /** + * Get the ccpFtn field for the FibRgLw95 record. + */ + @Internal + public int getCcpFtn() + { + return field_7_ccpFtn; + } + + /** + * Set the ccpFtn field for the FibRgLw95 record. + */ + @Internal + public void setCcpFtn( int field_7_ccpFtn ) + { + this.field_7_ccpFtn = field_7_ccpFtn; + } + + /** + * Get the ccpHdd field for the FibRgLw95 record. + */ + @Internal + public int getCcpHdd() + { + return field_8_ccpHdd; + } + + /** + * Set the ccpHdd field for the FibRgLw95 record. + */ + @Internal + public void setCcpHdd( int field_8_ccpHdd ) + { + this.field_8_ccpHdd = field_8_ccpHdd; + } + + /** + * Get the ccpMcr field for the FibRgLw95 record. + */ + @Internal + public int getCcpMcr() + { + return field_9_ccpMcr; + } + + /** + * Set the ccpMcr field for the FibRgLw95 record. + */ + @Internal + public void setCcpMcr( int field_9_ccpMcr ) + { + this.field_9_ccpMcr = field_9_ccpMcr; + } + + /** + * Get the ccpAtn field for the FibRgLw95 record. + */ + @Internal + public int getCcpAtn() + { + return field_10_ccpAtn; + } + + /** + * Set the ccpAtn field for the FibRgLw95 record. + */ + @Internal + public void setCcpAtn( int field_10_ccpAtn ) + { + this.field_10_ccpAtn = field_10_ccpAtn; + } + + /** + * Get the ccpEdn field for the FibRgLw95 record. + */ + @Internal + public int getCcpEdn() + { + return field_11_ccpEdn; + } + + /** + * Set the ccpEdn field for the FibRgLw95 record. + */ + @Internal + public void setCcpEdn( int field_11_ccpEdn ) + { + this.field_11_ccpEdn = field_11_ccpEdn; + } + + /** + * Get the ccpTxbx field for the FibRgLw95 record. + */ + @Internal + public int getCcpTxbx() + { + return field_12_ccpTxbx; + } + + /** + * Set the ccpTxbx field for the FibRgLw95 record. + */ + @Internal + public void setCcpTxbx( int field_12_ccpTxbx ) + { + this.field_12_ccpTxbx = field_12_ccpTxbx; + } + + /** + * Get the ccpHdrTxbx field for the FibRgLw95 record. + */ + @Internal + public int getCcpHdrTxbx() + { + return field_13_ccpHdrTxbx; + } + + /** + * Set the ccpHdrTxbx field for the FibRgLw95 record. + */ + @Internal + public void setCcpHdrTxbx( int field_13_ccpHdrTxbx ) + { + this.field_13_ccpHdrTxbx = field_13_ccpHdrTxbx; + } + + /** + * Get the reserved5 field for the FibRgLw95 record. + */ + @Internal + public int getReserved5() + { + return field_14_reserved5; + } + + /** + * Set the reserved5 field for the FibRgLw95 record. + */ + @Internal + public void setReserved5( int field_14_reserved5 ) + { + this.field_14_reserved5 = field_14_reserved5; + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw97AbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw97AbstractType.java index eee5278103..f81c9bc86f 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw97AbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgLw97AbstractType.java @@ -1,686 +1,686 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * The FibRgLw97 structure is the third section of the FIB. This contains an array of - 4-byte values.

    Class and fields descriptions are quoted from Microsoft Office Word - 97-2007 Binary File Format and [MS-DOC] - v20110608 Word (.doc) Binary File Format - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format - Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format - - */ -@Internal -public abstract class FibRgLw97AbstractType -{ - - protected int field_1_cbMac; - @Deprecated - protected int field_2_reserved1; - @Deprecated - protected int field_3_reserved2; - protected int field_4_ccpText; - protected int field_5_ccpFtn; - protected int field_6_ccpHdd; - @Deprecated - protected int field_7_reserved3; - protected int field_8_ccpAtn; - protected int field_9_ccpEdn; - protected int field_10_ccpTxbx; - protected int field_11_ccpHdrTxbx; - @Deprecated - protected int field_12_reserved4; - @Deprecated - protected int field_13_reserved5; - @Deprecated - protected int field_14_reserved6; - @Deprecated - protected int field_15_reserved7; - @Deprecated - protected int field_16_reserved8; - @Deprecated - protected int field_17_reserved9; - @Deprecated - protected int field_18_reserved10; - @Deprecated - protected int field_19_reserved11; - @Deprecated - protected int field_20_reserved12; - @Deprecated - protected int field_21_reserved13; - @Deprecated - protected int field_22_reserved14; - - protected FibRgLw97AbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_cbMac = LittleEndian.getInt( data, 0x0 + offset ); - field_2_reserved1 = LittleEndian.getInt( data, 0x4 + offset ); - field_3_reserved2 = LittleEndian.getInt( data, 0x8 + offset ); - field_4_ccpText = LittleEndian.getInt( data, 0xc + offset ); - field_5_ccpFtn = LittleEndian.getInt( data, 0x10 + offset ); - field_6_ccpHdd = LittleEndian.getInt( data, 0x14 + offset ); - field_7_reserved3 = LittleEndian.getInt( data, 0x18 + offset ); - field_8_ccpAtn = LittleEndian.getInt( data, 0x1c + offset ); - field_9_ccpEdn = LittleEndian.getInt( data, 0x20 + offset ); - field_10_ccpTxbx = LittleEndian.getInt( data, 0x24 + offset ); - field_11_ccpHdrTxbx = LittleEndian.getInt( data, 0x28 + offset ); - field_12_reserved4 = LittleEndian.getInt( data, 0x2c + offset ); - field_13_reserved5 = LittleEndian.getInt( data, 0x30 + offset ); - field_14_reserved6 = LittleEndian.getInt( data, 0x34 + offset ); - field_15_reserved7 = LittleEndian.getInt( data, 0x38 + offset ); - field_16_reserved8 = LittleEndian.getInt( data, 0x3c + offset ); - field_17_reserved9 = LittleEndian.getInt( data, 0x40 + offset ); - field_18_reserved10 = LittleEndian.getInt( data, 0x44 + offset ); - field_19_reserved11 = LittleEndian.getInt( data, 0x48 + offset ); - field_20_reserved12 = LittleEndian.getInt( data, 0x4c + offset ); - field_21_reserved13 = LittleEndian.getInt( data, 0x50 + offset ); - field_22_reserved14 = LittleEndian.getInt( data, 0x54 + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putInt( data, 0x0 + offset, field_1_cbMac ); - LittleEndian.putInt( data, 0x4 + offset, field_2_reserved1 ); - LittleEndian.putInt( data, 0x8 + offset, field_3_reserved2 ); - LittleEndian.putInt( data, 0xc + offset, field_4_ccpText ); - LittleEndian.putInt( data, 0x10 + offset, field_5_ccpFtn ); - LittleEndian.putInt( data, 0x14 + offset, field_6_ccpHdd ); - LittleEndian.putInt( data, 0x18 + offset, field_7_reserved3 ); - LittleEndian.putInt( data, 0x1c + offset, field_8_ccpAtn ); - LittleEndian.putInt( data, 0x20 + offset, field_9_ccpEdn ); - LittleEndian.putInt( data, 0x24 + offset, field_10_ccpTxbx ); - LittleEndian.putInt( data, 0x28 + offset, field_11_ccpHdrTxbx ); - LittleEndian.putInt( data, 0x2c + offset, field_12_reserved4 ); - LittleEndian.putInt( data, 0x30 + offset, field_13_reserved5 ); - LittleEndian.putInt( data, 0x34 + offset, field_14_reserved6 ); - LittleEndian.putInt( data, 0x38 + offset, field_15_reserved7 ); - LittleEndian.putInt( data, 0x3c + offset, field_16_reserved8 ); - LittleEndian.putInt( data, 0x40 + offset, field_17_reserved9 ); - LittleEndian.putInt( data, 0x44 + offset, field_18_reserved10 ); - LittleEndian.putInt( data, 0x48 + offset, field_19_reserved11 ); - LittleEndian.putInt( data, 0x4c + offset, field_20_reserved12 ); - LittleEndian.putInt( data, 0x50 + offset, field_21_reserved13 ); - LittleEndian.putInt( data, 0x54 + offset, field_22_reserved14 ); - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4; - } - - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - FibRgLw97AbstractType other = (FibRgLw97AbstractType) obj; - if ( field_1_cbMac != other.field_1_cbMac ) - return false; - if ( field_2_reserved1 != other.field_2_reserved1 ) - return false; - if ( field_3_reserved2 != other.field_3_reserved2 ) - return false; - if ( field_4_ccpText != other.field_4_ccpText ) - return false; - if ( field_5_ccpFtn != other.field_5_ccpFtn ) - return false; - if ( field_6_ccpHdd != other.field_6_ccpHdd ) - return false; - if ( field_7_reserved3 != other.field_7_reserved3 ) - return false; - if ( field_8_ccpAtn != other.field_8_ccpAtn ) - return false; - if ( field_9_ccpEdn != other.field_9_ccpEdn ) - return false; - if ( field_10_ccpTxbx != other.field_10_ccpTxbx ) - return false; - if ( field_11_ccpHdrTxbx != other.field_11_ccpHdrTxbx ) - return false; - if ( field_12_reserved4 != other.field_12_reserved4 ) - return false; - if ( field_13_reserved5 != other.field_13_reserved5 ) - return false; - if ( field_14_reserved6 != other.field_14_reserved6 ) - return false; - if ( field_15_reserved7 != other.field_15_reserved7 ) - return false; - if ( field_16_reserved8 != other.field_16_reserved8 ) - return false; - if ( field_17_reserved9 != other.field_17_reserved9 ) - return false; - if ( field_18_reserved10 != other.field_18_reserved10 ) - return false; - if ( field_19_reserved11 != other.field_19_reserved11 ) - return false; - if ( field_20_reserved12 != other.field_20_reserved12 ) - return false; - if ( field_21_reserved13 != other.field_21_reserved13 ) - return false; - if ( field_22_reserved14 != other.field_22_reserved14 ) - return false; - return true; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + field_1_cbMac; - result = prime * result + field_2_reserved1; - result = prime * result + field_3_reserved2; - result = prime * result + field_4_ccpText; - result = prime * result + field_5_ccpFtn; - result = prime * result + field_6_ccpHdd; - result = prime * result + field_7_reserved3; - result = prime * result + field_8_ccpAtn; - result = prime * result + field_9_ccpEdn; - result = prime * result + field_10_ccpTxbx; - result = prime * result + field_11_ccpHdrTxbx; - result = prime * result + field_12_reserved4; - result = prime * result + field_13_reserved5; - result = prime * result + field_14_reserved6; - result = prime * result + field_15_reserved7; - result = prime * result + field_16_reserved8; - result = prime * result + field_17_reserved9; - result = prime * result + field_18_reserved10; - result = prime * result + field_19_reserved11; - result = prime * result + field_20_reserved12; - result = prime * result + field_21_reserved13; - result = prime * result + field_22_reserved14; - return result; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[FibRgLw97]\n"); - builder.append(" .cbMac = "); - builder.append(" (").append(getCbMac()).append(" )\n"); - builder.append(" .reserved1 = "); - builder.append(" (").append(getReserved1()).append(" )\n"); - builder.append(" .reserved2 = "); - builder.append(" (").append(getReserved2()).append(" )\n"); - builder.append(" .ccpText = "); - builder.append(" (").append(getCcpText()).append(" )\n"); - builder.append(" .ccpFtn = "); - builder.append(" (").append(getCcpFtn()).append(" )\n"); - builder.append(" .ccpHdd = "); - builder.append(" (").append(getCcpHdd()).append(" )\n"); - builder.append(" .reserved3 = "); - builder.append(" (").append(getReserved3()).append(" )\n"); - builder.append(" .ccpAtn = "); - builder.append(" (").append(getCcpAtn()).append(" )\n"); - builder.append(" .ccpEdn = "); - builder.append(" (").append(getCcpEdn()).append(" )\n"); - builder.append(" .ccpTxbx = "); - builder.append(" (").append(getCcpTxbx()).append(" )\n"); - builder.append(" .ccpHdrTxbx = "); - builder.append(" (").append(getCcpHdrTxbx()).append(" )\n"); - builder.append(" .reserved4 = "); - builder.append(" (").append(getReserved4()).append(" )\n"); - builder.append(" .reserved5 = "); - builder.append(" (").append(getReserved5()).append(" )\n"); - builder.append(" .reserved6 = "); - builder.append(" (").append(getReserved6()).append(" )\n"); - builder.append(" .reserved7 = "); - builder.append(" (").append(getReserved7()).append(" )\n"); - builder.append(" .reserved8 = "); - builder.append(" (").append(getReserved8()).append(" )\n"); - builder.append(" .reserved9 = "); - builder.append(" (").append(getReserved9()).append(" )\n"); - builder.append(" .reserved10 = "); - builder.append(" (").append(getReserved10()).append(" )\n"); - builder.append(" .reserved11 = "); - builder.append(" (").append(getReserved11()).append(" )\n"); - builder.append(" .reserved12 = "); - builder.append(" (").append(getReserved12()).append(" )\n"); - builder.append(" .reserved13 = "); - builder.append(" (").append(getReserved13()).append(" )\n"); - builder.append(" .reserved14 = "); - builder.append(" (").append(getReserved14()).append(" )\n"); - - builder.append("[/FibRgLw97]\n"); - return builder.toString(); - } - - /** - * Specifies the count of bytes of those written to the WordDocument stream of the file that have any meaning. All bytes in the WordDocument stream at offset cbMac and greater MUST be ignored.. - */ - @Internal - public int getCbMac() - { - return field_1_cbMac; - } - - /** - * Specifies the count of bytes of those written to the WordDocument stream of the file that have any meaning. All bytes in the WordDocument stream at offset cbMac and greater MUST be ignored.. - */ - @Internal - public void setCbMac( int field_1_cbMac ) - { - this.field_1_cbMac = field_1_cbMac; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved1() - { - return field_2_reserved1; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved1( int field_2_reserved1 ) - { - this.field_2_reserved1 = field_2_reserved1; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved2() - { - return field_3_reserved2; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved2( int field_3_reserved2 ) - { - this.field_3_reserved2 = field_3_reserved2; - } - - /** - * A signed integer that specifies the count of CPs in the main document. This value MUST be zero, 1, or greater. - */ - @Internal - public int getCcpText() - { - return field_4_ccpText; - } - - /** - * A signed integer that specifies the count of CPs in the main document. This value MUST be zero, 1, or greater. - */ - @Internal - public void setCcpText( int field_4_ccpText ) - { - this.field_4_ccpText = field_4_ccpText; - } - - /** - * A signed integer that specifies the count of CPs in the footnote subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public int getCcpFtn() - { - return field_5_ccpFtn; - } - - /** - * A signed integer that specifies the count of CPs in the footnote subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public void setCcpFtn( int field_5_ccpFtn ) - { - this.field_5_ccpFtn = field_5_ccpFtn; - } - - /** - * A signed integer that specifies the count of CPs in the header subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public int getCcpHdd() - { - return field_6_ccpHdd; - } - - /** - * A signed integer that specifies the count of CPs in the header subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public void setCcpHdd( int field_6_ccpHdd ) - { - this.field_6_ccpHdd = field_6_ccpHdd; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved3() - { - return field_7_reserved3; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved3( int field_7_reserved3 ) - { - this.field_7_reserved3 = field_7_reserved3; - } - - /** - * A signed integer that specifies the count of CPs in the comment subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public int getCcpAtn() - { - return field_8_ccpAtn; - } - - /** - * A signed integer that specifies the count of CPs in the comment subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public void setCcpAtn( int field_8_ccpAtn ) - { - this.field_8_ccpAtn = field_8_ccpAtn; - } - - /** - * A signed integer that specifies the count of CPs in the endnote subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public int getCcpEdn() - { - return field_9_ccpEdn; - } - - /** - * A signed integer that specifies the count of CPs in the endnote subdocument. This value MUST be zero, 1, or greater. - */ - @Internal - public void setCcpEdn( int field_9_ccpEdn ) - { - this.field_9_ccpEdn = field_9_ccpEdn; - } - - /** - * A signed integer that specifies the count of CPs in the textbox subdocument of the main document. This value MUST be zero, 1, or greater. - */ - @Internal - public int getCcpTxbx() - { - return field_10_ccpTxbx; - } - - /** - * A signed integer that specifies the count of CPs in the textbox subdocument of the main document. This value MUST be zero, 1, or greater. - */ - @Internal - public void setCcpTxbx( int field_10_ccpTxbx ) - { - this.field_10_ccpTxbx = field_10_ccpTxbx; - } - - /** - * A signed integer that specifies the count of CPs in the textbox subdocument of the header. This value MUST be zero, 1, or greater. - */ - @Internal - public int getCcpHdrTxbx() - { - return field_11_ccpHdrTxbx; - } - - /** - * A signed integer that specifies the count of CPs in the textbox subdocument of the header. This value MUST be zero, 1, or greater. - */ - @Internal - public void setCcpHdrTxbx( int field_11_ccpHdrTxbx ) - { - this.field_11_ccpHdrTxbx = field_11_ccpHdrTxbx; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved4() - { - return field_12_reserved4; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved4( int field_12_reserved4 ) - { - this.field_12_reserved4 = field_12_reserved4; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved5() - { - return field_13_reserved5; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved5( int field_13_reserved5 ) - { - this.field_13_reserved5 = field_13_reserved5; - } - - /** - * This value MUST be equal or less than the number of data elements in PlcBteChpx, as specified by FibRgFcLcb97.fcPlcfBteChpx and FibRgFcLcb97.lcbPlcfBteChpx. This value MUST be ignored. - */ - @Internal - public int getReserved6() - { - return field_14_reserved6; - } - - /** - * This value MUST be equal or less than the number of data elements in PlcBteChpx, as specified by FibRgFcLcb97.fcPlcfBteChpx and FibRgFcLcb97.lcbPlcfBteChpx. This value MUST be ignored. - */ - @Internal - public void setReserved6( int field_14_reserved6 ) - { - this.field_14_reserved6 = field_14_reserved6; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved7() - { - return field_15_reserved7; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved7( int field_15_reserved7 ) - { - this.field_15_reserved7 = field_15_reserved7; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved8() - { - return field_16_reserved8; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved8( int field_16_reserved8 ) - { - this.field_16_reserved8 = field_16_reserved8; - } - - /** - * This value MUST be less than or equal to the number of data elements in PlcBtePapx, as specified by FibRgFcLcb97.fcPlcfBtePapx and FibRgFcLcb97.lcbPlcfBtePapx. This value MUST be ignored. - */ - @Internal - public int getReserved9() - { - return field_17_reserved9; - } - - /** - * This value MUST be less than or equal to the number of data elements in PlcBtePapx, as specified by FibRgFcLcb97.fcPlcfBtePapx and FibRgFcLcb97.lcbPlcfBtePapx. This value MUST be ignored. - */ - @Internal - public void setReserved9( int field_17_reserved9 ) - { - this.field_17_reserved9 = field_17_reserved9; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved10() - { - return field_18_reserved10; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved10( int field_18_reserved10 ) - { - this.field_18_reserved10 = field_18_reserved10; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public int getReserved11() - { - return field_19_reserved11; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved11( int field_19_reserved11 ) - { - this.field_19_reserved11 = field_19_reserved11; - } - - /** - * This value SHOULD be zero, and MUST be ignored. - */ - @Internal - public int getReserved12() - { - return field_20_reserved12; - } - - /** - * This value SHOULD be zero, and MUST be ignored. - */ - @Internal - public void setReserved12( int field_20_reserved12 ) - { - this.field_20_reserved12 = field_20_reserved12; - } - - /** - * This value MUST be zero and MUST be ignored. - */ - @Internal - public int getReserved13() - { - return field_21_reserved13; - } - - /** - * This value MUST be zero and MUST be ignored. - */ - @Internal - public void setReserved13( int field_21_reserved13 ) - { - this.field_21_reserved13 = field_21_reserved13; - } - - /** - * This value MUST be zero and MUST be ignored. - */ - @Internal - public int getReserved14() - { - return field_22_reserved14; - } - - /** - * This value MUST be zero and MUST be ignored. - */ - @Internal - public void setReserved14( int field_22_reserved14 ) - { - this.field_22_reserved14 = field_22_reserved14; - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * The FibRgLw97 structure is the third section of the FIB. This contains an array of + 4-byte values.

    Class and fields descriptions are quoted from Microsoft Office Word + 97-2007 Binary File Format and [MS-DOC] - v20110608 Word (.doc) Binary File Format + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format + Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format + + */ +@Internal +public abstract class FibRgLw97AbstractType +{ + + protected int field_1_cbMac; + @Deprecated + protected int field_2_reserved1; + @Deprecated + protected int field_3_reserved2; + protected int field_4_ccpText; + protected int field_5_ccpFtn; + protected int field_6_ccpHdd; + @Deprecated + protected int field_7_reserved3; + protected int field_8_ccpAtn; + protected int field_9_ccpEdn; + protected int field_10_ccpTxbx; + protected int field_11_ccpHdrTxbx; + @Deprecated + protected int field_12_reserved4; + @Deprecated + protected int field_13_reserved5; + @Deprecated + protected int field_14_reserved6; + @Deprecated + protected int field_15_reserved7; + @Deprecated + protected int field_16_reserved8; + @Deprecated + protected int field_17_reserved9; + @Deprecated + protected int field_18_reserved10; + @Deprecated + protected int field_19_reserved11; + @Deprecated + protected int field_20_reserved12; + @Deprecated + protected int field_21_reserved13; + @Deprecated + protected int field_22_reserved14; + + protected FibRgLw97AbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_cbMac = LittleEndian.getInt( data, 0x0 + offset ); + field_2_reserved1 = LittleEndian.getInt( data, 0x4 + offset ); + field_3_reserved2 = LittleEndian.getInt( data, 0x8 + offset ); + field_4_ccpText = LittleEndian.getInt( data, 0xc + offset ); + field_5_ccpFtn = LittleEndian.getInt( data, 0x10 + offset ); + field_6_ccpHdd = LittleEndian.getInt( data, 0x14 + offset ); + field_7_reserved3 = LittleEndian.getInt( data, 0x18 + offset ); + field_8_ccpAtn = LittleEndian.getInt( data, 0x1c + offset ); + field_9_ccpEdn = LittleEndian.getInt( data, 0x20 + offset ); + field_10_ccpTxbx = LittleEndian.getInt( data, 0x24 + offset ); + field_11_ccpHdrTxbx = LittleEndian.getInt( data, 0x28 + offset ); + field_12_reserved4 = LittleEndian.getInt( data, 0x2c + offset ); + field_13_reserved5 = LittleEndian.getInt( data, 0x30 + offset ); + field_14_reserved6 = LittleEndian.getInt( data, 0x34 + offset ); + field_15_reserved7 = LittleEndian.getInt( data, 0x38 + offset ); + field_16_reserved8 = LittleEndian.getInt( data, 0x3c + offset ); + field_17_reserved9 = LittleEndian.getInt( data, 0x40 + offset ); + field_18_reserved10 = LittleEndian.getInt( data, 0x44 + offset ); + field_19_reserved11 = LittleEndian.getInt( data, 0x48 + offset ); + field_20_reserved12 = LittleEndian.getInt( data, 0x4c + offset ); + field_21_reserved13 = LittleEndian.getInt( data, 0x50 + offset ); + field_22_reserved14 = LittleEndian.getInt( data, 0x54 + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putInt( data, 0x0 + offset, field_1_cbMac ); + LittleEndian.putInt( data, 0x4 + offset, field_2_reserved1 ); + LittleEndian.putInt( data, 0x8 + offset, field_3_reserved2 ); + LittleEndian.putInt( data, 0xc + offset, field_4_ccpText ); + LittleEndian.putInt( data, 0x10 + offset, field_5_ccpFtn ); + LittleEndian.putInt( data, 0x14 + offset, field_6_ccpHdd ); + LittleEndian.putInt( data, 0x18 + offset, field_7_reserved3 ); + LittleEndian.putInt( data, 0x1c + offset, field_8_ccpAtn ); + LittleEndian.putInt( data, 0x20 + offset, field_9_ccpEdn ); + LittleEndian.putInt( data, 0x24 + offset, field_10_ccpTxbx ); + LittleEndian.putInt( data, 0x28 + offset, field_11_ccpHdrTxbx ); + LittleEndian.putInt( data, 0x2c + offset, field_12_reserved4 ); + LittleEndian.putInt( data, 0x30 + offset, field_13_reserved5 ); + LittleEndian.putInt( data, 0x34 + offset, field_14_reserved6 ); + LittleEndian.putInt( data, 0x38 + offset, field_15_reserved7 ); + LittleEndian.putInt( data, 0x3c + offset, field_16_reserved8 ); + LittleEndian.putInt( data, 0x40 + offset, field_17_reserved9 ); + LittleEndian.putInt( data, 0x44 + offset, field_18_reserved10 ); + LittleEndian.putInt( data, 0x48 + offset, field_19_reserved11 ); + LittleEndian.putInt( data, 0x4c + offset, field_20_reserved12 ); + LittleEndian.putInt( data, 0x50 + offset, field_21_reserved13 ); + LittleEndian.putInt( data, 0x54 + offset, field_22_reserved14 ); + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4; + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + return true; + if ( obj == null ) + return false; + if ( getClass() != obj.getClass() ) + return false; + FibRgLw97AbstractType other = (FibRgLw97AbstractType) obj; + if ( field_1_cbMac != other.field_1_cbMac ) + return false; + if ( field_2_reserved1 != other.field_2_reserved1 ) + return false; + if ( field_3_reserved2 != other.field_3_reserved2 ) + return false; + if ( field_4_ccpText != other.field_4_ccpText ) + return false; + if ( field_5_ccpFtn != other.field_5_ccpFtn ) + return false; + if ( field_6_ccpHdd != other.field_6_ccpHdd ) + return false; + if ( field_7_reserved3 != other.field_7_reserved3 ) + return false; + if ( field_8_ccpAtn != other.field_8_ccpAtn ) + return false; + if ( field_9_ccpEdn != other.field_9_ccpEdn ) + return false; + if ( field_10_ccpTxbx != other.field_10_ccpTxbx ) + return false; + if ( field_11_ccpHdrTxbx != other.field_11_ccpHdrTxbx ) + return false; + if ( field_12_reserved4 != other.field_12_reserved4 ) + return false; + if ( field_13_reserved5 != other.field_13_reserved5 ) + return false; + if ( field_14_reserved6 != other.field_14_reserved6 ) + return false; + if ( field_15_reserved7 != other.field_15_reserved7 ) + return false; + if ( field_16_reserved8 != other.field_16_reserved8 ) + return false; + if ( field_17_reserved9 != other.field_17_reserved9 ) + return false; + if ( field_18_reserved10 != other.field_18_reserved10 ) + return false; + if ( field_19_reserved11 != other.field_19_reserved11 ) + return false; + if ( field_20_reserved12 != other.field_20_reserved12 ) + return false; + if ( field_21_reserved13 != other.field_21_reserved13 ) + return false; + if ( field_22_reserved14 != other.field_22_reserved14 ) + return false; + return true; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + field_1_cbMac; + result = prime * result + field_2_reserved1; + result = prime * result + field_3_reserved2; + result = prime * result + field_4_ccpText; + result = prime * result + field_5_ccpFtn; + result = prime * result + field_6_ccpHdd; + result = prime * result + field_7_reserved3; + result = prime * result + field_8_ccpAtn; + result = prime * result + field_9_ccpEdn; + result = prime * result + field_10_ccpTxbx; + result = prime * result + field_11_ccpHdrTxbx; + result = prime * result + field_12_reserved4; + result = prime * result + field_13_reserved5; + result = prime * result + field_14_reserved6; + result = prime * result + field_15_reserved7; + result = prime * result + field_16_reserved8; + result = prime * result + field_17_reserved9; + result = prime * result + field_18_reserved10; + result = prime * result + field_19_reserved11; + result = prime * result + field_20_reserved12; + result = prime * result + field_21_reserved13; + result = prime * result + field_22_reserved14; + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[FibRgLw97]\n"); + builder.append(" .cbMac = "); + builder.append(" (").append(getCbMac()).append(" )\n"); + builder.append(" .reserved1 = "); + builder.append(" (").append(getReserved1()).append(" )\n"); + builder.append(" .reserved2 = "); + builder.append(" (").append(getReserved2()).append(" )\n"); + builder.append(" .ccpText = "); + builder.append(" (").append(getCcpText()).append(" )\n"); + builder.append(" .ccpFtn = "); + builder.append(" (").append(getCcpFtn()).append(" )\n"); + builder.append(" .ccpHdd = "); + builder.append(" (").append(getCcpHdd()).append(" )\n"); + builder.append(" .reserved3 = "); + builder.append(" (").append(getReserved3()).append(" )\n"); + builder.append(" .ccpAtn = "); + builder.append(" (").append(getCcpAtn()).append(" )\n"); + builder.append(" .ccpEdn = "); + builder.append(" (").append(getCcpEdn()).append(" )\n"); + builder.append(" .ccpTxbx = "); + builder.append(" (").append(getCcpTxbx()).append(" )\n"); + builder.append(" .ccpHdrTxbx = "); + builder.append(" (").append(getCcpHdrTxbx()).append(" )\n"); + builder.append(" .reserved4 = "); + builder.append(" (").append(getReserved4()).append(" )\n"); + builder.append(" .reserved5 = "); + builder.append(" (").append(getReserved5()).append(" )\n"); + builder.append(" .reserved6 = "); + builder.append(" (").append(getReserved6()).append(" )\n"); + builder.append(" .reserved7 = "); + builder.append(" (").append(getReserved7()).append(" )\n"); + builder.append(" .reserved8 = "); + builder.append(" (").append(getReserved8()).append(" )\n"); + builder.append(" .reserved9 = "); + builder.append(" (").append(getReserved9()).append(" )\n"); + builder.append(" .reserved10 = "); + builder.append(" (").append(getReserved10()).append(" )\n"); + builder.append(" .reserved11 = "); + builder.append(" (").append(getReserved11()).append(" )\n"); + builder.append(" .reserved12 = "); + builder.append(" (").append(getReserved12()).append(" )\n"); + builder.append(" .reserved13 = "); + builder.append(" (").append(getReserved13()).append(" )\n"); + builder.append(" .reserved14 = "); + builder.append(" (").append(getReserved14()).append(" )\n"); + + builder.append("[/FibRgLw97]\n"); + return builder.toString(); + } + + /** + * Specifies the count of bytes of those written to the WordDocument stream of the file that have any meaning. All bytes in the WordDocument stream at offset cbMac and greater MUST be ignored.. + */ + @Internal + public int getCbMac() + { + return field_1_cbMac; + } + + /** + * Specifies the count of bytes of those written to the WordDocument stream of the file that have any meaning. All bytes in the WordDocument stream at offset cbMac and greater MUST be ignored.. + */ + @Internal + public void setCbMac( int field_1_cbMac ) + { + this.field_1_cbMac = field_1_cbMac; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved1() + { + return field_2_reserved1; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved1( int field_2_reserved1 ) + { + this.field_2_reserved1 = field_2_reserved1; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved2() + { + return field_3_reserved2; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved2( int field_3_reserved2 ) + { + this.field_3_reserved2 = field_3_reserved2; + } + + /** + * A signed integer that specifies the count of CPs in the main document. This value MUST be zero, 1, or greater. + */ + @Internal + public int getCcpText() + { + return field_4_ccpText; + } + + /** + * A signed integer that specifies the count of CPs in the main document. This value MUST be zero, 1, or greater. + */ + @Internal + public void setCcpText( int field_4_ccpText ) + { + this.field_4_ccpText = field_4_ccpText; + } + + /** + * A signed integer that specifies the count of CPs in the footnote subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public int getCcpFtn() + { + return field_5_ccpFtn; + } + + /** + * A signed integer that specifies the count of CPs in the footnote subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public void setCcpFtn( int field_5_ccpFtn ) + { + this.field_5_ccpFtn = field_5_ccpFtn; + } + + /** + * A signed integer that specifies the count of CPs in the header subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public int getCcpHdd() + { + return field_6_ccpHdd; + } + + /** + * A signed integer that specifies the count of CPs in the header subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public void setCcpHdd( int field_6_ccpHdd ) + { + this.field_6_ccpHdd = field_6_ccpHdd; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved3() + { + return field_7_reserved3; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved3( int field_7_reserved3 ) + { + this.field_7_reserved3 = field_7_reserved3; + } + + /** + * A signed integer that specifies the count of CPs in the comment subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public int getCcpAtn() + { + return field_8_ccpAtn; + } + + /** + * A signed integer that specifies the count of CPs in the comment subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public void setCcpAtn( int field_8_ccpAtn ) + { + this.field_8_ccpAtn = field_8_ccpAtn; + } + + /** + * A signed integer that specifies the count of CPs in the endnote subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public int getCcpEdn() + { + return field_9_ccpEdn; + } + + /** + * A signed integer that specifies the count of CPs in the endnote subdocument. This value MUST be zero, 1, or greater. + */ + @Internal + public void setCcpEdn( int field_9_ccpEdn ) + { + this.field_9_ccpEdn = field_9_ccpEdn; + } + + /** + * A signed integer that specifies the count of CPs in the textbox subdocument of the main document. This value MUST be zero, 1, or greater. + */ + @Internal + public int getCcpTxbx() + { + return field_10_ccpTxbx; + } + + /** + * A signed integer that specifies the count of CPs in the textbox subdocument of the main document. This value MUST be zero, 1, or greater. + */ + @Internal + public void setCcpTxbx( int field_10_ccpTxbx ) + { + this.field_10_ccpTxbx = field_10_ccpTxbx; + } + + /** + * A signed integer that specifies the count of CPs in the textbox subdocument of the header. This value MUST be zero, 1, or greater. + */ + @Internal + public int getCcpHdrTxbx() + { + return field_11_ccpHdrTxbx; + } + + /** + * A signed integer that specifies the count of CPs in the textbox subdocument of the header. This value MUST be zero, 1, or greater. + */ + @Internal + public void setCcpHdrTxbx( int field_11_ccpHdrTxbx ) + { + this.field_11_ccpHdrTxbx = field_11_ccpHdrTxbx; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved4() + { + return field_12_reserved4; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved4( int field_12_reserved4 ) + { + this.field_12_reserved4 = field_12_reserved4; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved5() + { + return field_13_reserved5; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved5( int field_13_reserved5 ) + { + this.field_13_reserved5 = field_13_reserved5; + } + + /** + * This value MUST be equal or less than the number of data elements in PlcBteChpx, as specified by FibRgFcLcb97.fcPlcfBteChpx and FibRgFcLcb97.lcbPlcfBteChpx. This value MUST be ignored. + */ + @Internal + public int getReserved6() + { + return field_14_reserved6; + } + + /** + * This value MUST be equal or less than the number of data elements in PlcBteChpx, as specified by FibRgFcLcb97.fcPlcfBteChpx and FibRgFcLcb97.lcbPlcfBteChpx. This value MUST be ignored. + */ + @Internal + public void setReserved6( int field_14_reserved6 ) + { + this.field_14_reserved6 = field_14_reserved6; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved7() + { + return field_15_reserved7; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved7( int field_15_reserved7 ) + { + this.field_15_reserved7 = field_15_reserved7; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved8() + { + return field_16_reserved8; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved8( int field_16_reserved8 ) + { + this.field_16_reserved8 = field_16_reserved8; + } + + /** + * This value MUST be less than or equal to the number of data elements in PlcBtePapx, as specified by FibRgFcLcb97.fcPlcfBtePapx and FibRgFcLcb97.lcbPlcfBtePapx. This value MUST be ignored. + */ + @Internal + public int getReserved9() + { + return field_17_reserved9; + } + + /** + * This value MUST be less than or equal to the number of data elements in PlcBtePapx, as specified by FibRgFcLcb97.fcPlcfBtePapx and FibRgFcLcb97.lcbPlcfBtePapx. This value MUST be ignored. + */ + @Internal + public void setReserved9( int field_17_reserved9 ) + { + this.field_17_reserved9 = field_17_reserved9; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved10() + { + return field_18_reserved10; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved10( int field_18_reserved10 ) + { + this.field_18_reserved10 = field_18_reserved10; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public int getReserved11() + { + return field_19_reserved11; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved11( int field_19_reserved11 ) + { + this.field_19_reserved11 = field_19_reserved11; + } + + /** + * This value SHOULD be zero, and MUST be ignored. + */ + @Internal + public int getReserved12() + { + return field_20_reserved12; + } + + /** + * This value SHOULD be zero, and MUST be ignored. + */ + @Internal + public void setReserved12( int field_20_reserved12 ) + { + this.field_20_reserved12 = field_20_reserved12; + } + + /** + * This value MUST be zero and MUST be ignored. + */ + @Internal + public int getReserved13() + { + return field_21_reserved13; + } + + /** + * This value MUST be zero and MUST be ignored. + */ + @Internal + public void setReserved13( int field_21_reserved13 ) + { + this.field_21_reserved13 = field_21_reserved13; + } + + /** + * This value MUST be zero and MUST be ignored. + */ + @Internal + public int getReserved14() + { + return field_22_reserved14; + } + + /** + * This value MUST be zero and MUST be ignored. + */ + @Internal + public void setReserved14( int field_22_reserved14 ) + { + this.field_22_reserved14 = field_22_reserved14; + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgW97AbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgW97AbstractType.java index 6dbc944670..21d2e4ae13 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgW97AbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FibRgW97AbstractType.java @@ -1,415 +1,415 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model.types; - - -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * The FibRgW97 structure is a variable-length portion of the Fib.

    Class and - fields descriptions are quoted from Microsoft Office Word 97-2007 Binary File Format and - [MS-DOC] - v20110608 Word (.doc) Binary File Format - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format - Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format - - */ -@Internal -public abstract class FibRgW97AbstractType -{ - - @Deprecated - protected short field_1_reserved1; - @Deprecated - protected short field_2_reserved2; - @Deprecated - protected short field_3_reserved3; - @Deprecated - protected short field_4_reserved4; - @Deprecated - protected short field_5_reserved5; - @Deprecated - protected short field_6_reserved6; - @Deprecated - protected short field_7_reserved7; - @Deprecated - protected short field_8_reserved8; - @Deprecated - protected short field_9_reserved9; - @Deprecated - protected short field_10_reserved10; - @Deprecated - protected short field_11_reserved11; - @Deprecated - protected short field_12_reserved12; - @Deprecated - protected short field_13_reserved13; - protected short field_14_lidFE; - - protected FibRgW97AbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_reserved1 = LittleEndian.getShort( data, 0x0 + offset ); - field_2_reserved2 = LittleEndian.getShort( data, 0x2 + offset ); - field_3_reserved3 = LittleEndian.getShort( data, 0x4 + offset ); - field_4_reserved4 = LittleEndian.getShort( data, 0x6 + offset ); - field_5_reserved5 = LittleEndian.getShort( data, 0x8 + offset ); - field_6_reserved6 = LittleEndian.getShort( data, 0xa + offset ); - field_7_reserved7 = LittleEndian.getShort( data, 0xc + offset ); - field_8_reserved8 = LittleEndian.getShort( data, 0xe + offset ); - field_9_reserved9 = LittleEndian.getShort( data, 0x10 + offset ); - field_10_reserved10 = LittleEndian.getShort( data, 0x12 + offset ); - field_11_reserved11 = LittleEndian.getShort( data, 0x14 + offset ); - field_12_reserved12 = LittleEndian.getShort( data, 0x16 + offset ); - field_13_reserved13 = LittleEndian.getShort( data, 0x18 + offset ); - field_14_lidFE = LittleEndian.getShort( data, 0x1a + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putShort( data, 0x0 + offset, field_1_reserved1 ); - LittleEndian.putShort( data, 0x2 + offset, field_2_reserved2 ); - LittleEndian.putShort( data, 0x4 + offset, field_3_reserved3 ); - LittleEndian.putShort( data, 0x6 + offset, field_4_reserved4 ); - LittleEndian.putShort( data, 0x8 + offset, field_5_reserved5 ); - LittleEndian.putShort( data, 0xa + offset, field_6_reserved6 ); - LittleEndian.putShort( data, 0xc + offset, field_7_reserved7 ); - LittleEndian.putShort( data, 0xe + offset, field_8_reserved8 ); - LittleEndian.putShort( data, 0x10 + offset, field_9_reserved9 ); - LittleEndian.putShort( data, 0x12 + offset, field_10_reserved10 ); - LittleEndian.putShort( data, 0x14 + offset, field_11_reserved11 ); - LittleEndian.putShort( data, 0x16 + offset, field_12_reserved12 ); - LittleEndian.putShort( data, 0x18 + offset, field_13_reserved13 ); - LittleEndian.putShort( data, 0x1a + offset, field_14_lidFE ); - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[FibRgW97]\n"); - builder.append(" .reserved1 = "); - builder.append(" (").append(getReserved1()).append(" )\n"); - builder.append(" .reserved2 = "); - builder.append(" (").append(getReserved2()).append(" )\n"); - builder.append(" .reserved3 = "); - builder.append(" (").append(getReserved3()).append(" )\n"); - builder.append(" .reserved4 = "); - builder.append(" (").append(getReserved4()).append(" )\n"); - builder.append(" .reserved5 = "); - builder.append(" (").append(getReserved5()).append(" )\n"); - builder.append(" .reserved6 = "); - builder.append(" (").append(getReserved6()).append(" )\n"); - builder.append(" .reserved7 = "); - builder.append(" (").append(getReserved7()).append(" )\n"); - builder.append(" .reserved8 = "); - builder.append(" (").append(getReserved8()).append(" )\n"); - builder.append(" .reserved9 = "); - builder.append(" (").append(getReserved9()).append(" )\n"); - builder.append(" .reserved10 = "); - builder.append(" (").append(getReserved10()).append(" )\n"); - builder.append(" .reserved11 = "); - builder.append(" (").append(getReserved11()).append(" )\n"); - builder.append(" .reserved12 = "); - builder.append(" (").append(getReserved12()).append(" )\n"); - builder.append(" .reserved13 = "); - builder.append(" (").append(getReserved13()).append(" )\n"); - builder.append(" .lidFE = "); - builder.append(" (").append(getLidFE()).append(" )\n"); - - builder.append("[/FibRgW97]\n"); - return builder.toString(); - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved1() - { - return field_1_reserved1; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved1( short field_1_reserved1 ) - { - this.field_1_reserved1 = field_1_reserved1; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved2() - { - return field_2_reserved2; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved2( short field_2_reserved2 ) - { - this.field_2_reserved2 = field_2_reserved2; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved3() - { - return field_3_reserved3; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved3( short field_3_reserved3 ) - { - this.field_3_reserved3 = field_3_reserved3; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved4() - { - return field_4_reserved4; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved4( short field_4_reserved4 ) - { - this.field_4_reserved4 = field_4_reserved4; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved5() - { - return field_5_reserved5; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved5( short field_5_reserved5 ) - { - this.field_5_reserved5 = field_5_reserved5; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved6() - { - return field_6_reserved6; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved6( short field_6_reserved6 ) - { - this.field_6_reserved6 = field_6_reserved6; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved7() - { - return field_7_reserved7; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved7( short field_7_reserved7 ) - { - this.field_7_reserved7 = field_7_reserved7; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved8() - { - return field_8_reserved8; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved8( short field_8_reserved8 ) - { - this.field_8_reserved8 = field_8_reserved8; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved9() - { - return field_9_reserved9; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved9( short field_9_reserved9 ) - { - this.field_9_reserved9 = field_9_reserved9; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved10() - { - return field_10_reserved10; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved10( short field_10_reserved10 ) - { - this.field_10_reserved10 = field_10_reserved10; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved11() - { - return field_11_reserved11; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved11( short field_11_reserved11 ) - { - this.field_11_reserved11 = field_11_reserved11; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved12() - { - return field_12_reserved12; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved12( short field_12_reserved12 ) - { - this.field_12_reserved12 = field_12_reserved12; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public short getReserved13() - { - return field_13_reserved13; - } - - /** - * This value is undefined and MUST be ignored. - */ - @Internal - public void setReserved13( short field_13_reserved13 ) - { - this.field_13_reserved13 = field_13_reserved13; - } - - /** - * A LID whose meaning depends on the nFib value. - */ - @Internal - public short getLidFE() - { - return field_14_lidFE; - } - - /** - * A LID whose meaning depends on the nFib value. - */ - @Internal - public void setLidFE( short field_14_lidFE ) - { - this.field_14_lidFE = field_14_lidFE; - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model.types; + + +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * The FibRgW97 structure is a variable-length portion of the Fib.

    Class and + fields descriptions are quoted from Microsoft Office Word 97-2007 Binary File Format and + [MS-DOC] - v20110608 Word (.doc) Binary File Format + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format + Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format + + */ +@Internal +public abstract class FibRgW97AbstractType +{ + + @Deprecated + protected short field_1_reserved1; + @Deprecated + protected short field_2_reserved2; + @Deprecated + protected short field_3_reserved3; + @Deprecated + protected short field_4_reserved4; + @Deprecated + protected short field_5_reserved5; + @Deprecated + protected short field_6_reserved6; + @Deprecated + protected short field_7_reserved7; + @Deprecated + protected short field_8_reserved8; + @Deprecated + protected short field_9_reserved9; + @Deprecated + protected short field_10_reserved10; + @Deprecated + protected short field_11_reserved11; + @Deprecated + protected short field_12_reserved12; + @Deprecated + protected short field_13_reserved13; + protected short field_14_lidFE; + + protected FibRgW97AbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_reserved1 = LittleEndian.getShort( data, 0x0 + offset ); + field_2_reserved2 = LittleEndian.getShort( data, 0x2 + offset ); + field_3_reserved3 = LittleEndian.getShort( data, 0x4 + offset ); + field_4_reserved4 = LittleEndian.getShort( data, 0x6 + offset ); + field_5_reserved5 = LittleEndian.getShort( data, 0x8 + offset ); + field_6_reserved6 = LittleEndian.getShort( data, 0xa + offset ); + field_7_reserved7 = LittleEndian.getShort( data, 0xc + offset ); + field_8_reserved8 = LittleEndian.getShort( data, 0xe + offset ); + field_9_reserved9 = LittleEndian.getShort( data, 0x10 + offset ); + field_10_reserved10 = LittleEndian.getShort( data, 0x12 + offset ); + field_11_reserved11 = LittleEndian.getShort( data, 0x14 + offset ); + field_12_reserved12 = LittleEndian.getShort( data, 0x16 + offset ); + field_13_reserved13 = LittleEndian.getShort( data, 0x18 + offset ); + field_14_lidFE = LittleEndian.getShort( data, 0x1a + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putShort( data, 0x0 + offset, field_1_reserved1 ); + LittleEndian.putShort( data, 0x2 + offset, field_2_reserved2 ); + LittleEndian.putShort( data, 0x4 + offset, field_3_reserved3 ); + LittleEndian.putShort( data, 0x6 + offset, field_4_reserved4 ); + LittleEndian.putShort( data, 0x8 + offset, field_5_reserved5 ); + LittleEndian.putShort( data, 0xa + offset, field_6_reserved6 ); + LittleEndian.putShort( data, 0xc + offset, field_7_reserved7 ); + LittleEndian.putShort( data, 0xe + offset, field_8_reserved8 ); + LittleEndian.putShort( data, 0x10 + offset, field_9_reserved9 ); + LittleEndian.putShort( data, 0x12 + offset, field_10_reserved10 ); + LittleEndian.putShort( data, 0x14 + offset, field_11_reserved11 ); + LittleEndian.putShort( data, 0x16 + offset, field_12_reserved12 ); + LittleEndian.putShort( data, 0x18 + offset, field_13_reserved13 ); + LittleEndian.putShort( data, 0x1a + offset, field_14_lidFE ); + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[FibRgW97]\n"); + builder.append(" .reserved1 = "); + builder.append(" (").append(getReserved1()).append(" )\n"); + builder.append(" .reserved2 = "); + builder.append(" (").append(getReserved2()).append(" )\n"); + builder.append(" .reserved3 = "); + builder.append(" (").append(getReserved3()).append(" )\n"); + builder.append(" .reserved4 = "); + builder.append(" (").append(getReserved4()).append(" )\n"); + builder.append(" .reserved5 = "); + builder.append(" (").append(getReserved5()).append(" )\n"); + builder.append(" .reserved6 = "); + builder.append(" (").append(getReserved6()).append(" )\n"); + builder.append(" .reserved7 = "); + builder.append(" (").append(getReserved7()).append(" )\n"); + builder.append(" .reserved8 = "); + builder.append(" (").append(getReserved8()).append(" )\n"); + builder.append(" .reserved9 = "); + builder.append(" (").append(getReserved9()).append(" )\n"); + builder.append(" .reserved10 = "); + builder.append(" (").append(getReserved10()).append(" )\n"); + builder.append(" .reserved11 = "); + builder.append(" (").append(getReserved11()).append(" )\n"); + builder.append(" .reserved12 = "); + builder.append(" (").append(getReserved12()).append(" )\n"); + builder.append(" .reserved13 = "); + builder.append(" (").append(getReserved13()).append(" )\n"); + builder.append(" .lidFE = "); + builder.append(" (").append(getLidFE()).append(" )\n"); + + builder.append("[/FibRgW97]\n"); + return builder.toString(); + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved1() + { + return field_1_reserved1; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved1( short field_1_reserved1 ) + { + this.field_1_reserved1 = field_1_reserved1; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved2() + { + return field_2_reserved2; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved2( short field_2_reserved2 ) + { + this.field_2_reserved2 = field_2_reserved2; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved3() + { + return field_3_reserved3; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved3( short field_3_reserved3 ) + { + this.field_3_reserved3 = field_3_reserved3; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved4() + { + return field_4_reserved4; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved4( short field_4_reserved4 ) + { + this.field_4_reserved4 = field_4_reserved4; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved5() + { + return field_5_reserved5; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved5( short field_5_reserved5 ) + { + this.field_5_reserved5 = field_5_reserved5; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved6() + { + return field_6_reserved6; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved6( short field_6_reserved6 ) + { + this.field_6_reserved6 = field_6_reserved6; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved7() + { + return field_7_reserved7; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved7( short field_7_reserved7 ) + { + this.field_7_reserved7 = field_7_reserved7; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved8() + { + return field_8_reserved8; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved8( short field_8_reserved8 ) + { + this.field_8_reserved8 = field_8_reserved8; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved9() + { + return field_9_reserved9; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved9( short field_9_reserved9 ) + { + this.field_9_reserved9 = field_9_reserved9; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved10() + { + return field_10_reserved10; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved10( short field_10_reserved10 ) + { + this.field_10_reserved10 = field_10_reserved10; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved11() + { + return field_11_reserved11; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved11( short field_11_reserved11 ) + { + this.field_11_reserved11 = field_11_reserved11; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved12() + { + return field_12_reserved12; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved12( short field_12_reserved12 ) + { + this.field_12_reserved12 = field_12_reserved12; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public short getReserved13() + { + return field_13_reserved13; + } + + /** + * This value is undefined and MUST be ignored. + */ + @Internal + public void setReserved13( short field_13_reserved13 ) + { + this.field_13_reserved13 = field_13_reserved13; + } + + /** + * A LID whose meaning depends on the nFib value. + */ + @Internal + public short getLidFE() + { + return field_14_lidFE; + } + + /** + * A LID whose meaning depends on the nFib value. + */ + @Internal + public void setLidFE( short field_14_lidFE ) + { + this.field_14_lidFE = field_14_lidFE; + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java index 511f9224ee..8aace00d85 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java @@ -1,307 +1,307 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model.types; - - -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; - -/** - * The grfhic structure is a set of HTML incompatibility flags that specify the HTML - incompatibilities of a list structure. The values specify possible incompatibilities between - an LVL or LVLF and HTML lists. The values do not define list properties.

    Class and - fields descriptions are quoted from [MS-DOC] -- v20110315 Word (.doc) Binary File Format - specification - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to [MS-DOC] -- v20110315 Word (.doc) Binary File Format - specification - - */ -@Internal -public abstract class GrfhicAbstractType -{ - - protected byte field_1_grfhic; - /**/private static final BitField fHtmlChecked = new BitField(0x01); - /**/private static final BitField fHtmlUnsupported = new BitField(0x02); - /**/private static final BitField fHtmlListTextNotSharpDot = new BitField(0x04); - /**/private static final BitField fHtmlNotPeriod = new BitField(0x08); - /**/private static final BitField fHtmlFirstLineMismatch = new BitField(0x10); - /**/private static final BitField fHtmlTabLeftIndentMismatch = new BitField(0x20); - /**/private static final BitField fHtmlHangingIndentBeneathNumber = new BitField(0x40); - /**/private static final BitField fHtmlBuiltInBullet = new BitField(0x80); - - protected GrfhicAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_grfhic = data[ 0x0 + offset ]; - } - - public void serialize( byte[] data, int offset ) - { - data[ 0x0 + offset ] = field_1_grfhic; - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 1; - } - - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - GrfhicAbstractType other = (GrfhicAbstractType) obj; - if ( field_1_grfhic != other.field_1_grfhic ) - return false; - return true; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + field_1_grfhic; - return result; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - - builder.append("[Grfhic]\n"); - builder.append( " .grfhic = " ); - builder.append(" ( ").append( field_1_grfhic ).append( " )\n" ); - builder.append(" .fHtmlChecked = ").append(isFHtmlChecked()).append('\n'); - builder.append(" .fHtmlUnsupported = ").append(isFHtmlUnsupported()).append('\n'); - builder.append(" .fHtmlListTextNotSharpDot = ").append(isFHtmlListTextNotSharpDot()).append('\n'); - builder.append(" .fHtmlNotPeriod = ").append(isFHtmlNotPeriod()).append('\n'); - builder.append(" .fHtmlFirstLineMismatch = ").append(isFHtmlFirstLineMismatch()).append('\n'); - builder.append(" .fHtmlTabLeftIndentMismatch = ").append(isFHtmlTabLeftIndentMismatch()).append('\n'); - builder.append(" .fHtmlHangingIndentBeneathNumber = ").append(isFHtmlHangingIndentBeneathNumber()).append('\n'); - builder.append(" .fHtmlBuiltInBullet = ").append(isFHtmlBuiltInBullet()).append('\n'); - - builder.append("[/Grfhic]"); - return builder.toString(); - } - - /** - * HTML compatibility flags. - */ - @Internal - public byte getGrfhic() - { - return field_1_grfhic; - } - - /** - * HTML compatibility flags. - */ - @Internal - public void setGrfhic( byte field_1_grfhic ) - { - this.field_1_grfhic = field_1_grfhic; - } - - /** - * Sets the fHtmlChecked field value. - * Checked - */ - @Internal - public void setFHtmlChecked( boolean value ) - { - field_1_grfhic = (byte)fHtmlChecked.setBoolean(field_1_grfhic, value); - } - - /** - * Checked - * @return the fHtmlChecked field value. - */ - @Internal - public boolean isFHtmlChecked() - { - return fHtmlChecked.isSet(field_1_grfhic); - } - - /** - * Sets the fHtmlUnsupported field value. - * The numbering sequence or format is unsupported (includes tab & size) - */ - @Internal - public void setFHtmlUnsupported( boolean value ) - { - field_1_grfhic = (byte)fHtmlUnsupported.setBoolean(field_1_grfhic, value); - } - - /** - * The numbering sequence or format is unsupported (includes tab & size) - * @return the fHtmlUnsupported field value. - */ - @Internal - public boolean isFHtmlUnsupported() - { - return fHtmlUnsupported.isSet(field_1_grfhic); - } - - /** - * Sets the fHtmlListTextNotSharpDot field value. - * The list text is not "#." - */ - @Internal - public void setFHtmlListTextNotSharpDot( boolean value ) - { - field_1_grfhic = (byte)fHtmlListTextNotSharpDot.setBoolean(field_1_grfhic, value); - } - - /** - * The list text is not "#." - * @return the fHtmlListTextNotSharpDot field value. - */ - @Internal - public boolean isFHtmlListTextNotSharpDot() - { - return fHtmlListTextNotSharpDot.isSet(field_1_grfhic); - } - - /** - * Sets the fHtmlNotPeriod field value. - * Something other than a period is used - */ - @Internal - public void setFHtmlNotPeriod( boolean value ) - { - field_1_grfhic = (byte)fHtmlNotPeriod.setBoolean(field_1_grfhic, value); - } - - /** - * Something other than a period is used - * @return the fHtmlNotPeriod field value. - */ - @Internal - public boolean isFHtmlNotPeriod() - { - return fHtmlNotPeriod.isSet(field_1_grfhic); - } - - /** - * Sets the fHtmlFirstLineMismatch field value. - * First line indent mismatch - */ - @Internal - public void setFHtmlFirstLineMismatch( boolean value ) - { - field_1_grfhic = (byte)fHtmlFirstLineMismatch.setBoolean(field_1_grfhic, value); - } - - /** - * First line indent mismatch - * @return the fHtmlFirstLineMismatch field value. - */ - @Internal - public boolean isFHtmlFirstLineMismatch() - { - return fHtmlFirstLineMismatch.isSet(field_1_grfhic); - } - - /** - * Sets the fHtmlTabLeftIndentMismatch field value. - * The list tab and the dxaLeft don't match (need table?) - */ - @Internal - public void setFHtmlTabLeftIndentMismatch( boolean value ) - { - field_1_grfhic = (byte)fHtmlTabLeftIndentMismatch.setBoolean(field_1_grfhic, value); - } - - /** - * The list tab and the dxaLeft don't match (need table?) - * @return the fHtmlTabLeftIndentMismatch field value. - */ - @Internal - public boolean isFHtmlTabLeftIndentMismatch() - { - return fHtmlTabLeftIndentMismatch.isSet(field_1_grfhic); - } - - /** - * Sets the fHtmlHangingIndentBeneathNumber field value. - * The hanging indent falls beneath the number (need plain text) - */ - @Internal - public void setFHtmlHangingIndentBeneathNumber( boolean value ) - { - field_1_grfhic = (byte)fHtmlHangingIndentBeneathNumber.setBoolean(field_1_grfhic, value); - } - - /** - * The hanging indent falls beneath the number (need plain text) - * @return the fHtmlHangingIndentBeneathNumber field value. - */ - @Internal - public boolean isFHtmlHangingIndentBeneathNumber() - { - return fHtmlHangingIndentBeneathNumber.isSet(field_1_grfhic); - } - - /** - * Sets the fHtmlBuiltInBullet field value. - * A built-in HTML bullet - */ - @Internal - public void setFHtmlBuiltInBullet( boolean value ) - { - field_1_grfhic = (byte)fHtmlBuiltInBullet.setBoolean(field_1_grfhic, value); - } - - /** - * A built-in HTML bullet - * @return the fHtmlBuiltInBullet field value. - */ - @Internal - public boolean isFHtmlBuiltInBullet() - { - return fHtmlBuiltInBullet.isSet(field_1_grfhic); - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.model.types; + + +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; + +/** + * The grfhic structure is a set of HTML incompatibility flags that specify the HTML + incompatibilities of a list structure. The values specify possible incompatibilities between + an LVL or LVLF and HTML lists. The values do not define list properties.

    Class and + fields descriptions are quoted from [MS-DOC] -- v20110315 Word (.doc) Binary File Format + specification + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov; according to [MS-DOC] -- v20110315 Word (.doc) Binary File Format + specification + + */ +@Internal +public abstract class GrfhicAbstractType +{ + + protected byte field_1_grfhic; + /**/private static final BitField fHtmlChecked = new BitField(0x01); + /**/private static final BitField fHtmlUnsupported = new BitField(0x02); + /**/private static final BitField fHtmlListTextNotSharpDot = new BitField(0x04); + /**/private static final BitField fHtmlNotPeriod = new BitField(0x08); + /**/private static final BitField fHtmlFirstLineMismatch = new BitField(0x10); + /**/private static final BitField fHtmlTabLeftIndentMismatch = new BitField(0x20); + /**/private static final BitField fHtmlHangingIndentBeneathNumber = new BitField(0x40); + /**/private static final BitField fHtmlBuiltInBullet = new BitField(0x80); + + protected GrfhicAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_grfhic = data[ 0x0 + offset ]; + } + + public void serialize( byte[] data, int offset ) + { + data[ 0x0 + offset ] = field_1_grfhic; + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 1; + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + return true; + if ( obj == null ) + return false; + if ( getClass() != obj.getClass() ) + return false; + GrfhicAbstractType other = (GrfhicAbstractType) obj; + if ( field_1_grfhic != other.field_1_grfhic ) + return false; + return true; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + field_1_grfhic; + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + + builder.append("[Grfhic]\n"); + builder.append( " .grfhic = " ); + builder.append(" ( ").append( field_1_grfhic ).append( " )\n" ); + builder.append(" .fHtmlChecked = ").append(isFHtmlChecked()).append('\n'); + builder.append(" .fHtmlUnsupported = ").append(isFHtmlUnsupported()).append('\n'); + builder.append(" .fHtmlListTextNotSharpDot = ").append(isFHtmlListTextNotSharpDot()).append('\n'); + builder.append(" .fHtmlNotPeriod = ").append(isFHtmlNotPeriod()).append('\n'); + builder.append(" .fHtmlFirstLineMismatch = ").append(isFHtmlFirstLineMismatch()).append('\n'); + builder.append(" .fHtmlTabLeftIndentMismatch = ").append(isFHtmlTabLeftIndentMismatch()).append('\n'); + builder.append(" .fHtmlHangingIndentBeneathNumber = ").append(isFHtmlHangingIndentBeneathNumber()).append('\n'); + builder.append(" .fHtmlBuiltInBullet = ").append(isFHtmlBuiltInBullet()).append('\n'); + + builder.append("[/Grfhic]"); + return builder.toString(); + } + + /** + * HTML compatibility flags. + */ + @Internal + public byte getGrfhic() + { + return field_1_grfhic; + } + + /** + * HTML compatibility flags. + */ + @Internal + public void setGrfhic( byte field_1_grfhic ) + { + this.field_1_grfhic = field_1_grfhic; + } + + /** + * Sets the fHtmlChecked field value. + * Checked + */ + @Internal + public void setFHtmlChecked( boolean value ) + { + field_1_grfhic = (byte)fHtmlChecked.setBoolean(field_1_grfhic, value); + } + + /** + * Checked + * @return the fHtmlChecked field value. + */ + @Internal + public boolean isFHtmlChecked() + { + return fHtmlChecked.isSet(field_1_grfhic); + } + + /** + * Sets the fHtmlUnsupported field value. + * The numbering sequence or format is unsupported (includes tab & size) + */ + @Internal + public void setFHtmlUnsupported( boolean value ) + { + field_1_grfhic = (byte)fHtmlUnsupported.setBoolean(field_1_grfhic, value); + } + + /** + * The numbering sequence or format is unsupported (includes tab & size) + * @return the fHtmlUnsupported field value. + */ + @Internal + public boolean isFHtmlUnsupported() + { + return fHtmlUnsupported.isSet(field_1_grfhic); + } + + /** + * Sets the fHtmlListTextNotSharpDot field value. + * The list text is not "#." + */ + @Internal + public void setFHtmlListTextNotSharpDot( boolean value ) + { + field_1_grfhic = (byte)fHtmlListTextNotSharpDot.setBoolean(field_1_grfhic, value); + } + + /** + * The list text is not "#." + * @return the fHtmlListTextNotSharpDot field value. + */ + @Internal + public boolean isFHtmlListTextNotSharpDot() + { + return fHtmlListTextNotSharpDot.isSet(field_1_grfhic); + } + + /** + * Sets the fHtmlNotPeriod field value. + * Something other than a period is used + */ + @Internal + public void setFHtmlNotPeriod( boolean value ) + { + field_1_grfhic = (byte)fHtmlNotPeriod.setBoolean(field_1_grfhic, value); + } + + /** + * Something other than a period is used + * @return the fHtmlNotPeriod field value. + */ + @Internal + public boolean isFHtmlNotPeriod() + { + return fHtmlNotPeriod.isSet(field_1_grfhic); + } + + /** + * Sets the fHtmlFirstLineMismatch field value. + * First line indent mismatch + */ + @Internal + public void setFHtmlFirstLineMismatch( boolean value ) + { + field_1_grfhic = (byte)fHtmlFirstLineMismatch.setBoolean(field_1_grfhic, value); + } + + /** + * First line indent mismatch + * @return the fHtmlFirstLineMismatch field value. + */ + @Internal + public boolean isFHtmlFirstLineMismatch() + { + return fHtmlFirstLineMismatch.isSet(field_1_grfhic); + } + + /** + * Sets the fHtmlTabLeftIndentMismatch field value. + * The list tab and the dxaLeft don't match (need table?) + */ + @Internal + public void setFHtmlTabLeftIndentMismatch( boolean value ) + { + field_1_grfhic = (byte)fHtmlTabLeftIndentMismatch.setBoolean(field_1_grfhic, value); + } + + /** + * The list tab and the dxaLeft don't match (need table?) + * @return the fHtmlTabLeftIndentMismatch field value. + */ + @Internal + public boolean isFHtmlTabLeftIndentMismatch() + { + return fHtmlTabLeftIndentMismatch.isSet(field_1_grfhic); + } + + /** + * Sets the fHtmlHangingIndentBeneathNumber field value. + * The hanging indent falls beneath the number (need plain text) + */ + @Internal + public void setFHtmlHangingIndentBeneathNumber( boolean value ) + { + field_1_grfhic = (byte)fHtmlHangingIndentBeneathNumber.setBoolean(field_1_grfhic, value); + } + + /** + * The hanging indent falls beneath the number (need plain text) + * @return the fHtmlHangingIndentBeneathNumber field value. + */ + @Internal + public boolean isFHtmlHangingIndentBeneathNumber() + { + return fHtmlHangingIndentBeneathNumber.isSet(field_1_grfhic); + } + + /** + * Sets the fHtmlBuiltInBullet field value. + * A built-in HTML bullet + */ + @Internal + public void setFHtmlBuiltInBullet( boolean value ) + { + field_1_grfhic = (byte)fHtmlBuiltInBullet.setBoolean(field_1_grfhic, value); + } + + /** + * A built-in HTML bullet + * @return the fHtmlBuiltInBullet field value. + */ + @Internal + public boolean isFHtmlBuiltInBullet() + { + return fHtmlBuiltInBullet.isSet(field_1_grfhic); + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/HRESIAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/HRESIAbstractType.java index 7c4f5d6853..0e9bd5fb63 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/HRESIAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/HRESIAbstractType.java @@ -1,136 +1,136 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.Internal; - -/** - * Hyphenation (HRESI). - *

    - * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 - * Binary File Format (.doc) Specification - * - * NOTE: This source is automatically generated please do not modify this file. - * Either subclass or remove the record in src/types/definitions. - * - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary - * File Format (.doc) Specification - */ -@Internal -public abstract class HRESIAbstractType -{ - - protected byte field_1_hres; - /**/public final static byte HRES_NO = 0; - /**/public final static byte HRES_NORMAL = 1; - /**/public final static byte HRES_ADD_LETTER_BEFORE = 2; - /**/public final static byte HRES_CHANGE_LETTER_BEFORE = 3; - /**/public final static byte HRES_DELETE_LETTER_BEFORE = 4; - /**/public final static byte HRES_CHANGE_LETTER_AFTER = 5; - /**/public final static byte HRES_DELETE_BEFORE_CHANGE_BEFORE = 6; - protected byte field_2_chHres; - - protected HRESIAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_hres = data[ 0x0 + offset ]; - field_2_chHres = data[ 0x1 + offset ]; - } - - public void serialize( byte[] data, int offset ) - { - data[ 0x0 + offset] = field_1_hres; - data[ 0x1 + offset] = field_2_chHres; - } - - /** - * Size of record (exluding 4 byte header) - */ - public static int getSize() - { - return 4 + + 1 + 1; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[HRESI]\n"); - builder.append(" .hres = "); - builder.append(" (").append(getHres()).append(" )\n"); - builder.append(" .chHres = "); - builder.append(" (").append(getChHres()).append(" )\n"); - - builder.append("[/HRESI]\n"); - return builder.toString(); - } - - /** - * Hyphenation rule. - * - * @return One of - *

  • {@link #HRES_NO} - *
  • {@link #HRES_NORMAL} - *
  • {@link #HRES_ADD_LETTER_BEFORE} - *
  • {@link #HRES_CHANGE_LETTER_BEFORE} - *
  • {@link #HRES_DELETE_LETTER_BEFORE} - *
  • {@link #HRES_CHANGE_LETTER_AFTER} - *
  • {@link #HRES_DELETE_BEFORE_CHANGE_BEFORE} - */ - public byte getHres() - { - return field_1_hres; - } - - /** - * Hyphenation rule. - * - * @param field_1_hres - * One of - *
  • {@link #HRES_NO} - *
  • {@link #HRES_NORMAL} - *
  • {@link #HRES_ADD_LETTER_BEFORE} - *
  • {@link #HRES_CHANGE_LETTER_BEFORE} - *
  • {@link #HRES_DELETE_LETTER_BEFORE} - *
  • {@link #HRES_CHANGE_LETTER_AFTER} - *
  • {@link #HRES_DELETE_BEFORE_CHANGE_BEFORE} - */ - public void setHres( byte field_1_hres ) - { - this.field_1_hres = field_1_hres; - } - - /** - * The character that will be used to add or change a letter when hres is 2, 3, 5 or 6. - */ - public byte getChHres() - { - return field_2_chHres; - } - - /** - * The character that will be used to add or change a letter when hres is 2, 3, 5 or 6. - */ - public void setChHres( byte field_2_chHres ) - { - this.field_2_chHres = field_2_chHres; - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.Internal; + +/** + * Hyphenation (HRESI). + *

    + * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 + * Binary File Format (.doc) Specification + * + * NOTE: This source is automatically generated please do not modify this file. + * Either subclass or remove the record in src/types/definitions. + * + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary + * File Format (.doc) Specification + */ +@Internal +public abstract class HRESIAbstractType +{ + + protected byte field_1_hres; + /**/public final static byte HRES_NO = 0; + /**/public final static byte HRES_NORMAL = 1; + /**/public final static byte HRES_ADD_LETTER_BEFORE = 2; + /**/public final static byte HRES_CHANGE_LETTER_BEFORE = 3; + /**/public final static byte HRES_DELETE_LETTER_BEFORE = 4; + /**/public final static byte HRES_CHANGE_LETTER_AFTER = 5; + /**/public final static byte HRES_DELETE_BEFORE_CHANGE_BEFORE = 6; + protected byte field_2_chHres; + + protected HRESIAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_hres = data[ 0x0 + offset ]; + field_2_chHres = data[ 0x1 + offset ]; + } + + public void serialize( byte[] data, int offset ) + { + data[ 0x0 + offset] = field_1_hres; + data[ 0x1 + offset] = field_2_chHres; + } + + /** + * Size of record (exluding 4 byte header) + */ + public static int getSize() + { + return 4 + + 1 + 1; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[HRESI]\n"); + builder.append(" .hres = "); + builder.append(" (").append(getHres()).append(" )\n"); + builder.append(" .chHres = "); + builder.append(" (").append(getChHres()).append(" )\n"); + + builder.append("[/HRESI]\n"); + return builder.toString(); + } + + /** + * Hyphenation rule. + * + * @return One of + *

  • {@link #HRES_NO} + *
  • {@link #HRES_NORMAL} + *
  • {@link #HRES_ADD_LETTER_BEFORE} + *
  • {@link #HRES_CHANGE_LETTER_BEFORE} + *
  • {@link #HRES_DELETE_LETTER_BEFORE} + *
  • {@link #HRES_CHANGE_LETTER_AFTER} + *
  • {@link #HRES_DELETE_BEFORE_CHANGE_BEFORE} + */ + public byte getHres() + { + return field_1_hres; + } + + /** + * Hyphenation rule. + * + * @param field_1_hres + * One of + *
  • {@link #HRES_NO} + *
  • {@link #HRES_NORMAL} + *
  • {@link #HRES_ADD_LETTER_BEFORE} + *
  • {@link #HRES_CHANGE_LETTER_BEFORE} + *
  • {@link #HRES_DELETE_LETTER_BEFORE} + *
  • {@link #HRES_CHANGE_LETTER_AFTER} + *
  • {@link #HRES_DELETE_BEFORE_CHANGE_BEFORE} + */ + public void setHres( byte field_1_hres ) + { + this.field_1_hres = field_1_hres; + } + + /** + * The character that will be used to add or change a letter when hres is 2, 3, 5 or 6. + */ + public byte getChHres() + { + return field_2_chHres; + } + + /** + * The character that will be used to add or change a letter when hres is 2, 3, 5 or 6. + */ + public void setChHres( byte field_2_chHres ) + { + this.field_2_chHres = field_2_chHres; + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java index 0289ef28ab..879bfe0bea 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java @@ -1,290 +1,290 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.hwpf.model.Grfhic; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * List Format Override (LFO).

    Class and fields descriptions are quoted from - [MS-DOC] --v20110315; Word (.doc) Binary File Format - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to [MS-DOC] --v20110315; Word (.doc) Binary File Format; - Copyright (c) Microsoft Corporation - - */ -@Internal -public abstract class LFOAbstractType -{ - - protected int field_1_lsid; - protected int field_2_unused1; - protected int field_3_unused2; - protected byte field_4_clfolvl; - protected byte field_5_ibstFltAutoNum; - protected Grfhic field_6_grfhic; - protected byte field_7_unused3; - - protected LFOAbstractType() - { - this.field_6_grfhic = new Grfhic(); - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); - field_2_unused1 = LittleEndian.getInt( data, 0x4 + offset ); - field_3_unused2 = LittleEndian.getInt( data, 0x8 + offset ); - field_4_clfolvl = data[ 0xc + offset ]; - field_5_ibstFltAutoNum = data[ 0xd + offset ]; - field_6_grfhic = new Grfhic( data, 0xe + offset ); - field_7_unused3 = data[ 0xf + offset ]; - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putInt( data, 0x0 + offset, field_1_lsid ); - LittleEndian.putInt( data, 0x4 + offset, field_2_unused1 ); - LittleEndian.putInt( data, 0x8 + offset, field_3_unused2 ); - data[ 0xc + offset ] = field_4_clfolvl; - data[ 0xd + offset ] = field_5_ibstFltAutoNum; - field_6_grfhic.serialize( data, 0xe + offset ); - data[ 0xf + offset ] = field_7_unused3; - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 4 + 4 + 4 + 1 + 1 + 1 + 1; - } - - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - LFOAbstractType other = (LFOAbstractType) obj; - if ( field_1_lsid != other.field_1_lsid ) - return false; - if ( field_2_unused1 != other.field_2_unused1 ) - return false; - if ( field_3_unused2 != other.field_3_unused2 ) - return false; - if ( field_4_clfolvl != other.field_4_clfolvl ) - return false; - if ( field_5_ibstFltAutoNum != other.field_5_ibstFltAutoNum ) - return false; - if ( field_6_grfhic == null ) - { - if ( other.field_6_grfhic != null ) - return false; - } - else if ( !field_6_grfhic.equals( other.field_6_grfhic ) ) - return false; - if ( field_7_unused3 != other.field_7_unused3 ) - return false; - return true; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + field_1_lsid; - result = prime * result + field_2_unused1; - result = prime * result + field_3_unused2; - result = prime * result + field_4_clfolvl; - result = prime * result + field_5_ibstFltAutoNum; - result = prime * result - + ((field_6_grfhic == null) ? 0 : field_6_grfhic.hashCode()); - result = prime * result + field_7_unused3; - return result; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - - builder.append("[LFO]\n"); - builder.append( " .lsid = " ); - builder.append(" ( ").append( field_1_lsid ).append( " )\n" ); - builder.append( " .unused1 = " ); - builder.append(" ( ").append( field_2_unused1 ).append( " )\n" ); - builder.append( " .unused2 = " ); - builder.append(" ( ").append( field_3_unused2 ).append( " )\n" ); - builder.append( " .clfolvl = " ); - builder.append(" ( ").append( field_4_clfolvl ).append( " )\n" ); - builder.append( " .ibstFltAutoNum = " ); - builder.append(" ( ").append( field_5_ibstFltAutoNum ).append( " )\n" ); - builder.append( " .grfhic = " ); - builder.append(" ( ").append( field_6_grfhic == null ? "null" : field_6_grfhic.toString().replaceAll( "\n", "\n " ) ).append( " )\n" ); - builder.append( " .unused3 = " ); - builder.append(" ( ").append( field_7_unused3 ).append( " )\n" ); - - builder.append("[/LFO]"); - return builder.toString(); - } - - /** - * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value.. - */ - @Internal - public int getLsid() - { - return field_1_lsid; - } - - /** - * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value.. - */ - @Internal - public void setLsid( int field_1_lsid ) - { - this.field_1_lsid = field_1_lsid; - } - - /** - * This field MUST be ignored. - */ - @Internal - public int getUnused1() - { - return field_2_unused1; - } - - /** - * This field MUST be ignored. - */ - @Internal - public void setUnused1( int field_2_unused1 ) - { - this.field_2_unused1 = field_2_unused1; - } - - /** - * This field MUST be ignored. - */ - @Internal - public int getUnused2() - { - return field_3_unused2; - } - - /** - * This field MUST be ignored. - */ - @Internal - public void setUnused2( int field_3_unused2 ) - { - this.field_3_unused2 = field_3_unused2; - } - - /** - * An unsigned integer that specifies the field that this LFO represents.. - */ - @Internal - public byte getClfolvl() - { - return field_4_clfolvl; - } - - /** - * An unsigned integer that specifies the field that this LFO represents.. - */ - @Internal - public void setClfolvl( byte field_4_clfolvl ) - { - this.field_4_clfolvl = field_4_clfolvl; - } - - /** - * Used for AUTONUM field emulation. - */ - @Internal - public byte getIbstFltAutoNum() - { - return field_5_ibstFltAutoNum; - } - - /** - * Used for AUTONUM field emulation. - */ - @Internal - public void setIbstFltAutoNum( byte field_5_ibstFltAutoNum ) - { - this.field_5_ibstFltAutoNum = field_5_ibstFltAutoNum; - } - - /** - * HTML compatibility flags. - */ - @Internal - public Grfhic getGrfhic() - { - return field_6_grfhic; - } - - /** - * HTML compatibility flags. - */ - @Internal - public void setGrfhic( Grfhic field_6_grfhic ) - { - this.field_6_grfhic = field_6_grfhic; - } - - /** - * This field MUST be ignored. - */ - @Internal - public byte getUnused3() - { - return field_7_unused3; - } - - /** - * This field MUST be ignored. - */ - @Internal - public void setUnused3( byte field_7_unused3 ) - { - this.field_7_unused3 = field_7_unused3; - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.hwpf.model.Grfhic; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * List Format Override (LFO).

    Class and fields descriptions are quoted from + [MS-DOC] --v20110315; Word (.doc) Binary File Format + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov; according to [MS-DOC] --v20110315; Word (.doc) Binary File Format; + Copyright (c) Microsoft Corporation + + */ +@Internal +public abstract class LFOAbstractType +{ + + protected int field_1_lsid; + protected int field_2_unused1; + protected int field_3_unused2; + protected byte field_4_clfolvl; + protected byte field_5_ibstFltAutoNum; + protected Grfhic field_6_grfhic; + protected byte field_7_unused3; + + protected LFOAbstractType() + { + this.field_6_grfhic = new Grfhic(); + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); + field_2_unused1 = LittleEndian.getInt( data, 0x4 + offset ); + field_3_unused2 = LittleEndian.getInt( data, 0x8 + offset ); + field_4_clfolvl = data[ 0xc + offset ]; + field_5_ibstFltAutoNum = data[ 0xd + offset ]; + field_6_grfhic = new Grfhic( data, 0xe + offset ); + field_7_unused3 = data[ 0xf + offset ]; + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putInt( data, 0x0 + offset, field_1_lsid ); + LittleEndian.putInt( data, 0x4 + offset, field_2_unused1 ); + LittleEndian.putInt( data, 0x8 + offset, field_3_unused2 ); + data[ 0xc + offset ] = field_4_clfolvl; + data[ 0xd + offset ] = field_5_ibstFltAutoNum; + field_6_grfhic.serialize( data, 0xe + offset ); + data[ 0xf + offset ] = field_7_unused3; + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 4 + 4 + 4 + 1 + 1 + 1 + 1; + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + return true; + if ( obj == null ) + return false; + if ( getClass() != obj.getClass() ) + return false; + LFOAbstractType other = (LFOAbstractType) obj; + if ( field_1_lsid != other.field_1_lsid ) + return false; + if ( field_2_unused1 != other.field_2_unused1 ) + return false; + if ( field_3_unused2 != other.field_3_unused2 ) + return false; + if ( field_4_clfolvl != other.field_4_clfolvl ) + return false; + if ( field_5_ibstFltAutoNum != other.field_5_ibstFltAutoNum ) + return false; + if ( field_6_grfhic == null ) + { + if ( other.field_6_grfhic != null ) + return false; + } + else if ( !field_6_grfhic.equals( other.field_6_grfhic ) ) + return false; + if ( field_7_unused3 != other.field_7_unused3 ) + return false; + return true; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + field_1_lsid; + result = prime * result + field_2_unused1; + result = prime * result + field_3_unused2; + result = prime * result + field_4_clfolvl; + result = prime * result + field_5_ibstFltAutoNum; + result = prime * result + + ((field_6_grfhic == null) ? 0 : field_6_grfhic.hashCode()); + result = prime * result + field_7_unused3; + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + + builder.append("[LFO]\n"); + builder.append( " .lsid = " ); + builder.append(" ( ").append( field_1_lsid ).append( " )\n" ); + builder.append( " .unused1 = " ); + builder.append(" ( ").append( field_2_unused1 ).append( " )\n" ); + builder.append( " .unused2 = " ); + builder.append(" ( ").append( field_3_unused2 ).append( " )\n" ); + builder.append( " .clfolvl = " ); + builder.append(" ( ").append( field_4_clfolvl ).append( " )\n" ); + builder.append( " .ibstFltAutoNum = " ); + builder.append(" ( ").append( field_5_ibstFltAutoNum ).append( " )\n" ); + builder.append( " .grfhic = " ); + builder.append(" ( ").append( field_6_grfhic == null ? "null" : field_6_grfhic.toString().replaceAll( "\n", "\n " ) ).append( " )\n" ); + builder.append( " .unused3 = " ); + builder.append(" ( ").append( field_7_unused3 ).append( " )\n" ); + + builder.append("[/LFO]"); + return builder.toString(); + } + + /** + * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value.. + */ + @Internal + public int getLsid() + { + return field_1_lsid; + } + + /** + * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value.. + */ + @Internal + public void setLsid( int field_1_lsid ) + { + this.field_1_lsid = field_1_lsid; + } + + /** + * This field MUST be ignored. + */ + @Internal + public int getUnused1() + { + return field_2_unused1; + } + + /** + * This field MUST be ignored. + */ + @Internal + public void setUnused1( int field_2_unused1 ) + { + this.field_2_unused1 = field_2_unused1; + } + + /** + * This field MUST be ignored. + */ + @Internal + public int getUnused2() + { + return field_3_unused2; + } + + /** + * This field MUST be ignored. + */ + @Internal + public void setUnused2( int field_3_unused2 ) + { + this.field_3_unused2 = field_3_unused2; + } + + /** + * An unsigned integer that specifies the field that this LFO represents.. + */ + @Internal + public byte getClfolvl() + { + return field_4_clfolvl; + } + + /** + * An unsigned integer that specifies the field that this LFO represents.. + */ + @Internal + public void setClfolvl( byte field_4_clfolvl ) + { + this.field_4_clfolvl = field_4_clfolvl; + } + + /** + * Used for AUTONUM field emulation. + */ + @Internal + public byte getIbstFltAutoNum() + { + return field_5_ibstFltAutoNum; + } + + /** + * Used for AUTONUM field emulation. + */ + @Internal + public void setIbstFltAutoNum( byte field_5_ibstFltAutoNum ) + { + this.field_5_ibstFltAutoNum = field_5_ibstFltAutoNum; + } + + /** + * HTML compatibility flags. + */ + @Internal + public Grfhic getGrfhic() + { + return field_6_grfhic; + } + + /** + * HTML compatibility flags. + */ + @Internal + public void setGrfhic( Grfhic field_6_grfhic ) + { + this.field_6_grfhic = field_6_grfhic; + } + + /** + * This field MUST be ignored. + */ + @Internal + public byte getUnused3() + { + return field_7_unused3; + } + + /** + * This field MUST be ignored. + */ + @Internal + public void setUnused3( byte field_7_unused3 ) + { + this.field_7_unused3 = field_7_unused3; + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOLVLBaseAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOLVLBaseAbstractType.java index 9e304b9fd4..6826b3d055 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOLVLBaseAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOLVLBaseAbstractType.java @@ -1,290 +1,290 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * The LFOLVL structure contains information that is used to override the formatting - information of a corresponding LVL.

    Class and fields descriptions are quoted from - Microsoft Office Word 97-2007 Binary File Format and [MS-DOC] - v20110608 Word (.doc) Binary - File Format - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format - Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format - - */ -@Internal -public abstract class LFOLVLBaseAbstractType -{ - - protected int field_1_iStartAt; - protected int field_2_flags; - /**/private static final BitField iLvl = new BitField(0x0000000F); - /**/private static final BitField fStartAt = new BitField(0x00000010); - /**/private static final BitField fFormatting = new BitField(0x00000020); - /**/private static final BitField grfhic = new BitField(0x00003FC0); - /**/private static final BitField unused1 = new BitField(0x1FFFC000); - /**/private static final BitField unused2 = new BitField(0xE0000000); - - protected LFOLVLBaseAbstractType() - { - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_iStartAt = LittleEndian.getInt( data, 0x0 + offset ); - field_2_flags = LittleEndian.getInt( data, 0x4 + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putInt( data, 0x0 + offset, field_1_iStartAt ); - LittleEndian.putInt( data, 0x4 + offset, field_2_flags ); - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 4 + 4; - } - - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - LFOLVLBaseAbstractType other = (LFOLVLBaseAbstractType) obj; - if ( field_1_iStartAt != other.field_1_iStartAt ) - return false; - if ( field_2_flags != other.field_2_flags ) - return false; - return true; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + field_1_iStartAt; - result = prime * result + field_2_flags; - return result; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[LFOLVLBase]\n"); - builder.append(" .iStartAt = "); - builder.append(" (").append(getIStartAt()).append(" )\n"); - builder.append(" .flags = "); - builder.append(" (").append(getFlags()).append(" )\n"); - builder.append(" .iLvl = ").append(getILvl()).append('\n'); - builder.append(" .fStartAt = ").append(isFStartAt()).append('\n'); - builder.append(" .fFormatting = ").append(isFFormatting()).append('\n'); - builder.append(" .grfhic = ").append(getGrfhic()).append('\n'); - builder.append(" .unused1 = ").append(getUnused1()).append('\n'); - builder.append(" .unused2 = ").append(getUnused2()).append('\n'); - - builder.append("[/LFOLVLBase]\n"); - return builder.toString(); - } - - /** - * If fStartAt is set to 0x1, this is a signed integer that specifies the start-at value that overrides lvlf.iStartAt of the corresponding LVL. This value MUST be less than or equal to 0x7FFF and MUST be greater than or equal to zero. If both fStartAt and fFormatting are set to 0x1, or if fStartAt is set to 0x0, this value is undefined and MUST be ignored. - */ - @Internal - public int getIStartAt() - { - return field_1_iStartAt; - } - - /** - * If fStartAt is set to 0x1, this is a signed integer that specifies the start-at value that overrides lvlf.iStartAt of the corresponding LVL. This value MUST be less than or equal to 0x7FFF and MUST be greater than or equal to zero. If both fStartAt and fFormatting are set to 0x1, or if fStartAt is set to 0x0, this value is undefined and MUST be ignored. - */ - @Internal - public void setIStartAt( int field_1_iStartAt ) - { - this.field_1_iStartAt = field_1_iStartAt; - } - - /** - * Get the flags field for the LFOLVLBase record. - */ - @Internal - public int getFlags() - { - return field_2_flags; - } - - /** - * Set the flags field for the LFOLVLBase record. - */ - @Internal - public void setFlags( int field_2_flags ) - { - this.field_2_flags = field_2_flags; - } - - /** - * Sets the iLvl field value. - * An unsigned integer that specifies the zero-based level of the list that this overrides. This LFOLVL overrides the LVL that specifies the level formatting of this level of the LSTF that is specified by the lsid field of the LFO to which this LFOLVL corresponds. This value MUST be less than or equal to 0x08 - */ - @Internal - public void setILvl( byte value ) - { - field_2_flags = iLvl.setValue(field_2_flags, value); - } - - /** - * An unsigned integer that specifies the zero-based level of the list that this overrides. This LFOLVL overrides the LVL that specifies the level formatting of this level of the LSTF that is specified by the lsid field of the LFO to which this LFOLVL corresponds. This value MUST be less than or equal to 0x08 - * @return the iLvl field value. - */ - @Internal - public byte getILvl() - { - return ( byte )iLvl.getValue(field_2_flags); - } - - /** - * Sets the fStartAt field value. - * A bit that specifies whether this LFOLVL overrides the start-at value of the level. - */ - @Internal - public void setFStartAt( boolean value ) - { - field_2_flags = fStartAt.setBoolean(field_2_flags, value); - } - - /** - * A bit that specifies whether this LFOLVL overrides the start-at value of the level. - * @return the fStartAt field value. - */ - @Internal - public boolean isFStartAt() - { - return fStartAt.isSet(field_2_flags); - } - - /** - * Sets the fFormatting field value. - * A bit that specifies whether lvl is an LVL that overrides the corresponding LVL - */ - @Internal - public void setFFormatting( boolean value ) - { - field_2_flags = fFormatting.setBoolean(field_2_flags, value); - } - - /** - * A bit that specifies whether lvl is an LVL that overrides the corresponding LVL - * @return the fFormatting field value. - */ - @Internal - public boolean isFFormatting() - { - return fFormatting.isSet(field_2_flags); - } - - /** - * Sets the grfhic field value. - * A grfhic that specifies the HTML incompatibilities of the overriding level formatting - */ - @Internal - public void setGrfhic( short value ) - { - field_2_flags = grfhic.setValue(field_2_flags, value); - } - - /** - * A grfhic that specifies the HTML incompatibilities of the overriding level formatting - * @return the grfhic field value. - */ - @Internal - public short getGrfhic() - { - return ( short )grfhic.getValue(field_2_flags); - } - - /** - * Sets the unused1 field value. - * This MUST be ignored - */ - @Internal - public void setUnused1( short value ) - { - field_2_flags = unused1.setValue(field_2_flags, value); - } - - /** - * This MUST be ignored - * @return the unused1 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public short getUnused1() - { - return ( short )unused1.getValue(field_2_flags); - } - - /** - * Sets the unused2 field value. - * This MUST be ignored - */ - @Internal - public void setUnused2( byte value ) - { - field_2_flags = unused2.setValue(field_2_flags, value); - } - - /** - * This MUST be ignored - * @return the unused2 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public byte getUnused2() - { - return ( byte )unused2.getValue(field_2_flags); - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * The LFOLVL structure contains information that is used to override the formatting + information of a corresponding LVL.

    Class and fields descriptions are quoted from + Microsoft Office Word 97-2007 Binary File Format and [MS-DOC] - v20110608 Word (.doc) Binary + File Format + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format + Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format + + */ +@Internal +public abstract class LFOLVLBaseAbstractType +{ + + protected int field_1_iStartAt; + protected int field_2_flags; + /**/private static final BitField iLvl = new BitField(0x0000000F); + /**/private static final BitField fStartAt = new BitField(0x00000010); + /**/private static final BitField fFormatting = new BitField(0x00000020); + /**/private static final BitField grfhic = new BitField(0x00003FC0); + /**/private static final BitField unused1 = new BitField(0x1FFFC000); + /**/private static final BitField unused2 = new BitField(0xE0000000); + + protected LFOLVLBaseAbstractType() + { + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_iStartAt = LittleEndian.getInt( data, 0x0 + offset ); + field_2_flags = LittleEndian.getInt( data, 0x4 + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putInt( data, 0x0 + offset, field_1_iStartAt ); + LittleEndian.putInt( data, 0x4 + offset, field_2_flags ); + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 4 + 4; + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + return true; + if ( obj == null ) + return false; + if ( getClass() != obj.getClass() ) + return false; + LFOLVLBaseAbstractType other = (LFOLVLBaseAbstractType) obj; + if ( field_1_iStartAt != other.field_1_iStartAt ) + return false; + if ( field_2_flags != other.field_2_flags ) + return false; + return true; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + field_1_iStartAt; + result = prime * result + field_2_flags; + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[LFOLVLBase]\n"); + builder.append(" .iStartAt = "); + builder.append(" (").append(getIStartAt()).append(" )\n"); + builder.append(" .flags = "); + builder.append(" (").append(getFlags()).append(" )\n"); + builder.append(" .iLvl = ").append(getILvl()).append('\n'); + builder.append(" .fStartAt = ").append(isFStartAt()).append('\n'); + builder.append(" .fFormatting = ").append(isFFormatting()).append('\n'); + builder.append(" .grfhic = ").append(getGrfhic()).append('\n'); + builder.append(" .unused1 = ").append(getUnused1()).append('\n'); + builder.append(" .unused2 = ").append(getUnused2()).append('\n'); + + builder.append("[/LFOLVLBase]\n"); + return builder.toString(); + } + + /** + * If fStartAt is set to 0x1, this is a signed integer that specifies the start-at value that overrides lvlf.iStartAt of the corresponding LVL. This value MUST be less than or equal to 0x7FFF and MUST be greater than or equal to zero. If both fStartAt and fFormatting are set to 0x1, or if fStartAt is set to 0x0, this value is undefined and MUST be ignored. + */ + @Internal + public int getIStartAt() + { + return field_1_iStartAt; + } + + /** + * If fStartAt is set to 0x1, this is a signed integer that specifies the start-at value that overrides lvlf.iStartAt of the corresponding LVL. This value MUST be less than or equal to 0x7FFF and MUST be greater than or equal to zero. If both fStartAt and fFormatting are set to 0x1, or if fStartAt is set to 0x0, this value is undefined and MUST be ignored. + */ + @Internal + public void setIStartAt( int field_1_iStartAt ) + { + this.field_1_iStartAt = field_1_iStartAt; + } + + /** + * Get the flags field for the LFOLVLBase record. + */ + @Internal + public int getFlags() + { + return field_2_flags; + } + + /** + * Set the flags field for the LFOLVLBase record. + */ + @Internal + public void setFlags( int field_2_flags ) + { + this.field_2_flags = field_2_flags; + } + + /** + * Sets the iLvl field value. + * An unsigned integer that specifies the zero-based level of the list that this overrides. This LFOLVL overrides the LVL that specifies the level formatting of this level of the LSTF that is specified by the lsid field of the LFO to which this LFOLVL corresponds. This value MUST be less than or equal to 0x08 + */ + @Internal + public void setILvl( byte value ) + { + field_2_flags = iLvl.setValue(field_2_flags, value); + } + + /** + * An unsigned integer that specifies the zero-based level of the list that this overrides. This LFOLVL overrides the LVL that specifies the level formatting of this level of the LSTF that is specified by the lsid field of the LFO to which this LFOLVL corresponds. This value MUST be less than or equal to 0x08 + * @return the iLvl field value. + */ + @Internal + public byte getILvl() + { + return ( byte )iLvl.getValue(field_2_flags); + } + + /** + * Sets the fStartAt field value. + * A bit that specifies whether this LFOLVL overrides the start-at value of the level. + */ + @Internal + public void setFStartAt( boolean value ) + { + field_2_flags = fStartAt.setBoolean(field_2_flags, value); + } + + /** + * A bit that specifies whether this LFOLVL overrides the start-at value of the level. + * @return the fStartAt field value. + */ + @Internal + public boolean isFStartAt() + { + return fStartAt.isSet(field_2_flags); + } + + /** + * Sets the fFormatting field value. + * A bit that specifies whether lvl is an LVL that overrides the corresponding LVL + */ + @Internal + public void setFFormatting( boolean value ) + { + field_2_flags = fFormatting.setBoolean(field_2_flags, value); + } + + /** + * A bit that specifies whether lvl is an LVL that overrides the corresponding LVL + * @return the fFormatting field value. + */ + @Internal + public boolean isFFormatting() + { + return fFormatting.isSet(field_2_flags); + } + + /** + * Sets the grfhic field value. + * A grfhic that specifies the HTML incompatibilities of the overriding level formatting + */ + @Internal + public void setGrfhic( short value ) + { + field_2_flags = grfhic.setValue(field_2_flags, value); + } + + /** + * A grfhic that specifies the HTML incompatibilities of the overriding level formatting + * @return the grfhic field value. + */ + @Internal + public short getGrfhic() + { + return ( short )grfhic.getValue(field_2_flags); + } + + /** + * Sets the unused1 field value. + * This MUST be ignored + */ + @Internal + public void setUnused1( short value ) + { + field_2_flags = unused1.setValue(field_2_flags, value); + } + + /** + * This MUST be ignored + * @return the unused1 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public short getUnused1() + { + return ( short )unused1.getValue(field_2_flags); + } + + /** + * Sets the unused2 field value. + * This MUST be ignored + */ + @Internal + public void setUnused2( byte value ) + { + field_2_flags = unused2.setValue(field_2_flags, value); + } + + /** + * This MUST be ignored + * @return the unused2 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public byte getUnused2() + { + return ( byte )unused2.getValue(field_2_flags); + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LSTFAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LSTFAbstractType.java index 020c235adc..8500073c3c 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LSTFAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LSTFAbstractType.java @@ -1,379 +1,379 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.model.types; - -import java.util.Arrays; - -import org.apache.poi.hwpf.model.Grfhic; -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * The LSTF structure contains formatting properties that apply to an entire list. -

    Class and fields descriptions are quoted from Microsoft Office Word 97-2007 Binary - File Format and [MS-DOC] - v20110608 Word (.doc) Binary File Format - - *

    - * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. - *

    - * This class is internal. It content or properties may change without notice - * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format - Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format - - */ -@Internal -public abstract class LSTFAbstractType -{ - - protected int field_1_lsid; - protected int field_2_tplc; - protected short[] field_3_rgistdPara; - protected byte field_4_flags; - /**/private static final BitField fSimpleList = new BitField(0x01); - /**/private static final BitField unused1 = new BitField(0x02); - /**/private static final BitField fAutoNum = new BitField(0x04); - /**/private static final BitField unused2 = new BitField(0x08); - /**/private static final BitField fHybrid = new BitField(0x10); - /**/private static final BitField reserved1 = new BitField(0xE0); - protected Grfhic field_5_grfhic; - - protected LSTFAbstractType() - { - this.field_3_rgistdPara = new short[0]; - this.field_5_grfhic = new Grfhic(); - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); - field_2_tplc = LittleEndian.getInt( data, 0x4 + offset ); - field_3_rgistdPara = LittleEndian.getShortArray( data, 0x8 + offset, 18 ); - field_4_flags = data[ 0x1a + offset ]; - field_5_grfhic = new Grfhic( data, 0x1b + offset ); - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putInt( data, 0x0 + offset, field_1_lsid ); - LittleEndian.putInt( data, 0x4 + offset, field_2_tplc ); - LittleEndian.putShortArray( data, 0x8 + offset, field_3_rgistdPara ); - data[ 0x1a + offset ] = field_4_flags; - field_5_grfhic.serialize( data, 0x1b + offset ); - } - - public byte[] serialize() - { - final byte[] result = new byte[ getSize() ]; - serialize( result, 0 ); - return result; - } - - /** - * Size of record - */ - public static int getSize() - { - return 0 + 4 + 4 + 18 + 1 + 1; - } - - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - LSTFAbstractType other = (LSTFAbstractType) obj; - if ( field_1_lsid != other.field_1_lsid ) - return false; - if ( field_2_tplc != other.field_2_tplc ) - return false; - if ( !Arrays.equals( field_3_rgistdPara, other.field_3_rgistdPara ) ) - return false; - if ( field_4_flags != other.field_4_flags ) - return false; - if ( field_5_grfhic == null ) - { - if ( other.field_5_grfhic != null ) - return false; - } - else if ( !field_5_grfhic.equals( other.field_5_grfhic ) ) - return false; - return true; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + field_1_lsid; - result = prime * result + field_2_tplc; - result = prime * result + Arrays.hashCode( field_3_rgistdPara ); - result = prime * result + field_4_flags; - result = prime * result + field_5_grfhic.hashCode(); - return result; - } - - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[LSTF]\n"); - builder.append(" .lsid = "); - builder.append(" (").append(getLsid()).append(" )\n"); - builder.append(" .tplc = "); - builder.append(" (").append(getTplc()).append(" )\n"); - builder.append(" .rgistdPara = "); - builder.append(" (").append(Arrays.toString(getRgistdPara())).append(" )\n"); - builder.append(" .flags = "); - builder.append(" (").append(getFlags()).append(" )\n"); - builder.append(" .fSimpleList = ").append(isFSimpleList()).append('\n'); - builder.append(" .unused1 = ").append(isUnused1()).append('\n'); - builder.append(" .fAutoNum = ").append(isFAutoNum()).append('\n'); - builder.append(" .unused2 = ").append(isUnused2()).append('\n'); - builder.append(" .fHybrid = ").append(isFHybrid()).append('\n'); - builder.append(" .reserved1 = ").append(getReserved1()).append('\n'); - builder.append(" .grfhic = "); - builder.append(" (").append(getGrfhic()).append(" )\n"); - - builder.append("[/LSTF]\n"); - return builder.toString(); - } - - /** - * A signed integer that specifies the list identifier. This MUST be unique for each LSTF. This value MUST not be 0xFFFFFFFF. - */ - @Internal - public int getLsid() - { - return field_1_lsid; - } - - /** - * A signed integer that specifies the list identifier. This MUST be unique for each LSTF. This value MUST not be 0xFFFFFFFF. - */ - @Internal - public void setLsid( int field_1_lsid ) - { - this.field_1_lsid = field_1_lsid; - } - - /** - * A Tplc that specifies a unique identifier for this LSTF that MAY be used for user interface purposes. If fHybrid is nonzero, this MUST be ignored. - */ - @Internal - public int getTplc() - { - return field_2_tplc; - } - - /** - * A Tplc that specifies a unique identifier for this LSTF that MAY be used for user interface purposes. If fHybrid is nonzero, this MUST be ignored. - */ - @Internal - public void setTplc( int field_2_tplc ) - { - this.field_2_tplc = field_2_tplc; - } - - /** - * An array of nine 16-bit signed integers. Each element of rgistdPara specifies the ISTD of the style that is linked to the corresponding level in the list. If no style is linked to a given level, the value of the corresponding element of rgistdPara MUST be 0x0FFF. - */ - @Internal - public short[] getRgistdPara() - { - return field_3_rgistdPara; - } - - /** - * An array of nine 16-bit signed integers. Each element of rgistdPara specifies the ISTD of the style that is linked to the corresponding level in the list. If no style is linked to a given level, the value of the corresponding element of rgistdPara MUST be 0x0FFF. - */ - @Internal - public void setRgistdPara( short[] field_3_rgistdPara ) - { - this.field_3_rgistdPara = field_3_rgistdPara; - } - - /** - * Get the flags field for the LSTF record. - */ - @Internal - public byte getFlags() - { - return field_4_flags; - } - - /** - * Set the flags field for the LSTF record. - */ - @Internal - public void setFlags( byte field_4_flags ) - { - this.field_4_flags = field_4_flags; - } - - /** - * A grfhic that specifies the HTML incompatibilities of the list.. - */ - @Internal - public Grfhic getGrfhic() - { - return field_5_grfhic; - } - - /** - * A grfhic that specifies the HTML incompatibilities of the list.. - */ - @Internal - public void setGrfhic( Grfhic field_5_grfhic ) - { - this.field_5_grfhic = field_5_grfhic; - } - - /** - * Sets the fSimpleList field value. - * A bit that, when set to 0x1, specifies that this LSTF represents a simple (one-level) list that has one corresponding LVL (see the fcPlfLst field of FibRgFcLcb97). Otherwise, this LSTF represents a multi-level list that has nine corresponding LVLs - */ - @Internal - public void setFSimpleList( boolean value ) - { - field_4_flags = (byte)fSimpleList.setBoolean(field_4_flags, value); - } - - /** - * A bit that, when set to 0x1, specifies that this LSTF represents a simple (one-level) list that has one corresponding LVL (see the fcPlfLst field of FibRgFcLcb97). Otherwise, this LSTF represents a multi-level list that has nine corresponding LVLs - * @return the fSimpleList field value. - */ - @Internal - public boolean isFSimpleList() - { - return fSimpleList.isSet(field_4_flags); - } - - /** - * Sets the unused1 field value. - * This bit MUST be ignored - */ - @Internal - public void setUnused1( boolean value ) - { - field_4_flags = (byte)unused1.setBoolean(field_4_flags, value); - } - - /** - * This bit MUST be ignored - * @return the unused1 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public boolean isUnused1() - { - return unused1.isSet(field_4_flags); - } - - /** - * Sets the fAutoNum field value. - * A bit that specifies whether the list that this LSTF represents is used for the AUTONUMOUT, AUTONUMLGL, and AUTONUM fields (see AUTONUMOUT, AUTONUMLGL, and AUTONUM in flt) - */ - @Internal - public void setFAutoNum( boolean value ) - { - field_4_flags = (byte)fAutoNum.setBoolean(field_4_flags, value); - } - - /** - * A bit that specifies whether the list that this LSTF represents is used for the AUTONUMOUT, AUTONUMLGL, and AUTONUM fields (see AUTONUMOUT, AUTONUMLGL, and AUTONUM in flt) - * @return the fAutoNum field value. - */ - @Internal - public boolean isFAutoNum() - { - return fAutoNum.isSet(field_4_flags); - } - - /** - * Sets the unused2 field value. - * This bit MUST be ignored - */ - @Internal - public void setUnused2( boolean value ) - { - field_4_flags = (byte)unused2.setBoolean(field_4_flags, value); - } - - /** - * This bit MUST be ignored - * @return the unused2 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public boolean isUnused2() - { - return unused2.isSet(field_4_flags); - } - - /** - * Sets the fHybrid field value. - * A bit that specifies whether the list this LSTF defines is a hybrid list - */ - @Internal - public void setFHybrid( boolean value ) - { - field_4_flags = (byte)fHybrid.setBoolean(field_4_flags, value); - } - - /** - * A bit that specifies whether the list this LSTF defines is a hybrid list - * @return the fHybrid field value. - */ - @Internal - public boolean isFHybrid() - { - return fHybrid.isSet(field_4_flags); - } - - /** - * Sets the reserved1 field value. - * This MUST be zero, and MUST be ignored. - */ - @Internal - public void setReserved1( byte value ) - { - field_4_flags = (byte)reserved1.setValue(field_4_flags, value); - } - - /** - * This MUST be zero, and MUST be ignored. - * @return the reserved1 field value. - * @deprecated This field should not be used according to specification - */ - @Internal - @Deprecated - public byte getReserved1() - { - return ( byte )reserved1.getValue(field_4_flags); - } - -} // END OF CLASS +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.model.types; + +import java.util.Arrays; + +import org.apache.poi.hwpf.model.Grfhic; +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * The LSTF structure contains formatting properties that apply to an entire list. +

    Class and fields descriptions are quoted from Microsoft Office Word 97-2007 Binary + File Format and [MS-DOC] - v20110608 Word (.doc) Binary File Format + + *

    + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. + *

    + * This class is internal. It content or properties may change without notice + * due to changes in our knowledge of internal Microsoft Word binary structures. + + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format + Specification [*.doc] and [MS-DOC] - v20110608 Word (.doc) Binary File Format + + */ +@Internal +public abstract class LSTFAbstractType +{ + + protected int field_1_lsid; + protected int field_2_tplc; + protected short[] field_3_rgistdPara; + protected byte field_4_flags; + /**/private static final BitField fSimpleList = new BitField(0x01); + /**/private static final BitField unused1 = new BitField(0x02); + /**/private static final BitField fAutoNum = new BitField(0x04); + /**/private static final BitField unused2 = new BitField(0x08); + /**/private static final BitField fHybrid = new BitField(0x10); + /**/private static final BitField reserved1 = new BitField(0xE0); + protected Grfhic field_5_grfhic; + + protected LSTFAbstractType() + { + this.field_3_rgistdPara = new short[0]; + this.field_5_grfhic = new Grfhic(); + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); + field_2_tplc = LittleEndian.getInt( data, 0x4 + offset ); + field_3_rgistdPara = LittleEndian.getShortArray( data, 0x8 + offset, 18 ); + field_4_flags = data[ 0x1a + offset ]; + field_5_grfhic = new Grfhic( data, 0x1b + offset ); + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putInt( data, 0x0 + offset, field_1_lsid ); + LittleEndian.putInt( data, 0x4 + offset, field_2_tplc ); + LittleEndian.putShortArray( data, 0x8 + offset, field_3_rgistdPara ); + data[ 0x1a + offset ] = field_4_flags; + field_5_grfhic.serialize( data, 0x1b + offset ); + } + + public byte[] serialize() + { + final byte[] result = new byte[ getSize() ]; + serialize( result, 0 ); + return result; + } + + /** + * Size of record + */ + public static int getSize() + { + return 0 + 4 + 4 + 18 + 1 + 1; + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + return true; + if ( obj == null ) + return false; + if ( getClass() != obj.getClass() ) + return false; + LSTFAbstractType other = (LSTFAbstractType) obj; + if ( field_1_lsid != other.field_1_lsid ) + return false; + if ( field_2_tplc != other.field_2_tplc ) + return false; + if ( !Arrays.equals( field_3_rgistdPara, other.field_3_rgistdPara ) ) + return false; + if ( field_4_flags != other.field_4_flags ) + return false; + if ( field_5_grfhic == null ) + { + if ( other.field_5_grfhic != null ) + return false; + } + else if ( !field_5_grfhic.equals( other.field_5_grfhic ) ) + return false; + return true; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + field_1_lsid; + result = prime * result + field_2_tplc; + result = prime * result + Arrays.hashCode( field_3_rgistdPara ); + result = prime * result + field_4_flags; + result = prime * result + field_5_grfhic.hashCode(); + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[LSTF]\n"); + builder.append(" .lsid = "); + builder.append(" (").append(getLsid()).append(" )\n"); + builder.append(" .tplc = "); + builder.append(" (").append(getTplc()).append(" )\n"); + builder.append(" .rgistdPara = "); + builder.append(" (").append(Arrays.toString(getRgistdPara())).append(" )\n"); + builder.append(" .flags = "); + builder.append(" (").append(getFlags()).append(" )\n"); + builder.append(" .fSimpleList = ").append(isFSimpleList()).append('\n'); + builder.append(" .unused1 = ").append(isUnused1()).append('\n'); + builder.append(" .fAutoNum = ").append(isFAutoNum()).append('\n'); + builder.append(" .unused2 = ").append(isUnused2()).append('\n'); + builder.append(" .fHybrid = ").append(isFHybrid()).append('\n'); + builder.append(" .reserved1 = ").append(getReserved1()).append('\n'); + builder.append(" .grfhic = "); + builder.append(" (").append(getGrfhic()).append(" )\n"); + + builder.append("[/LSTF]\n"); + return builder.toString(); + } + + /** + * A signed integer that specifies the list identifier. This MUST be unique for each LSTF. This value MUST not be 0xFFFFFFFF. + */ + @Internal + public int getLsid() + { + return field_1_lsid; + } + + /** + * A signed integer that specifies the list identifier. This MUST be unique for each LSTF. This value MUST not be 0xFFFFFFFF. + */ + @Internal + public void setLsid( int field_1_lsid ) + { + this.field_1_lsid = field_1_lsid; + } + + /** + * A Tplc that specifies a unique identifier for this LSTF that MAY be used for user interface purposes. If fHybrid is nonzero, this MUST be ignored. + */ + @Internal + public int getTplc() + { + return field_2_tplc; + } + + /** + * A Tplc that specifies a unique identifier for this LSTF that MAY be used for user interface purposes. If fHybrid is nonzero, this MUST be ignored. + */ + @Internal + public void setTplc( int field_2_tplc ) + { + this.field_2_tplc = field_2_tplc; + } + + /** + * An array of nine 16-bit signed integers. Each element of rgistdPara specifies the ISTD of the style that is linked to the corresponding level in the list. If no style is linked to a given level, the value of the corresponding element of rgistdPara MUST be 0x0FFF. + */ + @Internal + public short[] getRgistdPara() + { + return field_3_rgistdPara; + } + + /** + * An array of nine 16-bit signed integers. Each element of rgistdPara specifies the ISTD of the style that is linked to the corresponding level in the list. If no style is linked to a given level, the value of the corresponding element of rgistdPara MUST be 0x0FFF. + */ + @Internal + public void setRgistdPara( short[] field_3_rgistdPara ) + { + this.field_3_rgistdPara = field_3_rgistdPara; + } + + /** + * Get the flags field for the LSTF record. + */ + @Internal + public byte getFlags() + { + return field_4_flags; + } + + /** + * Set the flags field for the LSTF record. + */ + @Internal + public void setFlags( byte field_4_flags ) + { + this.field_4_flags = field_4_flags; + } + + /** + * A grfhic that specifies the HTML incompatibilities of the list.. + */ + @Internal + public Grfhic getGrfhic() + { + return field_5_grfhic; + } + + /** + * A grfhic that specifies the HTML incompatibilities of the list.. + */ + @Internal + public void setGrfhic( Grfhic field_5_grfhic ) + { + this.field_5_grfhic = field_5_grfhic; + } + + /** + * Sets the fSimpleList field value. + * A bit that, when set to 0x1, specifies that this LSTF represents a simple (one-level) list that has one corresponding LVL (see the fcPlfLst field of FibRgFcLcb97). Otherwise, this LSTF represents a multi-level list that has nine corresponding LVLs + */ + @Internal + public void setFSimpleList( boolean value ) + { + field_4_flags = (byte)fSimpleList.setBoolean(field_4_flags, value); + } + + /** + * A bit that, when set to 0x1, specifies that this LSTF represents a simple (one-level) list that has one corresponding LVL (see the fcPlfLst field of FibRgFcLcb97). Otherwise, this LSTF represents a multi-level list that has nine corresponding LVLs + * @return the fSimpleList field value. + */ + @Internal + public boolean isFSimpleList() + { + return fSimpleList.isSet(field_4_flags); + } + + /** + * Sets the unused1 field value. + * This bit MUST be ignored + */ + @Internal + public void setUnused1( boolean value ) + { + field_4_flags = (byte)unused1.setBoolean(field_4_flags, value); + } + + /** + * This bit MUST be ignored + * @return the unused1 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public boolean isUnused1() + { + return unused1.isSet(field_4_flags); + } + + /** + * Sets the fAutoNum field value. + * A bit that specifies whether the list that this LSTF represents is used for the AUTONUMOUT, AUTONUMLGL, and AUTONUM fields (see AUTONUMOUT, AUTONUMLGL, and AUTONUM in flt) + */ + @Internal + public void setFAutoNum( boolean value ) + { + field_4_flags = (byte)fAutoNum.setBoolean(field_4_flags, value); + } + + /** + * A bit that specifies whether the list that this LSTF represents is used for the AUTONUMOUT, AUTONUMLGL, and AUTONUM fields (see AUTONUMOUT, AUTONUMLGL, and AUTONUM in flt) + * @return the fAutoNum field value. + */ + @Internal + public boolean isFAutoNum() + { + return fAutoNum.isSet(field_4_flags); + } + + /** + * Sets the unused2 field value. + * This bit MUST be ignored + */ + @Internal + public void setUnused2( boolean value ) + { + field_4_flags = (byte)unused2.setBoolean(field_4_flags, value); + } + + /** + * This bit MUST be ignored + * @return the unused2 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public boolean isUnused2() + { + return unused2.isSet(field_4_flags); + } + + /** + * Sets the fHybrid field value. + * A bit that specifies whether the list this LSTF defines is a hybrid list + */ + @Internal + public void setFHybrid( boolean value ) + { + field_4_flags = (byte)fHybrid.setBoolean(field_4_flags, value); + } + + /** + * A bit that specifies whether the list this LSTF defines is a hybrid list + * @return the fHybrid field value. + */ + @Internal + public boolean isFHybrid() + { + return fHybrid.isSet(field_4_flags); + } + + /** + * Sets the reserved1 field value. + * This MUST be zero, and MUST be ignored. + */ + @Internal + public void setReserved1( byte value ) + { + field_4_flags = (byte)reserved1.setValue(field_4_flags, value); + } + + /** + * This MUST be zero, and MUST be ignored. + * @return the reserved1 field value. + * @deprecated This field should not be used according to specification + */ + @Internal + @Deprecated + public byte getReserved1() + { + return ( byte )reserved1.getValue(field_4_flags); + } + +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/TLPAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/TLPAbstractType.java index 58fab86528..0e6ad3a88f 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/TLPAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/TLPAbstractType.java @@ -1,292 +1,292 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model.types; - -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * Table Autoformat Look sPecifier (TLP). - *

    - * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 - * Binary File Format - * - * NOTE: This source is automatically generated please do not modify this file. - * Either subclass or remove the record in src/records/definitions. - * - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary - * File Format Specification [*.doc] - */ -@Internal -public abstract class TLPAbstractType -{ - - protected short field_1_itl; - protected byte field_2_tlp_flags; - private static final BitField fBorders = new BitField( 0x0001 ); - private static final BitField fShading = new BitField( 0x0002 ); - private static final BitField fFont = new BitField( 0x0004 ); - private static final BitField fColor = new BitField( 0x0008 ); - private static final BitField fBestFit = new BitField( 0x0010 ); - private static final BitField fHdrRows = new BitField( 0x0020 ); - private static final BitField fLastRow = new BitField( 0x0040 ); - - public TLPAbstractType() - { - - } - - protected void fillFields( byte[] data, int offset ) - { - field_1_itl = LittleEndian.getShort( data, 0x0 + offset ); - field_2_tlp_flags = data[0x2 + offset]; - } - - public void serialize( byte[] data, int offset ) - { - LittleEndian.putShort( data, 0x0 + offset, field_1_itl ); - data[0x2 + offset] = field_2_tlp_flags; - } - - public String toString() - { - StringBuffer buffer = new StringBuffer(); - - buffer.append( "[TLP]\n" ); - - buffer.append( " .itl = " ); - buffer.append( " (" ).append( getItl() ).append( " )\n" ); - - buffer.append( " .tlp_flags = " ); - buffer.append( " (" ).append( getTlp_flags() ).append( " )\n" ); - buffer.append( " .fBorders = " ) - .append( isFBorders() ).append( '\n' ); - buffer.append( " .fShading = " ) - .append( isFShading() ).append( '\n' ); - buffer.append( " .fFont = " ) - .append( isFFont() ).append( '\n' ); - buffer.append( " .fColor = " ) - .append( isFColor() ).append( '\n' ); - buffer.append( " .fBestFit = " ) - .append( isFBestFit() ).append( '\n' ); - buffer.append( " .fHdrRows = " ) - .append( isFHdrRows() ).append( '\n' ); - buffer.append( " .fLastRow = " ) - .append( isFLastRow() ).append( '\n' ); - - buffer.append( "[/TLP]\n" ); - return buffer.toString(); - } - - /** - * Size of record (exluding 4 byte header) - */ - public int getSize() - { - return 4 + +2 + 1; - } - - /** - * Get the itl field for the TLP record. - */ - public short getItl() - { - return field_1_itl; - } - - /** - * Set the itl field for the TLP record. - */ - public void setItl( short field_1_itl ) - { - this.field_1_itl = field_1_itl; - } - - /** - * Get the tlp_flags field for the TLP record. - */ - public byte getTlp_flags() - { - return field_2_tlp_flags; - } - - /** - * Set the tlp_flags field for the TLP record. - */ - public void setTlp_flags( byte field_2_tlp_flags ) - { - this.field_2_tlp_flags = field_2_tlp_flags; - } - - /** - * Sets the fBorders field value. When == 1, use the border properties from - * the selected table look - */ - public void setFBorders( boolean value ) - { - field_2_tlp_flags = (byte) fBorders.setBoolean( field_2_tlp_flags, - value ); - - } - - /** - * When == 1, use the border properties from the selected table look - * - * @return the fBorders field value. - */ - public boolean isFBorders() - { - return fBorders.isSet( field_2_tlp_flags ); - - } - - /** - * Sets the fShading field value. When == 1, use the shading properties from - * the selected table look - */ - public void setFShading( boolean value ) - { - field_2_tlp_flags = (byte) fShading.setBoolean( field_2_tlp_flags, - value ); - - } - - /** - * When == 1, use the shading properties from the selected table look - * - * @return the fShading field value. - */ - public boolean isFShading() - { - return fShading.isSet( field_2_tlp_flags ); - - } - - /** - * Sets the fFont field value. When == 1, use the font from the selected - * table look - */ - public void setFFont( boolean value ) - { - field_2_tlp_flags = (byte) fFont.setBoolean( field_2_tlp_flags, value ); - - } - - /** - * When == 1, use the font from the selected table look - * - * @return the fFont field value. - */ - public boolean isFFont() - { - return fFont.isSet( field_2_tlp_flags ); - - } - - /** - * Sets the fColor field value. When == 1, use the color from the selected - * table look - */ - public void setFColor( boolean value ) - { - field_2_tlp_flags = (byte) fColor.setBoolean( field_2_tlp_flags, value ); - - } - - /** - * When == 1, use the color from the selected table look - * - * @return the fColor field value. - */ - public boolean isFColor() - { - return fColor.isSet( field_2_tlp_flags ); - - } - - /** - * Sets the fBestFit field value. When == 1, do best fit from the selected - * table look - */ - public void setFBestFit( boolean value ) - { - field_2_tlp_flags = (byte) fBestFit.setBoolean( field_2_tlp_flags, - value ); - - } - - /** - * When == 1, do best fit from the selected table look - * - * @return the fBestFit field value. - */ - public boolean isFBestFit() - { - return fBestFit.isSet( field_2_tlp_flags ); - - } - - /** - * Sets the fHdrRows field value. When == 1, apply properties from the - * selected table look to the header rows in the table - */ - public void setFHdrRows( boolean value ) - { - field_2_tlp_flags = (byte) fHdrRows.setBoolean( field_2_tlp_flags, - value ); - - } - - /** - * When == 1, apply properties from the selected table look to the header - * rows in the table - * - * @return the fHdrRows field value. - */ - public boolean isFHdrRows() - { - return fHdrRows.isSet( field_2_tlp_flags ); - - } - - /** - * Sets the fLastRow field value. When == 1, apply properties from the - * selected table look to the last row in the table - */ - public void setFLastRow( boolean value ) - { - field_2_tlp_flags = (byte) fLastRow.setBoolean( field_2_tlp_flags, - value ); - - } - - /** - * When == 1, apply properties from the selected table look to the last row - * in the table - * - * @return the fLastRow field value. - */ - public boolean isFLastRow() - { - return fLastRow.isSet( field_2_tlp_flags ); - - } - -} // END OF CLASS - +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.model.types; + +import org.apache.poi.util.BitField; +import org.apache.poi.util.Internal; +import org.apache.poi.util.LittleEndian; + +/** + * Table Autoformat Look sPecifier (TLP). + *

    + * Class and fields descriptions are quoted from Microsoft Office Word 97-2007 + * Binary File Format + * + * NOTE: This source is automatically generated please do not modify this file. + * Either subclass or remove the record in src/records/definitions. + * + * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary + * File Format Specification [*.doc] + */ +@Internal +public abstract class TLPAbstractType +{ + + protected short field_1_itl; + protected byte field_2_tlp_flags; + private static final BitField fBorders = new BitField( 0x0001 ); + private static final BitField fShading = new BitField( 0x0002 ); + private static final BitField fFont = new BitField( 0x0004 ); + private static final BitField fColor = new BitField( 0x0008 ); + private static final BitField fBestFit = new BitField( 0x0010 ); + private static final BitField fHdrRows = new BitField( 0x0020 ); + private static final BitField fLastRow = new BitField( 0x0040 ); + + public TLPAbstractType() + { + + } + + protected void fillFields( byte[] data, int offset ) + { + field_1_itl = LittleEndian.getShort( data, 0x0 + offset ); + field_2_tlp_flags = data[0x2 + offset]; + } + + public void serialize( byte[] data, int offset ) + { + LittleEndian.putShort( data, 0x0 + offset, field_1_itl ); + data[0x2 + offset] = field_2_tlp_flags; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append( "[TLP]\n" ); + + buffer.append( " .itl = " ); + buffer.append( " (" ).append( getItl() ).append( " )\n" ); + + buffer.append( " .tlp_flags = " ); + buffer.append( " (" ).append( getTlp_flags() ).append( " )\n" ); + buffer.append( " .fBorders = " ) + .append( isFBorders() ).append( '\n' ); + buffer.append( " .fShading = " ) + .append( isFShading() ).append( '\n' ); + buffer.append( " .fFont = " ) + .append( isFFont() ).append( '\n' ); + buffer.append( " .fColor = " ) + .append( isFColor() ).append( '\n' ); + buffer.append( " .fBestFit = " ) + .append( isFBestFit() ).append( '\n' ); + buffer.append( " .fHdrRows = " ) + .append( isFHdrRows() ).append( '\n' ); + buffer.append( " .fLastRow = " ) + .append( isFLastRow() ).append( '\n' ); + + buffer.append( "[/TLP]\n" ); + return buffer.toString(); + } + + /** + * Size of record (exluding 4 byte header) + */ + public int getSize() + { + return 4 + +2 + 1; + } + + /** + * Get the itl field for the TLP record. + */ + public short getItl() + { + return field_1_itl; + } + + /** + * Set the itl field for the TLP record. + */ + public void setItl( short field_1_itl ) + { + this.field_1_itl = field_1_itl; + } + + /** + * Get the tlp_flags field for the TLP record. + */ + public byte getTlp_flags() + { + return field_2_tlp_flags; + } + + /** + * Set the tlp_flags field for the TLP record. + */ + public void setTlp_flags( byte field_2_tlp_flags ) + { + this.field_2_tlp_flags = field_2_tlp_flags; + } + + /** + * Sets the fBorders field value. When == 1, use the border properties from + * the selected table look + */ + public void setFBorders( boolean value ) + { + field_2_tlp_flags = (byte) fBorders.setBoolean( field_2_tlp_flags, + value ); + + } + + /** + * When == 1, use the border properties from the selected table look + * + * @return the fBorders field value. + */ + public boolean isFBorders() + { + return fBorders.isSet( field_2_tlp_flags ); + + } + + /** + * Sets the fShading field value. When == 1, use the shading properties from + * the selected table look + */ + public void setFShading( boolean value ) + { + field_2_tlp_flags = (byte) fShading.setBoolean( field_2_tlp_flags, + value ); + + } + + /** + * When == 1, use the shading properties from the selected table look + * + * @return the fShading field value. + */ + public boolean isFShading() + { + return fShading.isSet( field_2_tlp_flags ); + + } + + /** + * Sets the fFont field value. When == 1, use the font from the selected + * table look + */ + public void setFFont( boolean value ) + { + field_2_tlp_flags = (byte) fFont.setBoolean( field_2_tlp_flags, value ); + + } + + /** + * When == 1, use the font from the selected table look + * + * @return the fFont field value. + */ + public boolean isFFont() + { + return fFont.isSet( field_2_tlp_flags ); + + } + + /** + * Sets the fColor field value. When == 1, use the color from the selected + * table look + */ + public void setFColor( boolean value ) + { + field_2_tlp_flags = (byte) fColor.setBoolean( field_2_tlp_flags, value ); + + } + + /** + * When == 1, use the color from the selected table look + * + * @return the fColor field value. + */ + public boolean isFColor() + { + return fColor.isSet( field_2_tlp_flags ); + + } + + /** + * Sets the fBestFit field value. When == 1, do best fit from the selected + * table look + */ + public void setFBestFit( boolean value ) + { + field_2_tlp_flags = (byte) fBestFit.setBoolean( field_2_tlp_flags, + value ); + + } + + /** + * When == 1, do best fit from the selected table look + * + * @return the fBestFit field value. + */ + public boolean isFBestFit() + { + return fBestFit.isSet( field_2_tlp_flags ); + + } + + /** + * Sets the fHdrRows field value. When == 1, apply properties from the + * selected table look to the header rows in the table + */ + public void setFHdrRows( boolean value ) + { + field_2_tlp_flags = (byte) fHdrRows.setBoolean( field_2_tlp_flags, + value ); + + } + + /** + * When == 1, apply properties from the selected table look to the header + * rows in the table + * + * @return the fHdrRows field value. + */ + public boolean isFHdrRows() + { + return fHdrRows.isSet( field_2_tlp_flags ); + + } + + /** + * Sets the fLastRow field value. When == 1, apply properties from the + * selected table look to the last row in the table + */ + public void setFLastRow( boolean value ) + { + field_2_tlp_flags = (byte) fLastRow.setBoolean( field_2_tlp_flags, + value ); + + } + + /** + * When == 1, apply properties from the selected table look to the last row + * in the table + * + * @return the fLastRow field value. + */ + public boolean isFLastRow() + { + return fLastRow.isSet( field_2_tlp_flags ); + + } + +} // END OF CLASS + diff --git a/src/scratchpad/testcases/org/apache/poi/hmef/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hmef/TestBugs.java index 6b698e962f..27d69f69f0 100644 --- a/src/scratchpad/testcases/org/apache/poi/hmef/TestBugs.java +++ b/src/scratchpad/testcases/org/apache/poi/hmef/TestBugs.java @@ -1,69 +1,69 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hmef; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.hmef.attribute.MAPIAttribute; -import org.apache.poi.hmef.attribute.TNEFAttribute; -import org.apache.poi.hmef.attribute.TNEFProperty; -import org.apache.poi.hsmf.datatypes.MAPIProperty; -import org.apache.poi.util.LittleEndian; - -import org.junit.Test; - -public class TestBugs { - @Test - public void test52400ReadSimpleTNEF() throws Exception { - POIDataSamples samples = POIDataSamples.getHMEFInstance(); - String testFile = "bug52400-winmail-simple.dat"; - HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile)); - MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML); - String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat)); - assertTrue(bodyStr.contains("This is the message body.")); - } - - @Test - public void test52400ReadAttachedTNEF() throws Exception { - POIDataSamples samples = POIDataSamples.getHMEFInstance(); - String testFile = "bug52400-winmail-with-attachments.dat"; - HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile)); - MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML); - String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat)); - assertTrue(bodyStr.contains("There are also two attachments.")); - assertEquals(2, tnefDat.getAttachments().size()); - } - - private String getEncoding(HMEFMessage tnefDat) { - TNEFAttribute oemCP = tnefDat.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE); - MAPIAttribute cpId = tnefDat.getMessageMAPIAttribute(MAPIProperty.INTERNET_CPID); - int codePage = 1252; - if (oemCP != null) { - codePage = LittleEndian.getInt(oemCP.getData()); - } else if (cpId != null) { - codePage = LittleEndian.getInt(cpId.getData()); - } - switch (codePage) { - // see http://en.wikipedia.org/wiki/Code_page for more - case 1252: return "Windows-1252"; - case 20127: return "US-ASCII"; - default: return "cp"+codePage; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hmef; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.hmef.attribute.MAPIAttribute; +import org.apache.poi.hmef.attribute.TNEFAttribute; +import org.apache.poi.hmef.attribute.TNEFProperty; +import org.apache.poi.hsmf.datatypes.MAPIProperty; +import org.apache.poi.util.LittleEndian; + +import org.junit.Test; + +public class TestBugs { + @Test + public void test52400ReadSimpleTNEF() throws Exception { + POIDataSamples samples = POIDataSamples.getHMEFInstance(); + String testFile = "bug52400-winmail-simple.dat"; + HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile)); + MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML); + String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat)); + assertTrue(bodyStr.contains("This is the message body.")); + } + + @Test + public void test52400ReadAttachedTNEF() throws Exception { + POIDataSamples samples = POIDataSamples.getHMEFInstance(); + String testFile = "bug52400-winmail-with-attachments.dat"; + HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile)); + MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML); + String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat)); + assertTrue(bodyStr.contains("There are also two attachments.")); + assertEquals(2, tnefDat.getAttachments().size()); + } + + private String getEncoding(HMEFMessage tnefDat) { + TNEFAttribute oemCP = tnefDat.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE); + MAPIAttribute cpId = tnefDat.getMessageMAPIAttribute(MAPIProperty.INTERNET_CPID); + int codePage = 1252; + if (oemCP != null) { + codePage = LittleEndian.getInt(oemCP.getData()); + } else if (cpId != null) { + codePage = LittleEndian.getInt(cpId.getData()); + } + switch (codePage) { + // see http://en.wikipedia.org/wiki/Code_page for more + case 1252: return "Windows-1252"; + case 20127: return "US-ASCII"; + default: return "cp"+codePage; + } + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java index 227f2c4645..37e7e31dbc 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java @@ -1,195 +1,195 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.record; - - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.security.MessageDigest; -import java.util.List; - -import org.apache.commons.codec.binary.Base64; -import org.apache.poi.POIDataSamples; -import org.apache.poi.hpsf.DocumentSummaryInformation; -import org.apache.poi.hpsf.PropertySet; -import org.apache.poi.hpsf.PropertySetFactory; -import org.apache.poi.hpsf.SummaryInformation; -import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; -import org.apache.poi.hslf.usermodel.HSLFPictureData; -import org.apache.poi.hslf.usermodel.HSLFSlide; -import org.apache.poi.hslf.usermodel.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; -import org.apache.poi.hslf.usermodel.HSLFTextParagraph; -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor; -import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Tests that DocumentEncryption works properly. - */ -public class TestDocumentEncryption { - POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - - @Before - @After // also afterwards to not affect other tests running in the same JVM - public void resetPassword() { - Biff8EncryptionKey.setCurrentUserPassword(null); - } - - @Test - public void cryptoAPIDecryptionOther() throws Exception { - Biff8EncryptionKey.setCurrentUserPassword("hello"); - String encPpts[] = { - "Password_Protected-56-hello.ppt", - "Password_Protected-hello.ppt", - "Password_Protected-np-hello.ppt", - }; - - for (String pptFile : encPpts) { - try { - NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile(pptFile), true); - HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs); - new HSLFSlideShow(hss).close(); - fs.close(); - } catch (EncryptedPowerPointFileException e) { - fail(pptFile+" can't be decrypted"); - } - } - } - - @Test - public void cryptoAPIChangeKeySize() throws Exception { - String pptFile = "cryptoapi-proc2356.ppt"; - Biff8EncryptionKey.setCurrentUserPassword("crypto"); - NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile(pptFile), true); - HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs); - // need to cache data (i.e. read all data) before changing the key size - List picsExpected = hss.getPictureData(); - hss.getDocumentSummaryInformation(); - EncryptionInfo ei = hss.getDocumentEncryptionAtom().getEncryptionInfo(); - ((CryptoAPIEncryptionHeader)ei.getHeader()).setKeySize(0x78); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - hss.write(bos); - hss.close(); - fs.close(); - - fs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - hss = new HSLFSlideShowImpl(fs); - List picsActual = hss.getPictureData(); - - assertEquals(picsExpected.size(), picsActual.size()); - for (int i=0; i picsExpected = hss.getPictureData(); + hss.getDocumentSummaryInformation(); + EncryptionInfo ei = hss.getDocumentEncryptionAtom().getEncryptionInfo(); + ((CryptoAPIEncryptionHeader)ei.getHeader()).setKeySize(0x78); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + hss.write(bos); + hss.close(); + fs.close(); + + fs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); + hss = new HSLFSlideShowImpl(fs); + List picsActual = hss.getPictureData(); + + assertEquals(picsExpected.size(), picsActual.size()); + for (int i=0; i fontMap = new HashMap(); - Map fallbackMap = new HashMap(); - - for (String fontFile[] : fontFiles) { - File f = new File(fontFile[0]); - assumeTrue("necessary font file "+f.getName()+" not downloaded.", f.exists()); - - Font font = Font.createFont(Font.TRUETYPE_FONT, f); - ge.registerFont(font); - - Map map = ("mapped".equals(fontFile[1]) ? fontMap : fallbackMap); - map.put(fontFile[2], font.getFamily()); - } - - InputStream is = slTests.openResourceAsStream("bug55902-mixedFontChineseCharacters.ppt"); - HSLFSlideShow ss = new HSLFSlideShow(is); - is.close(); - - Dimension pgsize = ss.getPageSize(); - - HSLFSlide slide = ss.getSlides().get(0); - - // render it - double zoom = 1; - AffineTransform at = new AffineTransform(); - at.setToScale(zoom, zoom); - - BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR); - Graphics2D graphics = imgActual.createGraphics(); - graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap); - graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - graphics.setTransform(at); - graphics.setPaint(Color.white); - graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height)); - slide.draw(graphics); - - BufferedImage imgExpected = ImageIO.read(slTests.getFile("bug55902-mixedChars.png")); - DataBufferByte expectedDB = (DataBufferByte)imgExpected.getRaster().getDataBuffer(); - DataBufferByte actualDB = (DataBufferByte)imgActual.getRaster().getDataBuffer(); - byte[] expectedData = expectedDB.getData(0); - byte[] actualData = actualDB.getData(0); - - // allow to find out what the actual difference is in CI where this fails currently - if(!Arrays.equals(expectedData, actualData)) { - ImageIO.write(imgActual, "PNG", TempFile.createTempFile("TestFontRendering", ".png")); - } - - assertArrayEquals("Expected to have matching raster-arrays, but found differences", expectedData, actualData); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.usermodel; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assume.assumeTrue; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import java.io.File; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.imageio.ImageIO; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.sl.draw.Drawable; +import org.apache.poi.util.TempFile; +import org.junit.Test; + +/** + * Test font rendering of alternative and fallback fonts + */ +public class TestFontRendering { + private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); + + // @Ignore2("This fails on some systems because fonts are rendered slightly different") + @Test + public void bug55902mixedFontWithChineseCharacters() throws Exception { + // font files need to be downloaded first via + // ant test-scratchpad-download-resources + String fontFiles[][] = { + // Calibri is not available on *nix systems, so we need to use another similar free font + { "build/scratchpad-test-resources/Cabin-Regular.ttf", "mapped", "Calibri" }, + + // use "MS PGothic" if available (Windows only) ... + // for the junit test not all chars are rendered + { "build/scratchpad-test-resources/mona.ttf", "fallback", "Cabin" } + }; + + // setup fonts (especially needed, when run under *nix systems) + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Map fontMap = new HashMap(); + Map fallbackMap = new HashMap(); + + for (String fontFile[] : fontFiles) { + File f = new File(fontFile[0]); + assumeTrue("necessary font file "+f.getName()+" not downloaded.", f.exists()); + + Font font = Font.createFont(Font.TRUETYPE_FONT, f); + ge.registerFont(font); + + Map map = ("mapped".equals(fontFile[1]) ? fontMap : fallbackMap); + map.put(fontFile[2], font.getFamily()); + } + + InputStream is = slTests.openResourceAsStream("bug55902-mixedFontChineseCharacters.ppt"); + HSLFSlideShow ss = new HSLFSlideShow(is); + is.close(); + + Dimension pgsize = ss.getPageSize(); + + HSLFSlide slide = ss.getSlides().get(0); + + // render it + double zoom = 1; + AffineTransform at = new AffineTransform(); + at.setToScale(zoom, zoom); + + BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR); + Graphics2D graphics = imgActual.createGraphics(); + graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap); + graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + graphics.setTransform(at); + graphics.setPaint(Color.white); + graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height)); + slide.draw(graphics); + + BufferedImage imgExpected = ImageIO.read(slTests.getFile("bug55902-mixedChars.png")); + DataBufferByte expectedDB = (DataBufferByte)imgExpected.getRaster().getDataBuffer(); + DataBufferByte actualDB = (DataBufferByte)imgActual.getRaster().getDataBuffer(); + byte[] expectedData = expectedDB.getData(0); + byte[] actualData = actualDB.getData(0); + + // allow to find out what the actual difference is in CI where this fails currently + if(!Arrays.equals(expectedData, actualData)) { + ImageIO.write(imgActual, "PNG", TempFile.createTempFile("TestFontRendering", ".png")); + } + + assertArrayEquals("Expected to have matching raster-arrays, but found differences", expectedData, actualData); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunk.java b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunk.java index dc4f1c969f..d3ed7d49c2 100644 --- a/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunk.java +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunk.java @@ -1,58 +1,58 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hsmf; - -import java.io.IOException; - -import org.apache.poi.hsmf.MAPIMessage; -import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; -import org.apache.poi.POIDataSamples; - -import java.util.Calendar; - -import junit.framework.TestCase; - -public final class TestMessageSubmissionChunk extends TestCase { - - private final MAPIMessage mapiMessageExtraHyphenSubmissionChunk; - private final MAPIMessage mapiMessageNormalSubmissionChunk; - - /** - * Initialise this test, load up the test messages. - * @throws Exception - */ - public TestMessageSubmissionChunk() throws IOException { - POIDataSamples samples = POIDataSamples.getHSMFInstance(); - this.mapiMessageExtraHyphenSubmissionChunk = new MAPIMessage(samples.openResourceAsStream("message_extra_hyphen_submission_chunk.msg")); - this.mapiMessageNormalSubmissionChunk = new MAPIMessage(samples.openResourceAsStream("message_normal_submission_chunk.msg")); - } - - public void testReadMessageDateExtraHyphenSubmissionChunk() throws ChunkNotFoundException { - final Calendar date = mapiMessageExtraHyphenSubmissionChunk.getMessageDate(); - TestCase.assertNotNull(date); - final int year = date.get(Calendar.YEAR); - TestCase.assertEquals(2007, year); - } - - public void testReadMessageDateNormalSubmissionChunk() throws ChunkNotFoundException { - final Calendar date = mapiMessageNormalSubmissionChunk.getMessageDate(); - TestCase.assertNotNull(date); - final int year = date.get(Calendar.YEAR); - TestCase.assertEquals(2007, year); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hsmf; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.POIDataSamples; + +import java.util.Calendar; + +import junit.framework.TestCase; + +public final class TestMessageSubmissionChunk extends TestCase { + + private final MAPIMessage mapiMessageExtraHyphenSubmissionChunk; + private final MAPIMessage mapiMessageNormalSubmissionChunk; + + /** + * Initialise this test, load up the test messages. + * @throws Exception + */ + public TestMessageSubmissionChunk() throws IOException { + POIDataSamples samples = POIDataSamples.getHSMFInstance(); + this.mapiMessageExtraHyphenSubmissionChunk = new MAPIMessage(samples.openResourceAsStream("message_extra_hyphen_submission_chunk.msg")); + this.mapiMessageNormalSubmissionChunk = new MAPIMessage(samples.openResourceAsStream("message_normal_submission_chunk.msg")); + } + + public void testReadMessageDateExtraHyphenSubmissionChunk() throws ChunkNotFoundException { + final Calendar date = mapiMessageExtraHyphenSubmissionChunk.getMessageDate(); + TestCase.assertNotNull(date); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2007, year); + } + + public void testReadMessageDateNormalSubmissionChunk() throws ChunkNotFoundException { + final Calendar date = mapiMessageNormalSubmissionChunk.getMessageDate(); + TestCase.assertNotNull(date); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2007, year); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunkY2KRead.java b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunkY2KRead.java index ef770d441f..dd1d8f929a 100644 --- a/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunkY2KRead.java +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunkY2KRead.java @@ -1,67 +1,67 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hsmf; - -import java.io.IOException; - -import org.apache.poi.hsmf.MAPIMessage; -import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; -import org.apache.poi.POIDataSamples; - -import java.util.Calendar; - -import junit.framework.TestCase; - -public final class TestMessageSubmissionChunkY2KRead extends TestCase { - - private final MAPIMessage mapiMessage1979; - private final MAPIMessage mapiMessage1980; - private final MAPIMessage mapiMessage1981; - - /** - * Initialise this test, load up the three test messages. - * @throws Exception - */ - public TestMessageSubmissionChunkY2KRead() throws IOException { - POIDataSamples samples = POIDataSamples.getHSMFInstance(); - this.mapiMessage1979 = new MAPIMessage(samples.openResourceAsStream("message_1979.msg")); - this.mapiMessage1980 = new MAPIMessage(samples.openResourceAsStream("message_1980.msg")); - this.mapiMessage1981 = new MAPIMessage(samples.openResourceAsStream("message_1981.msg")); - } - - // 1979 is one year before our pivot year (so this is an expected "failure") - public void testReadMessageDate1979() throws ChunkNotFoundException { - final Calendar date = mapiMessage1979.getMessageDate(); - final int year = date.get(Calendar.YEAR); - TestCase.assertEquals(2079, year); - } - - // 1980 is our pivot year (so this is an expected "failure") - public void testReadMessageDate1980() throws ChunkNotFoundException { - final Calendar date = mapiMessage1980.getMessageDate(); - final int year = date.get(Calendar.YEAR); - TestCase.assertEquals(2080, year); - } - - // 1981 is one year after our pivot year (so this starts working) - public void testReadMessageDate1981() throws ChunkNotFoundException { - final Calendar date = mapiMessage1981.getMessageDate(); - final int year = date.get(Calendar.YEAR); - TestCase.assertEquals(1981, year); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hsmf; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.POIDataSamples; + +import java.util.Calendar; + +import junit.framework.TestCase; + +public final class TestMessageSubmissionChunkY2KRead extends TestCase { + + private final MAPIMessage mapiMessage1979; + private final MAPIMessage mapiMessage1980; + private final MAPIMessage mapiMessage1981; + + /** + * Initialise this test, load up the three test messages. + * @throws Exception + */ + public TestMessageSubmissionChunkY2KRead() throws IOException { + POIDataSamples samples = POIDataSamples.getHSMFInstance(); + this.mapiMessage1979 = new MAPIMessage(samples.openResourceAsStream("message_1979.msg")); + this.mapiMessage1980 = new MAPIMessage(samples.openResourceAsStream("message_1980.msg")); + this.mapiMessage1981 = new MAPIMessage(samples.openResourceAsStream("message_1981.msg")); + } + + // 1979 is one year before our pivot year (so this is an expected "failure") + public void testReadMessageDate1979() throws ChunkNotFoundException { + final Calendar date = mapiMessage1979.getMessageDate(); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2079, year); + } + + // 1980 is our pivot year (so this is an expected "failure") + public void testReadMessageDate1980() throws ChunkNotFoundException { + final Calendar date = mapiMessage1980.getMessageDate(); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2080, year); + } + + // 1981 is one year after our pivot year (so this starts working) + public void testReadMessageDate1981() throws ChunkNotFoundException { + final Calendar date = mapiMessage1981.getMessageDate(); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(1981, year); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java b/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java index 746c5b0218..07d251e2d2 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java +++ b/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java @@ -1,251 +1,251 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwmf; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import javax.imageio.ImageIO; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilterInputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Locale; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord; -import org.apache.poi.hwmf.record.HwmfFont; -import org.apache.poi.hwmf.record.HwmfRecord; -import org.apache.poi.hwmf.record.HwmfRecordType; -import org.apache.poi.hwmf.record.HwmfText; -import org.apache.poi.hwmf.usermodel.HwmfPicture; -import org.apache.poi.sl.usermodel.PictureData; -import org.apache.poi.sl.usermodel.PictureData.PictureType; -import org.apache.poi.sl.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.SlideShowFactory; -import org.apache.poi.util.LocaleUtil; -import org.apache.poi.util.Units; -import org.junit.Ignore; -import org.junit.Test; - -public class TestHwmfParsing { - @Test - public void parse() throws IOException { - File f = POIDataSamples.getSlideShowInstance().getFile("santa.wmf"); - FileInputStream fis = new FileInputStream(f); - HwmfPicture wmf = new HwmfPicture(fis); - fis.close(); - List records = wmf.getRecords(); - assertEquals(581, records.size()); - } - - @Test - @Ignore("This is work-in-progress and not a real unit test ...") - public void paint() throws IOException { - File f = POIDataSamples.getSlideShowInstance().getFile("santa.wmf"); - // File f = new File("bla.wmf"); - FileInputStream fis = new FileInputStream(f); - HwmfPicture wmf = new HwmfPicture(fis); - fis.close(); - - Dimension dim = wmf.getSize(); - int width = Units.pointsToPixel(dim.getWidth()); - // keep aspect ratio for height - int height = Units.pointsToPixel(dim.getHeight()); - double max = Math.max(width, height); - if (max > 1500) { - width *= 1500/max; - height *= 1500/max; - } - - BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = bufImg.createGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - - wmf.draw(g, new Rectangle2D.Double(0,0,width,height)); - - g.dispose(); - - ImageIO.write(bufImg, "PNG", new File("bla.png")); - } - - @Test - @Ignore("This is work-in-progress and not a real unit test ...") - public void fetchWmfFromGovdocs() throws IOException { - URL url = new URL("http://digitalcorpora.org/corpora/files/govdocs1/by_type/ppt.zip"); - File outdir = new File("build/ppt"); - outdir.mkdirs(); - ZipInputStream zis = new ZipInputStream(url.openStream()); - ZipEntry ze; - while ((ze = zis.getNextEntry()) != null) { - String basename = ze.getName().replaceAll(".*?([^/]+)\\.wmf", "$1"); - FilterInputStream fis = new FilterInputStream(zis){ - @Override - public void close() throws IOException {} - }; - try { - SlideShow ss = SlideShowFactory.create(fis); - int wmfIdx = 1; - for (PictureData pd : ss.getPictureData()) { - if (pd.getType() != PictureType.WMF) continue; - byte wmfData[] = pd.getData(); - String filename = String.format(Locale.ROOT, "%s-%04d.wmf", basename, wmfIdx); - FileOutputStream fos = new FileOutputStream(new File(outdir, filename)); - fos.write(wmfData); - fos.close(); - wmfIdx++; - } - ss.close(); - } catch (Exception e) { - System.out.println(ze.getName()+" ignored."); - } - } - } - - @Test - @Ignore("This is work-in-progress and not a real unit test ...") - public void parseWmfs() throws IOException { - // parse and render the extracted wmfs from the fetchWmfFromGovdocs step - boolean outputFiles = false; - boolean renderWmf = true; - File indir = new File("E:\\project\\poi\\misc\\govdocs-ppt"); - File outdir = new File("build/wmf"); - outdir.mkdirs(); - final String startFile = ""; - File files[] = indir.listFiles(new FileFilter() { - boolean foundStartFile = false; - @Override - public boolean accept(File pathname) { - foundStartFile |= startFile.isEmpty() || pathname.getName().contains(startFile); - return foundStartFile && pathname.getName().matches("(?i).*\\.wmf?$"); - } - }); - for (File f : files) { - try { - String basename = f.getName().replaceAll(".*?([^/]+)\\.wmf", "$1"); - FileInputStream fis = new FileInputStream(f); - HwmfPicture wmf = new HwmfPicture(fis); - fis.close(); - - int bmpIndex = 1; - for (HwmfRecord r : wmf.getRecords()) { - if (r instanceof HwmfImageRecord) { - BufferedImage bi = ((HwmfImageRecord)r).getImage(); - if (bi != null && outputFiles) { - String filename = String.format(Locale.ROOT, "%s-%04d.png", basename, bmpIndex); - ImageIO.write(bi, "PNG", new File(outdir, filename)); - } - bmpIndex++; - } - } - - if (renderWmf) { - Dimension dim = wmf.getSize(); - int width = Units.pointsToPixel(dim.getWidth()); - // keep aspect ratio for height - int height = Units.pointsToPixel(dim.getHeight()); - - BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = bufImg.createGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - - wmf.draw(g); - - g.dispose(); - - ImageIO.write(bufImg, "PNG", new File(outdir, basename+".png")); - } - } catch (Exception e) { - System.out.println(f.getName()+" ignored."); - } - } - } - - @Test - @Ignore("If we decide we can use common crawl file specified, we can turn this back on") - public void testCyrillic() throws Exception { - //TODO: move test file to framework and fix this - File dir = new File("C:/somethingOrOther"); - File f = new File(dir, "ZMLH54SPLI76NQ7XMKVB7SMUJA2HTXTS-2.wmf"); - HwmfPicture wmf = new HwmfPicture(new FileInputStream(f)); - - Charset charset = LocaleUtil.CHARSET_1252; - StringBuilder sb = new StringBuilder(); - //this is pure hackery for specifying the font - //this happens to work on this test file, but you need to - //do what Graphics does by maintaining the stack, etc.! - for (HwmfRecord r : wmf.getRecords()) { - if (r.getRecordType().equals(HwmfRecordType.createFontIndirect)) { - HwmfFont font = ((HwmfText.WmfCreateFontIndirect)r).getFont(); - charset = (font.getCharSet().getCharset() == null) ? LocaleUtil.CHARSET_1252 : font.getCharSet().getCharset(); - } - if (r.getRecordType().equals(HwmfRecordType.extTextOut)) { - HwmfText.WmfExtTextOut textOut = (HwmfText.WmfExtTextOut)r; - sb.append(textOut.getText(charset)).append("\n"); - } - } - String txt = sb.toString(); - assertTrue(txt.contains("\u041E\u0431\u0449\u043E")); - assertTrue(txt.contains("\u0411\u0430\u043B\u0430\u043D\u0441")); - } - - @Test - @Ignore("If we decide we can use the common crawl file attached to Bug 60677, " + - "we can turn this back on") - public void testShift_JIS() throws Exception { - //TODO: move test file to framework and fix this - File f = new File("C:/data/file8.wmf"); - HwmfPicture wmf = new HwmfPicture(new FileInputStream(f)); - - Charset charset = LocaleUtil.CHARSET_1252; - StringBuilder sb = new StringBuilder(); - //this is pure hackery for specifying the font - //this happens to work on this test file, but you need to - //do what Graphics does by maintaining the stack, etc.! - for (HwmfRecord r : wmf.getRecords()) { - if (r.getRecordType().equals(HwmfRecordType.createFontIndirect)) { - HwmfFont font = ((HwmfText.WmfCreateFontIndirect)r).getFont(); - charset = (font.getCharSet().getCharset() == null) ? LocaleUtil.CHARSET_1252 : font.getCharSet().getCharset(); - } - if (r.getRecordType().equals(HwmfRecordType.extTextOut)) { - HwmfText.WmfExtTextOut textOut = (HwmfText.WmfExtTextOut)r; - sb.append(textOut.getText(charset)).append("\n"); - } - } - String txt = sb.toString(); - assertTrue(txt.contains("\u822A\u7A7A\u60C5\u5831\u696D\u52D9\u3078\u306E\uFF27\uFF29\uFF33")); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwmf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import javax.imageio.ImageIO; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Locale; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord; +import org.apache.poi.hwmf.record.HwmfFont; +import org.apache.poi.hwmf.record.HwmfRecord; +import org.apache.poi.hwmf.record.HwmfRecordType; +import org.apache.poi.hwmf.record.HwmfText; +import org.apache.poi.hwmf.usermodel.HwmfPicture; +import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.sl.usermodel.PictureData.PictureType; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.util.LocaleUtil; +import org.apache.poi.util.Units; +import org.junit.Ignore; +import org.junit.Test; + +public class TestHwmfParsing { + @Test + public void parse() throws IOException { + File f = POIDataSamples.getSlideShowInstance().getFile("santa.wmf"); + FileInputStream fis = new FileInputStream(f); + HwmfPicture wmf = new HwmfPicture(fis); + fis.close(); + List records = wmf.getRecords(); + assertEquals(581, records.size()); + } + + @Test + @Ignore("This is work-in-progress and not a real unit test ...") + public void paint() throws IOException { + File f = POIDataSamples.getSlideShowInstance().getFile("santa.wmf"); + // File f = new File("bla.wmf"); + FileInputStream fis = new FileInputStream(f); + HwmfPicture wmf = new HwmfPicture(fis); + fis.close(); + + Dimension dim = wmf.getSize(); + int width = Units.pointsToPixel(dim.getWidth()); + // keep aspect ratio for height + int height = Units.pointsToPixel(dim.getHeight()); + double max = Math.max(width, height); + if (max > 1500) { + width *= 1500/max; + height *= 1500/max; + } + + BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = bufImg.createGraphics(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + wmf.draw(g, new Rectangle2D.Double(0,0,width,height)); + + g.dispose(); + + ImageIO.write(bufImg, "PNG", new File("bla.png")); + } + + @Test + @Ignore("This is work-in-progress and not a real unit test ...") + public void fetchWmfFromGovdocs() throws IOException { + URL url = new URL("http://digitalcorpora.org/corpora/files/govdocs1/by_type/ppt.zip"); + File outdir = new File("build/ppt"); + outdir.mkdirs(); + ZipInputStream zis = new ZipInputStream(url.openStream()); + ZipEntry ze; + while ((ze = zis.getNextEntry()) != null) { + String basename = ze.getName().replaceAll(".*?([^/]+)\\.wmf", "$1"); + FilterInputStream fis = new FilterInputStream(zis){ + @Override + public void close() throws IOException {} + }; + try { + SlideShow ss = SlideShowFactory.create(fis); + int wmfIdx = 1; + for (PictureData pd : ss.getPictureData()) { + if (pd.getType() != PictureType.WMF) continue; + byte wmfData[] = pd.getData(); + String filename = String.format(Locale.ROOT, "%s-%04d.wmf", basename, wmfIdx); + FileOutputStream fos = new FileOutputStream(new File(outdir, filename)); + fos.write(wmfData); + fos.close(); + wmfIdx++; + } + ss.close(); + } catch (Exception e) { + System.out.println(ze.getName()+" ignored."); + } + } + } + + @Test + @Ignore("This is work-in-progress and not a real unit test ...") + public void parseWmfs() throws IOException { + // parse and render the extracted wmfs from the fetchWmfFromGovdocs step + boolean outputFiles = false; + boolean renderWmf = true; + File indir = new File("E:\\project\\poi\\misc\\govdocs-ppt"); + File outdir = new File("build/wmf"); + outdir.mkdirs(); + final String startFile = ""; + File files[] = indir.listFiles(new FileFilter() { + boolean foundStartFile = false; + @Override + public boolean accept(File pathname) { + foundStartFile |= startFile.isEmpty() || pathname.getName().contains(startFile); + return foundStartFile && pathname.getName().matches("(?i).*\\.wmf?$"); + } + }); + for (File f : files) { + try { + String basename = f.getName().replaceAll(".*?([^/]+)\\.wmf", "$1"); + FileInputStream fis = new FileInputStream(f); + HwmfPicture wmf = new HwmfPicture(fis); + fis.close(); + + int bmpIndex = 1; + for (HwmfRecord r : wmf.getRecords()) { + if (r instanceof HwmfImageRecord) { + BufferedImage bi = ((HwmfImageRecord)r).getImage(); + if (bi != null && outputFiles) { + String filename = String.format(Locale.ROOT, "%s-%04d.png", basename, bmpIndex); + ImageIO.write(bi, "PNG", new File(outdir, filename)); + } + bmpIndex++; + } + } + + if (renderWmf) { + Dimension dim = wmf.getSize(); + int width = Units.pointsToPixel(dim.getWidth()); + // keep aspect ratio for height + int height = Units.pointsToPixel(dim.getHeight()); + + BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = bufImg.createGraphics(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + wmf.draw(g); + + g.dispose(); + + ImageIO.write(bufImg, "PNG", new File(outdir, basename+".png")); + } + } catch (Exception e) { + System.out.println(f.getName()+" ignored."); + } + } + } + + @Test + @Ignore("If we decide we can use common crawl file specified, we can turn this back on") + public void testCyrillic() throws Exception { + //TODO: move test file to framework and fix this + File dir = new File("C:/somethingOrOther"); + File f = new File(dir, "ZMLH54SPLI76NQ7XMKVB7SMUJA2HTXTS-2.wmf"); + HwmfPicture wmf = new HwmfPicture(new FileInputStream(f)); + + Charset charset = LocaleUtil.CHARSET_1252; + StringBuilder sb = new StringBuilder(); + //this is pure hackery for specifying the font + //this happens to work on this test file, but you need to + //do what Graphics does by maintaining the stack, etc.! + for (HwmfRecord r : wmf.getRecords()) { + if (r.getRecordType().equals(HwmfRecordType.createFontIndirect)) { + HwmfFont font = ((HwmfText.WmfCreateFontIndirect)r).getFont(); + charset = (font.getCharSet().getCharset() == null) ? LocaleUtil.CHARSET_1252 : font.getCharSet().getCharset(); + } + if (r.getRecordType().equals(HwmfRecordType.extTextOut)) { + HwmfText.WmfExtTextOut textOut = (HwmfText.WmfExtTextOut)r; + sb.append(textOut.getText(charset)).append("\n"); + } + } + String txt = sb.toString(); + assertTrue(txt.contains("\u041E\u0431\u0449\u043E")); + assertTrue(txt.contains("\u0411\u0430\u043B\u0430\u043D\u0441")); + } + + @Test + @Ignore("If we decide we can use the common crawl file attached to Bug 60677, " + + "we can turn this back on") + public void testShift_JIS() throws Exception { + //TODO: move test file to framework and fix this + File f = new File("C:/data/file8.wmf"); + HwmfPicture wmf = new HwmfPicture(new FileInputStream(f)); + + Charset charset = LocaleUtil.CHARSET_1252; + StringBuilder sb = new StringBuilder(); + //this is pure hackery for specifying the font + //this happens to work on this test file, but you need to + //do what Graphics does by maintaining the stack, etc.! + for (HwmfRecord r : wmf.getRecords()) { + if (r.getRecordType().equals(HwmfRecordType.createFontIndirect)) { + HwmfFont font = ((HwmfText.WmfCreateFontIndirect)r).getFont(); + charset = (font.getCharSet().getCharset() == null) ? LocaleUtil.CHARSET_1252 : font.getCharSet().getCharset(); + } + if (r.getRecordType().equals(HwmfRecordType.extTextOut)) { + HwmfText.WmfExtTextOut textOut = (HwmfText.WmfExtTextOut)r; + sb.append(textOut.getText(charset)).append("\n"); + } + } + String txt = sb.toString(); + assertTrue(txt.contains("\u822A\u7A7A\u60C5\u5831\u696D\u52D9\u3078\u306E\uFF27\uFF29\uFF33")); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/HWPFTestDataSamples.java b/src/scratchpad/testcases/org/apache/poi/hwpf/HWPFTestDataSamples.java index 6f6ae82a30..9cefffa012 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/HWPFTestDataSamples.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/HWPFTestDataSamples.java @@ -1,171 +1,171 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.zip.ZipInputStream; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -public class HWPFTestDataSamples { - - private static final POILogger logger = POILogFactory - .getLogger( HWPFTestDataSamples.class ); - - public static HWPFDocument openSampleFile(String sampleFileName) { - try { - InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(sampleFileName); - return new HWPFDocument(is); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static HWPFDocument openSampleFileFromArchive( String sampleFileName ) - { - final long start = System.currentTimeMillis(); - try - { - ZipInputStream is = new ZipInputStream( POIDataSamples - .getDocumentInstance() - .openResourceAsStream( sampleFileName ) ); - try - { - is.getNextEntry(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try - { - IOUtils.copy( is, baos ); - } - finally - { - baos.close(); - } - - final long endUnzip = System.currentTimeMillis(); - byte[] byteArray = baos.toByteArray(); - - logger.log( POILogger.DEBUG, "Unzipped in ", - Long.valueOf( endUnzip - start ), " ms -- ", - Long.valueOf( byteArray.length ), " byte(s)" ); - - ByteArrayInputStream bais = new ByteArrayInputStream( byteArray ); - HWPFDocument doc = new HWPFDocument( bais ); - final long endParse = System.currentTimeMillis(); - - logger.log( POILogger.DEBUG, "Parsed in ", - Long.valueOf( endParse - start ), " ms" ); - - return doc; - } - finally - { - is.close(); - } - } - catch ( IOException e ) - { - throw new RuntimeException( e ); - } - } - - /** - * Open a remote sample from URL. opening is performd in two phases: - * (1) download content into a byte array - * (2) construct HWPFDocument - * - * @param sampleFileUrl the url to open - */ - public static HWPFDocument openRemoteFile( String sampleFileUrl ) - { - final long start = System.currentTimeMillis(); - try - { - logger.log(POILogger.DEBUG, "Downloading ", sampleFileUrl, " ..."); - - InputStream is = new URL( sampleFileUrl ).openStream(); - try - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try - { - IOUtils.copy( is, baos ); - } - finally - { - baos.close(); - } - - final long endDownload = System.currentTimeMillis(); - byte[] byteArray = baos.toByteArray(); - - logger.log( POILogger.DEBUG, "Downloaded in ", - Long.valueOf( endDownload - start ), " ms -- ", - Long.valueOf( byteArray.length ), " byte(s)" ); - - ByteArrayInputStream bais = new ByteArrayInputStream( byteArray ); - HWPFDocument doc = new HWPFDocument( bais ); - final long endParse = System.currentTimeMillis(); - - logger.log( POILogger.DEBUG, "Parsed in ", - Long.valueOf( endParse - start ), " ms" ); - - return doc; - } - finally - { - is.close(); - } - } - catch ( IOException e ) - { - throw new RuntimeException( e ); - } - } - - public static HWPFOldDocument openOldSampleFile(String sampleFileName) { - try { - InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(sampleFileName); - return new HWPFOldDocument(new POIFSFileSystem(is)); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - /** - * Writes a spreadsheet to a ByteArrayOutputStream and reads it back - * from a ByteArrayInputStream.

    - * Useful for verifying that the serialisation round trip - */ - public static HWPFDocument writeOutAndReadBack(HWPFDocument original) { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); - original.write(baos); - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - return new HWPFDocument(bais); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.zip.ZipInputStream; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +public class HWPFTestDataSamples { + + private static final POILogger logger = POILogFactory + .getLogger( HWPFTestDataSamples.class ); + + public static HWPFDocument openSampleFile(String sampleFileName) { + try { + InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(sampleFileName); + return new HWPFDocument(is); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static HWPFDocument openSampleFileFromArchive( String sampleFileName ) + { + final long start = System.currentTimeMillis(); + try + { + ZipInputStream is = new ZipInputStream( POIDataSamples + .getDocumentInstance() + .openResourceAsStream( sampleFileName ) ); + try + { + is.getNextEntry(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try + { + IOUtils.copy( is, baos ); + } + finally + { + baos.close(); + } + + final long endUnzip = System.currentTimeMillis(); + byte[] byteArray = baos.toByteArray(); + + logger.log( POILogger.DEBUG, "Unzipped in ", + Long.valueOf( endUnzip - start ), " ms -- ", + Long.valueOf( byteArray.length ), " byte(s)" ); + + ByteArrayInputStream bais = new ByteArrayInputStream( byteArray ); + HWPFDocument doc = new HWPFDocument( bais ); + final long endParse = System.currentTimeMillis(); + + logger.log( POILogger.DEBUG, "Parsed in ", + Long.valueOf( endParse - start ), " ms" ); + + return doc; + } + finally + { + is.close(); + } + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + } + + /** + * Open a remote sample from URL. opening is performd in two phases: + * (1) download content into a byte array + * (2) construct HWPFDocument + * + * @param sampleFileUrl the url to open + */ + public static HWPFDocument openRemoteFile( String sampleFileUrl ) + { + final long start = System.currentTimeMillis(); + try + { + logger.log(POILogger.DEBUG, "Downloading ", sampleFileUrl, " ..."); + + InputStream is = new URL( sampleFileUrl ).openStream(); + try + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try + { + IOUtils.copy( is, baos ); + } + finally + { + baos.close(); + } + + final long endDownload = System.currentTimeMillis(); + byte[] byteArray = baos.toByteArray(); + + logger.log( POILogger.DEBUG, "Downloaded in ", + Long.valueOf( endDownload - start ), " ms -- ", + Long.valueOf( byteArray.length ), " byte(s)" ); + + ByteArrayInputStream bais = new ByteArrayInputStream( byteArray ); + HWPFDocument doc = new HWPFDocument( bais ); + final long endParse = System.currentTimeMillis(); + + logger.log( POILogger.DEBUG, "Parsed in ", + Long.valueOf( endParse - start ), " ms" ); + + return doc; + } + finally + { + is.close(); + } + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + } + + public static HWPFOldDocument openOldSampleFile(String sampleFileName) { + try { + InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(sampleFileName); + return new HWPFOldDocument(new POIFSFileSystem(is)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + /** + * Writes a spreadsheet to a ByteArrayOutputStream and reads it back + * from a ByteArrayInputStream.

    + * Useful for verifying that the serialisation round trip + */ + public static HWPFDocument writeOutAndReadBack(HWPFDocument original) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + original.write(baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + return new HWPFDocument(bais); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/model/PlfLfoTest.java b/src/scratchpad/testcases/org/apache/poi/hwpf/model/PlfLfoTest.java index cb90d99fdf..b9dafae62a 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/model/PlfLfoTest.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/model/PlfLfoTest.java @@ -1,56 +1,56 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ -package org.apache.poi.hwpf.model; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class PlfLfoTest { - @Test - public void testAdd() { - PlfLfo p = new PlfLfo(new byte[] {0, 0, 0, 0}, 0, 0); - assertEquals(0, p.getLfoMac()); - p.add(new LFO(new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0), new LFOData()); - assertEquals(1, p.getLfoMac()); - assertNotNull(p.getLfo(1)); - assertNotNull(p.getLfoData(1)); - } - - @Test - public void testEquals() { - PlfLfo p = new PlfLfo(new byte[] {0, 0, 0, 0}, 0, 0); - PlfLfo p2 = new PlfLfo(new byte[] {0, 0, 0, 0}, 0, 0); - assertEquals(0, p.getLfoMac()); - assertEquals(0, p2.getLfoMac()); - - assertTrue(p.equals(p2)); - //noinspection ObjectEqualsNull - assertFalse(p.equals(null)); - - p.add(new LFO(new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0), new LFOData()); - assertEquals(1, p.getLfoMac()); - - assertFalse(p.equals(p2)); - - p2.add(new LFO(new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0), new LFOData()); - assertEquals(1, p2.getLfoMac()); - assertTrue(p.equals(p2)); - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.hwpf.model; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PlfLfoTest { + @Test + public void testAdd() { + PlfLfo p = new PlfLfo(new byte[] {0, 0, 0, 0}, 0, 0); + assertEquals(0, p.getLfoMac()); + p.add(new LFO(new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0), new LFOData()); + assertEquals(1, p.getLfoMac()); + assertNotNull(p.getLfo(1)); + assertNotNull(p.getLfoData(1)); + } + + @Test + public void testEquals() { + PlfLfo p = new PlfLfo(new byte[] {0, 0, 0, 0}, 0, 0); + PlfLfo p2 = new PlfLfo(new byte[] {0, 0, 0, 0}, 0, 0); + assertEquals(0, p.getLfoMac()); + assertEquals(0, p2.getLfoMac()); + + assertTrue(p.equals(p2)); + //noinspection ObjectEqualsNull + assertFalse(p.equals(null)); + + p.add(new LFO(new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0), new LFOData()); + assertEquals(1, p.getLfoMac()); + + assertFalse(p.equals(p2)); + + p2.add(new LFO(new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0), new LFOData()); + assertEquals(1, p2.getLfoMac()); + assertTrue(p.equals(p2)); + } } \ No newline at end of file diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/sprm/TestSprms.java b/src/scratchpad/testcases/org/apache/poi/hwpf/sprm/TestSprms.java index e5c94d00b9..e83dbeeaa7 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/sprm/TestSprms.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/sprm/TestSprms.java @@ -1,100 +1,100 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.hwpf.sprm; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -import junit.framework.TestCase; -import org.apache.poi.POIDataSamples; -import org.apache.poi.hwpf.HWPFDocument; -import org.apache.poi.hwpf.usermodel.Paragraph; -import org.apache.poi.hwpf.usermodel.Range; - -public class TestSprms extends TestCase -{ - private static HWPFDocument reload( HWPFDocument hwpfDocument ) - throws IOException - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - hwpfDocument.write( baos ); - return new HWPFDocument( new ByteArrayInputStream( baos.toByteArray() ) ); - } - - /** - * Test correct processing of "sprmPItap" (0x6649) and "sprmPFInTable" - * (0x2416) - */ - public void testInnerTable() throws Exception - { - InputStream resourceAsStream = POIDataSamples.getDocumentInstance() - .openResourceAsStream( "innertable.doc" ); - HWPFDocument hwpfDocument = new HWPFDocument( resourceAsStream ); - resourceAsStream.close(); - - testInnerTable( hwpfDocument ); - hwpfDocument = reload( hwpfDocument ); - testInnerTable( hwpfDocument ); - } - - private void testInnerTable( HWPFDocument hwpfDocument ) - { - Range range = hwpfDocument.getRange(); - for ( int p = 0; p < range.numParagraphs(); p++ ) - { - Paragraph paragraph = range.getParagraph( p ); - char first = paragraph.text().toLowerCase(Locale.ROOT).charAt( 0 ); - if ( '1' <= first && first < '4' ) - { - assertTrue( paragraph.isInTable() ); - assertEquals( 2, paragraph.getTableLevel() ); - } - - if ( 'a' <= first && first < 'z' ) - { - assertTrue( paragraph.isInTable() ); - assertEquals( 1, paragraph.getTableLevel() ); - } - } - } - - /** - * Test correct processing of "sprmPJc" by uncompressor - */ - public void testSprmPJc() throws IOException - { - InputStream resourceAsStream = POIDataSamples.getDocumentInstance() - .openResourceAsStream( "Bug49820.doc" ); - HWPFDocument hwpfDocument = new HWPFDocument( resourceAsStream ); - resourceAsStream.close(); - - assertEquals( 1, hwpfDocument.getStyleSheet().getParagraphStyle( 8 ) - .getJustification() ); - - hwpfDocument = reload( hwpfDocument ); - - assertEquals( 1, hwpfDocument.getStyleSheet().getParagraphStyle( 8 ) - .getJustification() ); - - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.hwpf.sprm; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +import junit.framework.TestCase; +import org.apache.poi.POIDataSamples; +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.usermodel.Paragraph; +import org.apache.poi.hwpf.usermodel.Range; + +public class TestSprms extends TestCase +{ + private static HWPFDocument reload( HWPFDocument hwpfDocument ) + throws IOException + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + hwpfDocument.write( baos ); + return new HWPFDocument( new ByteArrayInputStream( baos.toByteArray() ) ); + } + + /** + * Test correct processing of "sprmPItap" (0x6649) and "sprmPFInTable" + * (0x2416) + */ + public void testInnerTable() throws Exception + { + InputStream resourceAsStream = POIDataSamples.getDocumentInstance() + .openResourceAsStream( "innertable.doc" ); + HWPFDocument hwpfDocument = new HWPFDocument( resourceAsStream ); + resourceAsStream.close(); + + testInnerTable( hwpfDocument ); + hwpfDocument = reload( hwpfDocument ); + testInnerTable( hwpfDocument ); + } + + private void testInnerTable( HWPFDocument hwpfDocument ) + { + Range range = hwpfDocument.getRange(); + for ( int p = 0; p < range.numParagraphs(); p++ ) + { + Paragraph paragraph = range.getParagraph( p ); + char first = paragraph.text().toLowerCase(Locale.ROOT).charAt( 0 ); + if ( '1' <= first && first < '4' ) + { + assertTrue( paragraph.isInTable() ); + assertEquals( 2, paragraph.getTableLevel() ); + } + + if ( 'a' <= first && first < 'z' ) + { + assertTrue( paragraph.isInTable() ); + assertEquals( 1, paragraph.getTableLevel() ); + } + } + } + + /** + * Test correct processing of "sprmPJc" by uncompressor + */ + public void testSprmPJc() throws IOException + { + InputStream resourceAsStream = POIDataSamples.getDocumentInstance() + .openResourceAsStream( "Bug49820.doc" ); + HWPFDocument hwpfDocument = new HWPFDocument( resourceAsStream ); + resourceAsStream.close(); + + assertEquals( 1, hwpfDocument.getStyleSheet().getParagraphStyle( 8 ) + .getJustification() ); + + hwpfDocument = reload( hwpfDocument ); + + assertEquals( 1, hwpfDocument.getStyleSheet().getParagraphStyle( 8 ) + .getJustification() ); + + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug47563.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug47563.java index ec64fd5a35..5dbef749d6 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug47563.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug47563.java @@ -1,85 +1,85 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hwpf.usermodel; - -import junit.framework.TestCase; - -import org.apache.poi.hwpf.HWPFDocument; -import org.apache.poi.hwpf.HWPFTestDataSamples; - -/** - * Bug 47563 - Exception when working with table - */ -public class TestBug47563 extends TestCase { - - public void test() throws Exception { - test(1, 5); - test(1, 6); - test(5, 1); - test(6, 1); - test(2, 2); - test(3, 2); - test(2, 3); - test(3, 3); - } - - private void test(int rows, int columns) throws Exception { - // POI apparently can't create a document from scratch, - // so we need an existing empty dummy document - HWPFDocument doc = HWPFTestDataSamples.openSampleFile("empty.doc"); - - Range range = doc.getRange(); - range.sanityCheck(); - - Table table = range.insertTableBefore((short) columns, rows); - table.sanityCheck(); - - for (int rowIdx = 0; rowIdx < table.numRows(); rowIdx++) { - TableRow row = table.getRow(rowIdx); - row.sanityCheck(); - - System.out.println("row " + rowIdx); - for (int colIdx = 0; colIdx < row.numCells(); colIdx++) { - TableCell cell = row.getCell(colIdx); - cell.sanityCheck(); - - System.out.println("column " + colIdx + ", num paragraphs " - + cell.numParagraphs()); - - Paragraph par = cell.getParagraph(0); - par.sanityCheck(); - - par.insertBefore("" + (rowIdx * row.numCells() + colIdx)); - par.sanityCheck(); - - row.sanityCheck(); - table.sanityCheck(); - range.sanityCheck(); - - } - } - - String text = range.text(); - int mustBeAfter = 0; - for (int i = 0; i < rows * columns; i++) { - int next = text.indexOf(Integer.toString(i), mustBeAfter); - assertTrue("Test with " + rows + "/" + columns + ": Should not find " + i + " but found it at " + next + " in " + text, - next != -1); - mustBeAfter = next; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hwpf.usermodel; + +import junit.framework.TestCase; + +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.HWPFTestDataSamples; + +/** + * Bug 47563 - Exception when working with table + */ +public class TestBug47563 extends TestCase { + + public void test() throws Exception { + test(1, 5); + test(1, 6); + test(5, 1); + test(6, 1); + test(2, 2); + test(3, 2); + test(2, 3); + test(3, 3); + } + + private void test(int rows, int columns) throws Exception { + // POI apparently can't create a document from scratch, + // so we need an existing empty dummy document + HWPFDocument doc = HWPFTestDataSamples.openSampleFile("empty.doc"); + + Range range = doc.getRange(); + range.sanityCheck(); + + Table table = range.insertTableBefore((short) columns, rows); + table.sanityCheck(); + + for (int rowIdx = 0; rowIdx < table.numRows(); rowIdx++) { + TableRow row = table.getRow(rowIdx); + row.sanityCheck(); + + System.out.println("row " + rowIdx); + for (int colIdx = 0; colIdx < row.numCells(); colIdx++) { + TableCell cell = row.getCell(colIdx); + cell.sanityCheck(); + + System.out.println("column " + colIdx + ", num paragraphs " + + cell.numParagraphs()); + + Paragraph par = cell.getParagraph(0); + par.sanityCheck(); + + par.insertBefore("" + (rowIdx * row.numCells() + colIdx)); + par.sanityCheck(); + + row.sanityCheck(); + table.sanityCheck(); + range.sanityCheck(); + + } + } + + String text = range.text(); + int mustBeAfter = 0; + for (int i = 0; i < rows * columns; i++) { + int next = text.indexOf(Integer.toString(i), mustBeAfter); + assertTrue("Test with " + rows + "/" + columns + ": Should not find " + i + " but found it at " + next + " in " + text, + next != -1); + mustBeAfter = next; + } + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug49820.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug49820.java index 4e96646f44..92d99c386c 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug49820.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBug49820.java @@ -1,63 +1,63 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.usermodel; - -import java.io.IOException; -import junit.framework.TestCase; - -import org.apache.poi.hwpf.HWPFDocument; -import org.apache.poi.hwpf.HWPFTestDataSamples; -import org.apache.poi.hwpf.model.StyleSheet; - -public final class TestBug49820 extends TestCase { - - public void test() throws IOException { - HWPFDocument doc = HWPFTestDataSamples.openSampleFile("Bug49820.doc"); - - Range documentRange = doc.getRange(); - StyleSheet styleSheet = doc.getStyleSheet(); - - // JUnit asserts - assertLevels(documentRange, styleSheet, 0, 0, 0); - assertLevels(documentRange, styleSheet, 1, 1, 1); - assertLevels(documentRange, styleSheet, 2, 2, 2); - assertLevels(documentRange, styleSheet, 3, 3, 3); - assertLevels(documentRange, styleSheet, 4, 4, 4); - assertLevels(documentRange, styleSheet, 5, 5, 5); - assertLevels(documentRange, styleSheet, 6, 6, 6); - assertLevels(documentRange, styleSheet, 7, 7, 7); - assertLevels(documentRange, styleSheet, 8, 8, 8); - assertLevels(documentRange, styleSheet, 9, 9, 9); - assertLevels(documentRange, styleSheet, 10, 9, 0); - assertLevels(documentRange, styleSheet, 11, 9, 4); - - // output to console - /*for (int i=0; i= 2); - CharacterRun chr = range.getCharacterRun(0); - assertEquals(false, chr.isSymbol()); - - chr = range.getCharacterRun(1); - assertEquals(true, chr.isSymbol()); - assertEquals("\u0028", chr.text()); - assertEquals("Wingdings", chr.getSymbolFont().getMainFontName()); - assertEquals(0xf028, chr.getSymbolCharacter()); - } - +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.usermodel; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.HWPFTestDataSamples; + +/** + * API for processing of symbols, see Bugzilla 49908 + */ +public final class TestRangeSymbols extends TestCase { + + public void test() throws IOException { + HWPFDocument doc = HWPFTestDataSamples.openSampleFile("Bug49908.doc"); + + Range range = doc.getRange(); + + assertTrue(range.numCharacterRuns() >= 2); + CharacterRun chr = range.getCharacterRun(0); + assertEquals(false, chr.isSymbol()); + + chr = range.getCharacterRun(1); + assertEquals(true, chr.isSymbol()); + assertEquals("\u0028", chr.text()); + assertEquals("Wingdings", chr.getSymbolFont().getMainFontName()); + assertEquals(0xf028, chr.getSymbolCharacter()); + } + } \ No newline at end of file diff --git a/src/testcases/org/apache/poi/POIDataSamples.java b/src/testcases/org/apache/poi/POIDataSamples.java index fbaa36b61b..f57d13dae0 100644 --- a/src/testcases/org/apache/poi/POIDataSamples.java +++ b/src/testcases/org/apache/poi/POIDataSamples.java @@ -1,281 +1,281 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -/** - * Centralises logic for finding/opening sample files - */ -public final class POIDataSamples { - - /** - * Name of the system property that defined path to the test data. - */ - public static final String TEST_PROPERTY = "POI.testdata.path"; - - private static POIDataSamples _instSlideshow; - private static POIDataSamples _instSpreadsheet; - private static POIDataSamples _instDocument; - private static POIDataSamples _instDiagram; - private static POIDataSamples _instOpenxml4j; - private static POIDataSamples _instPOIFS; - private static POIDataSamples _instDDF; - private static POIDataSamples _instHMEF; - private static POIDataSamples _instHPSF; - private static POIDataSamples _instHPBF; - private static POIDataSamples _instHSMF; - private static POIDataSamples _instXmlDSign; - - private File _resolvedDataDir; - /** true if standard system propery is not set, - * but the data is available on the test runtime classpath */ - private boolean _sampleDataIsAvaliableOnClassPath; - private final String _moduleDir; - - /** - * - * @param moduleDir the name of the directory containing the test files - */ - private POIDataSamples(String moduleDir){ - _moduleDir = moduleDir; - initialise(); - } - - public static POIDataSamples getSpreadSheetInstance(){ - if(_instSpreadsheet == null) _instSpreadsheet = new POIDataSamples("spreadsheet"); - return _instSpreadsheet; - } - - public static POIDataSamples getDocumentInstance(){ - if(_instDocument == null) _instDocument = new POIDataSamples("document"); - return _instDocument; - } - - public static POIDataSamples getSlideShowInstance(){ - if(_instSlideshow == null) _instSlideshow = new POIDataSamples("slideshow"); - return _instSlideshow; - } - - public static POIDataSamples getDiagramInstance(){ - if(_instOpenxml4j == null) _instOpenxml4j = new POIDataSamples("diagram"); - return _instOpenxml4j; - } - - public static POIDataSamples getOpenXML4JInstance(){ - if(_instDiagram == null) _instDiagram = new POIDataSamples("openxml4j"); - return _instDiagram; - } - - public static POIDataSamples getPOIFSInstance(){ - if(_instPOIFS == null) _instPOIFS = new POIDataSamples("poifs"); - return _instPOIFS; - } - - public static POIDataSamples getDDFInstance(){ - if(_instDDF == null) _instDDF = new POIDataSamples("ddf"); - return _instDDF; - } - - public static POIDataSamples getHPSFInstance(){ - if(_instHPSF == null) _instHPSF = new POIDataSamples("hpsf"); - return _instHPSF; - } - - public static POIDataSamples getPublisherInstance(){ - if(_instHPBF == null) _instHPBF = new POIDataSamples("publisher"); - return _instHPBF; - } - - public static POIDataSamples getHMEFInstance(){ - if(_instHMEF == null) _instHMEF = new POIDataSamples("hmef"); - return _instHMEF; - } - - public static POIDataSamples getHSMFInstance(){ - if(_instHSMF == null) _instHSMF = new POIDataSamples("hsmf"); - return _instHSMF; - } - - public static POIDataSamples getXmlDSignInstance(){ - if(_instXmlDSign == null) _instXmlDSign = new POIDataSamples("xmldsign"); - return _instXmlDSign; - } - - /** - * Opens a sample file from the test data directory - * - * @param sampleFileName the file to open - * @return an open InputStream for the specified sample file - */ - public InputStream openResourceAsStream(String sampleFileName) { - - if (_sampleDataIsAvaliableOnClassPath) { - InputStream result = sampleFileName == null ? null : - openClasspathResource(sampleFileName); - if(result == null) { - throw new RuntimeException("specified test sample file '" + sampleFileName - + "' not found on the classpath"); - } - // wrap to avoid temp warning method about auto-closing input stream - return new NonSeekableInputStream(result); - } - if (_resolvedDataDir == null) { - throw new RuntimeException("Must set system property '" - + TEST_PROPERTY - + "' properly before running tests"); - } - - File f = getFile(sampleFileName); - try { - return new FileInputStream(f); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - } - - /** - * - * @param sampleFileName the name of the test file - * @return - * @throws RuntimeException if the file was not found - */ - public File getFile(String sampleFileName) { - File f = new File(_resolvedDataDir, sampleFileName); - if (!f.exists()) { - throw new RuntimeException("Sample file '" + sampleFileName - + "' not found in data dir '" + _resolvedDataDir.getAbsolutePath() + "'"); - } - try { - if(sampleFileName.length() > 0) { - String fn = sampleFileName; - if(fn.indexOf('/') > 0) { - fn = fn.substring(fn.indexOf('/')+1); - } - if(!fn.equals(f.getCanonicalFile().getName())){ - throw new RuntimeException("File name is case-sensitive: requested '" + fn - + "' but actual file is '" + f.getCanonicalFile().getName() + "'"); - } - } - } catch (IOException e){ - throw new RuntimeException(e); - } - return f; - } - - private void initialise() { - String dataDirName = System.getProperty(TEST_PROPERTY); - if (dataDirName == null) { - // check to see if we can just get the resources from the classpath - InputStream is = openClasspathResource(""); - if (is != null) { - try { - is.close(); // be nice - } catch (IOException e) { - throw new RuntimeException(e); - } - _sampleDataIsAvaliableOnClassPath = true; - return; - } - - if(new File("test-data").exists()) { - dataDirName = "test-data"; - } else { - throw new RuntimeException("Must set system property '" + - TEST_PROPERTY + "' before running tests"); - } - } - File dataDir = new File(dataDirName, _moduleDir); - if (!dataDir.exists()) { - throw new RuntimeException("Data dir '" + _moduleDir + " does not exist"); - } - // convert to canonical file, to make any subsequent error messages - // clearer. - try { - _resolvedDataDir = dataDir.getCanonicalFile(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Opens a test sample file from the 'data' sub-package of this class's package. - * - * @param sampleFileName the file to open - * @return null if the sample file is not deployed on the classpath. - */ - private InputStream openClasspathResource(String sampleFileName) { - return getClass().getResourceAsStream("/" + _moduleDir + "/" + sampleFileName); - } - - private static final class NonSeekableInputStream extends InputStream { - - private final InputStream _is; - - public NonSeekableInputStream(InputStream is) { - _is = is; - } - - @Override - public int read() throws IOException { - return _is.read(); - } - @Override - public int read(byte[] b, int off, int len) throws IOException { - return _is.read(b, off, len); - } - @Override - public boolean markSupported() { - return false; - } - @Override - public void close() throws IOException { - _is.close(); - } - } - - /** - * @param fileName the file to open - * @return byte array of sample file content from file found in standard test-data directory - */ - public byte[] readFile(String fileName) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - - try { - InputStream fis = openResourceAsStream(fileName); - - byte[] buf = new byte[512]; - while (true) { - int bytesRead = fis.read(buf); - if (bytesRead < 1) { - break; - } - bos.write(buf, 0, bytesRead); - } - fis.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return bos.toByteArray(); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +/** + * Centralises logic for finding/opening sample files + */ +public final class POIDataSamples { + + /** + * Name of the system property that defined path to the test data. + */ + public static final String TEST_PROPERTY = "POI.testdata.path"; + + private static POIDataSamples _instSlideshow; + private static POIDataSamples _instSpreadsheet; + private static POIDataSamples _instDocument; + private static POIDataSamples _instDiagram; + private static POIDataSamples _instOpenxml4j; + private static POIDataSamples _instPOIFS; + private static POIDataSamples _instDDF; + private static POIDataSamples _instHMEF; + private static POIDataSamples _instHPSF; + private static POIDataSamples _instHPBF; + private static POIDataSamples _instHSMF; + private static POIDataSamples _instXmlDSign; + + private File _resolvedDataDir; + /** true if standard system propery is not set, + * but the data is available on the test runtime classpath */ + private boolean _sampleDataIsAvaliableOnClassPath; + private final String _moduleDir; + + /** + * + * @param moduleDir the name of the directory containing the test files + */ + private POIDataSamples(String moduleDir){ + _moduleDir = moduleDir; + initialise(); + } + + public static POIDataSamples getSpreadSheetInstance(){ + if(_instSpreadsheet == null) _instSpreadsheet = new POIDataSamples("spreadsheet"); + return _instSpreadsheet; + } + + public static POIDataSamples getDocumentInstance(){ + if(_instDocument == null) _instDocument = new POIDataSamples("document"); + return _instDocument; + } + + public static POIDataSamples getSlideShowInstance(){ + if(_instSlideshow == null) _instSlideshow = new POIDataSamples("slideshow"); + return _instSlideshow; + } + + public static POIDataSamples getDiagramInstance(){ + if(_instOpenxml4j == null) _instOpenxml4j = new POIDataSamples("diagram"); + return _instOpenxml4j; + } + + public static POIDataSamples getOpenXML4JInstance(){ + if(_instDiagram == null) _instDiagram = new POIDataSamples("openxml4j"); + return _instDiagram; + } + + public static POIDataSamples getPOIFSInstance(){ + if(_instPOIFS == null) _instPOIFS = new POIDataSamples("poifs"); + return _instPOIFS; + } + + public static POIDataSamples getDDFInstance(){ + if(_instDDF == null) _instDDF = new POIDataSamples("ddf"); + return _instDDF; + } + + public static POIDataSamples getHPSFInstance(){ + if(_instHPSF == null) _instHPSF = new POIDataSamples("hpsf"); + return _instHPSF; + } + + public static POIDataSamples getPublisherInstance(){ + if(_instHPBF == null) _instHPBF = new POIDataSamples("publisher"); + return _instHPBF; + } + + public static POIDataSamples getHMEFInstance(){ + if(_instHMEF == null) _instHMEF = new POIDataSamples("hmef"); + return _instHMEF; + } + + public static POIDataSamples getHSMFInstance(){ + if(_instHSMF == null) _instHSMF = new POIDataSamples("hsmf"); + return _instHSMF; + } + + public static POIDataSamples getXmlDSignInstance(){ + if(_instXmlDSign == null) _instXmlDSign = new POIDataSamples("xmldsign"); + return _instXmlDSign; + } + + /** + * Opens a sample file from the test data directory + * + * @param sampleFileName the file to open + * @return an open InputStream for the specified sample file + */ + public InputStream openResourceAsStream(String sampleFileName) { + + if (_sampleDataIsAvaliableOnClassPath) { + InputStream result = sampleFileName == null ? null : + openClasspathResource(sampleFileName); + if(result == null) { + throw new RuntimeException("specified test sample file '" + sampleFileName + + "' not found on the classpath"); + } + // wrap to avoid temp warning method about auto-closing input stream + return new NonSeekableInputStream(result); + } + if (_resolvedDataDir == null) { + throw new RuntimeException("Must set system property '" + + TEST_PROPERTY + + "' properly before running tests"); + } + + File f = getFile(sampleFileName); + try { + return new FileInputStream(f); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * + * @param sampleFileName the name of the test file + * @return + * @throws RuntimeException if the file was not found + */ + public File getFile(String sampleFileName) { + File f = new File(_resolvedDataDir, sampleFileName); + if (!f.exists()) { + throw new RuntimeException("Sample file '" + sampleFileName + + "' not found in data dir '" + _resolvedDataDir.getAbsolutePath() + "'"); + } + try { + if(sampleFileName.length() > 0) { + String fn = sampleFileName; + if(fn.indexOf('/') > 0) { + fn = fn.substring(fn.indexOf('/')+1); + } + if(!fn.equals(f.getCanonicalFile().getName())){ + throw new RuntimeException("File name is case-sensitive: requested '" + fn + + "' but actual file is '" + f.getCanonicalFile().getName() + "'"); + } + } + } catch (IOException e){ + throw new RuntimeException(e); + } + return f; + } + + private void initialise() { + String dataDirName = System.getProperty(TEST_PROPERTY); + if (dataDirName == null) { + // check to see if we can just get the resources from the classpath + InputStream is = openClasspathResource(""); + if (is != null) { + try { + is.close(); // be nice + } catch (IOException e) { + throw new RuntimeException(e); + } + _sampleDataIsAvaliableOnClassPath = true; + return; + } + + if(new File("test-data").exists()) { + dataDirName = "test-data"; + } else { + throw new RuntimeException("Must set system property '" + + TEST_PROPERTY + "' before running tests"); + } + } + File dataDir = new File(dataDirName, _moduleDir); + if (!dataDir.exists()) { + throw new RuntimeException("Data dir '" + _moduleDir + " does not exist"); + } + // convert to canonical file, to make any subsequent error messages + // clearer. + try { + _resolvedDataDir = dataDir.getCanonicalFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Opens a test sample file from the 'data' sub-package of this class's package. + * + * @param sampleFileName the file to open + * @return null if the sample file is not deployed on the classpath. + */ + private InputStream openClasspathResource(String sampleFileName) { + return getClass().getResourceAsStream("/" + _moduleDir + "/" + sampleFileName); + } + + private static final class NonSeekableInputStream extends InputStream { + + private final InputStream _is; + + public NonSeekableInputStream(InputStream is) { + _is = is; + } + + @Override + public int read() throws IOException { + return _is.read(); + } + @Override + public int read(byte[] b, int off, int len) throws IOException { + return _is.read(b, off, len); + } + @Override + public boolean markSupported() { + return false; + } + @Override + public void close() throws IOException { + _is.close(); + } + } + + /** + * @param fileName the file to open + * @return byte array of sample file content from file found in standard test-data directory + */ + public byte[] readFile(String fileName) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + try { + InputStream fis = openResourceAsStream(fileName); + + byte[] buf = new byte[512]; + while (true) { + int bytesRead = fis.read(buf); + if (bytesRead < 1) { + break; + } + bos.write(buf, 0, bytesRead); + } + fis.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return bos.toByteArray(); + } + +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index 2f929a06ff..ddeacd6fb8 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -1,946 +1,946 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hssf.model; - -import static org.apache.poi.poifs.storage.RawDataUtil.decompress; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.poi.ddf.DefaultEscherRecordFactory; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherRecordFactory; -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.ContinueRecord; -import org.apache.poi.hssf.record.DrawingRecord; -import org.apache.poi.hssf.record.EOFRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.NoteRecord; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.RecordBase; -import org.apache.poi.hssf.record.RecordFactory; -import org.apache.poi.hssf.record.TextObjectRecord; -import org.apache.poi.hssf.record.WindowTwoRecord; -import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; -import org.apache.poi.hssf.usermodel.HSSFPatriarch; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFTestHelper; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.util.HexDump; -import org.junit.Test; - -public class TestDrawingAggregate { - /** - * information about drawing aggregate in a worksheet - */ - private static class DrawingAggregateInfo { - /** - * start and end indices of the aggregate in the worksheet stream - */ - private int startRecordIndex, endRecordIndex; - /** - * the records being aggregated - */ - private List aggRecords; - - /** - * @return aggregate info or null if the sheet does not contain drawing objects - */ - static DrawingAggregateInfo get(HSSFSheet sheet){ - DrawingAggregateInfo info = null; - InternalSheet isheet = HSSFTestHelper.getSheetForTest(sheet); - List records = isheet.getRecords(); - for(int i = 0; i < records.size(); i++){ - RecordBase rb = records.get(i); - if((rb instanceof DrawingRecord) && info == null) { - info = new DrawingAggregateInfo(); - info.startRecordIndex = i; - info.endRecordIndex = i; - } else if (info != null && ( - rb instanceof DrawingRecord - || rb instanceof ObjRecord - || rb instanceof TextObjectRecord - || rb instanceof ContinueRecord - || rb instanceof NoteRecord - )){ - info.endRecordIndex = i; - } else { - if(rb instanceof EscherAggregate) - throw new IllegalStateException("Drawing data already aggregated. " + - "You should cal this method before the first invocation of HSSFSheet#getDrawingPatriarch()"); - if (info != null) break; - } - } - if(info != null){ - info.aggRecords = new ArrayList( - records.subList(info.startRecordIndex, info.endRecordIndex + 1)); - } - return info; - } - - /** - * @return the raw data being aggregated - */ - byte[] getRawBytes(){ - ByteArrayOutputStream out = new ByteArrayOutputStream(); - for (RecordBase rb : aggRecords) { - Record r = (Record) rb; - try { - out.write(r.serialize()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - return out.toByteArray(); - } - } - - /** - * iterate over all sheets, aggregate drawing records (if there are any) - * and remember information about the aggregated data. - * Then serialize the workbook, read back and assert that the aggregated data is preserved. - * - * The assertion is strict meaning that the drawing data before and after save must be equal. - */ - private static void assertWriteAndReadBack(HSSFWorkbook wb) throws IOException { - // map aggregate info by sheet index - Map aggs = new HashMap(); - for(int i = 0; i < wb.getNumberOfSheets(); i++){ - HSSFSheet sheet = wb.getSheetAt(i); - DrawingAggregateInfo info = DrawingAggregateInfo.get(sheet); - if(info != null) { - aggs.put(i, info); - HSSFPatriarch p = sheet.getDrawingPatriarch(); - - // compare aggregate.serialize() with raw bytes from the record stream - EscherAggregate agg = HSSFTestHelper.getEscherAggregate(p); - - byte[] dgBytes1 = info.getRawBytes(); - byte[] dgBytes2 = agg.serialize(); - - assertEquals("different size of raw data ande aggregate.serialize()", dgBytes1.length, dgBytes2.length); - assertTrue("raw drawing data ("+dgBytes1.length+" bytes) and aggregate.serialize() are different.", - Arrays.equals(dgBytes1, dgBytes2)); - } - } - - if(aggs.size() != 0){ - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb); - for(int i = 0; i < wb2.getNumberOfSheets(); i++){ - DrawingAggregateInfo info1 = aggs.get(i); - if(info1 != null) { - HSSFSheet sheet2 = wb2.getSheetAt(i); - DrawingAggregateInfo info2 = DrawingAggregateInfo.get(sheet2); - byte[] dgBytes1 = info1.getRawBytes(); - byte[] dgBytes2 = info2.getRawBytes(); - assertEquals("different size of drawing data before and after save", dgBytes1.length, dgBytes2.length); - assertTrue("drawing data ("+dgBytes1.length+" bytes) before and after save is different.", - Arrays.equals(dgBytes1, dgBytes2)); - } - } - wb2.close(); - } - } - - /** - * test that we correctly read and write drawing aggregates - * in all .xls files in POI test samples - */ - @Test - public void testAllTestSamples() throws IOException { - File[] xls = new File(System.getProperty("POI.testdata.path"), "spreadsheet").listFiles( - new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".xls"); - } - } - ); - assertNotNull( - "Need to find files in test-data path, had path: " + new File(System.getProperty("POI.testdata.path"), "spreadsheet"), - xls); - for(File file : xls) { - HSSFWorkbook wb; - try { - wb = HSSFTestDataSamples.openSampleWorkbook(file.getName()); - } catch (Throwable e){ - // don't bother about files we cannot read - they are different bugs - // System.out.println("[WARN] Cannot read " + file.getName()); - continue; - } - try { - assertWriteAndReadBack(wb); - } catch (Exception e) { - String filename = file.getName(); - System.out.println("Drawing Aggregate re-write test failed for " + filename); - e.printStackTrace(System.out); - - fail("Error when writing and re-reading workbook " + filename + "\n" + e); - } - wb.close(); - } - } - - /** - * when reading incomplete data ensure that the serialized bytes match the source - */ - @Test - public void testIncompleteData() throws IOException { - //EscherDgContainer and EscherSpgrContainer length exceeds the actual length of the data - String data = - "H4sIAAAAAAAAAGWOOw7CQAxE32YTsSRIWSgQJSUloqSm5g4ICURBg+iBK3APGi6wBWeh9xGYbEps2WON"+ - "P+OWwpYeIsECMFC8S2jxNvMdlrYQ5xha5N8K6ryHdir6+avwOer5l3hq2NPYWuWN0n1dIsgfbgshuSj1"+ - "+2eqbvLdxQ0ndhy5KJ/lc1ZZK9okY5X/gSbrHZTH1vE/ozagTcwAAAA="; - byte[] dgBytes = decompress(data); - - List records = new ArrayList(); - EscherRecordFactory recordFactory = new DefaultEscherRecordFactory(); - int pos = 0; - while (pos < dgBytes.length) { - EscherRecord r = recordFactory.createRecord(dgBytes, pos); - int bytesRead = r.fillFields(dgBytes, pos, recordFactory); - records.add(r); - pos += bytesRead; - } - assertEquals("data was not fully read", dgBytes.length, pos); - - // serialize to byte array - ByteArrayOutputStream out = new ByteArrayOutputStream(); - for(EscherRecord r : records) { - out.write(r.serialize()); - } - assertEquals(HexDump.toHex(dgBytes, 10), HexDump.toHex(out.toByteArray(), 10)); - } - - /** - * TODO: figure out why it fails with "RecordFormatException: 0 bytes written but getRecordSize() reports 80" - */ - @Test - public void testFailing() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("15573.xls"); - HSSFSheet sh = wb.getSheetAt(0); - sh.getDrawingPatriarch(); - - HSSFTestDataSamples.writeOutAndReadBack(wb).close(); - wb.close(); - } - - private static byte[] toByteArray(List records) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - for (RecordBase rb : records) { - Record r = (Record) rb; - try { - out.write(r.serialize()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - return out.toByteArray(); - } - - @Test - public void testSolverContainerMustBeSavedDuringSerialization() throws IOException{ - HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("SolverContainerAfterSPGR.xls"); - HSSFSheet sh = wb1.getSheetAt(0); - InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); - List records = ish.getRecords(); - // records to be aggregated - List dgRecords = records.subList(19, 22); - byte[] dgBytes = toByteArray(dgRecords); - sh.getDrawingPatriarch(); - EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); - assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); - assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER); - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); - wb1.close(); - sh = wb2.getSheetAt(0); - sh.getDrawingPatriarch(); - ish = HSSFTestHelper.getSheetForTest(sh); - agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); - assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); - assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER); - - - // collect drawing records into a byte buffer. - agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - wb2.close(); - } - - @Test - public void testFileWithTextbox() throws IOException{ - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("text.xls"); - HSSFSheet sh = wb.getSheetAt(0); - InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); - List records = ish.getRecords(); - // records to be aggregated - List dgRecords = records.subList(19, 23); - byte[] dgBytes = toByteArray(dgRecords); - sh.getDrawingPatriarch(); - - // collect drawing records into a byte buffer. - EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - wb.close(); - } - - @Test - public void testFileWithCharts() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls"); - HSSFSheet sh = wb.getSheetAt(0); - InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); - List records = ish.getRecords(); - // records to be aggregated - List dgRecords = records.subList(19, 21); - byte[] dgBytes = toByteArray(dgRecords); - sh.getDrawingPatriarch(); - - // collect drawing records into a byte buffer. - EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - for (int i=0; i< dgBytes.length; i++){ - if (dgBytes[i] != dgBytesAfterSave[i]){ - System.out.println("pos = " + i); - } - } - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - wb.close(); - } - - /** - * test reading drawing aggregate from a test file from Bugzilla 45129 - */ - @Test - public void test45129() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45129.xls"); - HSSFSheet sh = wb.getSheetAt(0); - - InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); - InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); - - List records = isheet.getRecords(); - - // the sheet's drawing is not aggregated - assertEquals("wrong size of sheet records stream", 394, records.size()); - // the last record before the drawing block - assertTrue( - "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), - records.get(18) instanceof RowRecordsAggregate); - - // records to be aggregated - List dgRecords = records.subList(19, 389); - // collect drawing records into a byte buffer. - byte[] dgBytes = toByteArray(dgRecords); - - for (RecordBase rb : dgRecords) { - Record r = (Record) rb; - short sid = r.getSid(); - // we expect that drawing block consists of either - // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord - assertTrue( - sid == DrawingRecord.sid || - sid == ContinueRecord.sid || - sid == ObjRecord.sid || - sid == TextObjectRecord.sid); - } - - // the first record after the drawing block - assertTrue( - "records.get(389) is expected to be Window2", - records.get(389) instanceof WindowTwoRecord); - - // aggregate drawing records. - // The subrange [19, 388] is expected to be replaced with a EscherAggregate object - DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); - int loc = isheet.aggregateDrawingRecords(drawingManager, false); - EscherAggregate agg = (EscherAggregate) records.get(loc); - - assertEquals("wrong size of the aggregated sheet records stream", 25, records.size()); - assertTrue( - "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), - records.get(18) instanceof RowRecordsAggregate); - assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), - records.get(19) instanceof EscherAggregate); - assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), - records.get(20) instanceof WindowTwoRecord); - - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - wb.close(); - } - - /** - * Try to check file with such record sequence - * ... - * DrawingRecord - * ContinueRecord - * ObjRecord | TextObjRecord - * ... - */ - @Test - public void testSerializeDrawingBigger8k() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls"); - InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); - HSSFSheet sh = wb.getSheetAt(0); - InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); - - - List records = isheet.getRecords(); - - // the sheet's drawing is not aggregated - assertEquals("wrong size of sheet records stream", 32, records.size()); - // the last record before the drawing block - assertTrue( - "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), - records.get(18) instanceof RowRecordsAggregate); - - // records to be aggregated - List dgRecords = records.subList(19, 26); - for (RecordBase rb : dgRecords) { - Record r = (Record) rb; - short sid = r.getSid(); - // we expect that drawing block consists of either - // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord - assertTrue( - sid == DrawingRecord.sid || - sid == ContinueRecord.sid || - sid == ObjRecord.sid || - sid == NoteRecord.sid || - sid == TextObjectRecord.sid); - } - // collect drawing records into a byte buffer. - byte[] dgBytes = toByteArray(dgRecords); - - // the first record after the drawing block - assertTrue( - "records.get(26) is expected to be Window2", - records.get(26) instanceof WindowTwoRecord); - - // aggregate drawing records. - // The subrange [19, 38] is expected to be replaced with a EscherAggregate object - DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); - int loc = isheet.aggregateDrawingRecords(drawingManager, false); - EscherAggregate agg = (EscherAggregate) records.get(loc); - - assertEquals("wrong size of the aggregated sheet records stream", 26, records.size()); - assertTrue( - "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), - records.get(18) instanceof RowRecordsAggregate); - assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), - records.get(19) instanceof EscherAggregate); - assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), - records.get(20) instanceof WindowTwoRecord); - - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - wb.close(); - } - - - @Test - public void testSerializeDrawingBigger8k_noAggregation() throws IOException { - HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls"); - - InternalSheet isheet = HSSFTestHelper.getSheetForTest(wb1.getSheetAt(0)); - List records = isheet.getRecords(); - - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); - wb1.close(); - InternalSheet isheet2 = HSSFTestHelper.getSheetForTest(wb2.getSheetAt(0)); - List records2 = isheet2.getRecords(); - - assertEquals(records.size(), records2.size()); - for (int i = 0; i < records.size(); i++) { - RecordBase r1 = records.get(i); - RecordBase r2 = records2.get(i); - assertTrue(r1.getClass() == r2.getClass()); - assertEquals(r1.getRecordSize(), r2.getRecordSize()); - if (r1 instanceof Record) { - assertEquals(((Record) r1).getSid(), ((Record) r2).getSid()); - assertArrayEquals(((Record) r1).serialize(), ((Record) r2).serialize()); - } - } - wb2.close(); - } - - @Test - public void testSerializeDrawingWithComments() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingAndComments.xls"); - HSSFSheet sh = wb.getSheetAt(0); - InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); - InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); - - List records = isheet.getRecords(); - - // the sheet's drawing is not aggregated - assertEquals("wrong size of sheet records stream", 46, records.size()); - // the last record before the drawing block - assertTrue( - "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), - records.get(18) instanceof RowRecordsAggregate); - - // records to be aggregated - List dgRecords = records.subList(19, 39); - for (RecordBase rb : dgRecords) { - Record r = (Record) rb; - short sid = r.getSid(); - // we expect that drawing block consists of either - // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord - assertTrue( - sid == DrawingRecord.sid || - sid == ContinueRecord.sid || - sid == ObjRecord.sid || - sid == NoteRecord.sid || - sid == TextObjectRecord.sid); - } - // collect drawing records into a byte buffer. - byte[] dgBytes = toByteArray(dgRecords); - - // the first record after the drawing block - assertTrue( - "records.get(39) is expected to be Window2", - records.get(39) instanceof WindowTwoRecord); - - // aggregate drawing records. - // The subrange [19, 38] is expected to be replaced with a EscherAggregate object - DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); - int loc = isheet.aggregateDrawingRecords(drawingManager, false); - EscherAggregate agg = (EscherAggregate) records.get(loc); - - assertEquals("wrong size of the aggregated sheet records stream", 27, records.size()); - assertTrue( - "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), - records.get(18) instanceof RowRecordsAggregate); - assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), - records.get(19) instanceof EscherAggregate); - assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), - records.get(20) instanceof WindowTwoRecord); - - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - wb.close(); - } - - - @Test - public void testFileWithPictures() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ContinueRecordProblem.xls"); - HSSFSheet sh = wb.getSheetAt(0); - - InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); - InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); - - List records = isheet.getRecords(); - - // the sheet's drawing is not aggregated - assertEquals("wrong size of sheet records stream", 315, records.size()); - // the last record before the drawing block - assertTrue( - "records.get(21) is expected to be RowRecordsAggregate but was " + records.get(21).getClass().getSimpleName(), - records.get(21) instanceof RowRecordsAggregate); - - // records to be aggregated - List dgRecords = records.subList(22, 300); - for (RecordBase rb : dgRecords) { - Record r = (Record) rb; - short sid = r.getSid(); - // we expect that drawing block consists of either - // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord - assertTrue( - sid == DrawingRecord.sid || - sid == ContinueRecord.sid || - sid == ObjRecord.sid || - sid == TextObjectRecord.sid); - } - // collect drawing records into a byte buffer. - byte[] dgBytes = toByteArray(dgRecords); - - // the first record after the drawing block - assertTrue( - "records.get(300) is expected to be Window2", - records.get(300) instanceof WindowTwoRecord); - - // aggregate drawing records. - // The subrange [19, 299] is expected to be replaced with a EscherAggregate object - DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); - int loc = isheet.aggregateDrawingRecords(drawingManager, false); - EscherAggregate agg = (EscherAggregate) records.get(loc); - - assertEquals("wrong size of the aggregated sheet records stream", 38, records.size()); - assertTrue( - "records.get(21) is expected to be RowRecordsAggregate but was " + records.get(21).getClass().getSimpleName(), - records.get(21) instanceof RowRecordsAggregate); - assertTrue("records.get(22) is expected to be EscherAggregate but was " + records.get(22).getClass().getSimpleName(), - records.get(22) instanceof EscherAggregate); - assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(), - records.get(23) instanceof WindowTwoRecord); - - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - wb.close(); - } - - @Test - public void testUnhandledContinue() throws IOException { - String data = - "H4sIAAAAAAAAAO3adVRU2/4A8EPHAEOnlEooNaSUdCNIg4CUDCEtQ6gwlITSjYiSkoKA0ikg0i1IyCjS"+ - "QwpSEr8B73v3PS6+9+67vz/eH+615pyz9tn71PqevT/rfGcJOIcLBtDXrNgAgBjAXcMFAAAb9SPDBAAw"+ - "gLGmzna8xlxjR9WhAXhrxMAfCzqAf9IPQPXBAn6078IBgAyCH/VgVD2ADwCxAGhNBbXpc9LUF2h8n4we"+ - "iOoNAKEnywaAFmAEGtDQABLgCA0AcAHfZvLjeozjc+gAUMATgAEygBNqzQTwHl8lcH5dGHWmvGY+1FJD"+ - "FQOTHHX1x+dkBta2H9UcoLam0I7bAYCRrJMjDOoIM9W56wx1vcnt6WAfF92t0gIhfrfqv0o8e9khH4fE"+ - "thqnQJHiJqOZUrbDByG8xwYeiEmYJPcUPoP17NH6hTz9cVtyfvnyyUuV3BzE06+vDH/Dlxi+/pYeV32e"+ - "IGIy2p+e90VyZ+i9OlDL+Rp6Dmot/G2tUgYbGW5vpkSep5Fk2eKtJthDdEvKkzrvC4cmWe7kKaliC7ip"+ - "0sMjlMUdN/akSG0ticE4nweeA7LUha1xyjNLXZEJUx80rOZMmgMIveJ5pQ7Hio17qM558+zaZgheNOHN"+ - "tk7hCxKIZgFTs9t1NGhTdj0EIdz0tEcV4KZebLmun1t9qpQ2fF6N29/P3I3j3pYc8kI9zaMjjFNPi/ej"+ - "qfkAaisS9bRAqLXpHai9Kw/38TIr6s3tZghB0GpAXUB/ncuYLE2mulOgiSpODb6R8rVbnQasDoj6bIiB"+ - "gpPYItWexPrqVgUk73GpZwT2sBroUQZ07ovZJ6SXgbdvjH//55ZoggllM0Rdw7K6gHmeIt/exXytDGpq"+ - "VeVUw1D6S2kCKezDar0iZnm3GGAy99/4bWY7VIgeWUlVmOVn8kdFOmIsel1/vx9MX9vNOZHYeqdvYnuy"+ - "PuP2uxHPjCotCFiHoJKzFzI4MTQn1bBVdLQQT0LmrX8os3+t4Nu7F1SC7mDgrFsvKsHS80DFHx3O8SsA"+ - "AJZ3XHlcbcydoagIOY6SWl1Vp3EIQT34gw8x7PqBwdNgkpp5LViiOWHMLE5uaQp1LIusFllOAzxrOusm"+ - "WExAlgdfVmW/LRLc67SnF1MHKe/PT2vXvfZQw1g/fIwStuEpmaxlQa9NEWv40J8h8PmVmRGejXo+EW2v"+ - "HEI0qo7ZNPb5niruyPOdHhnQLRUPGb+y4Wwo0WGygw6NOzBXGDYgzKBYzu+v6872oAZEaXgP4VtOrDV5"+ - "LyQtP9wxoKWMM/buA960eUbfNY0RKG1vKafEuMZMtwJjh5N0+JRy8JYlbS/r6OhsqifipW+Gx4NtrO4B"+ - "znA/UjinjWh9TytvuD/PeHSCSyZI5WEAslSzQZpIoczUQ5XM8tCuQSArrxGN5VGZ1OKFiaOi+zEpKW/o"+ - "vaSMwbfZQYveck70N1ZjZrwdxtKxlzAobG5kMl1LQFazAkJqVsrYDgCNeunmvRhm4c6jbinypsbQpyUr"+ - "wX1UwXJ9mtLhn3qC321JFsoymDATqy98V+hQ3ZBcpxN+W1+6wo6FrlRGKhW2ug7eAH3Dvn0rNWTG6vvr"+ - "qKDGWqAXYu0s8ZmmdMM3xFjWIjXsqtT56ly7tMPY9d40CZ/CQ0b4OLsD9qG5CB5n47N2/2qJMKo1+rUg"+ - "TTpa4D7au2JRC6XrayDXu7ZXGpvcwM5DWoz4HdBBTfQnmzN1K2YG+hpYNVGkX6ZlZGv7OM1XZeaZU1e2"+ - "Rt+QEzSTyLSYPXezW5pSbf62gbi5iHWB7xBAZ2leDdXI7Kat5+Epnor5sC3ZefMh0hUTSQ8VP+BIz2fh"+ - "t3eD2z9TLOhGRLoIErwXi+9yUgMZHhVGhWusRIi4J297mNL4iBUbHaKdFaRyobYMnKg9BWjH4+uPILV0"+ - "8nC8A3U/jlFjjX71Jgi595V1xmS7qScwAiEcrTYLmRbMfuaHL6EOo1NjPeWNa8hlBYLWd64rInOTrmyv"+ - "FPTmG8O5ys73rWL5VnYIcryPaJz1hicCpRGXFTgKhf3IKiBPTEzV5pMWMjt2zJfd24LZxbIx8ecWeVuF"+ - "eCqzynPsivav2VzI2+hbgvBvzjdDA5uZQkqynn+lwzfceOc/l4qsu1hsOTVzy6AnNW9HhaqZ8yHRS87z"+ - "01vZyoyAyGRlaOVkgW6lsSNCaOFlWqgRBJ2ZaR02lhwDHRJ1xN2B1xc64WubpudpxVONMUW7GMG/w61N"+ - "qLmi+xXRMaSqigzr33Iwc3owsLyZl1hUaNChDstgByZaRb2FUik+0vh0uZw72thqliZVKKQydVxsnHk3"+ - "yPj3tx8NnQv4+UTxz+WMaeP0AU6Pnb8XbrR/GklPdzw98vxeLqH/cRw63ft0SPxeejD/ECAaqljYP6Zo"+ - "TOAbas2G/aMp8RrpyQyOBpihYQAbqK0+1BxuiKojWTvefxM1J1MApKiTggESs9MPZ+nkUghPWpajkQKk"+ - "6H/bg/3bDYkDqHuDQT1hXLziJ1WUv+3+2wE6cY650PkPXCD+CRcAqPZf4ALfb1y4csIF3l9c+MWF/44L"+ - "j9ungt3+JRe6HacgxPUvhzyKvXJ2F/yZmvIM81egZfIaDI0XieSQH6KXZeYHV8Oe9jmC77MXmJyzbuVH"+ - "7Dxh7HWqUYgJgJQPP+qfFs2Wy5VJLBvjrb4LP6d2qSSiIEa1EDOTzXzBAf7NYTKe9Uv+BzvZxsBSGlzq"+ - "j2IjVpqWoXU2lXXDhRppha9tKwNMX4WqNEd+qo3WpH0X21ausDawEugMlpZ1XaXro5TpEAOTyMX3q32g"+ - "MJxtF2+idkYSmm3o6N6l7W39svNCNlqfzruLTTpsXDpob1SYnlNqhqsWeUW8X0QLFtb0RgBb4RFZ5sL0"+ - "d0/SQfbKUi5bT3OBzDhhYW67b3Rb0nlESHfbpvodNwNarcSwSY0MT4wUiebd+x+jYc7Y1n2+lUQtURRx"+ - "30MmxUonWXqrOwS88XfYSPvWDKWTxAd15QH75K4YXh20CYiyU3YjQcbGEoJcjplI/AMtEo7r7XINk573"+ - "ttxnL6/9tUHRi1OE6J/j4C+e18b5+n2Sujwc78Z2iVgqPx6w8gr3STZTEnam+x76oWmpHGSLuwkiJvTG"+ - "RlKOOIuBQ9oojJdCS+4ryVHpYg358B7SDCFMC46CEUMqT575UKujkzl/itEcCTxEr8cwQdh5o5lxmTEm"+ - "sBHYgkxtulQL0LCL7vs/j9lrs2FGJpAmZb1khCo2GylQdMmohMWCCNdlSh5UgdKDv7/24CGqTnOKID6P"+ - "zVFodIvClLZo9WhLi4c6eh1EzC5SzyMTLmTnaWpiPnzRRdLGOGLDNc4iUwyxMqmSe6ed0PRpeHenTdnu"+ - "OLWibGodMxRubxi1VyEzLFOFs7LTt8poQuMjWvzk6Ews6D2wxOX6F1iIMr2OwsJbhNo+Ubfgulo5Ravk"+ - "JUteZgv/qaiWkdJy++ryV4WQnU13JuY9z566hsH7oslDpXJGjvbpFH65FOhTlwdfaNChF1Qs3GSMctPh"+ - "Nbz9Fm+pKrB9Z++2XPC1VZ2OCtUKaQm5UWaWKDF9woBGK5HEoXLY2/hUPIeLbibJao0EH3edb2ALE9T4"+ - "ZQV+5Zl+PQUW6ZVIRMQ0pjyc21bn9c6Y4njsNgCvvVmcFDX+RLQKZ9pzmbtT97CkcWN3zy0+hSrChV8h"+ - "jVBJfGUk2+xSWQQden2qE/JJ0wf93E45aJWQUtYEJQ5idRqUycJ3TzENxD4I/XJlTx63k95POuxW6jSb"+ - "NU5wwAcj6djFzYfLB6U7YLpvGT2Swk3LEhF0wpUTMPJESYaj/zktnB54/pwWTsfE76Xr32uB9QwtYKOm"+ - "5GMt4ACzZ2iB+C9qge8/1QLJz7TQ/1e0wP9LC7+08P+hBWVCae5j4tP+VAtqruNMxHUe2Ud+n1fmLyTQ"+ - "2YXx5fEvPB/0XNrBMcMbTT7fB5TM7O+t+C9liWwSe9yRtqHauspQ07lU7sQyCrpFV0itVmSh8uCy2/tc"+ - "rkxkTnA/Icuwi65LXrzZJjtnHVc9/PG3+Paqyx5jxLjp9kTYCh49bnfJR++wGTq+hLGRe9o5GK58GrHP"+ - "7FjDwHSCxrWuXyx9SlJbKsY84b3W1/QO+3VV1NceWUxtBxid1fMEeb7QKAz1A+wk8WG36NZBztBeCYG7"+ - "Ff3BFrRdwldH+yS7B5aW1um8pvWF+8W0tsKaqgWwpTsuZC5YpqhZ0AYqlV/g4gm3iiPF6YRmwpvFhd/D"+ - "33NdS0ps2ALJJj/q52V5VMG0QPbiqOj+HW98bDtnDJerSZ+1+lZo6ggtvZWebZfZBtN9YuxrmAlHTxYf"+ - "cVMDllgfs9JcREuB7CZEfBGQhT07MvJnX2sM/PFxwfU8dYjmBZW53fWD60iNEH3cB9p76dFftdDU0XE0"+ - "eQtfiKn4AVpcWOxftPeb0ZsDA8pLJEO4ut35E4Okqnz7NKwgjs4EOccfF5rfSNDc95WDaY4wHbB9SZU+"+ - "2C3b89lxyHxNsxk8eXENfcuYb3FPwzTNo5HutoMS0IX1onkxJE5oLbCpVoAuDVGtSH07DxyWULrA7qew"+ - "93XSHVJ7S0eaI6tFWGSkkSqG5fXNNIaewY9XxXL904XR5S+itGBOaaoyMuLjYUtuabkPoKtE9IZqZH7D"+ - "f5ZINS+ovLSROlfUeChS3SrjUT9xwJ2ej3XF6+6k/TPFzm+IJyWCBBUe1XwIIS6DA21muvSJqx77Oqur"+ - "DDQNorlG+2d64a68eyEHak/+z7ygeeyFQJQXwMdeEGV970demkTM+/g3L7g4WBuZ7yC5LjyY/yKyDZ/b"+ - "gok76IaXN1V32OAfmGAqzTetqTixv5i0voLHNPd49oWQocYHEM5g+8zbpPDK0QVj+0R4gEyI+wWF9M16"+ - "GvOlR1rss/eySUS7skoe7TItY7t2ujMbvxeOyBB7YfC8OTBGcKqE/O3cVyPNtkqvXWqdV9asDQO7TNfb"+ - "3N/gPR/Rd9gD2kKHUxPpOKhcEgoRegu26aFPXPExpL7aNpRT9D7eaNLCPZAZ7yNnTZcxyqlmD5fnoyra"+ - "wzuIqH+twGznTh7ki6/NuB8Ajx/AYzQmjXV05puyUVLC3CFe7CZZDjaipzsyJ7tzBF55V6FcjB7We32x"+ - "ZTeUreF/TgunB54/p4XTEfF7+Q++LZylBTyA8EQL+IDrGVog+Yta4D9bC104p1MRpD/TgtBfSUUIAL9S"+ - "Eb+08P+gBSMhtMnjl5b+51rQHoecaEE6837xU9bHUW+s2AnqYPixjWDi8hTPy6oMyheJGuqdWNg0iK5G"+ - "EVHdMLHdXq4/6HsLRVwujx8WVJgTF1MVia0W0M0cEfHxqqTvFnE1mVdhz4T2bA+sd04hE0PrS0HpneEl"+ - "BKyvjaSiNsK3P55XNq6KLnS2zo6lzSkrKVzbKUNmlVrgfClUabUVVTW2fp47oaDiQ3bdk8QeY9nwshsF"+ - "U0ZueXZ4zUDu+RqlNpwxbCz7lcVq6py5Qdt74hc0hcut9C0DiJbBMtVR0FinhbSAV2lkYQ3nOyZflfbu"+ - "wsTpcz5lTcx5iT+5Zn3pegbXSIle3PB0Cn8kMr+/oSQy+F7N4orDRGJD+XaCIEWYS7Y8SI/R+ahmYXTa"+ - "jMBDyW+XwWI6cPpNZkWQMeQSpbfDODPeFMYlG/nMz9kGSdVWwBPruVFyNykS/+67tDLkoT7aUXKSberW"+ - "T4+Yu9slePniXDlUGffJxlN7yEheEmPmdDtkDuVhnsONyNKCijToxwBxJioQsvz9ZswLnz8JEfpVDhSl"+ - "FsVD56mJw9Wb9+TswrgB0jvhjcdeuAi7MXKcjIhMY4ZnHjHCx21u4RzyPrvIYsah0+PN+B3kpVibPhKE"+ - "nmaYJvFia3qArN6mS7sA7cIIwjwvfnSmVkftHY3VQuf90Z5H3HO0g1H8yPdlfg3sCcJ3P98Ly6m5tzXv"+ - "ny6SETr94g5cXtcrv4ZddXMiT68thBCEq+NvQp2nGMlRC+FJchk179vxn52zkQlfka3B4coruG/+9muu"+ - "fapi57uGeFsBglGxLM4wNRxbTy6dC2UNJCbn9g4+ipE5KrqHSp4ZpOM9XLvH352LfpaKuHn9RypCUmCk"+ - "5coC9RBwkoqwhBMoe3HZdVKOuJe7EfjU0ctAJD6muK6ILFcN3i24PISLVMm8tHmfhCndtVm17nkx3Ggi"+ - "DBDpFbCO7/dvMhFO6uXmybZv6la3zrixy4XPPKZGHdj0/Z5/SScoPQn52HA+TfkWxQbaGNdswrJMZb7z"+ - "OfkKgxKtYCp8vdDvMtOMBTzyzDNfF7wNuBke719LaLaXS6ZSZ6+rvx0rJmXy+rDW+IpQ+CBso1pdHRRc"+ - "yZIjBbQHH7QmiN/qAakyb4IcZLWTAvEd4udrIZTt1yq/im1+n3kuiH/jFagSzH5Flw3W8ipOfSeCgSgj"+ - "iiKLjELxlsz5xptFVxQ9vGDBuyNXI9okPSQZwiwGqtZ3jXCcJTaWcP7XuHB65PlzXDgdEn+KC2elIkBA"+ - "8gkXCI7/dfAHLpD+RS4InMUFcaDthAtt/8AFsp9wwZf/r3BB8DcuCJxwgfsXF35x4b/jQouTZIA7Kv7O"+ - "/YtUxI9/LojhVueUB4iqhbfJJ2bUENhFCYDT2u5YXEsgUFZLkThQaleuYHC3CTKxTCbd1WT0EahBGslv"+ - "DVS32ii8KogjzQvMo62Dwg72hZO1psRHKPQVVBUiB/prviITb5iO+tuV8Cf4gpbxNSDVG/UcMS0Pn9pX"+ - "1fA9HSo2ohu/A25wf6KTwNh4tyDGJVmddORGO0dF7IBkC70hNsJXKFHlI05Ibn6hbebFsMuvbvjzplET"+ - "SHnmI++kTM7evTcpq/uhfFbDakQz8qsyjX32rhp8Ep/1zTZd2tJVkquZu8KMOVIPhflEnxnPxcax9scj"+ - "lToDBcO0pj5X3t7kifqSPfmyOjC8dKfK1GBAJ0ydvb8WSyv18/6Vwdj9aYKeNLT1q7nMXLlgkoOFNqzE"+ - "2nm7cSKRT4xtUp10hOZfm4YE0Ypt3Z/MaGB/DmqcUQt5RHWUzfTQJS21R/ToZnLorfPzIZocgeD19QPw"+ - "XHTIFdwHg7Mlmota6OqYilolxSmSlx8CKjwsELJHKCrINvmNCxi34NV87Ipn6YNICQjQvqAz/rKMznR+"+ - "xLnkeisDE8nNYUGNo/Yd6z5nn79bwVxU+VrjMw6FYyvsRHjKviTE8i3z9Tag580i9Ern5SnETqo8xEsw"+ - "fIyRKSNIzwJRMUUgiRI8wm5TB8UZvJzFngq0eBhAJRO5vbBiKg5703eOV45AT6Sh6XK9gDG76nyVal0a"+ - "GR0lk4aLl1kWQ6H+WmNtU1jngMZR7RpLTy8JgWWcC6Gelj7Icfervb2pQuc3RKswbdDSUy3K1mwMB09O"+ - "lBZ8Pj1LRWmBn0xd0b0TcWaMvhRwTruEejUL/yMtjCZxXMuKevsgpH2fOmbNcDiBq2jZnuNYC7lyjL3W"+ - "qwueYx20DlUl8XqYe3XExPqBVvFjxAb1PUWkUsOab20KKdiK5yizYzde8dLz1mmLILgnsHdJoYpxUgvG"+ - "/PjoRnHGWuODhPomZGNKi+ICT3xpqjdmSokyIOcwY/Q6GjQGghDxtZ5GXkroNGSRBZXJVzXWn/V8EX8z"+ - "bh2EV1VrM2gkFVGxYum4qEsJHd2DPj6kJnJzVTADlCZWR7ItRI7zEPBUU2RiU8t1G6QOxXMhpekJvVQ4"+ - "IppKQdVys+cLtUY6Un0+hI2Z0wMzAxO8Lr0LbaILk8WtNsxpaFYMrTjC22723OH5GFkUi+ux8An2Hi0F"+ - "fvcr1v8aFU6POn+OCqfj4ffS/e+pcOEMKhABrCdUAAPhwB+pQHYGFcT/BBUEz6LC/wGpc+eRNSkAAA=="; - - byte[] dgBytes = decompress(data); - List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); - assertEquals(20, dgRecords.size()); - - short[] expectedSids = { - DrawingRecord.sid, - ObjRecord.sid, - DrawingRecord.sid, - TextObjectRecord.sid, - DrawingRecord.sid, - ObjRecord.sid, - DrawingRecord.sid, - TextObjectRecord.sid, - DrawingRecord.sid, - ObjRecord.sid, - DrawingRecord.sid, - TextObjectRecord.sid, - DrawingRecord.sid, - ObjRecord.sid, - DrawingRecord.sid, - TextObjectRecord.sid, - ContinueRecord.sid, - ObjRecord.sid, - ContinueRecord.sid, - TextObjectRecord.sid - }; - for (int i = 0; i < expectedSids.length; i++) { - assertEquals("unexpected record.sid and index[" + i + "]", expectedSids[i], dgRecords.get(i).getSid()); - } - DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); - - // create a dummy sheet consisting of our test data - InternalSheet sheet = InternalSheet.createSheet(); - List records = sheet.getRecords(); - records.clear(); - records.addAll(dgRecords); - records.add(EOFRecord.instance); - - - sheet.aggregateDrawingRecords(drawingManager, false); - assertEquals("drawing was not fully aggregated", 2, records.size()); - assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); - assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); - EscherAggregate agg = (EscherAggregate) records.get(0); - - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - } - - @Test - public void testUnhandledContinue2() throws IOException { - String data = - "H4sIAAAAAAAAAO3bdVRUW9sA8AGGrqFHSlpAhSEcQAkJ6UYQyaFBmiEFpCVEOiREGikJSekGlRJQuiQl"+ - "FQFB4ptBvxvIvd+97/fete4f7rWYc9aZc4aZw7P3/s3zbFYB/FiEANTNeD4AAATA2sQCAADIH0wgAEAI"+ - "QNv04kNugZusiGMoAOxNEODHhgrAObkOgLgGHfDt/GlMAID4+3EUxHEADgDgB8DdVEbsNgDAgPMAHxQl"+ - "nzpAAwoI8XsbUfh1QwCvUPiNAIBjFCzEO/BuoUOeiYZ89fPA60AloCBQGCgO5EE8XgPKA4WA/MCrQDoA"+ - "F+IsRgDDR0VM5JUAwHVAbosYYl9ZDg1ICsA4+Sz0gM3dkJpDxN4s4gwSxFZb3NbG0cTGUf+mm50JXJfD"+ - "1doqJrJbthUC6tjw3QAtsFvnYRJZvMDMlyLTPQ+TzrYehmInaLpMTTqKcMzi0JotHH9kzL01ZkHKc6Ni"+ - "kq2K4yJorozv7TaO8FulNhosxSW8sMlIXxqugsRXD+7W4bYy1NBcBKvi7KqW0pqLcXjSxXM+DifJFmzX"+ - "wxikWpWZvDlUODjJ7JArLYfB6yRHcy9MRtBma/86sYUxiBBz5k0WQBxc2B4jM7/6OjxudljZdFGvxQ/f"+ - "I5br+tFosU4PBbUn555F+hUmPa5ss2Tu+7yRzIRgVsuXDWrkr4Nxp5w01EYk7+l7XHgKn2n3qpbe8no+"+ - "ZuWesRfDsSsy6IG4v8fHaKfuFteEvsEbxF444m7hIrb6DiZWcE4O5GNmRNOdFgje/Q2/Or/+OvtR8XMZ"+ - "irYBenKYNTjaMvJGrzRZrKfqsyGakrbXPlDsC3/c2KmE5CaUuoZhvFXADUk3WXwPm17x0PT0jvLtn2mN"+ - "xBuXgU3VNawp8hrkSnHvM+WppoPBcjJPtB7QsKXyJrO+VegVgOUa0TqKuTf5fM62rrx6bHq9EpaXwRMR"+ - "boP2wUNp6CCQprb70nh8u0Pf+O5kffqdjneu6dWqEMKbeFWXeiED44OL1xt2nh0vxxKReN46EjuQz9/u"+ - "KKC44kwIOOujl5871I5HBQAOMJDdAQAwdoBzws0N7EwQEYKMkgJ1GZsxCOkExRIN1joJfgWxVDFpGcGo"+ - "Qj9YEQ7QSLdKI2WLKLhspp46hiokRtiv0E9vFmE7qKSqOuqo2bojlj1JcezuxZCzqNDWlyirjpMyPT3c"+ - "EfRJfo5Zn+XL/tDzDGxJWZIUEhZ+hc04do8U4Xu81g7nSFIK/SWmffPB3sCismdGvWojIRoSNA8SHYrJ"+ - "xTQkWvJ17lYzUdnpcXF+PiRRGoqK0ilkHaLo8VVb0bZtDeXeaVXlfxqR7pAvX8ybfFfS7/YofnHVpRBH"+ - "0lApA95hPONuVas3kX7dpR2hQkHNJRuE0Jq2/XrGQUM6mQ6/LRQe7XSZ6eMH/Eutk2bCD/ZpYNXv10Zu"+ - "PmSPkomEhfJa817co9K8plVfn7dYGr3pIBT/9DUJtWGrDHrAHZG1yTXhiqmxsYmvO3D3sXtjnuZeZfqj"+ - "RayNk8XdX7z5qNaLaGO3FWazI9RvwT55f9LInEuNb01nVUbDJ38oCeKRHAM+uZ/BM8WnJY3XlPZ6uCO6"+ - "05vVj9B3iZffJ/yhcE6rh5Zc1hO1kkp2Y2pmzTfy2gHGh2IWUkNqjm721ZDu7M9xKoy+H9EDvK3ei/Bz"+ - "KkOwBMpWnQ2XQmXKWC41Mb1ifefDUyitSEO9t7nyiWu1eKTEN7Q03XgVNnoVxTTxeHDBYejjCAM5OtMW"+ - "bO7omPh9p0WvOSPFgd2celfAQRIAQ32ZwcXDM7rqLUQ3PSmHYYpSpmjmPAZ8Sthn67Z+cwbMMHo6NPaK"+ - "pN3m5HhHpikPygTa1vuwBaAln7788kVGO302kID8dL1eAUknroFcleOjaGk34QtRlwBmrePCn9b6Zylt"+ - "nlDxY/umra1wTHlGrXVlAcrjUS4aWHEEsWRLVJA36DOSw6tlvFDPCuKXAuvz1Ii+G4aCHIu/BbGxrYuN"+ - "g4kzMoblI14ptkBAN3alD/yuSFuBnFJYY66qi4qZqEmMlsLMiBfpDa+VKkQfCUXH5U3s9Yzz8Lx7vken"+ - "XUrSDtXi2rxAC0pz0OXNMyyeqJ28cL3gfd50oYZvk57mo5x3t3iELzsWcZdo14RMg0xykkXXdPiyBhfK"+ - "I8YVHS+Q7shaM7mwKtzAbXGn5tCmdJ1Ei61VqUpbeOyae+Po+VFs1Zz4PZtt+KfydJcxYW2bKBYCknYb"+ - "2/ttJKALGC7Q4wFbdD+AdPW4V1J2Z5VTM6SRH0zgJxpCQbgmNl8OfV/Dq0Wc4Y5BH6FTiUm57X5bayYi"+ - "yK9TnFo7R3VJygCERmOfE14cfo3QEWg0Y+wZ2u/a1R68QXP7rhtmyBZfttcvowEK6mXAH08cv29nTCOn"+ - "X+D0WPpr40D53ch6+sLTI9GvjQ31x3Hp9NWnQ+DXtg78ISCU5dAxvk3fQMA2YsuH8e1U0Cbx9/kdhIoG"+ - "6EY824eGB8BHHCHaRB7XBVACyBCzPCpCBkSw0zdnFbCEeVoCqP+gBLh/SuCnBP57ErjpXBiC7H9HfyiB"+ - "7rABCKie8SNB3EbNnkXSZZVoMkd0ilYN3R0U+dkyojCakWwRd7HZkLLwRnE70YNVnkzb1mFFVZhPS4VQ"+ - "Zo+84BTf1Ovh6C0EBUK+UWDwOwWYvuxvb0VznabAyBw3i6A2TjAd8BYXmLh28EWYkJKJnBaRE/udl03a"+ - "WLeJ8IscZuajCuhd22r7dhlPKHCZDUEBPzUq7aK2GO6dQTF+Nfob8xoJMAv+j3iYz8uoYPa3SZchIT3N"+ - "Khs8LCtxho8JHo9cupb0EbPJbvprXa9NScmut9ZnumVhV9vnKs1NX/QbReV2aB1IBZd3vG3Dx2dyKdWZ"+ - "ohmawBYv+gvmbA3WvPc+5KV0xbXmD8mncyttAhgV2VnVtyx277mMediuO59P7O3W3bLeLdnr97CoTwe5"+ - "H0JJ0Catmhskb0KhwXwBBaPE0ZikVQzMmPVM5Dd8oH2G/a5AAaMyhc0vl1Bn8CmIxR1YeY7ovzQFcX+h"+ - "Az9GJ/Kw+iLAsjCgxX7oG+J3m56EtSnKdJSbKT9e9tpTgvShNguDUYXlyxn3ge/hONgjb72KOZQh0gJl"+ - "S86mSzEyZQzfJQC/LKP42G2upWgoY8pgqMQf7zlCAubjWqimKRtwuFa5a0XQDRRDWvzx4ycQgmTnICi8"+ - "KRxTL1ans4EIphwLhQe+uxJsiT/AfHdLfk5bfBn/oAVGO3rBTmxFzpVUvoAkuaS0HStsMknEWvV5rve6"+ - "z559INy3PIkz+3MsvSsrWSc1y2YfKxRrSWwY9RnNAqtqSm8QE7yYx3D9/N668T383V78ZKDo1I5TvsuF"+ - "UqFqUs01p0ZZcBJuejBbZGHbBkVwuYD1mydnBnFQfewychqIOFsCNyMUlE76sPRBYKe0DkhO5K3qy1IL"+ - "ujR7lJJC6qoAFt2LiZmyzaOH7oIYo1V75YfD94QS8POYtS10jXj97EgBkS940/upMNr2P15FmxV851sp"+ - "KYdxbRkGFRJJ2tR5pMc57zzPBww0j4djlO/qKuZetMytokpQvFOg3s6+rjKKTxa3y69TzovjG8M+aT6u"+ - "vKUoPFh6oOPJpvMpbxIH/qROZCA/XZ/j7e3o1nNG8RQtBwRB8X4i0OM3Sr6ieJlaq8JWjHHjbhbnUml4"+ - "A9thSAnoxJeXfK0qlSSyvIthRJdlcU6i+B2n+nymFAN1B8qs5r7cw4HPLLLe6/a2BHZBg4SPD3IGNsm1"+ - "lRA94DmaghKnqL3H3Geqf5sETo9Ef08Cp0Pg/ysBNCAgEfEtvw+ABxg9QwKoZ0rg/YkExn4jAbR/UAI8"+ - "3yUg8xsJCP2UwE8J/GcSKAnuIYz+05yAnM0YBPQ9J+BJPRICYzOnKUtK50peABRIjIixqdLd9ipl77P2"+ - "oU0LXMpeuoDMCdCzVT/8ert1p5m2126hbi/y/QOn7r4oWXXslNkTCOiQkj3J+bIw9DwazJiFzYlFkpzt"+ - "Kk5W30krQlmEmwBK4fSXAPnmA0nZ9MwnmFJyPqEXBl8lw5+HXQ4oCL7f4LBOFlVA59qNgEBgyh0m5gAt"+ - "5TzOx+hm0Aq9YGyT1eAAuzzVkFGZatgIbPUcgWQZAZ1OrIkzbUB/jyHpW9Y29pVByVWndmFKVKJFFJYV"+ - "A7RjsQHDwD7MESl8+pcNdn5hy8J2IILZyUVah/AcypvROiGkRpnLWs9DGlBGImderZiyXzPkjFcLzmNo"+ - "MwPbq4o/GVUacxkLX9vdsflafzg+WT5VcX70/Fr8zkVKmO2iqWEjYr7YIIp9qBDlxLbyrGEOZaJQps2H"+ - "U0bidvqV17cEgzAN/PsxjEVCpeptOyOApeLVAnbkUoupEtUCRA996ZOhQBoyeFmkrEjOLEyrEyhbklld"+ - "Qdr1KeANQV7gEs77EIP7Csv4SATw4JwbafKyM0g1inAw719r78OONpfRDJFJUXuGZqYV4XvVaa4lJ7+j"+ - "p0Wjg5j79cuQkgz7FaxH1kfRSfnqgWZJmnHKrzN8vh5fDEXLEUrv1tl87/OOjOKTLRDsmPVqfGZbfFay"+ - "RT5YT4SsrV35Ln5DcUJgD/Z47z5OvSyLBlvP7SEYkGJjrV7xDpQIIlQssn5HscT5a1tMPRRImIWa0IJB"+ - "S9mG4fMCBA2UChQIiaFQY+jC+xz66J1UvVDCROMKHJdPtJjqa3a+i76xuxNb32iHt3oxNF6CZIBh7MHX"+ - "3qCh6lFjEZSzAlh6X2qcCvHMw7+YD4iKIhZ7nEeXVooSCb00nNDqFjQcZjWQ6dWbmXXHpb4evi648EC0"+ - "wvhiqHWZ4bSSIJ3Y/Avzm210Y7Xjkr/kAxQ1NZniKeC0FC9u5Q4/070BkRh5xPP08YqhrLUebteahItY"+ - "2q07jNXiFuxa4EmjKiuLaTcedreMYvHuax91HhyYHV4s6Qo8eP1Z7fO2pG2psK51OkuyZKiuPv4rKTpF"+ - "vPWbB0oN5Hjr3jH5E5UWITHaF/DQdDDjW9romoIDnXM/aSV91KW8HNwv5AeSfqaNoQY+SQiAx3vt6uvg"+ - "B25YfqClzquedJ4SO6ySyWn3IA+LHcvCrLztMRNTwn1mHdvmCP9tCDg9CP09BJyOgF/bh/8bAdynEICG"+ - "eAPoAFMkAlDwAdlnIADtL6YDgP8gAngBP9MBPxHwX0PA6+aBzkeInnb4lxAgEzbf6ZuV6tRnE9Jul4hW"+ - "TGyCmyXtY3zYlXe9Ev2uP216UvqTZNF6lcBMJr7Dy4buBgM8c7V8tqadXW3ZhuY3stjRlezsPhhJuLF8"+ - "iuIk9tj6MCLjH/nGf9EfW5GkNgtHPzP8vAK0OhS7N06MAatJHe8+kLP8pDIQpSHxOCTRYfOkMqBfvekg"+ - "8xZUazjZuCuVksfMXK2lilAAZg5CAQ/YThSQLRbyspC76c3zYDP+R1lCgAf56dJ+KhBa/7reRwXaIU5X"+ - "HUyfr1q1e5Gj10/VrGJT3Q3PuREeuW60C4Ub8wdJHjfj3/f87N6o4jpJg6LoPk2gOPSUIYEUu1164KEp"+ - "sxeaJYVf0bOVBCuBWp1uJvYtYCACA6JpiUo1LjXh3bsLNrv1e+PjV6aczyee745fuEhpWCRygoGNIiQG"+ - "ZhXo8ysa51DmC6W7fDiDb6ik4vMOu66K94CtDWgkULAQFgCXiieMQEKbucAqps7+iyhBd5xdw0JGTkoD"+ - "9pDLxqgnpYEQ420xC8wh0bJmfi75SrY6k8EImIciPePYHiE5BjsGG+GlFzTnrpoQF2LJQbq4XzpN68hF"+ - "qZkReH4pu/v5QsHVuAgDjZhQmofaco2hW0/GkzUup1w2VPF+JIW2e3wBQQGabxS4xXxCgZtZ3eMzTgqz"+ - "Wi2OwZOCZHtvkRSAJATuYOv0ISiAw/IWu0fzthGQb2NtA5o7cvP6buNBVY1A02g3hdr+KEgwBseYgMTV"+ - "nJQK6EhvhVJEACdl6zWTiBIYPsfVG+7hzt3gs7j4dpzMc+xd4eTjzp0PqrDyopPKQPBJZWB3isgSPpp5"+ - "tgRy7xoJUP1ZZaAbKQH/Delav3JpHZDTG2iT/wt1UbE1dIlRu2lT4kWpVmeTJBZPd+gdFfct192xkZGR"+ - "9FuXR+RWKDME/DMAQYPVbJS69p0VRbt4QVtiFOlXtBz4pTEf7G0PyTMFLDuy71LpE1Gn6zLwD05uEMvq"+ - "6skxj3euZrZrWRQQ02YVmhvcCGxRl+sQBakxUz4kKB/uitdaEEnSD2A5/4GHp3d15eGkie6L0VKWREiP"+ - "re3+PAmI093LRrh/xVccmKlDU2+tltnsZiEAo8YLbIKFUe2uqS6Wl7TUlEkSWV4l4IoYL6NmgSztljq+"+ - "yTA08ObVOPJq5veglrqOOZrESKWoBNHSb7x0t7FHzvWq6Uei7Hj3VP4n9keY/zYJnB6J/p4ETkfAr23j"+ - "76cDEBJAwUB83UZIAJUAAD9DAsAzJCAImD+RwMRvJID+D0rgyncJyP1GAiI/JfBTAv+ZBPoZnjfFIXra"+ - "3l+TQNx81R9KwOF3EqhcNiNyN1LjSXYLR0pg7ywJHO7vdSHzAb3YJMksrnJkwkrnRRKtkGsELgdIRPjm"+ - "g/Gw9e7odqTklDIXBl0luzI/fdm/IOi+0okEIk5JIBkhgcoTCeT+KgG72XMEphZoyMKABRivRXTwa2jX"+ - "iyzNHLMeq7jH3V8OJ61cxsrcL13eP1gWtrXloe/n3zwOOFfGtSsaaJbBAdT5AQG4loGvbt3alq+g1is0"+ - "JY5185VCIiASgYDdmrEFd3jl1z4Pm/VEW4QIwhfktshuDK+0yBN8KV08vJJRWi1Ty2Y8RB4vmFpGxiaw"+ - "yVzCilMmswlgJ8FjCK3oMzcASyIzAmDFQO5hEF5HPwkk/fVqUA+qcufqJjXZ8/I42YZUZEqASbY4M6GC"+ - "tOtD1huCPD/zAHvDR4pqd189pW/6ktwcbPVORBP89FF/a/qYfZoaS39IMTD6UoYOZk85k4CTad8rNoy7"+ - "n4k0aOQ6IRdl28PaC5lhkntKNor55L3kJazXTzICJO0+AwT9Kb9jgFB1y0pia/n9ZeI6xF+vMO0zxpEB"+ - "N+EaSVXyNvPBL3UBm4mkr78wwP07A14iGZCMrAtcgmIj6wJ61G/1UASfEMkswMxaBYU+TXQdUKakUFVh"+ - "+9avrWhsKCIzAsWj8d6xECiFBIkag/aDqSnQHzvgA+7DVErEMyF/5AB9pWYIaduUwgFB95WPbdJ87bAE"+ - "R6ACXr05cMHP1mnlqLVcd/Rle+WiIt3mYMrY12u7KT0UdVadimBty7bG827X/V866uVHib7w9Az11uxQ"+ - "76EqBPrVFRdL29guCPY45bw1rLRnFiUxMepJdXj2kK38NjNTJeMEToBtADTqWkx2ZvUMTeKr+2FCtrLM"+ - "RWSKT10v6rFHHtocMRHsxejn3gurn1oWHy28NfaUwC+o5GvNvT1ga/CkbqLSZ+0eGE6m5pqX/OOi6l+W"+ - "CPhS7XarmsRCW+ogWsQZ1zB46BJswEDIUnh6cfNhtKZQfuMT4HvQ0vWrnnMHm8BZN3RFU7VV6ku9duC9"+ - "SaLsd9dSqzwMHAD/NgacHob+HgNOB8Cvbe3/ZgDvjwxAxURO4oA+NELE9PojA9DPZMDiCQOmfsMAjH+Q"+ - "AdDvDFD4DQNEfzLgJwP+MwY8biPYj/s7CYHwM6oC2j0/JAQyyxAMGMNNSqFfrHPjEe/pWYlKw4/NAwm2"+ - "N+WGE83nduLUh3zczje7QBIawyLIKG9H+Z5G/Yug24G5hhk3g6AuLnJ9ABHYsPbtixBBpSxLLWIndvaX"+ - "TUm4t4nxveZfvmIaEduMckObOu+WFxVjfEcht96ONnl4+O7FhZiSC+TNCQ5sspWy6HI9pikzsLgdwCWO"+ - "LcFzYZLvRYdPHDDMYmQGfdVjeiDKD96/t/Fcymr12vXLdyOMBzE3rKEvp60+cU6nCsHPu1E6X2iEB46l"+ - "5eLEMsUytIMttCw1NvmKnYs94OqXjeVm5k3pVSLbXEOJLjCT5u2VeVUeD3vY2uxuJPV2W29ZH6d9WyBA"+ - "tLNvxIJx8Hz5iFJlZJgpD367Ap2FkNVWBofAQ4bpE/UQFy1eNv1caD9BojU/dg7SAlil4mxWS6GsV641"+ - "20N8J+6nZhhWaKguL96klsdNuM4VxzsUxzBSqzwq6gQqhCjiDVjLboCvMIH1VTs7nY/8AnxCzimcZAPM"+ - "iK2xHnDJqCGzAZZRKr/LBsRRnM4GpPidzgbEo/+QDXj2JMTKjLXuvv6j1+JfgRzmntj6AiRj4JyCpxDf"+ - "pN2FeoU7UIo+IbsHNTUC7b8y4DfZAPRv2QByiSjm79mA0tr7i4sYNr6ptl/zhmpIRvR0cQp2rsDQQ7vR"+ - "+1tjOt/O7rq0jiZDu5TOjOGMJL/0P10oeCodkMhrgeWU5+s/ihtUMdPYzdQTHrT2Eqqwv2OlrQwv7bg2"+ - "tR5mtqVXYcyJrAxAaJEMcOp/GiJa4Vkd7oNgQJM2ggF+xRCloiJTQTZHBAMa7MmaWF6yJIuujXOknawU"+ - "DPusyFoQOyq9rpwYQn7fZVinYnC3Nkh2kjVZeeux67MbR3V7kfxzuveM99mOPLJcblfq2bxnwTNst7Hd"+ - "b2MEXbjrwnXcn+/bRCpdLeiRkK0JX/E38LaHUGP4kfKtjwW8tLQO231jLhO6rnjzmTYGCvW2NnKlINZh"+ - "cCB/3NETFhXebfFUqfFlHsEwRXIMV4KlQNBDcedVzI8JWS1Cyjr1XIfo/zYInB6I/h4ETofA34IA9EcI"+ - "oGECuhEv3od4K2ctFMQ4EwI/VgYw/0EI8AF+VgZ+QuC/BgGe5ra+P68M/HahoMwL61FJBY0+Mh2QttMI"+ - "JiR4QJLf2TgJOkFCfIuJ1idw2vfLiJn0VFDJY2MfdIKxnb4XPDseUx48Rr3/FAQIhdRlZLnLs2/q8xMq"+ - "WlnVkcFfDpPgzshXk2ZpZ/kytyR8rwy8ElTKzmh6ugv2c5ItUWD5lg7wg7kufK3rpS2J3JguW6KPKiac"+ - "HHsd2cRPfYDLb947Lk7gZ+GC4eHSSZOSpyyjymYYGpldboruhWaJ+Zrv1pBYBZOeDTkx2e3QNJ3kGOWn"+ - "CwNHE0dGW3XVEw22wnyV3ZWHgQtSW1l7Ie3DK+EJ4M1elgNLCROj6Kc9JiPkjwRTa5nZ+DeZIzvhNztc"+ - "IdRh9Gahzn1WMyPAGD5jaeBIGikU2NJljiMZk0iTYQ9qthHvU+HSvpj7Gc5OkB0gnwqWS7wjF2mlx7qW"+ - "ejVIA3zh/jI0yyWUkjiUk83Y+NpxU/P1tlAW8okwvMc8wVD/tkeZbPNX7Z5d6XrKE+5xlgU8v6UEuHpF"+ - "f5MSMOX48rHxlS/uHh8qXt4b0/XNFyz2hQYvJN4p3ajgidFr4ZRfSPNEpSir9y9KDrYOVdO4CW7qdt/K"+ - "+WYBiMi6TViJ81ZbTD33t0UCQOQiARRdLO2m/BbqGy+fo0caYztLvt5inEq5VDSzV+2TRLc0Vn9ne12i"+ - "4lY8ar4nviaKEVyUl4u5tPzLIU0JNEfhE8lZUWw72xT81yoD4mVICkRB6fG/U6DsfynQeUIBLWX30o6a"+ - "qfVQileiZT0plgOsMk1JVdN2CfnpkWQBVrsO532MLkWjW8bOkRKMN3JX12sVVynXye/ds7yIGShNwoNT"+ - "Xq4rH9RlyfEo4WmYXEGsLK6pyocQ0sRtfp2yVpeJCKy30uPKz8NE3gkeTx5h6XziEObeJvWsj6opUHpX"+ - "8xQ7myirkq/lAxH1K0x3m6MMPnT0z1rPCPVfsKmaXnpHCiG43wKLSH2fpttVq3G3Nl4LWyr/SHo+Lwvi"+ - "p9IQmzVDjm0LdSLqeHM8ILiJRsdoNYS93WyEhi7IOdKXZLTCvCLifxTMEi+snNzAtfevk8DpkejvSeB0"+ - "BPza/oPKABD5z4SARKQEELP1WQsFMc+QwP8ATkmhK404AAA="; - - byte[] dgBytes = decompress(data); - List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); - assertEquals(14, dgRecords.size()); - - short[] expectedSids = { - DrawingRecord.sid, - ObjRecord.sid, - DrawingRecord.sid, - ObjRecord.sid, - DrawingRecord.sid, - ObjRecord.sid, - DrawingRecord.sid, - ObjRecord.sid, - ContinueRecord.sid, - ObjRecord.sid, - ContinueRecord.sid, - ObjRecord.sid, - ContinueRecord.sid, - ObjRecord.sid - }; - - for (int i = 0; i < expectedSids.length; i++) { - assertEquals("unexpected record.sid and index[" + i + "]", expectedSids[i], dgRecords.get(i).getSid()); - } - DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); - - // create a dummy sheet consisting of our test data - InternalSheet sheet = InternalSheet.createSheet(); - List records = sheet.getRecords(); - records.clear(); - records.addAll(dgRecords); - records.add(EOFRecord.instance); - - sheet.aggregateDrawingRecords(drawingManager, false); - assertEquals("drawing was not fully aggregated", 2, records.size()); - assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); - assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); - - EscherAggregate agg = (EscherAggregate) records.get(0); - - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hssf.model; + +import static org.apache.poi.poifs.storage.RawDataUtil.decompress; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ddf.DefaultEscherRecordFactory; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherDggRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherRecordFactory; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.ContinueRecord; +import org.apache.poi.hssf.record.DrawingRecord; +import org.apache.poi.hssf.record.EOFRecord; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.NoteRecord; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordBase; +import org.apache.poi.hssf.record.RecordFactory; +import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.hssf.record.WindowTwoRecord; +import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; +import org.apache.poi.hssf.usermodel.HSSFPatriarch; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFTestHelper; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.util.HexDump; +import org.junit.Test; + +public class TestDrawingAggregate { + /** + * information about drawing aggregate in a worksheet + */ + private static class DrawingAggregateInfo { + /** + * start and end indices of the aggregate in the worksheet stream + */ + private int startRecordIndex, endRecordIndex; + /** + * the records being aggregated + */ + private List aggRecords; + + /** + * @return aggregate info or null if the sheet does not contain drawing objects + */ + static DrawingAggregateInfo get(HSSFSheet sheet){ + DrawingAggregateInfo info = null; + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sheet); + List records = isheet.getRecords(); + for(int i = 0; i < records.size(); i++){ + RecordBase rb = records.get(i); + if((rb instanceof DrawingRecord) && info == null) { + info = new DrawingAggregateInfo(); + info.startRecordIndex = i; + info.endRecordIndex = i; + } else if (info != null && ( + rb instanceof DrawingRecord + || rb instanceof ObjRecord + || rb instanceof TextObjectRecord + || rb instanceof ContinueRecord + || rb instanceof NoteRecord + )){ + info.endRecordIndex = i; + } else { + if(rb instanceof EscherAggregate) + throw new IllegalStateException("Drawing data already aggregated. " + + "You should cal this method before the first invocation of HSSFSheet#getDrawingPatriarch()"); + if (info != null) break; + } + } + if(info != null){ + info.aggRecords = new ArrayList( + records.subList(info.startRecordIndex, info.endRecordIndex + 1)); + } + return info; + } + + /** + * @return the raw data being aggregated + */ + byte[] getRawBytes(){ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (RecordBase rb : aggRecords) { + Record r = (Record) rb; + try { + out.write(r.serialize()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return out.toByteArray(); + } + } + + /** + * iterate over all sheets, aggregate drawing records (if there are any) + * and remember information about the aggregated data. + * Then serialize the workbook, read back and assert that the aggregated data is preserved. + * + * The assertion is strict meaning that the drawing data before and after save must be equal. + */ + private static void assertWriteAndReadBack(HSSFWorkbook wb) throws IOException { + // map aggregate info by sheet index + Map aggs = new HashMap(); + for(int i = 0; i < wb.getNumberOfSheets(); i++){ + HSSFSheet sheet = wb.getSheetAt(i); + DrawingAggregateInfo info = DrawingAggregateInfo.get(sheet); + if(info != null) { + aggs.put(i, info); + HSSFPatriarch p = sheet.getDrawingPatriarch(); + + // compare aggregate.serialize() with raw bytes from the record stream + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(p); + + byte[] dgBytes1 = info.getRawBytes(); + byte[] dgBytes2 = agg.serialize(); + + assertEquals("different size of raw data ande aggregate.serialize()", dgBytes1.length, dgBytes2.length); + assertTrue("raw drawing data ("+dgBytes1.length+" bytes) and aggregate.serialize() are different.", + Arrays.equals(dgBytes1, dgBytes2)); + } + } + + if(aggs.size() != 0){ + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb); + for(int i = 0; i < wb2.getNumberOfSheets(); i++){ + DrawingAggregateInfo info1 = aggs.get(i); + if(info1 != null) { + HSSFSheet sheet2 = wb2.getSheetAt(i); + DrawingAggregateInfo info2 = DrawingAggregateInfo.get(sheet2); + byte[] dgBytes1 = info1.getRawBytes(); + byte[] dgBytes2 = info2.getRawBytes(); + assertEquals("different size of drawing data before and after save", dgBytes1.length, dgBytes2.length); + assertTrue("drawing data ("+dgBytes1.length+" bytes) before and after save is different.", + Arrays.equals(dgBytes1, dgBytes2)); + } + } + wb2.close(); + } + } + + /** + * test that we correctly read and write drawing aggregates + * in all .xls files in POI test samples + */ + @Test + public void testAllTestSamples() throws IOException { + File[] xls = new File(System.getProperty("POI.testdata.path"), "spreadsheet").listFiles( + new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".xls"); + } + } + ); + assertNotNull( + "Need to find files in test-data path, had path: " + new File(System.getProperty("POI.testdata.path"), "spreadsheet"), + xls); + for(File file : xls) { + HSSFWorkbook wb; + try { + wb = HSSFTestDataSamples.openSampleWorkbook(file.getName()); + } catch (Throwable e){ + // don't bother about files we cannot read - they are different bugs + // System.out.println("[WARN] Cannot read " + file.getName()); + continue; + } + try { + assertWriteAndReadBack(wb); + } catch (Exception e) { + String filename = file.getName(); + System.out.println("Drawing Aggregate re-write test failed for " + filename); + e.printStackTrace(System.out); + + fail("Error when writing and re-reading workbook " + filename + "\n" + e); + } + wb.close(); + } + } + + /** + * when reading incomplete data ensure that the serialized bytes match the source + */ + @Test + public void testIncompleteData() throws IOException { + //EscherDgContainer and EscherSpgrContainer length exceeds the actual length of the data + String data = + "H4sIAAAAAAAAAGWOOw7CQAxE32YTsSRIWSgQJSUloqSm5g4ICURBg+iBK3APGi6wBWeh9xGYbEps2WON"+ + "P+OWwpYeIsECMFC8S2jxNvMdlrYQ5xha5N8K6ryHdir6+avwOer5l3hq2NPYWuWN0n1dIsgfbgshuSj1"+ + "+2eqbvLdxQ0ndhy5KJ/lc1ZZK9okY5X/gSbrHZTH1vE/ozagTcwAAAA="; + byte[] dgBytes = decompress(data); + + List records = new ArrayList(); + EscherRecordFactory recordFactory = new DefaultEscherRecordFactory(); + int pos = 0; + while (pos < dgBytes.length) { + EscherRecord r = recordFactory.createRecord(dgBytes, pos); + int bytesRead = r.fillFields(dgBytes, pos, recordFactory); + records.add(r); + pos += bytesRead; + } + assertEquals("data was not fully read", dgBytes.length, pos); + + // serialize to byte array + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for(EscherRecord r : records) { + out.write(r.serialize()); + } + assertEquals(HexDump.toHex(dgBytes, 10), HexDump.toHex(out.toByteArray(), 10)); + } + + /** + * TODO: figure out why it fails with "RecordFormatException: 0 bytes written but getRecordSize() reports 80" + */ + @Test + public void testFailing() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("15573.xls"); + HSSFSheet sh = wb.getSheetAt(0); + sh.getDrawingPatriarch(); + + HSSFTestDataSamples.writeOutAndReadBack(wb).close(); + wb.close(); + } + + private static byte[] toByteArray(List records) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (RecordBase rb : records) { + Record r = (Record) rb; + try { + out.write(r.serialize()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return out.toByteArray(); + } + + @Test + public void testSolverContainerMustBeSavedDuringSerialization() throws IOException{ + HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("SolverContainerAfterSPGR.xls"); + HSSFSheet sh = wb1.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 22); + byte[] dgBytes = toByteArray(dgRecords); + sh.getDrawingPatriarch(); + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); + assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER); + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); + wb1.close(); + sh = wb2.getSheetAt(0); + sh.getDrawingPatriarch(); + ish = HSSFTestHelper.getSheetForTest(sh); + agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); + assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER); + + + // collect drawing records into a byte buffer. + agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + wb2.close(); + } + + @Test + public void testFileWithTextbox() throws IOException{ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("text.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 23); + byte[] dgBytes = toByteArray(dgRecords); + sh.getDrawingPatriarch(); + + // collect drawing records into a byte buffer. + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + wb.close(); + } + + @Test + public void testFileWithCharts() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 21); + byte[] dgBytes = toByteArray(dgRecords); + sh.getDrawingPatriarch(); + + // collect drawing records into a byte buffer. + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + for (int i=0; i< dgBytes.length; i++){ + if (dgBytes[i] != dgBytesAfterSave[i]){ + System.out.println("pos = " + i); + } + } + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + wb.close(); + } + + /** + * test reading drawing aggregate from a test file from Bugzilla 45129 + */ + @Test + public void test45129() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45129.xls"); + HSSFSheet sh = wb.getSheetAt(0); + + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + List records = isheet.getRecords(); + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 394, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(19, 389); + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == TextObjectRecord.sid); + } + + // the first record after the drawing block + assertTrue( + "records.get(389) is expected to be Window2", + records.get(389) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 388] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 25, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + wb.close(); + } + + /** + * Try to check file with such record sequence + * ... + * DrawingRecord + * ContinueRecord + * ObjRecord | TextObjRecord + * ... + */ + @Test + public void testSerializeDrawingBigger8k() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls"); + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + + List records = isheet.getRecords(); + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 32, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(19, 26); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == NoteRecord.sid || + sid == TextObjectRecord.sid); + } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + + // the first record after the drawing block + assertTrue( + "records.get(26) is expected to be Window2", + records.get(26) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 38] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 26, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + wb.close(); + } + + + @Test + public void testSerializeDrawingBigger8k_noAggregation() throws IOException { + HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls"); + + InternalSheet isheet = HSSFTestHelper.getSheetForTest(wb1.getSheetAt(0)); + List records = isheet.getRecords(); + + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); + wb1.close(); + InternalSheet isheet2 = HSSFTestHelper.getSheetForTest(wb2.getSheetAt(0)); + List records2 = isheet2.getRecords(); + + assertEquals(records.size(), records2.size()); + for (int i = 0; i < records.size(); i++) { + RecordBase r1 = records.get(i); + RecordBase r2 = records2.get(i); + assertTrue(r1.getClass() == r2.getClass()); + assertEquals(r1.getRecordSize(), r2.getRecordSize()); + if (r1 instanceof Record) { + assertEquals(((Record) r1).getSid(), ((Record) r2).getSid()); + assertArrayEquals(((Record) r1).serialize(), ((Record) r2).serialize()); + } + } + wb2.close(); + } + + @Test + public void testSerializeDrawingWithComments() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingAndComments.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + List records = isheet.getRecords(); + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 46, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(19, 39); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == NoteRecord.sid || + sid == TextObjectRecord.sid); + } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + + // the first record after the drawing block + assertTrue( + "records.get(39) is expected to be Window2", + records.get(39) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 38] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 27, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + wb.close(); + } + + + @Test + public void testFileWithPictures() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ContinueRecordProblem.xls"); + HSSFSheet sh = wb.getSheetAt(0); + + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + List records = isheet.getRecords(); + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 315, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(21) is expected to be RowRecordsAggregate but was " + records.get(21).getClass().getSimpleName(), + records.get(21) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(22, 300); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == TextObjectRecord.sid); + } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + + // the first record after the drawing block + assertTrue( + "records.get(300) is expected to be Window2", + records.get(300) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 299] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 38, records.size()); + assertTrue( + "records.get(21) is expected to be RowRecordsAggregate but was " + records.get(21).getClass().getSimpleName(), + records.get(21) instanceof RowRecordsAggregate); + assertTrue("records.get(22) is expected to be EscherAggregate but was " + records.get(22).getClass().getSimpleName(), + records.get(22) instanceof EscherAggregate); + assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(), + records.get(23) instanceof WindowTwoRecord); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + wb.close(); + } + + @Test + public void testUnhandledContinue() throws IOException { + String data = + "H4sIAAAAAAAAAO3adVRU2/4A8EPHAEOnlEooNaSUdCNIg4CUDCEtQ6gwlITSjYiSkoKA0ikg0i1IyCjS"+ + "QwpSEr8B73v3PS6+9+67vz/eH+615pyz9tn71PqevT/rfGcJOIcLBtDXrNgAgBjAXcMFAAAb9SPDBAAw"+ + "gLGmzna8xlxjR9WhAXhrxMAfCzqAf9IPQPXBAn6078IBgAyCH/VgVD2ADwCxAGhNBbXpc9LUF2h8n4we"+ + "iOoNAKEnywaAFmAEGtDQABLgCA0AcAHfZvLjeozjc+gAUMATgAEygBNqzQTwHl8lcH5dGHWmvGY+1FJD"+ + "FQOTHHX1x+dkBta2H9UcoLam0I7bAYCRrJMjDOoIM9W56wx1vcnt6WAfF92t0gIhfrfqv0o8e9khH4fE"+ + "thqnQJHiJqOZUrbDByG8xwYeiEmYJPcUPoP17NH6hTz9cVtyfvnyyUuV3BzE06+vDH/Dlxi+/pYeV32e"+ + "IGIy2p+e90VyZ+i9OlDL+Rp6Dmot/G2tUgYbGW5vpkSep5Fk2eKtJthDdEvKkzrvC4cmWe7kKaliC7ip"+ + "0sMjlMUdN/akSG0ticE4nweeA7LUha1xyjNLXZEJUx80rOZMmgMIveJ5pQ7Hio17qM558+zaZgheNOHN"+ + "tk7hCxKIZgFTs9t1NGhTdj0EIdz0tEcV4KZebLmun1t9qpQ2fF6N29/P3I3j3pYc8kI9zaMjjFNPi/ej"+ + "qfkAaisS9bRAqLXpHai9Kw/38TIr6s3tZghB0GpAXUB/ncuYLE2mulOgiSpODb6R8rVbnQasDoj6bIiB"+ + "gpPYItWexPrqVgUk73GpZwT2sBroUQZ07ovZJ6SXgbdvjH//55ZoggllM0Rdw7K6gHmeIt/exXytDGpq"+ + "VeVUw1D6S2kCKezDar0iZnm3GGAy99/4bWY7VIgeWUlVmOVn8kdFOmIsel1/vx9MX9vNOZHYeqdvYnuy"+ + "PuP2uxHPjCotCFiHoJKzFzI4MTQn1bBVdLQQT0LmrX8os3+t4Nu7F1SC7mDgrFsvKsHS80DFHx3O8SsA"+ + "AJZ3XHlcbcydoagIOY6SWl1Vp3EIQT34gw8x7PqBwdNgkpp5LViiOWHMLE5uaQp1LIusFllOAzxrOusm"+ + "WExAlgdfVmW/LRLc67SnF1MHKe/PT2vXvfZQw1g/fIwStuEpmaxlQa9NEWv40J8h8PmVmRGejXo+EW2v"+ + "HEI0qo7ZNPb5niruyPOdHhnQLRUPGb+y4Wwo0WGygw6NOzBXGDYgzKBYzu+v6872oAZEaXgP4VtOrDV5"+ + "LyQtP9wxoKWMM/buA960eUbfNY0RKG1vKafEuMZMtwJjh5N0+JRy8JYlbS/r6OhsqifipW+Gx4NtrO4B"+ + "znA/UjinjWh9TytvuD/PeHSCSyZI5WEAslSzQZpIoczUQ5XM8tCuQSArrxGN5VGZ1OKFiaOi+zEpKW/o"+ + "vaSMwbfZQYveck70N1ZjZrwdxtKxlzAobG5kMl1LQFazAkJqVsrYDgCNeunmvRhm4c6jbinypsbQpyUr"+ + "wX1UwXJ9mtLhn3qC321JFsoymDATqy98V+hQ3ZBcpxN+W1+6wo6FrlRGKhW2ug7eAH3Dvn0rNWTG6vvr"+ + "qKDGWqAXYu0s8ZmmdMM3xFjWIjXsqtT56ly7tMPY9d40CZ/CQ0b4OLsD9qG5CB5n47N2/2qJMKo1+rUg"+ + "TTpa4D7au2JRC6XrayDXu7ZXGpvcwM5DWoz4HdBBTfQnmzN1K2YG+hpYNVGkX6ZlZGv7OM1XZeaZU1e2"+ + "Rt+QEzSTyLSYPXezW5pSbf62gbi5iHWB7xBAZ2leDdXI7Kat5+Epnor5sC3ZefMh0hUTSQ8VP+BIz2fh"+ + "t3eD2z9TLOhGRLoIErwXi+9yUgMZHhVGhWusRIi4J297mNL4iBUbHaKdFaRyobYMnKg9BWjH4+uPILV0"+ + "8nC8A3U/jlFjjX71Jgi595V1xmS7qScwAiEcrTYLmRbMfuaHL6EOo1NjPeWNa8hlBYLWd64rInOTrmyv"+ + "FPTmG8O5ys73rWL5VnYIcryPaJz1hicCpRGXFTgKhf3IKiBPTEzV5pMWMjt2zJfd24LZxbIx8ecWeVuF"+ + "eCqzynPsivav2VzI2+hbgvBvzjdDA5uZQkqynn+lwzfceOc/l4qsu1hsOTVzy6AnNW9HhaqZ8yHRS87z"+ + "01vZyoyAyGRlaOVkgW6lsSNCaOFlWqgRBJ2ZaR02lhwDHRJ1xN2B1xc64WubpudpxVONMUW7GMG/w61N"+ + "qLmi+xXRMaSqigzr33Iwc3owsLyZl1hUaNChDstgByZaRb2FUik+0vh0uZw72thqliZVKKQydVxsnHk3"+ + "yPj3tx8NnQv4+UTxz+WMaeP0AU6Pnb8XbrR/GklPdzw98vxeLqH/cRw63ft0SPxeejD/ECAaqljYP6Zo"+ + "TOAbas2G/aMp8RrpyQyOBpihYQAbqK0+1BxuiKojWTvefxM1J1MApKiTggESs9MPZ+nkUghPWpajkQKk"+ + "6H/bg/3bDYkDqHuDQT1hXLziJ1WUv+3+2wE6cY650PkPXCD+CRcAqPZf4ALfb1y4csIF3l9c+MWF/44L"+ + "j9ungt3+JRe6HacgxPUvhzyKvXJ2F/yZmvIM81egZfIaDI0XieSQH6KXZeYHV8Oe9jmC77MXmJyzbuVH"+ + "7Dxh7HWqUYgJgJQPP+qfFs2Wy5VJLBvjrb4LP6d2qSSiIEa1EDOTzXzBAf7NYTKe9Uv+BzvZxsBSGlzq"+ + "j2IjVpqWoXU2lXXDhRppha9tKwNMX4WqNEd+qo3WpH0X21ausDawEugMlpZ1XaXro5TpEAOTyMX3q32g"+ + "MJxtF2+idkYSmm3o6N6l7W39svNCNlqfzruLTTpsXDpob1SYnlNqhqsWeUW8X0QLFtb0RgBb4RFZ5sL0"+ + "d0/SQfbKUi5bT3OBzDhhYW67b3Rb0nlESHfbpvodNwNarcSwSY0MT4wUiebd+x+jYc7Y1n2+lUQtURRx"+ + "30MmxUonWXqrOwS88XfYSPvWDKWTxAd15QH75K4YXh20CYiyU3YjQcbGEoJcjplI/AMtEo7r7XINk573"+ + "ttxnL6/9tUHRi1OE6J/j4C+e18b5+n2Sujwc78Z2iVgqPx6w8gr3STZTEnam+x76oWmpHGSLuwkiJvTG"+ + "RlKOOIuBQ9oojJdCS+4ryVHpYg358B7SDCFMC46CEUMqT575UKujkzl/itEcCTxEr8cwQdh5o5lxmTEm"+ + "sBHYgkxtulQL0LCL7vs/j9lrs2FGJpAmZb1khCo2GylQdMmohMWCCNdlSh5UgdKDv7/24CGqTnOKID6P"+ + "zVFodIvClLZo9WhLi4c6eh1EzC5SzyMTLmTnaWpiPnzRRdLGOGLDNc4iUwyxMqmSe6ed0PRpeHenTdnu"+ + "OLWibGodMxRubxi1VyEzLFOFs7LTt8poQuMjWvzk6Ews6D2wxOX6F1iIMr2OwsJbhNo+Ubfgulo5Ravk"+ + "JUteZgv/qaiWkdJy++ryV4WQnU13JuY9z566hsH7oslDpXJGjvbpFH65FOhTlwdfaNChF1Qs3GSMctPh"+ + "Nbz9Fm+pKrB9Z++2XPC1VZ2OCtUKaQm5UWaWKDF9woBGK5HEoXLY2/hUPIeLbibJao0EH3edb2ALE9T4"+ + "ZQV+5Zl+PQUW6ZVIRMQ0pjyc21bn9c6Y4njsNgCvvVmcFDX+RLQKZ9pzmbtT97CkcWN3zy0+hSrChV8h"+ + "jVBJfGUk2+xSWQQden2qE/JJ0wf93E45aJWQUtYEJQ5idRqUycJ3TzENxD4I/XJlTx63k95POuxW6jSb"+ + "NU5wwAcj6djFzYfLB6U7YLpvGT2Swk3LEhF0wpUTMPJESYaj/zktnB54/pwWTsfE76Xr32uB9QwtYKOm"+ + "5GMt4ACzZ2iB+C9qge8/1QLJz7TQ/1e0wP9LC7+08P+hBWVCae5j4tP+VAtqruNMxHUe2Ud+n1fmLyTQ"+ + "2YXx5fEvPB/0XNrBMcMbTT7fB5TM7O+t+C9liWwSe9yRtqHauspQ07lU7sQyCrpFV0itVmSh8uCy2/tc"+ + "rkxkTnA/Icuwi65LXrzZJjtnHVc9/PG3+Paqyx5jxLjp9kTYCh49bnfJR++wGTq+hLGRe9o5GK58GrHP"+ + "7FjDwHSCxrWuXyx9SlJbKsY84b3W1/QO+3VV1NceWUxtBxid1fMEeb7QKAz1A+wk8WG36NZBztBeCYG7"+ + "Ff3BFrRdwldH+yS7B5aW1um8pvWF+8W0tsKaqgWwpTsuZC5YpqhZ0AYqlV/g4gm3iiPF6YRmwpvFhd/D"+ + "33NdS0ps2ALJJj/q52V5VMG0QPbiqOj+HW98bDtnDJerSZ+1+lZo6ggtvZWebZfZBtN9YuxrmAlHTxYf"+ + "cVMDllgfs9JcREuB7CZEfBGQhT07MvJnX2sM/PFxwfU8dYjmBZW53fWD60iNEH3cB9p76dFftdDU0XE0"+ + "eQtfiKn4AVpcWOxftPeb0ZsDA8pLJEO4ut35E4Okqnz7NKwgjs4EOccfF5rfSNDc95WDaY4wHbB9SZU+"+ + "2C3b89lxyHxNsxk8eXENfcuYb3FPwzTNo5HutoMS0IX1onkxJE5oLbCpVoAuDVGtSH07DxyWULrA7qew"+ + "93XSHVJ7S0eaI6tFWGSkkSqG5fXNNIaewY9XxXL904XR5S+itGBOaaoyMuLjYUtuabkPoKtE9IZqZH7D"+ + "f5ZINS+ovLSROlfUeChS3SrjUT9xwJ2ej3XF6+6k/TPFzm+IJyWCBBUe1XwIIS6DA21muvSJqx77Oqur"+ + "DDQNorlG+2d64a68eyEHak/+z7ygeeyFQJQXwMdeEGV970demkTM+/g3L7g4WBuZ7yC5LjyY/yKyDZ/b"+ + "gok76IaXN1V32OAfmGAqzTetqTixv5i0voLHNPd49oWQocYHEM5g+8zbpPDK0QVj+0R4gEyI+wWF9M16"+ + "GvOlR1rss/eySUS7skoe7TItY7t2ujMbvxeOyBB7YfC8OTBGcKqE/O3cVyPNtkqvXWqdV9asDQO7TNfb"+ + "3N/gPR/Rd9gD2kKHUxPpOKhcEgoRegu26aFPXPExpL7aNpRT9D7eaNLCPZAZ7yNnTZcxyqlmD5fnoyra"+ + "wzuIqH+twGznTh7ki6/NuB8Ajx/AYzQmjXV05puyUVLC3CFe7CZZDjaipzsyJ7tzBF55V6FcjB7We32x"+ + "ZTeUreF/TgunB54/p4XTEfF7+Q++LZylBTyA8EQL+IDrGVog+Yta4D9bC104p1MRpD/TgtBfSUUIAL9S"+ + "Eb+08P+gBSMhtMnjl5b+51rQHoecaEE6837xU9bHUW+s2AnqYPixjWDi8hTPy6oMyheJGuqdWNg0iK5G"+ + "EVHdMLHdXq4/6HsLRVwujx8WVJgTF1MVia0W0M0cEfHxqqTvFnE1mVdhz4T2bA+sd04hE0PrS0HpneEl"+ + "BKyvjaSiNsK3P55XNq6KLnS2zo6lzSkrKVzbKUNmlVrgfClUabUVVTW2fp47oaDiQ3bdk8QeY9nwshsF"+ + "U0ZueXZ4zUDu+RqlNpwxbCz7lcVq6py5Qdt74hc0hcut9C0DiJbBMtVR0FinhbSAV2lkYQ3nOyZflfbu"+ + "wsTpcz5lTcx5iT+5Zn3pegbXSIle3PB0Cn8kMr+/oSQy+F7N4orDRGJD+XaCIEWYS7Y8SI/R+ahmYXTa"+ + "jMBDyW+XwWI6cPpNZkWQMeQSpbfDODPeFMYlG/nMz9kGSdVWwBPruVFyNykS/+67tDLkoT7aUXKSberW"+ + "T4+Yu9slePniXDlUGffJxlN7yEheEmPmdDtkDuVhnsONyNKCijToxwBxJioQsvz9ZswLnz8JEfpVDhSl"+ + "FsVD56mJw9Wb9+TswrgB0jvhjcdeuAi7MXKcjIhMY4ZnHjHCx21u4RzyPrvIYsah0+PN+B3kpVibPhKE"+ + "nmaYJvFia3qArN6mS7sA7cIIwjwvfnSmVkftHY3VQuf90Z5H3HO0g1H8yPdlfg3sCcJ3P98Ly6m5tzXv"+ + "ny6SETr94g5cXtcrv4ZddXMiT68thBCEq+NvQp2nGMlRC+FJchk179vxn52zkQlfka3B4coruG/+9muu"+ + "fapi57uGeFsBglGxLM4wNRxbTy6dC2UNJCbn9g4+ipE5KrqHSp4ZpOM9XLvH352LfpaKuHn9RypCUmCk"+ + "5coC9RBwkoqwhBMoe3HZdVKOuJe7EfjU0ctAJD6muK6ILFcN3i24PISLVMm8tHmfhCndtVm17nkx3Ggi"+ + "DBDpFbCO7/dvMhFO6uXmybZv6la3zrixy4XPPKZGHdj0/Z5/SScoPQn52HA+TfkWxQbaGNdswrJMZb7z"+ + "OfkKgxKtYCp8vdDvMtOMBTzyzDNfF7wNuBke719LaLaXS6ZSZ6+rvx0rJmXy+rDW+IpQ+CBso1pdHRRc"+ + "yZIjBbQHH7QmiN/qAakyb4IcZLWTAvEd4udrIZTt1yq/im1+n3kuiH/jFagSzH5Flw3W8ipOfSeCgSgj"+ + "iiKLjELxlsz5xptFVxQ9vGDBuyNXI9okPSQZwiwGqtZ3jXCcJTaWcP7XuHB65PlzXDgdEn+KC2elIkBA"+ + "8gkXCI7/dfAHLpD+RS4InMUFcaDthAtt/8AFsp9wwZf/r3BB8DcuCJxwgfsXF35x4b/jQouTZIA7Kv7O"+ + "/YtUxI9/LojhVueUB4iqhbfJJ2bUENhFCYDT2u5YXEsgUFZLkThQaleuYHC3CTKxTCbd1WT0EahBGslv"+ + "DVS32ii8KogjzQvMo62Dwg72hZO1psRHKPQVVBUiB/prviITb5iO+tuV8Cf4gpbxNSDVG/UcMS0Pn9pX"+ + "1fA9HSo2ohu/A25wf6KTwNh4tyDGJVmddORGO0dF7IBkC70hNsJXKFHlI05Ibn6hbebFsMuvbvjzplET"+ + "SHnmI++kTM7evTcpq/uhfFbDakQz8qsyjX32rhp8Ep/1zTZd2tJVkquZu8KMOVIPhflEnxnPxcax9scj"+ + "lToDBcO0pj5X3t7kifqSPfmyOjC8dKfK1GBAJ0ydvb8WSyv18/6Vwdj9aYKeNLT1q7nMXLlgkoOFNqzE"+ + "2nm7cSKRT4xtUp10hOZfm4YE0Ypt3Z/MaGB/DmqcUQt5RHWUzfTQJS21R/ToZnLorfPzIZocgeD19QPw"+ + "XHTIFdwHg7Mlmota6OqYilolxSmSlx8CKjwsELJHKCrINvmNCxi34NV87Ipn6YNICQjQvqAz/rKMznR+"+ + "xLnkeisDE8nNYUGNo/Yd6z5nn79bwVxU+VrjMw6FYyvsRHjKviTE8i3z9Tag580i9Ern5SnETqo8xEsw"+ + "fIyRKSNIzwJRMUUgiRI8wm5TB8UZvJzFngq0eBhAJRO5vbBiKg5703eOV45AT6Sh6XK9gDG76nyVal0a"+ + "GR0lk4aLl1kWQ6H+WmNtU1jngMZR7RpLTy8JgWWcC6Gelj7Icfervb2pQuc3RKswbdDSUy3K1mwMB09O"+ + "lBZ8Pj1LRWmBn0xd0b0TcWaMvhRwTruEejUL/yMtjCZxXMuKevsgpH2fOmbNcDiBq2jZnuNYC7lyjL3W"+ + "qwueYx20DlUl8XqYe3XExPqBVvFjxAb1PUWkUsOab20KKdiK5yizYzde8dLz1mmLILgnsHdJoYpxUgvG"+ + "/PjoRnHGWuODhPomZGNKi+ICT3xpqjdmSokyIOcwY/Q6GjQGghDxtZ5GXkroNGSRBZXJVzXWn/V8EX8z"+ + "bh2EV1VrM2gkFVGxYum4qEsJHd2DPj6kJnJzVTADlCZWR7ItRI7zEPBUU2RiU8t1G6QOxXMhpekJvVQ4"+ + "IppKQdVys+cLtUY6Un0+hI2Z0wMzAxO8Lr0LbaILk8WtNsxpaFYMrTjC22723OH5GFkUi+ux8An2Hi0F"+ + "fvcr1v8aFU6POn+OCqfj4ffS/e+pcOEMKhABrCdUAAPhwB+pQHYGFcT/BBUEz6LC/wGpc+eRNSkAAA=="; + + byte[] dgBytes = decompress(data); + List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); + assertEquals(20, dgRecords.size()); + + short[] expectedSids = { + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + ContinueRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + TextObjectRecord.sid + }; + for (int i = 0; i < expectedSids.length; i++) { + assertEquals("unexpected record.sid and index[" + i + "]", expectedSids[i], dgRecords.get(i).getSid()); + } + DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); + + // create a dummy sheet consisting of our test data + InternalSheet sheet = InternalSheet.createSheet(); + List records = sheet.getRecords(); + records.clear(); + records.addAll(dgRecords); + records.add(EOFRecord.instance); + + + sheet.aggregateDrawingRecords(drawingManager, false); + assertEquals("drawing was not fully aggregated", 2, records.size()); + assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); + assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); + EscherAggregate agg = (EscherAggregate) records.get(0); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + } + + @Test + public void testUnhandledContinue2() throws IOException { + String data = + "H4sIAAAAAAAAAO3bdVRUW9sA8AGGrqFHSlpAhSEcQAkJ6UYQyaFBmiEFpCVEOiREGikJSekGlRJQuiQl"+ + "FQFB4ptBvxvIvd+97/fete4f7rWYc9aZc4aZw7P3/s3zbFYB/FiEANTNeD4AAATA2sQCAADIH0wgAEAI"+ + "QNv04kNugZusiGMoAOxNEODHhgrAObkOgLgGHfDt/GlMAID4+3EUxHEADgDgB8DdVEbsNgDAgPMAHxQl"+ + "nzpAAwoI8XsbUfh1QwCvUPiNAIBjFCzEO/BuoUOeiYZ89fPA60AloCBQGCgO5EE8XgPKA4WA/MCrQDoA"+ + "F+IsRgDDR0VM5JUAwHVAbosYYl9ZDg1ICsA4+Sz0gM3dkJpDxN4s4gwSxFZb3NbG0cTGUf+mm50JXJfD"+ + "1doqJrJbthUC6tjw3QAtsFvnYRJZvMDMlyLTPQ+TzrYehmInaLpMTTqKcMzi0JotHH9kzL01ZkHKc6Ni"+ + "kq2K4yJorozv7TaO8FulNhosxSW8sMlIXxqugsRXD+7W4bYy1NBcBKvi7KqW0pqLcXjSxXM+DifJFmzX"+ + "wxikWpWZvDlUODjJ7JArLYfB6yRHcy9MRtBma/86sYUxiBBz5k0WQBxc2B4jM7/6OjxudljZdFGvxQ/f"+ + "I5br+tFosU4PBbUn555F+hUmPa5ss2Tu+7yRzIRgVsuXDWrkr4Nxp5w01EYk7+l7XHgKn2n3qpbe8no+"+ + "ZuWesRfDsSsy6IG4v8fHaKfuFteEvsEbxF444m7hIrb6DiZWcE4O5GNmRNOdFgje/Q2/Or/+OvtR8XMZ"+ + "irYBenKYNTjaMvJGrzRZrKfqsyGakrbXPlDsC3/c2KmE5CaUuoZhvFXADUk3WXwPm17x0PT0jvLtn2mN"+ + "xBuXgU3VNawp8hrkSnHvM+WppoPBcjJPtB7QsKXyJrO+VegVgOUa0TqKuTf5fM62rrx6bHq9EpaXwRMR"+ + "boP2wUNp6CCQprb70nh8u0Pf+O5kffqdjneu6dWqEMKbeFWXeiED44OL1xt2nh0vxxKReN46EjuQz9/u"+ + "KKC44kwIOOujl5871I5HBQAOMJDdAQAwdoBzws0N7EwQEYKMkgJ1GZsxCOkExRIN1joJfgWxVDFpGcGo"+ + "Qj9YEQ7QSLdKI2WLKLhspp46hiokRtiv0E9vFmE7qKSqOuqo2bojlj1JcezuxZCzqNDWlyirjpMyPT3c"+ + "EfRJfo5Zn+XL/tDzDGxJWZIUEhZ+hc04do8U4Xu81g7nSFIK/SWmffPB3sCismdGvWojIRoSNA8SHYrJ"+ + "xTQkWvJ17lYzUdnpcXF+PiRRGoqK0ilkHaLo8VVb0bZtDeXeaVXlfxqR7pAvX8ybfFfS7/YofnHVpRBH"+ + "0lApA95hPONuVas3kX7dpR2hQkHNJRuE0Jq2/XrGQUM6mQ6/LRQe7XSZ6eMH/Eutk2bCD/ZpYNXv10Zu"+ + "PmSPkomEhfJa817co9K8plVfn7dYGr3pIBT/9DUJtWGrDHrAHZG1yTXhiqmxsYmvO3D3sXtjnuZeZfqj"+ + "RayNk8XdX7z5qNaLaGO3FWazI9RvwT55f9LInEuNb01nVUbDJ38oCeKRHAM+uZ/BM8WnJY3XlPZ6uCO6"+ + "05vVj9B3iZffJ/yhcE6rh5Zc1hO1kkp2Y2pmzTfy2gHGh2IWUkNqjm721ZDu7M9xKoy+H9EDvK3ei/Bz"+ + "KkOwBMpWnQ2XQmXKWC41Mb1ifefDUyitSEO9t7nyiWu1eKTEN7Q03XgVNnoVxTTxeHDBYejjCAM5OtMW"+ + "bO7omPh9p0WvOSPFgd2celfAQRIAQ32ZwcXDM7rqLUQ3PSmHYYpSpmjmPAZ8Sthn67Z+cwbMMHo6NPaK"+ + "pN3m5HhHpikPygTa1vuwBaAln7788kVGO302kID8dL1eAUknroFcleOjaGk34QtRlwBmrePCn9b6Zylt"+ + "nlDxY/umra1wTHlGrXVlAcrjUS4aWHEEsWRLVJA36DOSw6tlvFDPCuKXAuvz1Ii+G4aCHIu/BbGxrYuN"+ + "g4kzMoblI14ptkBAN3alD/yuSFuBnFJYY66qi4qZqEmMlsLMiBfpDa+VKkQfCUXH5U3s9Yzz8Lx7vken"+ + "XUrSDtXi2rxAC0pz0OXNMyyeqJ28cL3gfd50oYZvk57mo5x3t3iELzsWcZdo14RMg0xykkXXdPiyBhfK"+ + "I8YVHS+Q7shaM7mwKtzAbXGn5tCmdJ1Ei61VqUpbeOyae+Po+VFs1Zz4PZtt+KfydJcxYW2bKBYCknYb"+ + "2/ttJKALGC7Q4wFbdD+AdPW4V1J2Z5VTM6SRH0zgJxpCQbgmNl8OfV/Dq0Wc4Y5BH6FTiUm57X5bayYi"+ + "yK9TnFo7R3VJygCERmOfE14cfo3QEWg0Y+wZ2u/a1R68QXP7rhtmyBZfttcvowEK6mXAH08cv29nTCOn"+ + "X+D0WPpr40D53ch6+sLTI9GvjQ31x3Hp9NWnQ+DXtg78ISCU5dAxvk3fQMA2YsuH8e1U0Cbx9/kdhIoG"+ + "6EY824eGB8BHHCHaRB7XBVACyBCzPCpCBkSw0zdnFbCEeVoCqP+gBLh/SuCnBP57ErjpXBiC7H9HfyiB"+ + "7rABCKie8SNB3EbNnkXSZZVoMkd0ilYN3R0U+dkyojCakWwRd7HZkLLwRnE70YNVnkzb1mFFVZhPS4VQ"+ + "Zo+84BTf1Ovh6C0EBUK+UWDwOwWYvuxvb0VznabAyBw3i6A2TjAd8BYXmLh28EWYkJKJnBaRE/udl03a"+ + "WLeJ8IscZuajCuhd22r7dhlPKHCZDUEBPzUq7aK2GO6dQTF+Nfob8xoJMAv+j3iYz8uoYPa3SZchIT3N"+ + "Khs8LCtxho8JHo9cupb0EbPJbvprXa9NScmut9ZnumVhV9vnKs1NX/QbReV2aB1IBZd3vG3Dx2dyKdWZ"+ + "ohmawBYv+gvmbA3WvPc+5KV0xbXmD8mncyttAhgV2VnVtyx277mMediuO59P7O3W3bLeLdnr97CoTwe5"+ + "H0JJ0Catmhskb0KhwXwBBaPE0ZikVQzMmPVM5Dd8oH2G/a5AAaMyhc0vl1Bn8CmIxR1YeY7ovzQFcX+h"+ + "Az9GJ/Kw+iLAsjCgxX7oG+J3m56EtSnKdJSbKT9e9tpTgvShNguDUYXlyxn3ge/hONgjb72KOZQh0gJl"+ + "S86mSzEyZQzfJQC/LKP42G2upWgoY8pgqMQf7zlCAubjWqimKRtwuFa5a0XQDRRDWvzx4ycQgmTnICi8"+ + "KRxTL1ans4EIphwLhQe+uxJsiT/AfHdLfk5bfBn/oAVGO3rBTmxFzpVUvoAkuaS0HStsMknEWvV5rve6"+ + "z559INy3PIkz+3MsvSsrWSc1y2YfKxRrSWwY9RnNAqtqSm8QE7yYx3D9/N668T383V78ZKDo1I5TvsuF"+ + "UqFqUs01p0ZZcBJuejBbZGHbBkVwuYD1mydnBnFQfewychqIOFsCNyMUlE76sPRBYKe0DkhO5K3qy1IL"+ + "ujR7lJJC6qoAFt2LiZmyzaOH7oIYo1V75YfD94QS8POYtS10jXj97EgBkS940/upMNr2P15FmxV851sp"+ + "KYdxbRkGFRJJ2tR5pMc57zzPBww0j4djlO/qKuZetMytokpQvFOg3s6+rjKKTxa3y69TzovjG8M+aT6u"+ + "vKUoPFh6oOPJpvMpbxIH/qROZCA/XZ/j7e3o1nNG8RQtBwRB8X4i0OM3Sr6ieJlaq8JWjHHjbhbnUml4"+ + "A9thSAnoxJeXfK0qlSSyvIthRJdlcU6i+B2n+nymFAN1B8qs5r7cw4HPLLLe6/a2BHZBg4SPD3IGNsm1"+ + "lRA94DmaghKnqL3H3Geqf5sETo9Ef08Cp0Pg/ysBNCAgEfEtvw+ABxg9QwKoZ0rg/YkExn4jAbR/UAI8"+ + "3yUg8xsJCP2UwE8J/GcSKAnuIYz+05yAnM0YBPQ9J+BJPRICYzOnKUtK50peABRIjIixqdLd9ipl77P2"+ + "oU0LXMpeuoDMCdCzVT/8ert1p5m2126hbi/y/QOn7r4oWXXslNkTCOiQkj3J+bIw9DwazJiFzYlFkpzt"+ + "Kk5W30krQlmEmwBK4fSXAPnmA0nZ9MwnmFJyPqEXBl8lw5+HXQ4oCL7f4LBOFlVA59qNgEBgyh0m5gAt"+ + "5TzOx+hm0Aq9YGyT1eAAuzzVkFGZatgIbPUcgWQZAZ1OrIkzbUB/jyHpW9Y29pVByVWndmFKVKJFFJYV"+ + "A7RjsQHDwD7MESl8+pcNdn5hy8J2IILZyUVah/AcypvROiGkRpnLWs9DGlBGImderZiyXzPkjFcLzmNo"+ + "MwPbq4o/GVUacxkLX9vdsflafzg+WT5VcX70/Fr8zkVKmO2iqWEjYr7YIIp9qBDlxLbyrGEOZaJQps2H"+ + "U0bidvqV17cEgzAN/PsxjEVCpeptOyOApeLVAnbkUoupEtUCRA996ZOhQBoyeFmkrEjOLEyrEyhbklld"+ + "Qdr1KeANQV7gEs77EIP7Csv4SATw4JwbafKyM0g1inAw719r78OONpfRDJFJUXuGZqYV4XvVaa4lJ7+j"+ + "p0Wjg5j79cuQkgz7FaxH1kfRSfnqgWZJmnHKrzN8vh5fDEXLEUrv1tl87/OOjOKTLRDsmPVqfGZbfFay"+ + "RT5YT4SsrV35Ln5DcUJgD/Z47z5OvSyLBlvP7SEYkGJjrV7xDpQIIlQssn5HscT5a1tMPRRImIWa0IJB"+ + "S9mG4fMCBA2UChQIiaFQY+jC+xz66J1UvVDCROMKHJdPtJjqa3a+i76xuxNb32iHt3oxNF6CZIBh7MHX"+ + "3qCh6lFjEZSzAlh6X2qcCvHMw7+YD4iKIhZ7nEeXVooSCb00nNDqFjQcZjWQ6dWbmXXHpb4evi648EC0"+ + "wvhiqHWZ4bSSIJ3Y/Avzm210Y7Xjkr/kAxQ1NZniKeC0FC9u5Q4/070BkRh5xPP08YqhrLUebteahItY"+ + "2q07jNXiFuxa4EmjKiuLaTcedreMYvHuax91HhyYHV4s6Qo8eP1Z7fO2pG2psK51OkuyZKiuPv4rKTpF"+ + "vPWbB0oN5Hjr3jH5E5UWITHaF/DQdDDjW9romoIDnXM/aSV91KW8HNwv5AeSfqaNoQY+SQiAx3vt6uvg"+ + "B25YfqClzquedJ4SO6ySyWn3IA+LHcvCrLztMRNTwn1mHdvmCP9tCDg9CP09BJyOgF/bh/8bAdynEICG"+ + "eAPoAFMkAlDwAdlnIADtL6YDgP8gAngBP9MBPxHwX0PA6+aBzkeInnb4lxAgEzbf6ZuV6tRnE9Jul4hW"+ + "TGyCmyXtY3zYlXe9Ev2uP216UvqTZNF6lcBMJr7Dy4buBgM8c7V8tqadXW3ZhuY3stjRlezsPhhJuLF8"+ + "iuIk9tj6MCLjH/nGf9EfW5GkNgtHPzP8vAK0OhS7N06MAatJHe8+kLP8pDIQpSHxOCTRYfOkMqBfvekg"+ + "8xZUazjZuCuVksfMXK2lilAAZg5CAQ/YThSQLRbyspC76c3zYDP+R1lCgAf56dJ+KhBa/7reRwXaIU5X"+ + "HUyfr1q1e5Gj10/VrGJT3Q3PuREeuW60C4Ub8wdJHjfj3/f87N6o4jpJg6LoPk2gOPSUIYEUu1164KEp"+ + "sxeaJYVf0bOVBCuBWp1uJvYtYCACA6JpiUo1LjXh3bsLNrv1e+PjV6aczyee745fuEhpWCRygoGNIiQG"+ + "ZhXo8ysa51DmC6W7fDiDb6ik4vMOu66K94CtDWgkULAQFgCXiieMQEKbucAqps7+iyhBd5xdw0JGTkoD"+ + "9pDLxqgnpYEQ420xC8wh0bJmfi75SrY6k8EImIciPePYHiE5BjsGG+GlFzTnrpoQF2LJQbq4XzpN68hF"+ + "qZkReH4pu/v5QsHVuAgDjZhQmofaco2hW0/GkzUup1w2VPF+JIW2e3wBQQGabxS4xXxCgZtZ3eMzTgqz"+ + "Wi2OwZOCZHtvkRSAJATuYOv0ISiAw/IWu0fzthGQb2NtA5o7cvP6buNBVY1A02g3hdr+KEgwBseYgMTV"+ + "nJQK6EhvhVJEACdl6zWTiBIYPsfVG+7hzt3gs7j4dpzMc+xd4eTjzp0PqrDyopPKQPBJZWB3isgSPpp5"+ + "tgRy7xoJUP1ZZaAbKQH/Delav3JpHZDTG2iT/wt1UbE1dIlRu2lT4kWpVmeTJBZPd+gdFfct192xkZGR"+ + "9FuXR+RWKDME/DMAQYPVbJS69p0VRbt4QVtiFOlXtBz4pTEf7G0PyTMFLDuy71LpE1Gn6zLwD05uEMvq"+ + "6skxj3euZrZrWRQQ02YVmhvcCGxRl+sQBakxUz4kKB/uitdaEEnSD2A5/4GHp3d15eGkie6L0VKWREiP"+ + "re3+PAmI093LRrh/xVccmKlDU2+tltnsZiEAo8YLbIKFUe2uqS6Wl7TUlEkSWV4l4IoYL6NmgSztljq+"+ + "yTA08ObVOPJq5veglrqOOZrESKWoBNHSb7x0t7FHzvWq6Uei7Hj3VP4n9keY/zYJnB6J/p4ETkfAr23j"+ + "76cDEBJAwUB83UZIAJUAAD9DAsAzJCAImD+RwMRvJID+D0rgyncJyP1GAiI/JfBTAv+ZBPoZnjfFIXra"+ + "3l+TQNx81R9KwOF3EqhcNiNyN1LjSXYLR0pg7ywJHO7vdSHzAb3YJMksrnJkwkrnRRKtkGsELgdIRPjm"+ + "g/Gw9e7odqTklDIXBl0luzI/fdm/IOi+0okEIk5JIBkhgcoTCeT+KgG72XMEphZoyMKABRivRXTwa2jX"+ + "iyzNHLMeq7jH3V8OJ61cxsrcL13eP1gWtrXloe/n3zwOOFfGtSsaaJbBAdT5AQG4loGvbt3alq+g1is0"+ + "JY5185VCIiASgYDdmrEFd3jl1z4Pm/VEW4QIwhfktshuDK+0yBN8KV08vJJRWi1Ty2Y8RB4vmFpGxiaw"+ + "yVzCilMmswlgJ8FjCK3oMzcASyIzAmDFQO5hEF5HPwkk/fVqUA+qcufqJjXZ8/I42YZUZEqASbY4M6GC"+ + "tOtD1huCPD/zAHvDR4pqd189pW/6ktwcbPVORBP89FF/a/qYfZoaS39IMTD6UoYOZk85k4CTad8rNoy7"+ + "n4k0aOQ6IRdl28PaC5lhkntKNor55L3kJazXTzICJO0+AwT9Kb9jgFB1y0pia/n9ZeI6xF+vMO0zxpEB"+ + "N+EaSVXyNvPBL3UBm4mkr78wwP07A14iGZCMrAtcgmIj6wJ61G/1UASfEMkswMxaBYU+TXQdUKakUFVh"+ + "+9avrWhsKCIzAsWj8d6xECiFBIkag/aDqSnQHzvgA+7DVErEMyF/5AB9pWYIaduUwgFB95WPbdJ87bAE"+ + "R6ACXr05cMHP1mnlqLVcd/Rle+WiIt3mYMrY12u7KT0UdVadimBty7bG827X/V866uVHib7w9Az11uxQ"+ + "76EqBPrVFRdL29guCPY45bw1rLRnFiUxMepJdXj2kK38NjNTJeMEToBtADTqWkx2ZvUMTeKr+2FCtrLM"+ + "RWSKT10v6rFHHtocMRHsxejn3gurn1oWHy28NfaUwC+o5GvNvT1ga/CkbqLSZ+0eGE6m5pqX/OOi6l+W"+ + "CPhS7XarmsRCW+ogWsQZ1zB46BJswEDIUnh6cfNhtKZQfuMT4HvQ0vWrnnMHm8BZN3RFU7VV6ku9duC9"+ + "SaLsd9dSqzwMHAD/NgacHob+HgNOB8Cvbe3/ZgDvjwxAxURO4oA+NELE9PojA9DPZMDiCQOmfsMAjH+Q"+ + "AdDvDFD4DQNEfzLgJwP+MwY8biPYj/s7CYHwM6oC2j0/JAQyyxAMGMNNSqFfrHPjEe/pWYlKw4/NAwm2"+ + "N+WGE83nduLUh3zczje7QBIawyLIKG9H+Z5G/Yug24G5hhk3g6AuLnJ9ABHYsPbtixBBpSxLLWIndvaX"+ + "TUm4t4nxveZfvmIaEduMckObOu+WFxVjfEcht96ONnl4+O7FhZiSC+TNCQ5sspWy6HI9pikzsLgdwCWO"+ + "LcFzYZLvRYdPHDDMYmQGfdVjeiDKD96/t/Fcymr12vXLdyOMBzE3rKEvp60+cU6nCsHPu1E6X2iEB46l"+ + "5eLEMsUytIMttCw1NvmKnYs94OqXjeVm5k3pVSLbXEOJLjCT5u2VeVUeD3vY2uxuJPV2W29ZH6d9WyBA"+ + "tLNvxIJx8Hz5iFJlZJgpD367Ap2FkNVWBofAQ4bpE/UQFy1eNv1caD9BojU/dg7SAlil4mxWS6GsV641"+ + "20N8J+6nZhhWaKguL96klsdNuM4VxzsUxzBSqzwq6gQqhCjiDVjLboCvMIH1VTs7nY/8AnxCzimcZAPM"+ + "iK2xHnDJqCGzAZZRKr/LBsRRnM4GpPidzgbEo/+QDXj2JMTKjLXuvv6j1+JfgRzmntj6AiRj4JyCpxDf"+ + "pN2FeoU7UIo+IbsHNTUC7b8y4DfZAPRv2QByiSjm79mA0tr7i4sYNr6ptl/zhmpIRvR0cQp2rsDQQ7vR"+ + "+1tjOt/O7rq0jiZDu5TOjOGMJL/0P10oeCodkMhrgeWU5+s/ihtUMdPYzdQTHrT2Eqqwv2OlrQwv7bg2"+ + "tR5mtqVXYcyJrAxAaJEMcOp/GiJa4Vkd7oNgQJM2ggF+xRCloiJTQTZHBAMa7MmaWF6yJIuujXOknawU"+ + "DPusyFoQOyq9rpwYQn7fZVinYnC3Nkh2kjVZeeux67MbR3V7kfxzuveM99mOPLJcblfq2bxnwTNst7Hd"+ + "b2MEXbjrwnXcn+/bRCpdLeiRkK0JX/E38LaHUGP4kfKtjwW8tLQO231jLhO6rnjzmTYGCvW2NnKlINZh"+ + "cCB/3NETFhXebfFUqfFlHsEwRXIMV4KlQNBDcedVzI8JWS1Cyjr1XIfo/zYInB6I/h4ETofA34IA9EcI"+ + "oGECuhEv3od4K2ctFMQ4EwI/VgYw/0EI8AF+VgZ+QuC/BgGe5ra+P68M/HahoMwL61FJBY0+Mh2QttMI"+ + "JiR4QJLf2TgJOkFCfIuJ1idw2vfLiJn0VFDJY2MfdIKxnb4XPDseUx48Rr3/FAQIhdRlZLnLs2/q8xMq"+ + "WlnVkcFfDpPgzshXk2ZpZ/kytyR8rwy8ElTKzmh6ugv2c5ItUWD5lg7wg7kufK3rpS2J3JguW6KPKiac"+ + "HHsd2cRPfYDLb947Lk7gZ+GC4eHSSZOSpyyjymYYGpldboruhWaJ+Zrv1pBYBZOeDTkx2e3QNJ3kGOWn"+ + "CwNHE0dGW3XVEw22wnyV3ZWHgQtSW1l7Ie3DK+EJ4M1elgNLCROj6Kc9JiPkjwRTa5nZ+DeZIzvhNztc"+ + "IdRh9Gahzn1WMyPAGD5jaeBIGikU2NJljiMZk0iTYQ9qthHvU+HSvpj7Gc5OkB0gnwqWS7wjF2mlx7qW"+ + "ejVIA3zh/jI0yyWUkjiUk83Y+NpxU/P1tlAW8okwvMc8wVD/tkeZbPNX7Z5d6XrKE+5xlgU8v6UEuHpF"+ + "f5MSMOX48rHxlS/uHh8qXt4b0/XNFyz2hQYvJN4p3ajgidFr4ZRfSPNEpSir9y9KDrYOVdO4CW7qdt/K"+ + "+WYBiMi6TViJ81ZbTD33t0UCQOQiARRdLO2m/BbqGy+fo0caYztLvt5inEq5VDSzV+2TRLc0Vn9ne12i"+ + "4lY8ar4nviaKEVyUl4u5tPzLIU0JNEfhE8lZUWw72xT81yoD4mVICkRB6fG/U6DsfynQeUIBLWX30o6a"+ + "qfVQileiZT0plgOsMk1JVdN2CfnpkWQBVrsO532MLkWjW8bOkRKMN3JX12sVVynXye/ds7yIGShNwoNT"+ + "Xq4rH9RlyfEo4WmYXEGsLK6pyocQ0sRtfp2yVpeJCKy30uPKz8NE3gkeTx5h6XziEObeJvWsj6opUHpX"+ + "8xQ7myirkq/lAxH1K0x3m6MMPnT0z1rPCPVfsKmaXnpHCiG43wKLSH2fpttVq3G3Nl4LWyr/SHo+Lwvi"+ + "p9IQmzVDjm0LdSLqeHM8ILiJRsdoNYS93WyEhi7IOdKXZLTCvCLifxTMEi+snNzAtfevk8DpkejvSeB0"+ + "BPza/oPKABD5z4SARKQEELP1WQsFMc+QwP8ATkmhK404AAA="; + + byte[] dgBytes = decompress(data); + List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); + assertEquals(14, dgRecords.size()); + + short[] expectedSids = { + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + ObjRecord.sid + }; + + for (int i = 0; i < expectedSids.length; i++) { + assertEquals("unexpected record.sid and index[" + i + "]", expectedSids[i], dgRecords.get(i).getSid()); + } + DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); + + // create a dummy sheet consisting of our test data + InternalSheet sheet = InternalSheet.createSheet(); + List records = sheet.getRecords(); + records.clear(); + records.addAll(dgRecords); + records.add(EOFRecord.instance); + + sheet.aggregateDrawingRecords(drawingManager, false); + assertEquals("drawing was not fully aggregated", 2, records.size()); + assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); + assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); + + EscherAggregate agg = (EscherAggregate) records.get(0); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + } +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java b/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java index 4ff7c441ee..7b1c2078c1 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java +++ b/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java @@ -1,99 +1,99 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.model; - -import junit.framework.TestCase; -import org.apache.poi.ddf.DefaultEscherRecordFactory; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherTextboxRecord; -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.RecordBase; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFTestHelper; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -/** - * @author Evgeniy Berlog - * @date 18.06.12 - */ -public class TestEscherRecordFactory extends TestCase{ - - private static byte[] toByteArray(List records) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - for (RecordBase rb : records) { - Record r = (Record) rb; - try { - out.write(r.serialize()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - return out.toByteArray(); - } - - public void testDetectContainer() { - Random rnd = new Random(); - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DG_CONTAINER)); - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SOLVER_CONTAINER)); - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SP_CONTAINER)); - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DGG_CONTAINER)); - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.BSTORE_CONTAINER)); - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SPGR_CONTAINER)); - - for (Short i=EscherContainerRecord.DGG_CONTAINER; i<= EscherContainerRecord.SOLVER_CONTAINER; i++){ - assertEquals(true, DefaultEscherRecordFactory.isContainer(Integer.valueOf(rnd.nextInt(Short.MAX_VALUE)).shortValue(), i)); - } - - assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); - assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.SOLVER_CONTAINER+1).shortValue())); - - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x000F, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); - assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0xFFFF, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); - assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000C, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); - assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); - assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000F, EscherTextboxRecord.RECORD_ID)); - assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, EscherTextboxRecord.RECORD_ID)); - } - - public void testDgContainerMustBeRootOfHSSFSheetEscherRecords() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("47251.xls"); - HSSFSheet sh = wb.getSheetAt(0); - InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); - List records = ish.getRecords(); - // records to be aggregated - List dgRecords = records.subList(19, 23); - byte[] dgBytes = toByteArray(dgRecords); - sh.getDrawingPatriarch(); - EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); - assertEquals(true, agg.getEscherRecords().get(0) instanceof EscherContainerRecord); - assertEquals(EscherContainerRecord.DG_CONTAINER, agg.getEscherRecords().get(0).getRecordId()); - assertEquals((short) 0x0, agg.getEscherRecords().get(0).getOptions()); - agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); - byte[] dgBytesAfterSave = agg.serialize(); - assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.DefaultEscherRecordFactory; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordBase; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFTestHelper; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +/** + * @author Evgeniy Berlog + * @date 18.06.12 + */ +public class TestEscherRecordFactory extends TestCase{ + + private static byte[] toByteArray(List records) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (RecordBase rb : records) { + Record r = (Record) rb; + try { + out.write(r.serialize()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return out.toByteArray(); + } + + public void testDetectContainer() { + Random rnd = new Random(); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DG_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SOLVER_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SP_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DGG_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.BSTORE_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SPGR_CONTAINER)); + + for (Short i=EscherContainerRecord.DGG_CONTAINER; i<= EscherContainerRecord.SOLVER_CONTAINER; i++){ + assertEquals(true, DefaultEscherRecordFactory.isContainer(Integer.valueOf(rnd.nextInt(Short.MAX_VALUE)).shortValue(), i)); + } + + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.SOLVER_CONTAINER+1).shortValue())); + + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x000F, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0xFFFF, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000C, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000F, EscherTextboxRecord.RECORD_ID)); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, EscherTextboxRecord.RECORD_ID)); + } + + public void testDgContainerMustBeRootOfHSSFSheetEscherRecords() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("47251.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 23); + byte[] dgBytes = toByteArray(dgRecords); + sh.getDrawingPatriarch(); + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + assertEquals(true, agg.getEscherRecords().get(0) instanceof EscherContainerRecord); + assertEquals(EscherContainerRecord.DG_CONTAINER, agg.getEscherRecords().get(0).getRecordId()); + assertEquals((short) 0x0, agg.getEscherRecords().get(0).getOptions()); + agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + } +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index 84ef3c4115..c79b29928f 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -1,428 +1,428 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.model; - -import junit.framework.TestCase; -import org.apache.poi.ddf.*; -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.usermodel.*; -import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; - -/** - * @author Evgeniy Berlog - * @date 12.06.12 - */ -public class TestHSSFAnchor extends TestCase { - - public void testDefaultValues(){ - HSSFClientAnchor clientAnchor = new HSSFClientAnchor(); - assertEquals(clientAnchor.getAnchorType(), AnchorType.MOVE_AND_RESIZE); - assertEquals(clientAnchor.getCol1(), 0); - assertEquals(clientAnchor.getCol2(), 0); - assertEquals(clientAnchor.getDx1(), 0); - assertEquals(clientAnchor.getDx2(), 0); - assertEquals(clientAnchor.getDy1(), 0); - assertEquals(clientAnchor.getDy2(), 0); - assertEquals(clientAnchor.getRow1(), 0); - assertEquals(clientAnchor.getRow2(), 0); - - clientAnchor = new HSSFClientAnchor(new EscherClientAnchorRecord()); - assertEquals(clientAnchor.getAnchorType(), AnchorType.MOVE_AND_RESIZE); - assertEquals(clientAnchor.getCol1(), 0); - assertEquals(clientAnchor.getCol2(), 0); - assertEquals(clientAnchor.getDx1(), 0); - assertEquals(clientAnchor.getDx2(), 0); - assertEquals(clientAnchor.getDy1(), 0); - assertEquals(clientAnchor.getDy2(), 0); - assertEquals(clientAnchor.getRow1(), 0); - assertEquals(clientAnchor.getRow2(), 0); - - HSSFChildAnchor childAnchor = new HSSFChildAnchor(); - assertEquals(childAnchor.getDx1(), 0); - assertEquals(childAnchor.getDx2(), 0); - assertEquals(childAnchor.getDy1(), 0); - assertEquals(childAnchor.getDy2(), 0); - - childAnchor = new HSSFChildAnchor(new EscherChildAnchorRecord()); - assertEquals(childAnchor.getDx1(), 0); - assertEquals(childAnchor.getDx2(), 0); - assertEquals(childAnchor.getDy1(), 0); - assertEquals(childAnchor.getDy2(), 0); - } - - public void testCorrectOrderInSpContainer(){ - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); - HSSFSheet sheet = wb.getSheet("pictures"); - HSSFPatriarch drawing = sheet.getDrawingPatriarch(); - - HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0); - - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); - - rectangle.setAnchor(new HSSFClientAnchor()); - - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); - assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); - } - - public void testCreateClientAnchorFromContainer(){ - EscherContainerRecord container = new EscherContainerRecord(); - EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); - escher.setFlag((short) 3); - escher.setCol1((short)11); - escher.setCol2((short)12); - escher.setRow1((short)13); - escher.setRow2((short) 14); - escher.setDx1((short) 15); - escher.setDx2((short) 16); - escher.setDy1((short) 17); - escher.setDy2((short) 18); - container.addChildRecord(escher); - - HSSFClientAnchor anchor = (HSSFClientAnchor) HSSFAnchor.createAnchorFromEscher(container); - assertEquals(anchor.getCol1(), 11); - assertEquals(escher.getCol1(), 11); - assertEquals(anchor.getCol2(), 12); - assertEquals(escher.getCol2(), 12); - assertEquals(anchor.getRow1(), 13); - assertEquals(escher.getRow1(), 13); - assertEquals(anchor.getRow2(), 14); - assertEquals(escher.getRow2(), 14); - assertEquals(anchor.getDx1(), 15); - assertEquals(escher.getDx1(), 15); - assertEquals(anchor.getDx2(), 16); - assertEquals(escher.getDx2(), 16); - assertEquals(anchor.getDy1(), 17); - assertEquals(escher.getDy1(), 17); - assertEquals(anchor.getDy2(), 18); - assertEquals(escher.getDy2(), 18); - } - - public void testCreateChildAnchorFromContainer(){ - EscherContainerRecord container = new EscherContainerRecord(); - EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); - escher.setDx1((short) 15); - escher.setDx2((short) 16); - escher.setDy1((short) 17); - escher.setDy2((short) 18); - container.addChildRecord(escher); - - HSSFChildAnchor anchor = (HSSFChildAnchor) HSSFAnchor.createAnchorFromEscher(container); - assertEquals(anchor.getDx1(), 15); - assertEquals(escher.getDx1(), 15); - assertEquals(anchor.getDx2(), 16); - assertEquals(escher.getDx2(), 16); - assertEquals(anchor.getDy1(), 17); - assertEquals(escher.getDy1(), 17); - assertEquals(anchor.getDy2(), 18); - assertEquals(escher.getDy2(), 18); - } - - public void testShapeEscherMustHaveAnchorRecord(){ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(); - - HSSFPatriarch drawing = sheet.createDrawingPatriarch(); - HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15); - anchor.setAnchorType(AnchorType.MOVE_DONT_RESIZE); - - HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor); - rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); - - rectangle.setAnchor(anchor); - - assertNotNull(HSSFTestHelper.getEscherAnchor(anchor)); - assertNotNull(HSSFTestHelper.getEscherContainer(rectangle)); - assertTrue(HSSFTestHelper.getEscherAnchor(anchor).equals(HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherClientAnchorRecord.RECORD_ID))); - } - - public void testClientAnchorFromEscher(){ - EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); - escher.setCol1((short)11); - escher.setCol2((short)12); - escher.setRow1((short)13); - escher.setRow2((short) 14); - escher.setDx1((short) 15); - escher.setDx2((short) 16); - escher.setDy1((short) 17); - escher.setDy2((short) 18); - - HSSFClientAnchor anchor = new HSSFClientAnchor(escher); - assertEquals(anchor.getCol1(), 11); - assertEquals(escher.getCol1(), 11); - assertEquals(anchor.getCol2(), 12); - assertEquals(escher.getCol2(), 12); - assertEquals(anchor.getRow1(), 13); - assertEquals(escher.getRow1(), 13); - assertEquals(anchor.getRow2(), 14); - assertEquals(escher.getRow2(), 14); - assertEquals(anchor.getDx1(), 15); - assertEquals(escher.getDx1(), 15); - assertEquals(anchor.getDx2(), 16); - assertEquals(escher.getDx2(), 16); - assertEquals(anchor.getDy1(), 17); - assertEquals(escher.getDy1(), 17); - assertEquals(anchor.getDy2(), 18); - assertEquals(escher.getDy2(), 18); - } - - public void testClientAnchorFromScratch(){ - HSSFClientAnchor anchor = new HSSFClientAnchor(); - EscherClientAnchorRecord escher = (EscherClientAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor); - anchor.setAnchor((short)11, 12, 13, 14, (short)15, 16, 17, 18); - - assertEquals(anchor.getCol1(), 11); - assertEquals(escher.getCol1(), 11); - assertEquals(anchor.getCol2(), 15); - assertEquals(escher.getCol2(), 15); - assertEquals(anchor.getRow1(), 12); - assertEquals(escher.getRow1(), 12); - assertEquals(anchor.getRow2(), 16); - assertEquals(escher.getRow2(), 16); - assertEquals(anchor.getDx1(), 13); - assertEquals(escher.getDx1(), 13); - assertEquals(anchor.getDx2(), 17); - assertEquals(escher.getDx2(), 17); - assertEquals(anchor.getDy1(), 14); - assertEquals(escher.getDy1(), 14); - assertEquals(anchor.getDy2(), 18); - assertEquals(escher.getDy2(), 18); - - anchor.setCol1(111); - assertEquals(anchor.getCol1(), 111); - assertEquals(escher.getCol1(), 111); - anchor.setCol2(112); - assertEquals(anchor.getCol2(), 112); - assertEquals(escher.getCol2(), 112); - anchor.setRow1(113); - assertEquals(anchor.getRow1(), 113); - assertEquals(escher.getRow1(), 113); - anchor.setRow2(114); - assertEquals(anchor.getRow2(), 114); - assertEquals(escher.getRow2(), 114); - anchor.setDx1(115); - assertEquals(anchor.getDx1(), 115); - assertEquals(escher.getDx1(), 115); - anchor.setDx2(116); - assertEquals(anchor.getDx2(), 116); - assertEquals(escher.getDx2(), 116); - anchor.setDy1(117); - assertEquals(anchor.getDy1(), 117); - assertEquals(escher.getDy1(), 117); - anchor.setDy2(118); - assertEquals(anchor.getDy2(), 118); - assertEquals(escher.getDy2(), 118); - } - - public void testChildAnchorFromEscher(){ - EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); - escher.setDx1((short) 15); - escher.setDx2((short) 16); - escher.setDy1((short) 17); - escher.setDy2((short) 18); - - HSSFChildAnchor anchor = new HSSFChildAnchor(escher); - assertEquals(anchor.getDx1(), 15); - assertEquals(escher.getDx1(), 15); - assertEquals(anchor.getDx2(), 16); - assertEquals(escher.getDx2(), 16); - assertEquals(anchor.getDy1(), 17); - assertEquals(escher.getDy1(), 17); - assertEquals(anchor.getDy2(), 18); - assertEquals(escher.getDy2(), 18); - } - - public void testChildAnchorFromScratch(){ - HSSFChildAnchor anchor = new HSSFChildAnchor(); - EscherChildAnchorRecord escher = (EscherChildAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor); - anchor.setAnchor(11, 12, 13, 14); - - assertEquals(anchor.getDx1(), 11); - assertEquals(escher.getDx1(), 11); - assertEquals(anchor.getDx2(), 13); - assertEquals(escher.getDx2(), 13); - assertEquals(anchor.getDy1(), 12); - assertEquals(escher.getDy1(), 12); - assertEquals(anchor.getDy2(), 14); - assertEquals(escher.getDy2(), 14); - - anchor.setDx1(115); - assertEquals(anchor.getDx1(), 115); - assertEquals(escher.getDx1(), 115); - anchor.setDx2(116); - assertEquals(anchor.getDx2(), 116); - assertEquals(escher.getDx2(), 116); - anchor.setDy1(117); - assertEquals(anchor.getDy1(), 117); - assertEquals(escher.getDy1(), 117); - anchor.setDy2(118); - assertEquals(anchor.getDy2(), 118); - assertEquals(escher.getDy2(), 118); - } - - public void testEqualsToSelf(){ - HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); - assertEquals(clientAnchor, clientAnchor); - - HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); - assertEquals(childAnchor, childAnchor); - } - - public void testPassIncompatibleTypeIsFalse(){ - HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); - assertNotSame(clientAnchor, "wrongType"); - - HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); - assertNotSame(childAnchor, "wrongType"); - } - - public void testNullReferenceIsFalse() { - HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); - assertFalse("Passing null to equals should return false", clientAnchor.equals(null)); - - HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); - assertFalse("Passing null to equals should return false", childAnchor.equals(null)); - } - - public void testEqualsIsReflexiveIsSymmetric() { - HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); - HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); - - assertTrue(clientAnchor1.equals(clientAnchor2)); - assertTrue(clientAnchor1.equals(clientAnchor2)); - - HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3); - HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3); - - assertTrue(childAnchor1.equals(childAnchor2)); - assertTrue(childAnchor2.equals(childAnchor1)); - } - - public void testEqualsValues(){ - HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); - HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setDx1(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setDx1(0); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setDy1(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setDy1(1); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setDx2(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setDx2(2); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setDy2(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setDy2(3); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setCol1(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setCol1(4); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setRow1(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setRow1(5); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setCol2(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setCol2(6); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setRow2(10); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setRow2(7); - assertEquals(clientAnchor1, clientAnchor2); - - clientAnchor2.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE); - assertNotSame(clientAnchor1, clientAnchor2); - clientAnchor2.setAnchorType(AnchorType.MOVE_AND_RESIZE); - assertEquals(clientAnchor1, clientAnchor2); - - HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3); - HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3); - - childAnchor1.setDx1(10); - assertNotSame(childAnchor1, childAnchor2); - childAnchor1.setDx1(0); - assertEquals(childAnchor1, childAnchor2); - - childAnchor2.setDy1(10); - assertNotSame(childAnchor1, childAnchor2); - childAnchor2.setDy1(1); - assertEquals(childAnchor1, childAnchor2); - - childAnchor2.setDx2(10); - assertNotSame(childAnchor1, childAnchor2); - childAnchor2.setDx2(2); - assertEquals(childAnchor1, childAnchor2); - - childAnchor2.setDy2(10); - assertNotSame(childAnchor1, childAnchor2); - childAnchor2.setDy2(3); - assertEquals(childAnchor1, childAnchor2); - } - - public void testFlipped(){ - HSSFChildAnchor child = new HSSFChildAnchor(2,2,1,1); - assertEquals(child.isHorizontallyFlipped(), true); - assertEquals(child.isVerticallyFlipped(), true); - assertEquals(child.getDx1(), 1); - assertEquals(child.getDx2(), 2); - assertEquals(child.getDy1(), 1); - assertEquals(child.getDy2(), 2); - - child = new HSSFChildAnchor(3,3,4,4); - assertEquals(child.isHorizontallyFlipped(), false); - assertEquals(child.isVerticallyFlipped(), false); - assertEquals(child.getDx1(), 3); - assertEquals(child.getDx2(), 4); - assertEquals(child.getDy1(), 3); - assertEquals(child.getDy2(), 4); - - HSSFClientAnchor client = new HSSFClientAnchor(1,1,1,1, (short)4,4,(short)3,3); - assertEquals(client.isVerticallyFlipped(), true); - assertEquals(client.isHorizontallyFlipped(), true); - assertEquals(client.getCol1(), 3); - assertEquals(client.getCol2(), 4); - assertEquals(client.getRow1(), 3); - assertEquals(client.getRow2(), 4); - - client = new HSSFClientAnchor(1,1,1,1, (short)5,5,(short)6,6); - assertEquals(client.isVerticallyFlipped(), false); - assertEquals(client.isHorizontallyFlipped(), false); - assertEquals(client.getCol1(), 5); - assertEquals(client.getCol2(), 6); - assertEquals(client.getRow1(), 5); - assertEquals(client.getRow2(), 6); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; + +/** + * @author Evgeniy Berlog + * @date 12.06.12 + */ +public class TestHSSFAnchor extends TestCase { + + public void testDefaultValues(){ + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(); + assertEquals(clientAnchor.getAnchorType(), AnchorType.MOVE_AND_RESIZE); + assertEquals(clientAnchor.getCol1(), 0); + assertEquals(clientAnchor.getCol2(), 0); + assertEquals(clientAnchor.getDx1(), 0); + assertEquals(clientAnchor.getDx2(), 0); + assertEquals(clientAnchor.getDy1(), 0); + assertEquals(clientAnchor.getDy2(), 0); + assertEquals(clientAnchor.getRow1(), 0); + assertEquals(clientAnchor.getRow2(), 0); + + clientAnchor = new HSSFClientAnchor(new EscherClientAnchorRecord()); + assertEquals(clientAnchor.getAnchorType(), AnchorType.MOVE_AND_RESIZE); + assertEquals(clientAnchor.getCol1(), 0); + assertEquals(clientAnchor.getCol2(), 0); + assertEquals(clientAnchor.getDx1(), 0); + assertEquals(clientAnchor.getDx2(), 0); + assertEquals(clientAnchor.getDy1(), 0); + assertEquals(clientAnchor.getDy2(), 0); + assertEquals(clientAnchor.getRow1(), 0); + assertEquals(clientAnchor.getRow2(), 0); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(); + assertEquals(childAnchor.getDx1(), 0); + assertEquals(childAnchor.getDx2(), 0); + assertEquals(childAnchor.getDy1(), 0); + assertEquals(childAnchor.getDy2(), 0); + + childAnchor = new HSSFChildAnchor(new EscherChildAnchorRecord()); + assertEquals(childAnchor.getDx1(), 0); + assertEquals(childAnchor.getDx2(), 0); + assertEquals(childAnchor.getDy1(), 0); + assertEquals(childAnchor.getDy2(), 0); + } + + public void testCorrectOrderInSpContainer(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("pictures"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + + HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0); + + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); + + rectangle.setAnchor(new HSSFClientAnchor()); + + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); + } + + public void testCreateClientAnchorFromContainer(){ + EscherContainerRecord container = new EscherContainerRecord(); + EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); + escher.setFlag((short) 3); + escher.setCol1((short)11); + escher.setCol2((short)12); + escher.setRow1((short)13); + escher.setRow2((short) 14); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + container.addChildRecord(escher); + + HSSFClientAnchor anchor = (HSSFClientAnchor) HSSFAnchor.createAnchorFromEscher(container); + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 12); + assertEquals(escher.getCol2(), 12); + assertEquals(anchor.getRow1(), 13); + assertEquals(escher.getRow1(), 13); + assertEquals(anchor.getRow2(), 14); + assertEquals(escher.getRow2(), 14); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testCreateChildAnchorFromContainer(){ + EscherContainerRecord container = new EscherContainerRecord(); + EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + container.addChildRecord(escher); + + HSSFChildAnchor anchor = (HSSFChildAnchor) HSSFAnchor.createAnchorFromEscher(container); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testShapeEscherMustHaveAnchorRecord(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + + HSSFPatriarch drawing = sheet.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15); + anchor.setAnchorType(AnchorType.MOVE_DONT_RESIZE); + + HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + rectangle.setAnchor(anchor); + + assertNotNull(HSSFTestHelper.getEscherAnchor(anchor)); + assertNotNull(HSSFTestHelper.getEscherContainer(rectangle)); + assertTrue(HSSFTestHelper.getEscherAnchor(anchor).equals(HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherClientAnchorRecord.RECORD_ID))); + } + + public void testClientAnchorFromEscher(){ + EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); + escher.setCol1((short)11); + escher.setCol2((short)12); + escher.setRow1((short)13); + escher.setRow2((short) 14); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + + HSSFClientAnchor anchor = new HSSFClientAnchor(escher); + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 12); + assertEquals(escher.getCol2(), 12); + assertEquals(anchor.getRow1(), 13); + assertEquals(escher.getRow1(), 13); + assertEquals(anchor.getRow2(), 14); + assertEquals(escher.getRow2(), 14); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testClientAnchorFromScratch(){ + HSSFClientAnchor anchor = new HSSFClientAnchor(); + EscherClientAnchorRecord escher = (EscherClientAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor); + anchor.setAnchor((short)11, 12, 13, 14, (short)15, 16, 17, 18); + + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 15); + assertEquals(escher.getCol2(), 15); + assertEquals(anchor.getRow1(), 12); + assertEquals(escher.getRow1(), 12); + assertEquals(anchor.getRow2(), 16); + assertEquals(escher.getRow2(), 16); + assertEquals(anchor.getDx1(), 13); + assertEquals(escher.getDx1(), 13); + assertEquals(anchor.getDx2(), 17); + assertEquals(escher.getDx2(), 17); + assertEquals(anchor.getDy1(), 14); + assertEquals(escher.getDy1(), 14); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + + anchor.setCol1(111); + assertEquals(anchor.getCol1(), 111); + assertEquals(escher.getCol1(), 111); + anchor.setCol2(112); + assertEquals(anchor.getCol2(), 112); + assertEquals(escher.getCol2(), 112); + anchor.setRow1(113); + assertEquals(anchor.getRow1(), 113); + assertEquals(escher.getRow1(), 113); + anchor.setRow2(114); + assertEquals(anchor.getRow2(), 114); + assertEquals(escher.getRow2(), 114); + anchor.setDx1(115); + assertEquals(anchor.getDx1(), 115); + assertEquals(escher.getDx1(), 115); + anchor.setDx2(116); + assertEquals(anchor.getDx2(), 116); + assertEquals(escher.getDx2(), 116); + anchor.setDy1(117); + assertEquals(anchor.getDy1(), 117); + assertEquals(escher.getDy1(), 117); + anchor.setDy2(118); + assertEquals(anchor.getDy2(), 118); + assertEquals(escher.getDy2(), 118); + } + + public void testChildAnchorFromEscher(){ + EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + + HSSFChildAnchor anchor = new HSSFChildAnchor(escher); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testChildAnchorFromScratch(){ + HSSFChildAnchor anchor = new HSSFChildAnchor(); + EscherChildAnchorRecord escher = (EscherChildAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor); + anchor.setAnchor(11, 12, 13, 14); + + assertEquals(anchor.getDx1(), 11); + assertEquals(escher.getDx1(), 11); + assertEquals(anchor.getDx2(), 13); + assertEquals(escher.getDx2(), 13); + assertEquals(anchor.getDy1(), 12); + assertEquals(escher.getDy1(), 12); + assertEquals(anchor.getDy2(), 14); + assertEquals(escher.getDy2(), 14); + + anchor.setDx1(115); + assertEquals(anchor.getDx1(), 115); + assertEquals(escher.getDx1(), 115); + anchor.setDx2(116); + assertEquals(anchor.getDx2(), 116); + assertEquals(escher.getDx2(), 116); + anchor.setDy1(117); + assertEquals(anchor.getDy1(), 117); + assertEquals(escher.getDy1(), 117); + anchor.setDy2(118); + assertEquals(anchor.getDy2(), 118); + assertEquals(escher.getDy2(), 118); + } + + public void testEqualsToSelf(){ + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertEquals(clientAnchor, clientAnchor); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); + assertEquals(childAnchor, childAnchor); + } + + public void testPassIncompatibleTypeIsFalse(){ + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertNotSame(clientAnchor, "wrongType"); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); + assertNotSame(childAnchor, "wrongType"); + } + + public void testNullReferenceIsFalse() { + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertFalse("Passing null to equals should return false", clientAnchor.equals(null)); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); + assertFalse("Passing null to equals should return false", childAnchor.equals(null)); + } + + public void testEqualsIsReflexiveIsSymmetric() { + HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + + assertTrue(clientAnchor1.equals(clientAnchor2)); + assertTrue(clientAnchor1.equals(clientAnchor2)); + + HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3); + HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3); + + assertTrue(childAnchor1.equals(childAnchor2)); + assertTrue(childAnchor2.equals(childAnchor1)); + } + + public void testEqualsValues(){ + HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDx1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDx1(0); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDy1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDy1(1); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDx2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDx2(2); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDy2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDy2(3); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setCol1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setCol1(4); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setRow1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setRow1(5); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setCol2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setCol2(6); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setRow2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setRow2(7); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setAnchorType(AnchorType.MOVE_AND_RESIZE); + assertEquals(clientAnchor1, clientAnchor2); + + HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3); + HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3); + + childAnchor1.setDx1(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor1.setDx1(0); + assertEquals(childAnchor1, childAnchor2); + + childAnchor2.setDy1(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor2.setDy1(1); + assertEquals(childAnchor1, childAnchor2); + + childAnchor2.setDx2(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor2.setDx2(2); + assertEquals(childAnchor1, childAnchor2); + + childAnchor2.setDy2(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor2.setDy2(3); + assertEquals(childAnchor1, childAnchor2); + } + + public void testFlipped(){ + HSSFChildAnchor child = new HSSFChildAnchor(2,2,1,1); + assertEquals(child.isHorizontallyFlipped(), true); + assertEquals(child.isVerticallyFlipped(), true); + assertEquals(child.getDx1(), 1); + assertEquals(child.getDx2(), 2); + assertEquals(child.getDy1(), 1); + assertEquals(child.getDy2(), 2); + + child = new HSSFChildAnchor(3,3,4,4); + assertEquals(child.isHorizontallyFlipped(), false); + assertEquals(child.isVerticallyFlipped(), false); + assertEquals(child.getDx1(), 3); + assertEquals(child.getDx2(), 4); + assertEquals(child.getDy1(), 3); + assertEquals(child.getDy2(), 4); + + HSSFClientAnchor client = new HSSFClientAnchor(1,1,1,1, (short)4,4,(short)3,3); + assertEquals(client.isVerticallyFlipped(), true); + assertEquals(client.isHorizontallyFlipped(), true); + assertEquals(client.getCol1(), 3); + assertEquals(client.getCol2(), 4); + assertEquals(client.getRow1(), 3); + assertEquals(client.getRow2(), 4); + + client = new HSSFClientAnchor(1,1,1,1, (short)5,5,(short)6,6); + assertEquals(client.isVerticallyFlipped(), false); + assertEquals(client.isHorizontallyFlipped(), false); + assertEquals(client.getCol1(), 5); + assertEquals(client.getCol2(), 6); + assertEquals(client.getRow1(), 5); + assertEquals(client.getRow2(), 6); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java index fe04ebb3a1..7d9fadaa84 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java @@ -1,62 +1,62 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.usermodel; - -import junit.framework.TestCase; -import org.apache.poi.hssf.HSSFTestDataSamples; - -import java.io.IOException; -import java.util.List; - -/** - * Tests for the embedded object fetching support in HSSF - */ -public class TestEmbeddedObjects extends TestCase{ - public void testReadExistingObject() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); - List list = wb.getAllEmbeddedObjects(); - assertEquals(list.size(), 1); - HSSFObjectData obj = list.get(0); - assertNotNull(obj.getObjectData()); - assertNotNull(obj.getDirectory()); - assertNotNull(obj.getOLE2ClassName()); - } - - /** - * Need to recurse into the shapes to find this one - * See https://github.com/apache/poi/pull/2 - */ - public void testReadNestedObject() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithCheckBoxes.xls"); - List list = wb.getAllEmbeddedObjects(); - assertEquals(list.size(), 1); - HSSFObjectData obj = list.get(0); - assertNotNull(obj.getObjectData()); - assertNotNull(obj.getOLE2ClassName()); - } - - /** - * One with large numbers of recursivly embedded resources - * See https://github.com/apache/poi/pull/2 - */ - public void testReadManyNestedObjects() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45538_form_Header.xls"); - List list = wb.getAllEmbeddedObjects(); - assertEquals(list.size(), 40); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.hssf.HSSFTestDataSamples; + +import java.io.IOException; +import java.util.List; + +/** + * Tests for the embedded object fetching support in HSSF + */ +public class TestEmbeddedObjects extends TestCase{ + public void testReadExistingObject() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + List list = wb.getAllEmbeddedObjects(); + assertEquals(list.size(), 1); + HSSFObjectData obj = list.get(0); + assertNotNull(obj.getObjectData()); + assertNotNull(obj.getDirectory()); + assertNotNull(obj.getOLE2ClassName()); + } + + /** + * Need to recurse into the shapes to find this one + * See https://github.com/apache/poi/pull/2 + */ + public void testReadNestedObject() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithCheckBoxes.xls"); + List list = wb.getAllEmbeddedObjects(); + assertEquals(list.size(), 1); + HSSFObjectData obj = list.get(0); + assertNotNull(obj.getObjectData()); + assertNotNull(obj.getOLE2ClassName()); + } + + /** + * One with large numbers of recursivly embedded resources + * See https://github.com/apache/poi/pull/2 + */ + public void testReadManyNestedObjects() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45538_form_Header.xls"); + List list = wb.getAllEmbeddedObjects(); + assertEquals(list.size(), 40); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java index 9ad147a7ac..a54d8f1e74 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHyperlink.java @@ -251,19 +251,19 @@ public final class TestHSSFHyperlink extends BaseTestHyperlink { sheet.shiftRows(sheet.getFirstRowNum(), sheet.getLastRowNum(), 2); //cells A3 and A4 don't contain hyperlinks anymore - assertNull(sheet.getRow(2).getCell(0).getHyperlink()); - assertNull(sheet.getRow(3).getCell(0).getHyperlink()); - - //the first hyperlink now belongs to A5 - HSSFHyperlink link1_shifted = sheet.getRow(2+2).getCell(0).getHyperlink(); - assertNotNull(link1_shifted); - assertEquals(4, link1_shifted.getFirstRow()); - assertEquals(4, link1_shifted.getLastRow()); - - //the second hyperlink now belongs to A6 - HSSFHyperlink link2_shifted = sheet.getRow(3+2).getCell(0).getHyperlink(); - assertNotNull(link2_shifted); - assertEquals(5, link2_shifted.getFirstRow()); + assertNull(sheet.getRow(2).getCell(0).getHyperlink()); + assertNull(sheet.getRow(3).getCell(0).getHyperlink()); + + //the first hyperlink now belongs to A5 + HSSFHyperlink link1_shifted = sheet.getRow(2+2).getCell(0).getHyperlink(); + assertNotNull(link1_shifted); + assertEquals(4, link1_shifted.getFirstRow()); + assertEquals(4, link1_shifted.getLastRow()); + + //the second hyperlink now belongs to A6 + HSSFHyperlink link2_shifted = sheet.getRow(3+2).getCell(0).getHyperlink(); + assertNotNull(link2_shifted); + assertEquals(5, link2_shifted.getFirstRow()); assertEquals(5, link2_shifted.getLastRow()); } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java index 49cbaeec02..d7ce833063 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java @@ -1,57 +1,57 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.usermodel; - -import junit.framework.TestCase; -import org.apache.poi.ddf.EscherDgRecord; -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.EscherAggregate; - -/** - * @author Evgeniy Berlog - * @date 01.08.12 - */ -public class TestPatriarch extends TestCase { - - public void testGetPatriarch(){ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sh = wb.createSheet(); - assertNull(sh.getDrawingPatriarch()); - - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - assertNotNull(patriarch); - patriarch.createSimpleShape(new HSSFClientAnchor()); - patriarch.createSimpleShape(new HSSFClientAnchor()); - - assertSame(patriarch, sh.getDrawingPatriarch()); - - EscherAggregate agg = patriarch.getBoundAggregate(); - - EscherDgRecord dg = agg.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); - int lastId = dg.getLastMSOSPID(); - - assertSame(patriarch, sh.createDrawingPatriarch()); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); - patriarch = sh.createDrawingPatriarch(); - dg = patriarch.getBoundAggregate().getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); - - assertEquals(lastId, dg.getLastMSOSPID()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherDgRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.EscherAggregate; + +/** + * @author Evgeniy Berlog + * @date 01.08.12 + */ +public class TestPatriarch extends TestCase { + + public void testGetPatriarch(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + assertNull(sh.getDrawingPatriarch()); + + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + assertNotNull(patriarch); + patriarch.createSimpleShape(new HSSFClientAnchor()); + patriarch.createSimpleShape(new HSSFClientAnchor()); + + assertSame(patriarch, sh.getDrawingPatriarch()); + + EscherAggregate agg = patriarch.getBoundAggregate(); + + EscherDgRecord dg = agg.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); + int lastId = dg.getLastMSOSPID(); + + assertSame(patriarch, sh.createDrawingPatriarch()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.createDrawingPatriarch(); + dg = patriarch.getBoundAggregate().getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); + + assertEquals(lastId, dg.getLastMSOSPID()); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java index 1b9ad1ffa6..1e250bdfd8 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java @@ -1,276 +1,276 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.usermodel; - -import static org.apache.poi.poifs.storage.RawDataUtil.decompress; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; - -import org.apache.poi.ddf.EscherArrayProperty; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.ObjRecord; -import org.junit.Test; - -public class TestPolygon { - @Test - public void testResultEqualsToAbstractShape() throws IOException { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sh = wb.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - - HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); - polygon.setPolygonDrawArea( 100, 100 ); - polygon.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} ); - polygon.setShapeId(1024); - - assertEquals(polygon.getEscherContainer().getChildRecords().size(), 4); - - //sp record - byte[] expected = decompress("H4sIAAAAAAAAAGNi4PrAwQAELEDMxcAAAAU6ZlwQAAAA"); - byte[] actual = polygon.getEscherContainer().getChild(0).serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - expected = decompress("H4sIAAAAAAAAAGNgEPggxIANAABK4+laGgAAAA=="); - actual = polygon.getEscherContainer().getChild(2).serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - expected = decompress("H4sIAAAAAAAAAGNgEPzAAAQACl6c5QgAAAA="); - actual = polygon.getEscherContainer().getChild(3).serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - ObjRecord obj = polygon.getObjRecord(); - - expected = decompress("H4sIAAAAAAAAAItlkGIQZRBikGNgYBBMYEADAOAV/ZkeAAAA"); - actual = obj.serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - wb.close(); - } - - @Test - public void testPolygonPoints() throws IOException { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sh = wb.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - - HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); - polygon.setPolygonDrawArea( 100, 100 ); - polygon.setPoints( new int[]{0, 90, 50, 90}, new int[]{5, 5, 44, 88} ); - - EscherArrayProperty verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); - - String expected = - ""+ - "[00, 00, 05, 00]"+ - "[5A, 00, 05, 00]"+ - "[32, 00, 2C, 00]"+ - "[5A, 00, 58, 00]"+ - "[00, 00, 05, 00]"+ - ""; - String actual = verticesProp1.toXml("").replaceAll("[\r\n\t]",""); - - assertEquals(verticesProp1.getNumberOfElementsInArray(), 5); - assertEquals(expected, actual); - - polygon.setPoints(new int[]{1,2,3}, new int[] {4,5,6}); - assertArrayEquals(polygon.getXPoints(), new int[]{1, 2, 3}); - assertArrayEquals(polygon.getYPoints(), new int[]{4, 5, 6}); - - verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); - - expected = - "" + - "[01, 00, 04, 00]" + - "[02, 00, 05, 00]" + - "[03, 00, 06, 00]" + - "[01, 00, 04, 00]" + - ""; - actual = verticesProp1.toXml("").replaceAll("[\r\n\t]",""); - - assertEquals(verticesProp1.getNumberOfElementsInArray(), 4); - assertEquals(expected, actual); - - wb.close(); - } - - @Test - public void testSetGetProperties() throws IOException { - HSSFWorkbook wb1 = new HSSFWorkbook(); - HSSFSheet sh = wb1.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - - HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); - polygon.setPolygonDrawArea( 102, 101 ); - polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); - - assertArrayEquals(polygon.getXPoints(), new int[]{1,2,3}); - assertArrayEquals(polygon.getYPoints(), new int[]{4, 5, 6}); - assertEquals(polygon.getDrawAreaHeight(), 101); - assertEquals(polygon.getDrawAreaWidth(), 102); - - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); - wb1.close(); - sh = wb2.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - polygon = (HSSFPolygon) patriarch.getChildren().get(0); - assertArrayEquals(polygon.getXPoints(), new int[]{1, 2, 3}); - assertArrayEquals(polygon.getYPoints(), new int[]{4, 5, 6}); - assertEquals(polygon.getDrawAreaHeight(), 101); - assertEquals(polygon.getDrawAreaWidth(), 102); - - polygon.setPolygonDrawArea( 1021, 1011 ); - polygon.setPoints( new int[]{11,21,31}, new int[]{41,51,61} ); - - assertArrayEquals(polygon.getXPoints(), new int[]{11, 21, 31}); - assertArrayEquals(polygon.getYPoints(), new int[]{41, 51, 61}); - assertEquals(polygon.getDrawAreaHeight(), 1011); - assertEquals(polygon.getDrawAreaWidth(), 1021); - - HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); - wb2.close(); - sh = wb3.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - polygon = (HSSFPolygon) patriarch.getChildren().get(0); - - assertArrayEquals(polygon.getXPoints(), new int[]{11, 21, 31}); - assertArrayEquals(polygon.getYPoints(), new int[]{41, 51, 61}); - assertEquals(polygon.getDrawAreaHeight(), 1011); - assertEquals(polygon.getDrawAreaWidth(), 1021); - - wb3.close(); - } - - @Test - public void testAddToExistingFile() throws IOException { - HSSFWorkbook wb1 = new HSSFWorkbook(); - HSSFSheet sh = wb1.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - - HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); - polygon.setPolygonDrawArea( 102, 101 ); - polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); - - HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); - polygon1.setPolygonDrawArea( 103, 104 ); - polygon1.setPoints( new int[]{11,12,13}, new int[]{14,15,16} ); - - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); - wb1.close(); - sh = wb2.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - assertEquals(patriarch.getChildren().size(), 2); - - HSSFPolygon polygon2 = patriarch.createPolygon(new HSSFClientAnchor()); - polygon2.setPolygonDrawArea( 203, 204 ); - polygon2.setPoints( new int[]{21,22,23}, new int[]{24,25,26} ); - - HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); - wb2.close(); - sh = wb3.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - assertEquals(patriarch.getChildren().size(), 3); - - polygon = (HSSFPolygon) patriarch.getChildren().get(0); - polygon1 = (HSSFPolygon) patriarch.getChildren().get(1); - polygon2 = (HSSFPolygon) patriarch.getChildren().get(2); - - assertArrayEquals(polygon.getXPoints(), new int[]{1, 2, 3}); - assertArrayEquals(polygon.getYPoints(), new int[]{4,5,6}); - assertEquals(polygon.getDrawAreaHeight(), 101); - assertEquals(polygon.getDrawAreaWidth(), 102); - - assertArrayEquals(polygon1.getXPoints(), new int[]{11,12,13}); - assertArrayEquals(polygon1.getYPoints(), new int[]{14,15,16}); - assertEquals(polygon1.getDrawAreaHeight(), 104); - assertEquals(polygon1.getDrawAreaWidth(), 103); - - assertArrayEquals(polygon2.getXPoints(), new int[]{21,22,23}); - assertArrayEquals(polygon2.getYPoints(), new int[]{24,25,26}); - assertEquals(polygon2.getDrawAreaHeight(), 204); - assertEquals(polygon2.getDrawAreaWidth(), 203); - - wb3.close(); - } - - @Test - public void testExistingFile() throws IOException { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); - HSSFSheet sheet = wb.getSheet("polygon"); - HSSFPatriarch drawing = sheet.getDrawingPatriarch(); - assertEquals(1, drawing.getChildren().size()); - - HSSFPolygon polygon = (HSSFPolygon) drawing.getChildren().get(0); - assertEquals(polygon.getDrawAreaHeight(), 2466975); - assertEquals(polygon.getDrawAreaWidth(), 3686175); - assertArrayEquals(polygon.getXPoints(), new int[]{0, 0, 31479, 16159, 19676, 20502}); - assertArrayEquals(polygon.getYPoints(), new int[]{0, 0, 36, 56, 34, 18}); - - wb.close(); - } - - @Test - public void testPolygonType() throws IOException { - HSSFWorkbook wb1 = new HSSFWorkbook(); - HSSFSheet sh = wb1.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - - HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); - polygon.setPolygonDrawArea( 102, 101 ); - polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); - - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); - wb1.close(); - sh = wb2.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); - polygon1.setPolygonDrawArea( 102, 101 ); - polygon1.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); - - EscherSpRecord spRecord = polygon1.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - - spRecord.setShapeType((short)77/**RANDOM**/); - - HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); - wb2.close(); - sh = wb3.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - assertEquals(patriarch.getChildren().size(), 2); - assertTrue(patriarch.getChildren().get(0) instanceof HSSFPolygon); - assertTrue(patriarch.getChildren().get(1) instanceof HSSFPolygon); - wb3.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import static org.apache.poi.poifs.storage.RawDataUtil.decompress; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.apache.poi.ddf.EscherArrayProperty; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.ObjRecord; +import org.junit.Test; + +public class TestPolygon { + @Test + public void testResultEqualsToAbstractShape() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 100, 100 ); + polygon.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} ); + polygon.setShapeId(1024); + + assertEquals(polygon.getEscherContainer().getChildRecords().size(), 4); + + //sp record + byte[] expected = decompress("H4sIAAAAAAAAAGNi4PrAwQAELEDMxcAAAAU6ZlwQAAAA"); + byte[] actual = polygon.getEscherContainer().getChild(0).serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + expected = decompress("H4sIAAAAAAAAAGNgEPggxIANAABK4+laGgAAAA=="); + actual = polygon.getEscherContainer().getChild(2).serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + expected = decompress("H4sIAAAAAAAAAGNgEPzAAAQACl6c5QgAAAA="); + actual = polygon.getEscherContainer().getChild(3).serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + ObjRecord obj = polygon.getObjRecord(); + + expected = decompress("H4sIAAAAAAAAAItlkGIQZRBikGNgYBBMYEADAOAV/ZkeAAAA"); + actual = obj.serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + wb.close(); + } + + @Test + public void testPolygonPoints() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 100, 100 ); + polygon.setPoints( new int[]{0, 90, 50, 90}, new int[]{5, 5, 44, 88} ); + + EscherArrayProperty verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); + + String expected = + ""+ + "[00, 00, 05, 00]"+ + "[5A, 00, 05, 00]"+ + "[32, 00, 2C, 00]"+ + "[5A, 00, 58, 00]"+ + "[00, 00, 05, 00]"+ + ""; + String actual = verticesProp1.toXml("").replaceAll("[\r\n\t]",""); + + assertEquals(verticesProp1.getNumberOfElementsInArray(), 5); + assertEquals(expected, actual); + + polygon.setPoints(new int[]{1,2,3}, new int[] {4,5,6}); + assertArrayEquals(polygon.getXPoints(), new int[]{1, 2, 3}); + assertArrayEquals(polygon.getYPoints(), new int[]{4, 5, 6}); + + verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); + + expected = + "" + + "[01, 00, 04, 00]" + + "[02, 00, 05, 00]" + + "[03, 00, 06, 00]" + + "[01, 00, 04, 00]" + + ""; + actual = verticesProp1.toXml("").replaceAll("[\r\n\t]",""); + + assertEquals(verticesProp1.getNumberOfElementsInArray(), 4); + assertEquals(expected, actual); + + wb.close(); + } + + @Test + public void testSetGetProperties() throws IOException { + HSSFWorkbook wb1 = new HSSFWorkbook(); + HSSFSheet sh = wb1.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + assertArrayEquals(polygon.getXPoints(), new int[]{1,2,3}); + assertArrayEquals(polygon.getYPoints(), new int[]{4, 5, 6}); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); + wb1.close(); + sh = wb2.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + assertArrayEquals(polygon.getXPoints(), new int[]{1, 2, 3}); + assertArrayEquals(polygon.getYPoints(), new int[]{4, 5, 6}); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + polygon.setPolygonDrawArea( 1021, 1011 ); + polygon.setPoints( new int[]{11,21,31}, new int[]{41,51,61} ); + + assertArrayEquals(polygon.getXPoints(), new int[]{11, 21, 31}); + assertArrayEquals(polygon.getYPoints(), new int[]{41, 51, 61}); + assertEquals(polygon.getDrawAreaHeight(), 1011); + assertEquals(polygon.getDrawAreaWidth(), 1021); + + HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); + wb2.close(); + sh = wb3.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + + assertArrayEquals(polygon.getXPoints(), new int[]{11, 21, 31}); + assertArrayEquals(polygon.getYPoints(), new int[]{41, 51, 61}); + assertEquals(polygon.getDrawAreaHeight(), 1011); + assertEquals(polygon.getDrawAreaWidth(), 1021); + + wb3.close(); + } + + @Test + public void testAddToExistingFile() throws IOException { + HSSFWorkbook wb1 = new HSSFWorkbook(); + HSSFSheet sh = wb1.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon1.setPolygonDrawArea( 103, 104 ); + polygon1.setPoints( new int[]{11,12,13}, new int[]{14,15,16} ); + + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); + wb1.close(); + sh = wb2.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + + HSSFPolygon polygon2 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon2.setPolygonDrawArea( 203, 204 ); + polygon2.setPoints( new int[]{21,22,23}, new int[]{24,25,26} ); + + HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); + wb2.close(); + sh = wb3.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + polygon1 = (HSSFPolygon) patriarch.getChildren().get(1); + polygon2 = (HSSFPolygon) patriarch.getChildren().get(2); + + assertArrayEquals(polygon.getXPoints(), new int[]{1, 2, 3}); + assertArrayEquals(polygon.getYPoints(), new int[]{4,5,6}); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + assertArrayEquals(polygon1.getXPoints(), new int[]{11,12,13}); + assertArrayEquals(polygon1.getYPoints(), new int[]{14,15,16}); + assertEquals(polygon1.getDrawAreaHeight(), 104); + assertEquals(polygon1.getDrawAreaWidth(), 103); + + assertArrayEquals(polygon2.getXPoints(), new int[]{21,22,23}); + assertArrayEquals(polygon2.getYPoints(), new int[]{24,25,26}); + assertEquals(polygon2.getDrawAreaHeight(), 204); + assertEquals(polygon2.getDrawAreaWidth(), 203); + + wb3.close(); + } + + @Test + public void testExistingFile() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("polygon"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + HSSFPolygon polygon = (HSSFPolygon) drawing.getChildren().get(0); + assertEquals(polygon.getDrawAreaHeight(), 2466975); + assertEquals(polygon.getDrawAreaWidth(), 3686175); + assertArrayEquals(polygon.getXPoints(), new int[]{0, 0, 31479, 16159, 19676, 20502}); + assertArrayEquals(polygon.getYPoints(), new int[]{0, 0, 36, 56, 34, 18}); + + wb.close(); + } + + @Test + public void testPolygonType() throws IOException { + HSSFWorkbook wb1 = new HSSFWorkbook(); + HSSFSheet sh = wb1.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); + wb1.close(); + sh = wb2.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon1.setPolygonDrawArea( 102, 101 ); + polygon1.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + EscherSpRecord spRecord = polygon1.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + + spRecord.setShapeType((short)77/**RANDOM**/); + + HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); + wb2.close(); + sh = wb3.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + assertTrue(patriarch.getChildren().get(0) instanceof HSSFPolygon); + assertTrue(patriarch.getChildren().get(1) instanceof HSSFPolygon); + wb3.close(); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java index e1e2ebccf5..bbe81c381c 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java @@ -1,265 +1,265 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.usermodel; - -import org.apache.poi.POITestCase; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherSpgrRecord; -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.EscherAggregate; - -import junit.framework.TestCase; - -/** - * @author Evgeniy Berlog - * @date 29.06.12 - */ -public class TestShapeGroup extends TestCase{ - - public void testSetGetCoordinates(){ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sh = wb.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); - assertEquals(group.getX1(), 0); - assertEquals(group.getY1(), 0); - assertEquals(group.getX2(), 1023); - assertEquals(group.getY2(), 255); - - group.setCoordinates(1,2,3,4); - - assertEquals(group.getX1(), 1); - assertEquals(group.getY1(), 2); - assertEquals(group.getX2(), 3); - assertEquals(group.getY2(), 4); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - group = (HSSFShapeGroup) patriarch.getChildren().get(0); - assertEquals(group.getX1(), 1); - assertEquals(group.getY1(), 2); - assertEquals(group.getX2(), 3); - assertEquals(group.getY2(), 4); - } - - public void testAddToExistingFile(){ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sh = wb.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - HSSFShapeGroup group1 = patriarch.createGroup(new HSSFClientAnchor()); - HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); - - group1.setCoordinates(1,2,3,4); - group2.setCoordinates(5,6,7,8); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - assertEquals(patriarch.getChildren().size(), 2); - - HSSFShapeGroup group3 = patriarch.createGroup(new HSSFClientAnchor()); - group3.setCoordinates(9,10,11,12); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - assertEquals(patriarch.getChildren().size(), 3); - } - - public void testModify() throws Exception { - HSSFWorkbook wb = new HSSFWorkbook(); - - // create a sheet with a text box - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - - HSSFShapeGroup group1 = patriarch.createGroup(new - HSSFClientAnchor(0,0,0,0, - (short)0, 0, (short)15, 25)); - group1.setCoordinates(0, 0, 792, 612); - - HSSFTextbox textbox1 = group1.createTextbox(new - HSSFChildAnchor(100, 100, 300, 300)); - HSSFRichTextString rt1 = new HSSFRichTextString("Hello, World!"); - textbox1.setString(rt1); - - // write, read back and check that our text box is there - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sheet = wb.getSheetAt(0); - patriarch = sheet.getDrawingPatriarch(); - assertEquals(1, patriarch.getChildren().size()); - - group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); - assertEquals(1, group1.getChildren().size()); - textbox1 = (HSSFTextbox)group1.getChildren().get(0); - assertEquals("Hello, World!", textbox1.getString().getString()); - - // modify anchor - assertEquals(new HSSFChildAnchor(100, 100, 300, 300), - textbox1.getAnchor()); - HSSFChildAnchor newAnchor = new HSSFChildAnchor(200,200, 400, 400); - textbox1.setAnchor(newAnchor); - // modify text - textbox1.setString(new HSSFRichTextString("Hello, World! (modified)")); - - // add a new text box - HSSFTextbox textbox2 = group1.createTextbox(new - HSSFChildAnchor(400, 400, 600, 600)); - HSSFRichTextString rt2 = new HSSFRichTextString("Hello, World-2"); - textbox2.setString(rt2); - assertEquals(2, group1.getChildren().size()); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sheet = wb.getSheetAt(0); - patriarch = sheet.getDrawingPatriarch(); - assertEquals(1, patriarch.getChildren().size()); - - group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); - assertEquals(2, group1.getChildren().size()); - textbox1 = (HSSFTextbox)group1.getChildren().get(0); - assertEquals("Hello, World! (modified)", - textbox1.getString().getString()); - assertEquals(new HSSFChildAnchor(200,200, 400, 400), - textbox1.getAnchor()); - - textbox2 = (HSSFTextbox)group1.getChildren().get(1); - assertEquals("Hello, World-2", textbox2.getString().getString()); - assertEquals(new HSSFChildAnchor(400, 400, 600, 600), - textbox2.getAnchor()); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sheet = wb.getSheetAt(0); - patriarch = sheet.getDrawingPatriarch(); - group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); - textbox1 = (HSSFTextbox)group1.getChildren().get(0); - textbox2 = (HSSFTextbox)group1.getChildren().get(1); - HSSFTextbox textbox3 = group1.createTextbox(new - HSSFChildAnchor(400,200, 600, 400)); - HSSFRichTextString rt3 = new HSSFRichTextString("Hello, World-3"); - textbox3.setString(rt3); - } - - public void testAddShapesToGroup(){ - HSSFWorkbook wb = new HSSFWorkbook(); - - // create a sheet with a text box - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - - HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); - int index = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_JPEG); - group.createPicture(new HSSFChildAnchor(), index); - HSSFPolygon polygon = group.createPolygon(new HSSFChildAnchor()); - polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); - group.createTextbox(new HSSFChildAnchor()); - group.createShape(new HSSFChildAnchor()); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sheet = wb.getSheetAt(0); - patriarch = sheet.getDrawingPatriarch(); - assertEquals(1, patriarch.getChildren().size()); - - assertTrue(patriarch.getChildren().get(0) instanceof HSSFShapeGroup); - group = (HSSFShapeGroup) patriarch.getChildren().get(0); - - assertEquals(group.getChildren().size(), 4); - - assertTrue(group.getChildren().get(0) instanceof HSSFPicture); - assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); - assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); - assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); - - HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); - - index = wb.addPicture(new byte[]{2,2,2}, HSSFWorkbook.PICTURE_TYPE_JPEG); - group2.createPicture(new HSSFChildAnchor(), index); - polygon = group2.createPolygon(new HSSFChildAnchor()); - polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); - group2.createTextbox(new HSSFChildAnchor()); - group2.createShape(new HSSFChildAnchor()); - group2.createShape(new HSSFChildAnchor()); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sheet = wb.getSheetAt(0); - patriarch = sheet.getDrawingPatriarch(); - assertEquals(2, patriarch.getChildren().size()); - - group = (HSSFShapeGroup) patriarch.getChildren().get(1); - - assertEquals(group.getChildren().size(), 5); - - assertTrue(group.getChildren().get(0) instanceof HSSFPicture); - assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); - assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); - assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); - assertTrue(group.getChildren().get(4) instanceof HSSFSimpleShape); - - group.getShapeId(); - } - - public void testSpgrRecord(){ - HSSFWorkbook wb = new HSSFWorkbook(); - - // create a sheet with a text box - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - - HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); - assertSame(((EscherContainerRecord)group.getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID), getSpgrRecord(group)); - } - - private static EscherSpgrRecord getSpgrRecord(HSSFShapeGroup group) { - return POITestCase.getFieldValue(HSSFShapeGroup.class, group, EscherSpgrRecord.class, "_spgrRecord"); - } - - public void testClearShapes(){ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); - - group.createShape(new HSSFChildAnchor()); - group.createShape(new HSSFChildAnchor()); - - EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); - - assertEquals(agg.getShapeToObjMapping().size(), 5); - assertEquals(agg.getTailRecords().size(), 0); - assertEquals(group.getChildren().size(), 2); - - group.clear(); - - assertEquals(agg.getShapeToObjMapping().size(), 1); - assertEquals(agg.getTailRecords().size(), 0); - assertEquals(group.getChildren().size(), 0); - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sheet = wb.getSheetAt(0); - patriarch = sheet.getDrawingPatriarch(); - - group = (HSSFShapeGroup) patriarch.getChildren().get(0); - - assertEquals(agg.getShapeToObjMapping().size(), 1); - assertEquals(agg.getTailRecords().size(), 0); - assertEquals(group.getChildren().size(), 0); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.POITestCase; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherSpgrRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.EscherAggregate; + +import junit.framework.TestCase; + +/** + * @author Evgeniy Berlog + * @date 29.06.12 + */ +public class TestShapeGroup extends TestCase{ + + public void testSetGetCoordinates(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + assertEquals(group.getX1(), 0); + assertEquals(group.getY1(), 0); + assertEquals(group.getX2(), 1023); + assertEquals(group.getY2(), 255); + + group.setCoordinates(1,2,3,4); + + assertEquals(group.getX1(), 1); + assertEquals(group.getY1(), 2); + assertEquals(group.getX2(), 3); + assertEquals(group.getY2(), 4); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + assertEquals(group.getX1(), 1); + assertEquals(group.getY1(), 2); + assertEquals(group.getX2(), 3); + assertEquals(group.getY2(), 4); + } + + public void testAddToExistingFile(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFShapeGroup group1 = patriarch.createGroup(new HSSFClientAnchor()); + HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); + + group1.setCoordinates(1,2,3,4); + group2.setCoordinates(5,6,7,8); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + + HSSFShapeGroup group3 = patriarch.createGroup(new HSSFClientAnchor()); + group3.setCoordinates(9,10,11,12); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + } + + public void testModify() throws Exception { + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group1 = patriarch.createGroup(new + HSSFClientAnchor(0,0,0,0, + (short)0, 0, (short)15, 25)); + group1.setCoordinates(0, 0, 792, 612); + + HSSFTextbox textbox1 = group1.createTextbox(new + HSSFChildAnchor(100, 100, 300, 300)); + HSSFRichTextString rt1 = new HSSFRichTextString("Hello, World!"); + textbox1.setString(rt1); + + // write, read back and check that our text box is there + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + assertEquals(1, group1.getChildren().size()); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + assertEquals("Hello, World!", textbox1.getString().getString()); + + // modify anchor + assertEquals(new HSSFChildAnchor(100, 100, 300, 300), + textbox1.getAnchor()); + HSSFChildAnchor newAnchor = new HSSFChildAnchor(200,200, 400, 400); + textbox1.setAnchor(newAnchor); + // modify text + textbox1.setString(new HSSFRichTextString("Hello, World! (modified)")); + + // add a new text box + HSSFTextbox textbox2 = group1.createTextbox(new + HSSFChildAnchor(400, 400, 600, 600)); + HSSFRichTextString rt2 = new HSSFRichTextString("Hello, World-2"); + textbox2.setString(rt2); + assertEquals(2, group1.getChildren().size()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + assertEquals(2, group1.getChildren().size()); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + assertEquals("Hello, World! (modified)", + textbox1.getString().getString()); + assertEquals(new HSSFChildAnchor(200,200, 400, 400), + textbox1.getAnchor()); + + textbox2 = (HSSFTextbox)group1.getChildren().get(1); + assertEquals("Hello, World-2", textbox2.getString().getString()); + assertEquals(new HSSFChildAnchor(400, 400, 600, 600), + textbox2.getAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + textbox2 = (HSSFTextbox)group1.getChildren().get(1); + HSSFTextbox textbox3 = group1.createTextbox(new + HSSFChildAnchor(400,200, 600, 400)); + HSSFRichTextString rt3 = new HSSFRichTextString("Hello, World-3"); + textbox3.setString(rt3); + } + + public void testAddShapesToGroup(){ + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + int index = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_JPEG); + group.createPicture(new HSSFChildAnchor(), index); + HSSFPolygon polygon = group.createPolygon(new HSSFChildAnchor()); + polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); + group.createTextbox(new HSSFChildAnchor()); + group.createShape(new HSSFChildAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + assertTrue(patriarch.getChildren().get(0) instanceof HSSFShapeGroup); + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + + assertEquals(group.getChildren().size(), 4); + + assertTrue(group.getChildren().get(0) instanceof HSSFPicture); + assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); + assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); + assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); + + HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); + + index = wb.addPicture(new byte[]{2,2,2}, HSSFWorkbook.PICTURE_TYPE_JPEG); + group2.createPicture(new HSSFChildAnchor(), index); + polygon = group2.createPolygon(new HSSFChildAnchor()); + polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); + group2.createTextbox(new HSSFChildAnchor()); + group2.createShape(new HSSFChildAnchor()); + group2.createShape(new HSSFChildAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(2, patriarch.getChildren().size()); + + group = (HSSFShapeGroup) patriarch.getChildren().get(1); + + assertEquals(group.getChildren().size(), 5); + + assertTrue(group.getChildren().get(0) instanceof HSSFPicture); + assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); + assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); + assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); + assertTrue(group.getChildren().get(4) instanceof HSSFSimpleShape); + + group.getShapeId(); + } + + public void testSpgrRecord(){ + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + assertSame(((EscherContainerRecord)group.getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID), getSpgrRecord(group)); + } + + private static EscherSpgrRecord getSpgrRecord(HSSFShapeGroup group) { + return POITestCase.getFieldValue(HSSFShapeGroup.class, group, EscherSpgrRecord.class, "_spgrRecord"); + } + + public void testClearShapes(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + + group.createShape(new HSSFChildAnchor()); + group.createShape(new HSSFChildAnchor()); + + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); + + assertEquals(agg.getShapeToObjMapping().size(), 5); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(group.getChildren().size(), 2); + + group.clear(); + + assertEquals(agg.getShapeToObjMapping().size(), 1); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(group.getChildren().size(), 0); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + + assertEquals(agg.getShapeToObjMapping().size(), 1); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(group.getChildren().size(), 0); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java index cb8f1d4bd5..bb16cf9879 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java @@ -1,214 +1,214 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.usermodel; - -import static org.apache.poi.poifs.storage.RawDataUtil.decompress; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.TextObjectRecord; -import org.junit.Test; - -/** - * @author Evgeniy Berlog - * @date 25.06.12 - */ -public class TestText { - - @Test - public void testResultEqualsToNonExistingAbstractShape() throws IOException { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sh = wb.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); - - assertEquals(textbox.getEscherContainer().getChildRecords().size(), 5); - - //sp record - byte[] expected = decompress("H4sIAAAAAAAAAFvEw/WBg4GBgZEFSHAxMAAA9gX7nhAAAAA="); - byte[] actual = textbox.getEscherContainer().getChild(0).serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - expected = decompress("H4sIAAAAAAAAAGNgEPggxIANAABK4+laGgAAAA=="); - actual = textbox.getEscherContainer().getChild(2).serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - expected = decompress("H4sIAAAAAAAAAGNgEPzAAAQACl6c5QgAAAA="); - actual = textbox.getEscherContainer().getChild(3).serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - expected = decompress("H4sIAAAAAAAAAGNg4P3AAAQA6pyIkQgAAAA="); - actual = textbox.getEscherContainer().getChild(4).serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - ObjRecord obj = textbox.getObjRecord(); - - expected = decompress("H4sIAAAAAAAAAItlkGIQZRBiYGNgZBBMYEADAOdCLuweAAAA"); - actual = obj.serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - TextObjectRecord tor = textbox.getTextObjectRecord(); - - expected = decompress("H4sIAAAAAAAAANvGKMQgxMSABgBGi8T+FgAAAA=="); - actual = tor.serialize(); - - assertEquals(expected.length, actual.length); - assertArrayEquals(expected, actual); - - wb.close(); - } - - @Test - public void testAddTextToExistingFile() throws Exception { - HSSFWorkbook wb1 = new HSSFWorkbook(); - HSSFSheet sh = wb1.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); - textbox.setString(new HSSFRichTextString("just for test")); - HSSFTextbox textbox2 = patriarch.createTextbox(new HSSFClientAnchor()); - textbox2.setString(new HSSFRichTextString("just for test2")); - - assertEquals(patriarch.getChildren().size(), 2); - - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); - wb1.close(); - sh = wb2.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - assertEquals(patriarch.getChildren().size(), 2); - HSSFTextbox text3 = patriarch.createTextbox(new HSSFClientAnchor()); - text3.setString(new HSSFRichTextString("text3")); - assertEquals(patriarch.getChildren().size(), 3); - - HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); - wb2.close(); - sh = wb3.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - - assertEquals(patriarch.getChildren().size(), 3); - assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test"); - assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2"); - assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3"); - - wb3.close(); - } - - @Test - public void testSetGetProperties() throws Exception { - HSSFWorkbook wb1 = new HSSFWorkbook(); - HSSFSheet sh = wb1.createSheet(); - HSSFPatriarch patriarch = sh.createDrawingPatriarch(); - HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); - textbox.setString(new HSSFRichTextString("test")); - assertEquals(textbox.getString().getString(), "test"); - - textbox.setHorizontalAlignment((short) 5); - assertEquals(textbox.getHorizontalAlignment(), 5); - - textbox.setVerticalAlignment((short) 6); - assertEquals(textbox.getVerticalAlignment(), (short) 6); - - textbox.setMarginBottom(7); - assertEquals(textbox.getMarginBottom(), 7); - - textbox.setMarginLeft(8); - assertEquals(textbox.getMarginLeft(), 8); - - textbox.setMarginRight(9); - assertEquals(textbox.getMarginRight(), 9); - - textbox.setMarginTop(10); - assertEquals(textbox.getMarginTop(), 10); - - HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); - wb1.close(); - sh = wb2.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - textbox = (HSSFTextbox) patriarch.getChildren().get(0); - assertEquals(textbox.getString().getString(), "test"); - assertEquals(textbox.getHorizontalAlignment(), 5); - assertEquals(textbox.getVerticalAlignment(), (short) 6); - assertEquals(textbox.getMarginBottom(), 7); - assertEquals(textbox.getMarginLeft(), 8); - assertEquals(textbox.getMarginRight(), 9); - assertEquals(textbox.getMarginTop(), 10); - - textbox.setString(new HSSFRichTextString("test1")); - textbox.setHorizontalAlignment(HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); - textbox.setVerticalAlignment(HSSFTextbox.VERTICAL_ALIGNMENT_TOP); - textbox.setMarginBottom(71); - textbox.setMarginLeft(81); - textbox.setMarginRight(91); - textbox.setMarginTop(101); - - assertEquals(textbox.getString().getString(), "test1"); - assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); - assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); - assertEquals(textbox.getMarginBottom(), 71); - assertEquals(textbox.getMarginLeft(), 81); - assertEquals(textbox.getMarginRight(), 91); - assertEquals(textbox.getMarginTop(), 101); - - HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); - wb2.close(); - sh = wb3.getSheetAt(0); - patriarch = sh.getDrawingPatriarch(); - textbox = (HSSFTextbox) patriarch.getChildren().get(0); - - assertEquals(textbox.getString().getString(), "test1"); - assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); - assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); - assertEquals(textbox.getMarginBottom(), 71); - assertEquals(textbox.getMarginLeft(), 81); - assertEquals(textbox.getMarginRight(), 91); - assertEquals(textbox.getMarginTop(), 101); - - wb3.close(); - } - - @Test - public void testExistingFileWithText() throws Exception { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); - HSSFSheet sheet = wb.getSheet("text"); - HSSFPatriarch drawing = sheet.getDrawingPatriarch(); - assertEquals(1, drawing.getChildren().size()); - HSSFTextbox textbox = (HSSFTextbox) drawing.getChildren().get(0); - assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_LEFT); - assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); - assertEquals(textbox.getMarginTop(), 0); - assertEquals(textbox.getMarginBottom(), 3600000); - assertEquals(textbox.getMarginLeft(), 3600000); - assertEquals(textbox.getMarginRight(), 0); - assertEquals(textbox.getString().getString(), "teeeeesssstttt"); - wb.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import static org.apache.poi.poifs.storage.RawDataUtil.decompress; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.TextObjectRecord; +import org.junit.Test; + +/** + * @author Evgeniy Berlog + * @date 25.06.12 + */ +public class TestText { + + @Test + public void testResultEqualsToNonExistingAbstractShape() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + + assertEquals(textbox.getEscherContainer().getChildRecords().size(), 5); + + //sp record + byte[] expected = decompress("H4sIAAAAAAAAAFvEw/WBg4GBgZEFSHAxMAAA9gX7nhAAAAA="); + byte[] actual = textbox.getEscherContainer().getChild(0).serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + expected = decompress("H4sIAAAAAAAAAGNgEPggxIANAABK4+laGgAAAA=="); + actual = textbox.getEscherContainer().getChild(2).serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + expected = decompress("H4sIAAAAAAAAAGNgEPzAAAQACl6c5QgAAAA="); + actual = textbox.getEscherContainer().getChild(3).serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + expected = decompress("H4sIAAAAAAAAAGNg4P3AAAQA6pyIkQgAAAA="); + actual = textbox.getEscherContainer().getChild(4).serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + ObjRecord obj = textbox.getObjRecord(); + + expected = decompress("H4sIAAAAAAAAAItlkGIQZRBiYGNgZBBMYEADAOdCLuweAAAA"); + actual = obj.serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + TextObjectRecord tor = textbox.getTextObjectRecord(); + + expected = decompress("H4sIAAAAAAAAANvGKMQgxMSABgBGi8T+FgAAAA=="); + actual = tor.serialize(); + + assertEquals(expected.length, actual.length); + assertArrayEquals(expected, actual); + + wb.close(); + } + + @Test + public void testAddTextToExistingFile() throws Exception { + HSSFWorkbook wb1 = new HSSFWorkbook(); + HSSFSheet sh = wb1.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + textbox.setString(new HSSFRichTextString("just for test")); + HSSFTextbox textbox2 = patriarch.createTextbox(new HSSFClientAnchor()); + textbox2.setString(new HSSFRichTextString("just for test2")); + + assertEquals(patriarch.getChildren().size(), 2); + + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); + wb1.close(); + sh = wb2.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + HSSFTextbox text3 = patriarch.createTextbox(new HSSFClientAnchor()); + text3.setString(new HSSFRichTextString("text3")); + assertEquals(patriarch.getChildren().size(), 3); + + HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); + wb2.close(); + sh = wb3.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test"); + assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2"); + assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3"); + + wb3.close(); + } + + @Test + public void testSetGetProperties() throws Exception { + HSSFWorkbook wb1 = new HSSFWorkbook(); + HSSFSheet sh = wb1.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + textbox.setString(new HSSFRichTextString("test")); + assertEquals(textbox.getString().getString(), "test"); + + textbox.setHorizontalAlignment((short) 5); + assertEquals(textbox.getHorizontalAlignment(), 5); + + textbox.setVerticalAlignment((short) 6); + assertEquals(textbox.getVerticalAlignment(), (short) 6); + + textbox.setMarginBottom(7); + assertEquals(textbox.getMarginBottom(), 7); + + textbox.setMarginLeft(8); + assertEquals(textbox.getMarginLeft(), 8); + + textbox.setMarginRight(9); + assertEquals(textbox.getMarginRight(), 9); + + textbox.setMarginTop(10); + assertEquals(textbox.getMarginTop(), 10); + + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1); + wb1.close(); + sh = wb2.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + textbox = (HSSFTextbox) patriarch.getChildren().get(0); + assertEquals(textbox.getString().getString(), "test"); + assertEquals(textbox.getHorizontalAlignment(), 5); + assertEquals(textbox.getVerticalAlignment(), (short) 6); + assertEquals(textbox.getMarginBottom(), 7); + assertEquals(textbox.getMarginLeft(), 8); + assertEquals(textbox.getMarginRight(), 9); + assertEquals(textbox.getMarginTop(), 10); + + textbox.setString(new HSSFRichTextString("test1")); + textbox.setHorizontalAlignment(HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); + textbox.setVerticalAlignment(HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + textbox.setMarginBottom(71); + textbox.setMarginLeft(81); + textbox.setMarginRight(91); + textbox.setMarginTop(101); + + assertEquals(textbox.getString().getString(), "test1"); + assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); + assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + assertEquals(textbox.getMarginBottom(), 71); + assertEquals(textbox.getMarginLeft(), 81); + assertEquals(textbox.getMarginRight(), 91); + assertEquals(textbox.getMarginTop(), 101); + + HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2); + wb2.close(); + sh = wb3.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + textbox = (HSSFTextbox) patriarch.getChildren().get(0); + + assertEquals(textbox.getString().getString(), "test1"); + assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); + assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + assertEquals(textbox.getMarginBottom(), 71); + assertEquals(textbox.getMarginLeft(), 81); + assertEquals(textbox.getMarginRight(), 91); + assertEquals(textbox.getMarginTop(), 101); + + wb3.close(); + } + + @Test + public void testExistingFileWithText() throws Exception { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("text"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + HSSFTextbox textbox = (HSSFTextbox) drawing.getChildren().get(0); + assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_LEFT); + assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + assertEquals(textbox.getMarginTop(), 0); + assertEquals(textbox.getMarginBottom(), 3600000); + assertEquals(textbox.getMarginLeft(), 3600000); + assertEquals(textbox.getMarginRight(), 0); + assertEquals(textbox.getString().getString(), "teeeeesssstttt"); + wb.close(); + } +} diff --git a/src/testcases/org/apache/poi/poifs/crypt/TestXorEncryption.java b/src/testcases/org/apache/poi/poifs/crypt/TestXorEncryption.java index 7b35fef8cb..20dec4552f 100644 --- a/src/testcases/org/apache/poi/poifs/crypt/TestXorEncryption.java +++ b/src/testcases/org/apache/poi/poifs/crypt/TestXorEncryption.java @@ -1,75 +1,75 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.poifs.crypt; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -import java.io.IOException; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.util.HexRead; -import org.junit.After; -import org.junit.Test; - -public class TestXorEncryption { - - private static final HSSFTestDataSamples samples = new HSSFTestDataSamples(); - - // to not affect other tests running in the same JVM - @After - public void resetPassword() { - Biff8EncryptionKey.setCurrentUserPassword(null); - } - - @Test - public void testXorEncryption() throws IOException { - // Xor-Password: abc - // 2.5.343 XORObfuscation - // key = 20810 - // verifier = 52250 - int verifier = CryptoFunctions.createXorVerifier1("abc"); - int key = CryptoFunctions.createXorKey1("abc"); - assertEquals(20810, key); - assertEquals(52250, verifier); - - byte xorArrAct[] = CryptoFunctions.createXorArray1("abc"); - byte xorArrExp[] = HexRead.readFromString("AC-CC-A4-AB-D6-BA-C3-BA-D6-A3-2B-45-D3-79-29-BB"); - assertThat(xorArrExp, equalTo(xorArrAct)); - } - - @SuppressWarnings("static-access") - @Test - public void testUserFile() throws IOException { - Biff8EncryptionKey.setCurrentUserPassword("abc"); - NPOIFSFileSystem fs = new NPOIFSFileSystem(samples.getSampleFile("xor-encryption-abc.xls"), true); - HSSFWorkbook hwb = new HSSFWorkbook(fs.getRoot(), true); - - HSSFSheet sh = hwb.getSheetAt(0); - assertEquals(1.0, sh.getRow(0).getCell(0).getNumericCellValue(), 0.0); - assertEquals(2.0, sh.getRow(1).getCell(0).getNumericCellValue(), 0.0); - assertEquals(3.0, sh.getRow(2).getCell(0).getNumericCellValue(), 0.0); - hwb.close(); - fs.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.IOException; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.util.HexRead; +import org.junit.After; +import org.junit.Test; + +public class TestXorEncryption { + + private static final HSSFTestDataSamples samples = new HSSFTestDataSamples(); + + // to not affect other tests running in the same JVM + @After + public void resetPassword() { + Biff8EncryptionKey.setCurrentUserPassword(null); + } + + @Test + public void testXorEncryption() throws IOException { + // Xor-Password: abc + // 2.5.343 XORObfuscation + // key = 20810 + // verifier = 52250 + int verifier = CryptoFunctions.createXorVerifier1("abc"); + int key = CryptoFunctions.createXorKey1("abc"); + assertEquals(20810, key); + assertEquals(52250, verifier); + + byte xorArrAct[] = CryptoFunctions.createXorArray1("abc"); + byte xorArrExp[] = HexRead.readFromString("AC-CC-A4-AB-D6-BA-C3-BA-D6-A3-2B-45-D3-79-29-BB"); + assertThat(xorArrExp, equalTo(xorArrAct)); + } + + @SuppressWarnings("static-access") + @Test + public void testUserFile() throws IOException { + Biff8EncryptionKey.setCurrentUserPassword("abc"); + NPOIFSFileSystem fs = new NPOIFSFileSystem(samples.getSampleFile("xor-encryption-abc.xls"), true); + HSSFWorkbook hwb = new HSSFWorkbook(fs.getRoot(), true); + + HSSFSheet sh = hwb.getSheetAt(0); + assertEquals(1.0, sh.getRow(0).getCell(0).getNumericCellValue(), 0.0); + assertEquals(2.0, sh.getRow(1).getCell(0).getNumericCellValue(), 0.0); + assertEquals(3.0, sh.getRow(2).getCell(0).getNumericCellValue(), 0.0); + hwb.close(); + fs.close(); + } +} diff --git a/src/testcases/org/apache/poi/sl/TestCommonSL.java b/src/testcases/org/apache/poi/sl/TestCommonSL.java index ab27ca42e1..bb04ad71cb 100644 --- a/src/testcases/org/apache/poi/sl/TestCommonSL.java +++ b/src/testcases/org/apache/poi/sl/TestCommonSL.java @@ -1,38 +1,38 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.sl; - -import java.awt.Color; - -import org.apache.poi.sl.draw.DrawPaint; -import org.apache.poi.sl.usermodel.PaintStyle; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.junit.Ignore; - -/** - * Currently only contains helper methods - */ -@Ignore -public class TestCommonSL { - - public static boolean sameColor(Color colorExpected, PaintStyle paintActual) { - if (!(paintActual instanceof SolidPaint)) return false; - Color thisC = DrawPaint.applyColorTransform(((SolidPaint)paintActual).getSolidColor()); - return thisC.equals(colorExpected); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.sl; + +import java.awt.Color; + +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.junit.Ignore; + +/** + * Currently only contains helper methods + */ +@Ignore +public class TestCommonSL { + + public static boolean sameColor(Color colorExpected, PaintStyle paintActual) { + if (!(paintActual instanceof SolidPaint)) return false; + Color thisC = DrawPaint.applyColorTransform(((SolidPaint)paintActual).getSolidColor()); + return thisC.equals(colorExpected); + } + +} diff --git a/src/testcases/org/apache/poi/ss/formula/TestMissingWorkbook.java b/src/testcases/org/apache/poi/ss/formula/TestMissingWorkbook.java index 304dafffb2..3e467b2bef 100644 --- a/src/testcases/org/apache/poi/ss/formula/TestMissingWorkbook.java +++ b/src/testcases/org/apache/poi/ss/formula/TestMissingWorkbook.java @@ -1,133 +1,133 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.formula; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import junit.framework.TestCase; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.FormulaEvaluator; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; - -public class TestMissingWorkbook extends TestCase { - protected Workbook mainWorkbook; - protected Workbook sourceWorkbook; - - protected final String MAIN_WORKBOOK_FILENAME; - protected final String SOURCE_DUMMY_WORKBOOK_FILENAME; - protected final String SOURCE_WORKBOOK_FILENAME; - - public TestMissingWorkbook() { - this("52575_main.xls", "source_dummy.xls", "52575_source.xls"); - } - protected TestMissingWorkbook(String MAIN_WORKBOOK_FILENAME, - String SOURCE_DUMMY_WORKBOOK_FILENAME, String SOURCE_WORKBOOK_FILENAME) { - this.MAIN_WORKBOOK_FILENAME = MAIN_WORKBOOK_FILENAME; - this.SOURCE_DUMMY_WORKBOOK_FILENAME = SOURCE_DUMMY_WORKBOOK_FILENAME; - this.SOURCE_WORKBOOK_FILENAME = SOURCE_WORKBOOK_FILENAME; - } - - @Override - protected void setUp() throws Exception { - mainWorkbook = HSSFTestDataSamples.openSampleWorkbook(MAIN_WORKBOOK_FILENAME); - sourceWorkbook = HSSFTestDataSamples.openSampleWorkbook(SOURCE_WORKBOOK_FILENAME); - - assertNotNull(mainWorkbook); - assertNotNull(sourceWorkbook); - } - - public void testMissingWorkbookMissing() throws IOException { - FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator(); - - Sheet lSheet = mainWorkbook.getSheetAt(0); - Row lARow = lSheet.getRow(0); - Cell lA1Cell = lARow.getCell(0); - - assertEquals(CellType.FORMULA, lA1Cell.getCellTypeEnum()); - try { - evaluator.evaluateFormulaCellEnum(lA1Cell); - fail("Missing external workbook reference exception expected!"); - }catch(RuntimeException re) { - assertTrue("Unexpected exception: " + re, re.getMessage().indexOf(SOURCE_DUMMY_WORKBOOK_FILENAME) != -1); - } - } - - public void testMissingWorkbookMissingOverride() throws IOException { - Sheet lSheet = mainWorkbook.getSheetAt(0); - Cell lA1Cell = lSheet.getRow(0).getCell(0); - Cell lB1Cell = lSheet.getRow(1).getCell(0); - Cell lC1Cell = lSheet.getRow(2).getCell(0); - - assertEquals(CellType.FORMULA, lA1Cell.getCellTypeEnum()); - assertEquals(CellType.FORMULA, lB1Cell.getCellTypeEnum()); - assertEquals(CellType.FORMULA, lC1Cell.getCellTypeEnum()); - - // Check cached values - assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d); - assertEquals("POI rocks!", lB1Cell.getStringCellValue()); - assertEquals(true, lC1Cell.getBooleanCellValue()); - - // Evaluate - FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator(); - evaluator.setIgnoreMissingWorkbooks(true); - - assertEquals(CellType.NUMERIC, evaluator.evaluateFormulaCellEnum(lA1Cell)); - assertEquals(CellType.STRING, evaluator.evaluateFormulaCellEnum(lB1Cell)); - assertEquals(CellType.BOOLEAN, evaluator.evaluateFormulaCellEnum(lC1Cell)); - - assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d); - assertEquals("POI rocks!", lB1Cell.getStringCellValue()); - assertEquals(true, lC1Cell.getBooleanCellValue()); - } - - - public void testExistingWorkbook() throws IOException { - Sheet lSheet = mainWorkbook.getSheetAt(0); - Cell lA1Cell = lSheet.getRow(0).getCell(0); - Cell lB1Cell = lSheet.getRow(1).getCell(0); - Cell lC1Cell = lSheet.getRow(2).getCell(0); - - assertEquals(CellType.FORMULA, lA1Cell.getCellTypeEnum()); - assertEquals(CellType.FORMULA, lB1Cell.getCellTypeEnum()); - assertEquals(CellType.FORMULA, lC1Cell.getCellTypeEnum()); - - FormulaEvaluator lMainWorkbookEvaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator(); - FormulaEvaluator lSourceEvaluator = sourceWorkbook.getCreationHelper().createFormulaEvaluator(); - Map workbooks = new HashMap(); - workbooks.put(MAIN_WORKBOOK_FILENAME, lMainWorkbookEvaluator); - workbooks.put(SOURCE_DUMMY_WORKBOOK_FILENAME, lSourceEvaluator); - lMainWorkbookEvaluator.setupReferencedWorkbooks(workbooks); - - assertEquals(CellType.NUMERIC, lMainWorkbookEvaluator.evaluateFormulaCellEnum(lA1Cell)); - assertEquals(CellType.STRING, lMainWorkbookEvaluator.evaluateFormulaCellEnum(lB1Cell)); - assertEquals(CellType.BOOLEAN, lMainWorkbookEvaluator.evaluateFormulaCellEnum(lC1Cell)); - - assertEquals(20.0d, lA1Cell.getNumericCellValue(), 0.00001d); - assertEquals("Apache rocks!", lB1Cell.getStringCellValue()); - assertEquals(false, lC1Cell.getBooleanCellValue()); - } -} +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.formula; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; + +public class TestMissingWorkbook extends TestCase { + protected Workbook mainWorkbook; + protected Workbook sourceWorkbook; + + protected final String MAIN_WORKBOOK_FILENAME; + protected final String SOURCE_DUMMY_WORKBOOK_FILENAME; + protected final String SOURCE_WORKBOOK_FILENAME; + + public TestMissingWorkbook() { + this("52575_main.xls", "source_dummy.xls", "52575_source.xls"); + } + protected TestMissingWorkbook(String MAIN_WORKBOOK_FILENAME, + String SOURCE_DUMMY_WORKBOOK_FILENAME, String SOURCE_WORKBOOK_FILENAME) { + this.MAIN_WORKBOOK_FILENAME = MAIN_WORKBOOK_FILENAME; + this.SOURCE_DUMMY_WORKBOOK_FILENAME = SOURCE_DUMMY_WORKBOOK_FILENAME; + this.SOURCE_WORKBOOK_FILENAME = SOURCE_WORKBOOK_FILENAME; + } + + @Override + protected void setUp() throws Exception { + mainWorkbook = HSSFTestDataSamples.openSampleWorkbook(MAIN_WORKBOOK_FILENAME); + sourceWorkbook = HSSFTestDataSamples.openSampleWorkbook(SOURCE_WORKBOOK_FILENAME); + + assertNotNull(mainWorkbook); + assertNotNull(sourceWorkbook); + } + + public void testMissingWorkbookMissing() throws IOException { + FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator(); + + Sheet lSheet = mainWorkbook.getSheetAt(0); + Row lARow = lSheet.getRow(0); + Cell lA1Cell = lARow.getCell(0); + + assertEquals(CellType.FORMULA, lA1Cell.getCellTypeEnum()); + try { + evaluator.evaluateFormulaCellEnum(lA1Cell); + fail("Missing external workbook reference exception expected!"); + }catch(RuntimeException re) { + assertTrue("Unexpected exception: " + re, re.getMessage().indexOf(SOURCE_DUMMY_WORKBOOK_FILENAME) != -1); + } + } + + public void testMissingWorkbookMissingOverride() throws IOException { + Sheet lSheet = mainWorkbook.getSheetAt(0); + Cell lA1Cell = lSheet.getRow(0).getCell(0); + Cell lB1Cell = lSheet.getRow(1).getCell(0); + Cell lC1Cell = lSheet.getRow(2).getCell(0); + + assertEquals(CellType.FORMULA, lA1Cell.getCellTypeEnum()); + assertEquals(CellType.FORMULA, lB1Cell.getCellTypeEnum()); + assertEquals(CellType.FORMULA, lC1Cell.getCellTypeEnum()); + + // Check cached values + assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d); + assertEquals("POI rocks!", lB1Cell.getStringCellValue()); + assertEquals(true, lC1Cell.getBooleanCellValue()); + + // Evaluate + FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator(); + evaluator.setIgnoreMissingWorkbooks(true); + + assertEquals(CellType.NUMERIC, evaluator.evaluateFormulaCellEnum(lA1Cell)); + assertEquals(CellType.STRING, evaluator.evaluateFormulaCellEnum(lB1Cell)); + assertEquals(CellType.BOOLEAN, evaluator.evaluateFormulaCellEnum(lC1Cell)); + + assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d); + assertEquals("POI rocks!", lB1Cell.getStringCellValue()); + assertEquals(true, lC1Cell.getBooleanCellValue()); + } + + + public void testExistingWorkbook() throws IOException { + Sheet lSheet = mainWorkbook.getSheetAt(0); + Cell lA1Cell = lSheet.getRow(0).getCell(0); + Cell lB1Cell = lSheet.getRow(1).getCell(0); + Cell lC1Cell = lSheet.getRow(2).getCell(0); + + assertEquals(CellType.FORMULA, lA1Cell.getCellTypeEnum()); + assertEquals(CellType.FORMULA, lB1Cell.getCellTypeEnum()); + assertEquals(CellType.FORMULA, lC1Cell.getCellTypeEnum()); + + FormulaEvaluator lMainWorkbookEvaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator(); + FormulaEvaluator lSourceEvaluator = sourceWorkbook.getCreationHelper().createFormulaEvaluator(); + Map workbooks = new HashMap(); + workbooks.put(MAIN_WORKBOOK_FILENAME, lMainWorkbookEvaluator); + workbooks.put(SOURCE_DUMMY_WORKBOOK_FILENAME, lSourceEvaluator); + lMainWorkbookEvaluator.setupReferencedWorkbooks(workbooks); + + assertEquals(CellType.NUMERIC, lMainWorkbookEvaluator.evaluateFormulaCellEnum(lA1Cell)); + assertEquals(CellType.STRING, lMainWorkbookEvaluator.evaluateFormulaCellEnum(lB1Cell)); + assertEquals(CellType.BOOLEAN, lMainWorkbookEvaluator.evaluateFormulaCellEnum(lC1Cell)); + + assertEquals(20.0d, lA1Cell.getNumericCellValue(), 0.00001d); + assertEquals("Apache rocks!", lB1Cell.getStringCellValue()); + assertEquals(false, lC1Cell.getBooleanCellValue()); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/AllSpreadsheetBasedTests.java b/src/testcases/org/apache/poi/ss/formula/functions/AllSpreadsheetBasedTests.java index e2d0095caf..2b34dcf8a4 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/AllSpreadsheetBasedTests.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/AllSpreadsheetBasedTests.java @@ -1,48 +1,48 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -/** - * Direct tests for all implementors of Function. - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - TestCodeFunctionsFromSpreadsheet.class, - TestComplexFunctionsFromSpreadsheet.class, - TestDeltaFunctionsFromSpreadsheet.class, - TestDGetFunctionsFromSpreadsheet.class, - TestDStarFunctionsFromSpreadsheet.class, - TestFactDoubleFunctionsFromSpreadsheet.class, - TestFixedFunctionsFromSpreadsheet.class, - TestImaginaryFunctionsFromSpreadsheet.class, - TestImRealFunctionsFromSpreadsheet.class, - TestIndexFunctionFromSpreadsheet.class, - TestIndirectFunctionFromSpreadsheet.class, - TestLookupFunctionsFromSpreadsheet.class, - TestMatchFunctionsFromSpreadsheet.class, - TestQuotientFunctionsFromSpreadsheet.class, - TestReptFunctionsFromSpreadsheet.class, - TestRomanFunctionsFromSpreadsheet.class, - TestWeekNumFunctionsFromSpreadsheet.class, - TestWeekNumFunctionsFromSpreadsheet2013.class -}) -public class AllSpreadsheetBasedTests { -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Direct tests for all implementors of Function. + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestCodeFunctionsFromSpreadsheet.class, + TestComplexFunctionsFromSpreadsheet.class, + TestDeltaFunctionsFromSpreadsheet.class, + TestDGetFunctionsFromSpreadsheet.class, + TestDStarFunctionsFromSpreadsheet.class, + TestFactDoubleFunctionsFromSpreadsheet.class, + TestFixedFunctionsFromSpreadsheet.class, + TestImaginaryFunctionsFromSpreadsheet.class, + TestImRealFunctionsFromSpreadsheet.class, + TestIndexFunctionFromSpreadsheet.class, + TestIndirectFunctionFromSpreadsheet.class, + TestLookupFunctionsFromSpreadsheet.class, + TestMatchFunctionsFromSpreadsheet.class, + TestQuotientFunctionsFromSpreadsheet.class, + TestReptFunctionsFromSpreadsheet.class, + TestRomanFunctionsFromSpreadsheet.class, + TestWeekNumFunctionsFromSpreadsheet.class, + TestWeekNumFunctionsFromSpreadsheet2013.class +}) +public class AllSpreadsheetBasedTests { +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/BaseTestFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/BaseTestFunctionsFromSpreadsheet.java index e32f3e05bf..2d589217ed 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/BaseTestFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/BaseTestFunctionsFromSpreadsheet.java @@ -1,239 +1,239 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.CellValue; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; - -@RunWith(Parameterized.class) -public abstract class BaseTestFunctionsFromSpreadsheet { - - /** - * This class defines constants for navigating around the test data spreadsheet used for these tests. - */ - interface SS { - /** Name of the test spreadsheet (found in the standard test data folder) */ - - /** Name of the first sheet in the spreadsheet (contains comments) */ - String README_SHEET_NAME = "Read Me"; - - /** Row (zero-based) in each sheet where the evaluation cases start. */ - int START_TEST_CASES_ROW_INDEX = 4; // Row '5' - /** Index of the column that contains the function names */ - int COLUMN_INDEX_MARKER = 0; // Column 'A' - int COLUMN_INDEX_EVALUATION = 1; // Column 'B' - int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C' - int COLUMN_ROW_COMMENT = 3; // Column 'D' - - /** Used to indicate when there are no more test cases on the current sheet */ - String TEST_CASES_END_MARKER = ""; - /** Used to indicate that the test on the current row should be ignored */ - String SKIP_CURRENT_TEST_CASE_MARKER = ""; - - } - - @Parameter(value = 0) - public String testName; - @Parameter(value = 1) - public String filename; - @Parameter(value = 2) - public HSSFSheet sheet; - @Parameter(value = 3) - public int formulasRowIdx; - @Parameter(value = 4) - public HSSFFormulaEvaluator evaluator; - - - - protected static Collection data(Class clazz, String filename) throws Exception { - HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(filename); - confirmReadMeSheet(workbook, clazz); - - List data = new ArrayList(); - - int nSheets = workbook.getNumberOfSheets(); - for(int sheetIdx=1; sheetIdx< nSheets; sheetIdx++) { - HSSFSheet sheet = workbook.getSheetAt(sheetIdx); - processFunctionGroup(data, sheet, SS.START_TEST_CASES_ROW_INDEX, null, filename); - } - - workbook.close(); - - return data; - } - - private static void processFunctionGroup(List data, HSSFSheet sheet, final int startRowIndex, String testFocusFunctionName, String filename) { - HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet.getWorkbook()); - - String currentGroupComment = ""; - final int maxRows = sheet.getLastRowNum()+1; - for(int rowIndex=startRowIndex; rowIndex clazz) { - String firstSheetName = workbook.getSheetName(0); - assertTrue("First sheet's name was '" + firstSheetName + "' but expected '" + SS.README_SHEET_NAME + "'", - firstSheetName.equalsIgnoreCase(SS.README_SHEET_NAME)); - HSSFSheet sheet = workbook.getSheetAt(0); - String specifiedClassName = sheet.getRow(2).getCell(0).getRichStringCellValue().getString(); - assertEquals("Test class name in spreadsheet comment", clazz.getName(), specifiedClassName); - } - - /** - * @return null if cell is missing, empty or blank - */ - private static String getCellTextValue(HSSFRow r, int colIndex, String columnName) { - if(r == null) { - return null; - } - HSSFCell cell = r.getCell(colIndex); - if(cell == null) { - return null; - } - if(cell.getCellTypeEnum() == CellType.BLANK) { - return null; - } - if(cell.getCellTypeEnum() == CellType.STRING) { - return cell.getRichStringCellValue().getString(); - } - - fail("Bad cell type for '" + columnName + "' column: (" - + cell.getCellTypeEnum() + ") row (" + (r.getRowNum() +1) + ")"); - return ""; - } - - private static String formatValue(HSSFCell expecedCell) { - switch (expecedCell.getCellTypeEnum()) { - case BLANK: return ""; - case BOOLEAN: return Boolean.toString(expecedCell.getBooleanCellValue()); - case NUMERIC: return Double.toString(expecedCell.getNumericCellValue()); - case STRING: return expecedCell.getRichStringCellValue().getString(); - default: fail("Unexpected cell type of expected value (" + expecedCell.getCellTypeEnum() + ")"); - } - return ""; - } - - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hssf.util.CellReference; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CellValue; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; + +@RunWith(Parameterized.class) +public abstract class BaseTestFunctionsFromSpreadsheet { + + /** + * This class defines constants for navigating around the test data spreadsheet used for these tests. + */ + interface SS { + /** Name of the test spreadsheet (found in the standard test data folder) */ + + /** Name of the first sheet in the spreadsheet (contains comments) */ + String README_SHEET_NAME = "Read Me"; + + /** Row (zero-based) in each sheet where the evaluation cases start. */ + int START_TEST_CASES_ROW_INDEX = 4; // Row '5' + /** Index of the column that contains the function names */ + int COLUMN_INDEX_MARKER = 0; // Column 'A' + int COLUMN_INDEX_EVALUATION = 1; // Column 'B' + int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C' + int COLUMN_ROW_COMMENT = 3; // Column 'D' + + /** Used to indicate when there are no more test cases on the current sheet */ + String TEST_CASES_END_MARKER = ""; + /** Used to indicate that the test on the current row should be ignored */ + String SKIP_CURRENT_TEST_CASE_MARKER = ""; + + } + + @Parameter(value = 0) + public String testName; + @Parameter(value = 1) + public String filename; + @Parameter(value = 2) + public HSSFSheet sheet; + @Parameter(value = 3) + public int formulasRowIdx; + @Parameter(value = 4) + public HSSFFormulaEvaluator evaluator; + + + + protected static Collection data(Class clazz, String filename) throws Exception { + HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(filename); + confirmReadMeSheet(workbook, clazz); + + List data = new ArrayList(); + + int nSheets = workbook.getNumberOfSheets(); + for(int sheetIdx=1; sheetIdx< nSheets; sheetIdx++) { + HSSFSheet sheet = workbook.getSheetAt(sheetIdx); + processFunctionGroup(data, sheet, SS.START_TEST_CASES_ROW_INDEX, null, filename); + } + + workbook.close(); + + return data; + } + + private static void processFunctionGroup(List data, HSSFSheet sheet, final int startRowIndex, String testFocusFunctionName, String filename) { + HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet.getWorkbook()); + + String currentGroupComment = ""; + final int maxRows = sheet.getLastRowNum()+1; + for(int rowIndex=startRowIndex; rowIndex clazz) { + String firstSheetName = workbook.getSheetName(0); + assertTrue("First sheet's name was '" + firstSheetName + "' but expected '" + SS.README_SHEET_NAME + "'", + firstSheetName.equalsIgnoreCase(SS.README_SHEET_NAME)); + HSSFSheet sheet = workbook.getSheetAt(0); + String specifiedClassName = sheet.getRow(2).getCell(0).getRichStringCellValue().getString(); + assertEquals("Test class name in spreadsheet comment", clazz.getName(), specifiedClassName); + } + + /** + * @return null if cell is missing, empty or blank + */ + private static String getCellTextValue(HSSFRow r, int colIndex, String columnName) { + if(r == null) { + return null; + } + HSSFCell cell = r.getCell(colIndex); + if(cell == null) { + return null; + } + if(cell.getCellTypeEnum() == CellType.BLANK) { + return null; + } + if(cell.getCellTypeEnum() == CellType.STRING) { + return cell.getRichStringCellValue().getString(); + } + + fail("Bad cell type for '" + columnName + "' column: (" + + cell.getCellTypeEnum() + ") row (" + (r.getRowNum() +1) + ")"); + return ""; + } + + private static String formatValue(HSSFCell expecedCell) { + switch (expecedCell.getCellTypeEnum()) { + case BLANK: return ""; + case BOOLEAN: return Boolean.toString(expecedCell.getBooleanCellValue()); + case NUMERIC: return Double.toString(expecedCell.getNumericCellValue()); + case STRING: return expecedCell.getRichStringCellValue().getString(); + default: fail("Unexpected cell type of expected value (" + expecedCell.getCellTypeEnum() + ")"); + } + return ""; + } + + +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/RefEvalImplementation.java b/src/testcases/org/apache/poi/ss/formula/functions/RefEvalImplementation.java index 1a3fc1e62b..05cfdfc8a2 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/RefEvalImplementation.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/RefEvalImplementation.java @@ -1,68 +1,68 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.ss.formula.eval.AreaEval; -import org.apache.poi.ss.formula.eval.RefEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -final class RefEvalImplementation implements RefEval { - - private final ValueEval value; - - public RefEvalImplementation(ValueEval value) { - this.value = value; - } - - @Override - public AreaEval offset(int relFirstRowIx, int relLastRowIx, - int relFirstColIx, int relLastColIx) { - throw new UnsupportedOperationException(); - } - - @Override - public ValueEval getInnerValueEval(int sheetIndex) { - return value; - } - - @Override - public int getNumberOfSheets() { - return 1; - } - - @Override - public int getFirstSheetIndex() { - return 0; - } - - @Override - public int getLastSheetIndex() { - return 0; - } - - @Override - public int getRow() { - throw new UnsupportedOperationException(); - } - - @Override - public int getColumn() { - throw new UnsupportedOperationException(); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.AreaEval; +import org.apache.poi.ss.formula.eval.RefEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +final class RefEvalImplementation implements RefEval { + + private final ValueEval value; + + public RefEvalImplementation(ValueEval value) { + this.value = value; + } + + @Override + public AreaEval offset(int relFirstRowIx, int relLastRowIx, + int relFirstColIx, int relLastColIx) { + throw new UnsupportedOperationException(); + } + + @Override + public ValueEval getInnerValueEval(int sheetIndex) { + return value; + } + + @Override + public int getNumberOfSheets() { + return 1; + } + + @Override + public int getFirstSheetIndex() { + return 0; + } + + @Override + public int getLastSheetIndex() { + return 0; + } + + @Override + public int getRow() { + throw new UnsupportedOperationException(); + } + + @Override + public int getColumn() { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestAddress.java b/src/testcases/org/apache/poi/ss/formula/functions/TestAddress.java index 84c1778f35..527477bbcc 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestAddress.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestAddress.java @@ -1,79 +1,79 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.CellValue; - -import junit.framework.TestCase; - -public final class TestAddress extends TestCase { - - public void testAddress() { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFCell cell = wb.createSheet().createRow(0).createCell(0); - HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); - - String formulaText = "ADDRESS(1,2)"; - confirmResult(fe, cell, formulaText, "$B$1"); - - formulaText = "ADDRESS(1,2,)"; // with explicitly empty third parameter - confirmResult(fe, cell, formulaText, "$B$1"); - - formulaText = "ADDRESS(22,44)"; - confirmResult(fe, cell, formulaText, "$AR$22"); - - formulaText = "ADDRESS(1,1)"; - confirmResult(fe, cell, formulaText, "$A$1"); - - formulaText = "ADDRESS(1,128)"; - confirmResult(fe, cell, formulaText, "$DX$1"); - - formulaText = "ADDRESS(1,512)"; - confirmResult(fe, cell, formulaText, "$SR$1"); - - formulaText = "ADDRESS(1,1000)"; - confirmResult(fe, cell, formulaText, "$ALL$1"); - - formulaText = "ADDRESS(1,10000)"; - confirmResult(fe, cell, formulaText, "$NTP$1"); - - formulaText = "ADDRESS(2,3)"; - confirmResult(fe, cell, formulaText, "$C$2"); - - formulaText = "ADDRESS(2,3,2)"; - confirmResult(fe, cell, formulaText, "C$2"); - - formulaText = "ADDRESS(2,3,2,,\"EXCEL SHEET\")"; - confirmResult(fe, cell, formulaText, "'EXCEL SHEET'!C$2"); - - formulaText = "ADDRESS(2,3,3,TRUE,\"[Book1]Sheet1\")"; - confirmResult(fe, cell, formulaText, "'[Book1]Sheet1'!$C2"); - } - - private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText, - String expectedResult) { - cell.setCellFormula(formulaText); - fe.notifyUpdateCell(cell); - CellValue result = fe.evaluate(cell); - assertEquals(result.getCellTypeEnum(), CellType.STRING); - assertEquals(expectedResult, result.getStringValue()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CellValue; + +import junit.framework.TestCase; + +public final class TestAddress extends TestCase { + + public void testAddress() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFCell cell = wb.createSheet().createRow(0).createCell(0); + HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); + + String formulaText = "ADDRESS(1,2)"; + confirmResult(fe, cell, formulaText, "$B$1"); + + formulaText = "ADDRESS(1,2,)"; // with explicitly empty third parameter + confirmResult(fe, cell, formulaText, "$B$1"); + + formulaText = "ADDRESS(22,44)"; + confirmResult(fe, cell, formulaText, "$AR$22"); + + formulaText = "ADDRESS(1,1)"; + confirmResult(fe, cell, formulaText, "$A$1"); + + formulaText = "ADDRESS(1,128)"; + confirmResult(fe, cell, formulaText, "$DX$1"); + + formulaText = "ADDRESS(1,512)"; + confirmResult(fe, cell, formulaText, "$SR$1"); + + formulaText = "ADDRESS(1,1000)"; + confirmResult(fe, cell, formulaText, "$ALL$1"); + + formulaText = "ADDRESS(1,10000)"; + confirmResult(fe, cell, formulaText, "$NTP$1"); + + formulaText = "ADDRESS(2,3)"; + confirmResult(fe, cell, formulaText, "$C$2"); + + formulaText = "ADDRESS(2,3,2)"; + confirmResult(fe, cell, formulaText, "C$2"); + + formulaText = "ADDRESS(2,3,2,,\"EXCEL SHEET\")"; + confirmResult(fe, cell, formulaText, "'EXCEL SHEET'!C$2"); + + formulaText = "ADDRESS(2,3,3,TRUE,\"[Book1]Sheet1\")"; + confirmResult(fe, cell, formulaText, "'[Book1]Sheet1'!$C2"); + } + + private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText, + String expectedResult) { + cell.setCellFormula(formulaText); + fe.notifyUpdateCell(cell); + CellValue result = fe.evaluate(cell); + assertEquals(result.getCellTypeEnum(), CellType.STRING); + assertEquals(expectedResult, result.getStringValue()); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestClean.java b/src/testcases/org/apache/poi/ss/formula/functions/TestClean.java index e0137aee47..39bb4d0857 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestClean.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestClean.java @@ -1,66 +1,66 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.CellValue; - -import junit.framework.TestCase; - -public final class TestClean extends TestCase { - - public void testClean() { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFCell cell = wb.createSheet().createRow(0).createCell(0); - HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); - - String[] asserts = { - "aniket\u0007\u0017\u0019", "aniket", - "\u0011aniket\u0007\u0017\u0010", "aniket", - "\u0011aniket\u0007\u0017\u007F", "aniket\u007F", - "\u2116aniket\u2211\uFB5E\u2039", "\u2116aniket\u2211\uFB5E\u2039", - }; - - for(int i = 0; i < asserts.length; i+= 2){ - String formulaText = "CLEAN(\"" + asserts[i] + "\")"; - confirmResult(fe, cell, formulaText, asserts[i + 1]); - } - - asserts = new String[] { - "CHAR(7)&\"text\"&CHAR(7)", "text", - "CHAR(7)&\"text\"&CHAR(17)", "text", - "CHAR(181)&\"text\"&CHAR(190)", "\u00B5text\u00BE", - "\"text\"&CHAR(160)&\"'\"", "text\u00A0'", - }; - for(int i = 0; i < asserts.length; i+= 2){ - String formulaText = "CLEAN(" + asserts[i] + ")"; - confirmResult(fe, cell, formulaText, asserts[i + 1]); - } - } - - private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText, - String expectedResult) { - cell.setCellFormula(formulaText); - fe.notifyUpdateCell(cell); - CellValue result = fe.evaluate(cell); - assertEquals(result.getCellTypeEnum(), CellType.STRING); - assertEquals(expectedResult, result.getStringValue()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CellValue; + +import junit.framework.TestCase; + +public final class TestClean extends TestCase { + + public void testClean() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFCell cell = wb.createSheet().createRow(0).createCell(0); + HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); + + String[] asserts = { + "aniket\u0007\u0017\u0019", "aniket", + "\u0011aniket\u0007\u0017\u0010", "aniket", + "\u0011aniket\u0007\u0017\u007F", "aniket\u007F", + "\u2116aniket\u2211\uFB5E\u2039", "\u2116aniket\u2211\uFB5E\u2039", + }; + + for(int i = 0; i < asserts.length; i+= 2){ + String formulaText = "CLEAN(\"" + asserts[i] + "\")"; + confirmResult(fe, cell, formulaText, asserts[i + 1]); + } + + asserts = new String[] { + "CHAR(7)&\"text\"&CHAR(7)", "text", + "CHAR(7)&\"text\"&CHAR(17)", "text", + "CHAR(181)&\"text\"&CHAR(190)", "\u00B5text\u00BE", + "\"text\"&CHAR(160)&\"'\"", "text\u00A0'", + }; + for(int i = 0; i < asserts.length; i+= 2){ + String formulaText = "CLEAN(" + asserts[i] + ")"; + confirmResult(fe, cell, formulaText, asserts[i + 1]); + } + } + + private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText, + String expectedResult) { + cell.setCellFormula(formulaText); + fe.notifyUpdateCell(cell); + CellValue result = fe.evaluate(cell); + assertEquals(result.getCellTypeEnum(), CellType.STRING); + assertEquals(expectedResult, result.getStringValue()); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestCode.java b/src/testcases/org/apache/poi/ss/formula/functions/TestCode.java index 7a83f9c573..6069f40941 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestCode.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestCode.java @@ -1,59 +1,59 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import junit.framework.TestCase; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Tests for {@link Code} - * - * @author cedric dot walter @ gmail dot com - */ -public class TestCode extends TestCase -{ - private static ValueEval invokeValue(String number1) { - ValueEval[] args = new ValueEval[]{new StringEval(number1),}; - return new Code().evaluate(args, -1, -1); - } - - private static void confirmValue(String msg, String number1, String expected) { - ValueEval result = invokeValue(number1); - assertEquals(StringEval.class, result.getClass()); - assertEquals(msg, expected, ((StringEval) result).getStringValue()); - } - - private static void confirmValueError(String msg, String number1, ErrorEval numError) { - ValueEval result = invokeValue(number1); - assertEquals(ErrorEval.class, result.getClass()); - assertEquals(msg, numError, result); - } - - - public void testBasic() { - confirmValue("Displays the numeric code for A (65)", "A", "65"); - confirmValue("Displays the numeric code for the first character in text ABCDEFGHI (65)", "ABCDEFGHI", "65"); - - confirmValue("Displays the numeric code for ! (33)", "!", "33"); - } - - public void testErrors() { - confirmValueError("Empty text", "", ErrorEval.VALUE_INVALID); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import junit.framework.TestCase; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Tests for {@link Code} + * + * @author cedric dot walter @ gmail dot com + */ +public class TestCode extends TestCase +{ + private static ValueEval invokeValue(String number1) { + ValueEval[] args = new ValueEval[]{new StringEval(number1),}; + return new Code().evaluate(args, -1, -1); + } + + private static void confirmValue(String msg, String number1, String expected) { + ValueEval result = invokeValue(number1); + assertEquals(StringEval.class, result.getClass()); + assertEquals(msg, expected, ((StringEval) result).getStringValue()); + } + + private static void confirmValueError(String msg, String number1, ErrorEval numError) { + ValueEval result = invokeValue(number1); + assertEquals(ErrorEval.class, result.getClass()); + assertEquals(msg, numError, result); + } + + + public void testBasic() { + confirmValue("Displays the numeric code for A (65)", "A", "65"); + confirmValue("Displays the numeric code for the first character in text ABCDEFGHI (65)", "ABCDEFGHI", "65"); + + confirmValue("Displays the numeric code for ! (33)", "!", "33"); + } + + public void testErrors() { + confirmValueError("Empty text", "", ErrorEval.VALUE_INVALID); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestCodeFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestCodeFunctionsFromSpreadsheet.java index 3d78d40da6..8cc6ea3b1d 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestCodeFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestCodeFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests CODE() as loaded from a test data spreadsheet.

    - */ -public class TestCodeFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestCodeFunctionsFromSpreadsheet.class, "CodeFunctionTestCaseData.xls"); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests CODE() as loaded from a test data spreadsheet.

    + */ +public class TestCodeFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestCodeFunctionsFromSpreadsheet.class, "CodeFunctionTestCaseData.xls"); + } } \ No newline at end of file diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java b/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java index a371588988..ce1cce91e5 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestComplex.java @@ -1,69 +1,69 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import junit.framework.TestCase; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Tests for {@link Complex} - * - * @author cedric dot walter @ gmail dot com - */ -public class TestComplex extends TestCase -{ - private static ValueEval invokeValue(String real_num, String i_num, String suffix) { - ValueEval[] args = new ValueEval[]{new StringEval(real_num), new StringEval(i_num), new StringEval(suffix)}; - return new Complex().evaluate(args, -1, -1); - } - - private static void confirmValue(String msg, String real_num, String i_num, String suffix, String expected) { - ValueEval result = invokeValue(real_num, i_num, suffix); - assertEquals(StringEval.class, result.getClass()); - assertEquals(msg, expected, ((StringEval) result).getStringValue()); - } - - private static void confirmValueError(String msg, String real_num, String i_num, String suffix, ErrorEval numError) { - ValueEval result = invokeValue(real_num, i_num, suffix); - assertEquals(ErrorEval.class, result.getClass()); - assertEquals(msg, numError, result); - } - - public void testBasic() { - confirmValue("Complex number with 3 and 4 as the real and imaginary coefficients (3 + 4i)", "3","4", "", "3+4i"); - confirmValue("Complex number with 3 and 4 as the real and imaginary coefficients, and j as the suffix (3 + 4j)", "3","4", "j", "3+4j"); - - confirmValue("Complex number with 0 and 1 as the real and imaginary coefficients (i)", "0","1", "", "i"); - confirmValue("Complex number with 1 and 0 as the real and imaginary coefficients (1)", "1","0", "", "1"); - - confirmValue("Complex number with 2 and 3 as the real and imaginary coefficients (2 + 3i)", "2","3", "", "2+3i"); - confirmValue("Complex number with -2 and -3 as the real and imaginary coefficients (-2-3i)", "-2","-3", "", "-2-3i"); - - confirmValue("Complex number with -2 and -3 as the real and imaginary coefficients (-0.5-3.2i)", "-0.5","-3.2", "", "-0.5-3.2i"); - } - - public void testErrors() { - confirmValueError("argument is nonnumeric", "ABCD", "","", ErrorEval.VALUE_INVALID); - confirmValueError("argument is nonnumeric", "1", "ABCD","", ErrorEval.VALUE_INVALID); - confirmValueError("f suffix is neither \"i\" nor \"j\"", "1", "1","k", ErrorEval.VALUE_INVALID); - - confirmValueError("never use \"I\" ", "1", "1","I", ErrorEval.VALUE_INVALID); - confirmValueError("never use \"J\" ", "1", "1","J", ErrorEval.VALUE_INVALID); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import junit.framework.TestCase; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Tests for {@link Complex} + * + * @author cedric dot walter @ gmail dot com + */ +public class TestComplex extends TestCase +{ + private static ValueEval invokeValue(String real_num, String i_num, String suffix) { + ValueEval[] args = new ValueEval[]{new StringEval(real_num), new StringEval(i_num), new StringEval(suffix)}; + return new Complex().evaluate(args, -1, -1); + } + + private static void confirmValue(String msg, String real_num, String i_num, String suffix, String expected) { + ValueEval result = invokeValue(real_num, i_num, suffix); + assertEquals(StringEval.class, result.getClass()); + assertEquals(msg, expected, ((StringEval) result).getStringValue()); + } + + private static void confirmValueError(String msg, String real_num, String i_num, String suffix, ErrorEval numError) { + ValueEval result = invokeValue(real_num, i_num, suffix); + assertEquals(ErrorEval.class, result.getClass()); + assertEquals(msg, numError, result); + } + + public void testBasic() { + confirmValue("Complex number with 3 and 4 as the real and imaginary coefficients (3 + 4i)", "3","4", "", "3+4i"); + confirmValue("Complex number with 3 and 4 as the real and imaginary coefficients, and j as the suffix (3 + 4j)", "3","4", "j", "3+4j"); + + confirmValue("Complex number with 0 and 1 as the real and imaginary coefficients (i)", "0","1", "", "i"); + confirmValue("Complex number with 1 and 0 as the real and imaginary coefficients (1)", "1","0", "", "1"); + + confirmValue("Complex number with 2 and 3 as the real and imaginary coefficients (2 + 3i)", "2","3", "", "2+3i"); + confirmValue("Complex number with -2 and -3 as the real and imaginary coefficients (-2-3i)", "-2","-3", "", "-2-3i"); + + confirmValue("Complex number with -2 and -3 as the real and imaginary coefficients (-0.5-3.2i)", "-0.5","-3.2", "", "-0.5-3.2i"); + } + + public void testErrors() { + confirmValueError("argument is nonnumeric", "ABCD", "","", ErrorEval.VALUE_INVALID); + confirmValueError("argument is nonnumeric", "1", "ABCD","", ErrorEval.VALUE_INVALID); + confirmValueError("f suffix is neither \"i\" nor \"j\"", "1", "1","k", ErrorEval.VALUE_INVALID); + + confirmValueError("never use \"I\" ", "1", "1","I", ErrorEval.VALUE_INVALID); + confirmValueError("never use \"J\" ", "1", "1","J", ErrorEval.VALUE_INVALID); + } } \ No newline at end of file diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestComplexFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestComplexFunctionsFromSpreadsheet.java index 748b0cacd1..760974c283 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestComplexFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestComplexFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests COMPLEX() as loaded from a test data spreadsheet.

    - */ -public class TestComplexFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestComplexFunctionsFromSpreadsheet.class, "ComplexFunctionTestCaseData.xls"); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests COMPLEX() as loaded from a test data spreadsheet.

    + */ +public class TestComplexFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestComplexFunctionsFromSpreadsheet.class, "ComplexFunctionTestCaseData.xls"); + } } \ No newline at end of file diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestDeltaFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestDeltaFunctionsFromSpreadsheet.java index 68b281d4bb..d469f930ab 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestDeltaFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestDeltaFunctionsFromSpreadsheet.java @@ -1,31 +1,31 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests DELTA() as loaded from a test data spreadsheet.

    - */ -public class TestDeltaFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestDeltaFunctionsFromSpreadsheet.class, "DeltaFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests DELTA() as loaded from a test data spreadsheet.

    + */ +public class TestDeltaFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestDeltaFunctionsFromSpreadsheet.class, "DeltaFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestEOMonth.java b/src/testcases/org/apache/poi/ss/formula/functions/TestEOMonth.java index ecaecec6b4..71c49cf753 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestEOMonth.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestEOMonth.java @@ -1,152 +1,152 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Calendar; -import java.util.Date; - -import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.BlankEval; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.FormulaError; -import org.apache.poi.util.LocaleUtil; -import org.junit.Test; - -public class TestEOMonth { - - private static final double BAD_DATE = -1.0; - - private static final double DATE_1900_01_01 = 1.0; - private static final double DATE_1900_01_31 = 31.0; - private static final double DATE_1900_02_28 = 59.0; - private static final double DATE_1902_09_26 = 1000.0; - private static final double DATE_1902_09_30 = 1004.0; - private static final double DATE_2034_06_09 = 49104.0; - private static final double DATE_2034_06_30 = 49125.0; - private static final double DATE_2034_07_31 = 49156.0; - - private final FreeRefFunction eOMonth = EOMonth.instance; - private final OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null); - - @Test - public void testEOMonthProperValues() { - // verify some border-case combinations of startDate and month-increase - checkValue(DATE_1900_01_01, 0, DATE_1900_01_31); - checkValue(DATE_1900_01_01, 1, DATE_1900_02_28); - checkValue(DATE_1902_09_26, 0, DATE_1902_09_30); - checkValue(DATE_2034_06_09, 0, DATE_2034_06_30); - checkValue(DATE_2034_06_09, 1, DATE_2034_07_31); - } - - @Test - public void testEOMonthBadDateValues() { - checkValue(0.0, -2, BAD_DATE); - checkValue(0.0, -3, BAD_DATE); - checkValue(DATE_1900_01_31, -1, BAD_DATE); - } - - private void checkValue(double startDate, int monthInc, double expectedResult) { - ValueEval ve[] = {new NumberEval(startDate), new NumberEval(monthInc)}; - NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); - assertEquals(expectedResult, result.getNumberValue(), 0); - } - - @Test - public void testEOMonthZeroDate() { - NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(0)}, ec); - assertEquals("0 startDate is 1900-01-00", DATE_1900_01_31, result.getNumberValue(), 0); - - result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(1)}, ec); - assertEquals("0 startDate is 1900-01-00", DATE_1900_02_28, result.getNumberValue(), 0); - } - - @Test - public void testEOMonthInvalidArguments() { - ValueEval result = eOMonth.evaluate(new ValueEval[] {new NumberEval(DATE_1902_09_26)}, ec); - assertTrue(result instanceof ErrorEval); - assertEquals(FormulaError.VALUE.getCode(), ((ErrorEval) result).getErrorCode(), 0); - - result = eOMonth.evaluate(new ValueEval[] {new StringEval("a"), new StringEval("b")}, ec); - assertTrue(result instanceof ErrorEval); - assertEquals(FormulaError.VALUE.getCode(), ((ErrorEval) result).getErrorCode(), 0); - } - - @Test - public void checkOffset() { - for (int offset=-12; offset<=12; offset++) { - Calendar cal = LocaleUtil.getLocaleCalendar(); - Date startDate = cal.getTime(); - - cal.add(Calendar.MONTH, offset); - cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); - cal.clear(Calendar.HOUR); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.clear(Calendar.MINUTE); - cal.clear(Calendar.SECOND); - cal.clear(Calendar.MILLISECOND); - Date expDate = cal.getTime(); - - ValueEval ve[] = { - new NumberEval(DateUtil.getExcelDate(startDate)), - new NumberEval(offset) - }; - NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); - Date actDate = DateUtil.getJavaDate(result.getNumberValue()); - - assertEquals(expDate, actDate); - } - } - - @Test - public void testBug56688() { - ValueEval ve[] = {new NumberEval(DATE_1902_09_26), new RefEvalImplementation(new NumberEval(0))}; - NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); - assertEquals(DATE_1902_09_30, result.getNumberValue(), 0); - } - - @Test - public void testRefEvalStartDate() { - ValueEval ve[] = {new RefEvalImplementation(new NumberEval(DATE_1902_09_26)), new NumberEval(0)}; - NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); - assertEquals(DATE_1902_09_30, result.getNumberValue(), 0); - } - - @Test - public void testEOMonthBlankValueEval() { - NumberEval evaluate = (NumberEval) eOMonth.evaluate(new ValueEval[] {BlankEval.instance, new NumberEval(0)}, ec); - assertEquals("Blank is handled as 0", DATE_1900_01_31, evaluate.getNumberValue(), 0); - } - - @Test - public void testEOMonthBlankRefValueEval() { - ValueEval[] ve1 = {new RefEvalImplementation(BlankEval.instance), new NumberEval(1)}; - NumberEval result = (NumberEval) eOMonth.evaluate(ve1, ec); - assertEquals("Blank is handled as 0", DATE_1900_02_28, result.getNumberValue(), 0); - - ValueEval[] ve2 = {new NumberEval(1), new RefEvalImplementation(BlankEval.instance)}; - result = (NumberEval) eOMonth.evaluate(ve2, ec); - assertEquals("Blank is handled as 0", DATE_1900_01_31, result.getNumberValue(), 0); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Calendar; +import java.util.Date; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.BlankEval; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.FormulaError; +import org.apache.poi.util.LocaleUtil; +import org.junit.Test; + +public class TestEOMonth { + + private static final double BAD_DATE = -1.0; + + private static final double DATE_1900_01_01 = 1.0; + private static final double DATE_1900_01_31 = 31.0; + private static final double DATE_1900_02_28 = 59.0; + private static final double DATE_1902_09_26 = 1000.0; + private static final double DATE_1902_09_30 = 1004.0; + private static final double DATE_2034_06_09 = 49104.0; + private static final double DATE_2034_06_30 = 49125.0; + private static final double DATE_2034_07_31 = 49156.0; + + private final FreeRefFunction eOMonth = EOMonth.instance; + private final OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null); + + @Test + public void testEOMonthProperValues() { + // verify some border-case combinations of startDate and month-increase + checkValue(DATE_1900_01_01, 0, DATE_1900_01_31); + checkValue(DATE_1900_01_01, 1, DATE_1900_02_28); + checkValue(DATE_1902_09_26, 0, DATE_1902_09_30); + checkValue(DATE_2034_06_09, 0, DATE_2034_06_30); + checkValue(DATE_2034_06_09, 1, DATE_2034_07_31); + } + + @Test + public void testEOMonthBadDateValues() { + checkValue(0.0, -2, BAD_DATE); + checkValue(0.0, -3, BAD_DATE); + checkValue(DATE_1900_01_31, -1, BAD_DATE); + } + + private void checkValue(double startDate, int monthInc, double expectedResult) { + ValueEval ve[] = {new NumberEval(startDate), new NumberEval(monthInc)}; + NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); + assertEquals(expectedResult, result.getNumberValue(), 0); + } + + @Test + public void testEOMonthZeroDate() { + NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(0)}, ec); + assertEquals("0 startDate is 1900-01-00", DATE_1900_01_31, result.getNumberValue(), 0); + + result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(1)}, ec); + assertEquals("0 startDate is 1900-01-00", DATE_1900_02_28, result.getNumberValue(), 0); + } + + @Test + public void testEOMonthInvalidArguments() { + ValueEval result = eOMonth.evaluate(new ValueEval[] {new NumberEval(DATE_1902_09_26)}, ec); + assertTrue(result instanceof ErrorEval); + assertEquals(FormulaError.VALUE.getCode(), ((ErrorEval) result).getErrorCode(), 0); + + result = eOMonth.evaluate(new ValueEval[] {new StringEval("a"), new StringEval("b")}, ec); + assertTrue(result instanceof ErrorEval); + assertEquals(FormulaError.VALUE.getCode(), ((ErrorEval) result).getErrorCode(), 0); + } + + @Test + public void checkOffset() { + for (int offset=-12; offset<=12; offset++) { + Calendar cal = LocaleUtil.getLocaleCalendar(); + Date startDate = cal.getTime(); + + cal.add(Calendar.MONTH, offset); + cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); + cal.clear(Calendar.HOUR); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.clear(Calendar.MINUTE); + cal.clear(Calendar.SECOND); + cal.clear(Calendar.MILLISECOND); + Date expDate = cal.getTime(); + + ValueEval ve[] = { + new NumberEval(DateUtil.getExcelDate(startDate)), + new NumberEval(offset) + }; + NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); + Date actDate = DateUtil.getJavaDate(result.getNumberValue()); + + assertEquals(expDate, actDate); + } + } + + @Test + public void testBug56688() { + ValueEval ve[] = {new NumberEval(DATE_1902_09_26), new RefEvalImplementation(new NumberEval(0))}; + NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); + assertEquals(DATE_1902_09_30, result.getNumberValue(), 0); + } + + @Test + public void testRefEvalStartDate() { + ValueEval ve[] = {new RefEvalImplementation(new NumberEval(DATE_1902_09_26)), new NumberEval(0)}; + NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec); + assertEquals(DATE_1902_09_30, result.getNumberValue(), 0); + } + + @Test + public void testEOMonthBlankValueEval() { + NumberEval evaluate = (NumberEval) eOMonth.evaluate(new ValueEval[] {BlankEval.instance, new NumberEval(0)}, ec); + assertEquals("Blank is handled as 0", DATE_1900_01_31, evaluate.getNumberValue(), 0); + } + + @Test + public void testEOMonthBlankRefValueEval() { + ValueEval[] ve1 = {new RefEvalImplementation(BlankEval.instance), new NumberEval(1)}; + NumberEval result = (NumberEval) eOMonth.evaluate(ve1, ec); + assertEquals("Blank is handled as 0", DATE_1900_02_28, result.getNumberValue(), 0); + + ValueEval[] ve2 = {new NumberEval(1), new RefEvalImplementation(BlankEval.instance)}; + result = (NumberEval) eOMonth.evaluate(ve2, ec); + assertEquals("Blank is handled as 0", DATE_1900_01_31, result.getNumberValue(), 0); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java index fb45ac2fa9..df3001e89c 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests FactDouble() as loaded from a test data spreadsheet.

    - */ -public class TestFactDoubleFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestFactDoubleFunctionsFromSpreadsheet.class, "FactDoubleFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests FactDouble() as loaded from a test data spreadsheet.

    + */ +public class TestFactDoubleFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestFactDoubleFunctionsFromSpreadsheet.class, "FactDoubleFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestImRealFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestImRealFunctionsFromSpreadsheet.java index db98cff93b..88f27a19ed 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestImRealFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestImRealFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests ImReal() as loaded from a test data spreadsheet.

    - */ -public class TestImRealFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestImRealFunctionsFromSpreadsheet.class, "ImRealFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests ImReal() as loaded from a test data spreadsheet.

    + */ +public class TestImRealFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestImRealFunctionsFromSpreadsheet.class, "ImRealFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestImaginaryFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestImaginaryFunctionsFromSpreadsheet.java index 9693025516..7fe71ce624 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestImaginaryFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestImaginaryFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests Imaginary() as loaded from a test data spreadsheet.

    - */ -public class TestImaginaryFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestImaginaryFunctionsFromSpreadsheet.class, "ImaginaryFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests Imaginary() as loaded from a test data spreadsheet.

    + */ +public class TestImaginaryFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestImaginaryFunctionsFromSpreadsheet.class, "ImaginaryFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestIndirectFunctionFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestIndirectFunctionFromSpreadsheet.java index c475ef526d..a78b5fd5ec 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestIndirectFunctionFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestIndirectFunctionFromSpreadsheet.java @@ -1,36 +1,36 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests INDIRECT() as loaded from a test data spreadsheet.

    - * - * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class - * (TestXxxx) of the target (Xxxx) implementor, where execution can be observed - * more easily. - */ -public final class TestIndirectFunctionFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestIndirectFunctionFromSpreadsheet.class, "IndirectFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests INDIRECT() as loaded from a test data spreadsheet.

    + * + * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class + * (TestXxxx) of the target (Xxxx) implementor, where execution can be observed + * more easily. + */ +public final class TestIndirectFunctionFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestIndirectFunctionFromSpreadsheet.class, "IndirectFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunction.java b/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunction.java index 52b72dfa25..1e48ced660 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunction.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunction.java @@ -1,107 +1,107 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.io.IOException; - -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.CellValue; -import org.apache.poi.ss.usermodel.FormulaEvaluator; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellReference; - -import junit.framework.TestCase; - -/** - * LogicalFunction unit tests. - */ -public class TestLogicalFunction extends TestCase { - - private FormulaEvaluator evaluator; - private Row row3; - private Cell cell1; - private Cell cell2; - - @Override - public void setUp() throws IOException { - Workbook wb = new HSSFWorkbook(); - try { - buildWorkbook(wb); - } finally { - wb.close(); - } - } - - private void buildWorkbook(Workbook wb) { - Sheet sh = wb.createSheet(); - Row row1 = sh.createRow(0); - Row row2 = sh.createRow(1); - row3 = sh.createRow(2); - - row1.createCell(0, CellType.NUMERIC); - row1.createCell(1, CellType.NUMERIC); - - row2.createCell(0, CellType.NUMERIC); - row2.createCell(1, CellType.NUMERIC); - - row3.createCell(0); - row3.createCell(1); - - CellReference a1 = new CellReference("A1"); - CellReference a2 = new CellReference("A2"); - CellReference b1 = new CellReference("B1"); - CellReference b2 = new CellReference("B2"); - - sh.getRow(a1.getRow()).getCell(a1.getCol()).setCellValue(35); - sh.getRow(a2.getRow()).getCell(a2.getCol()).setCellValue(0); - sh.getRow(b1.getRow()).getCell(b1.getCol()).setCellFormula("A1/A2"); - sh.getRow(b2.getRow()).getCell(b2.getCol()).setCellFormula("NA()"); - - evaluator = wb.getCreationHelper().createFormulaEvaluator(); - } - - public void testIsErr() { - cell1 = row3.createCell(0); - cell1.setCellFormula("ISERR(B1)"); // produces #DIV/0! - cell2 = row3.createCell(1); - cell2.setCellFormula("ISERR(B2)"); // produces #N/A - - CellValue cell1Value = evaluator.evaluate(cell1); - CellValue cell2Value = evaluator.evaluate(cell2); - - assertEquals(true, cell1Value.getBooleanValue()); - assertEquals(false, cell2Value.getBooleanValue()); - } - - public void testIsError() { - cell1 = row3.createCell(0); - cell1.setCellFormula("ISERROR(B1)"); // produces #DIV/0! - cell2 = row3.createCell(1); - cell2.setCellFormula("ISERROR(B2)"); // produces #N/A - - CellValue cell1Value = evaluator.evaluate(cell1); - CellValue cell2Value = evaluator.evaluate(cell2); - - assertEquals(true, cell1Value.getBooleanValue()); - assertEquals(true, cell2Value.getBooleanValue()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.io.IOException; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellReference; + +import junit.framework.TestCase; + +/** + * LogicalFunction unit tests. + */ +public class TestLogicalFunction extends TestCase { + + private FormulaEvaluator evaluator; + private Row row3; + private Cell cell1; + private Cell cell2; + + @Override + public void setUp() throws IOException { + Workbook wb = new HSSFWorkbook(); + try { + buildWorkbook(wb); + } finally { + wb.close(); + } + } + + private void buildWorkbook(Workbook wb) { + Sheet sh = wb.createSheet(); + Row row1 = sh.createRow(0); + Row row2 = sh.createRow(1); + row3 = sh.createRow(2); + + row1.createCell(0, CellType.NUMERIC); + row1.createCell(1, CellType.NUMERIC); + + row2.createCell(0, CellType.NUMERIC); + row2.createCell(1, CellType.NUMERIC); + + row3.createCell(0); + row3.createCell(1); + + CellReference a1 = new CellReference("A1"); + CellReference a2 = new CellReference("A2"); + CellReference b1 = new CellReference("B1"); + CellReference b2 = new CellReference("B2"); + + sh.getRow(a1.getRow()).getCell(a1.getCol()).setCellValue(35); + sh.getRow(a2.getRow()).getCell(a2.getCol()).setCellValue(0); + sh.getRow(b1.getRow()).getCell(b1.getCol()).setCellFormula("A1/A2"); + sh.getRow(b2.getRow()).getCell(b2.getCol()).setCellFormula("NA()"); + + evaluator = wb.getCreationHelper().createFormulaEvaluator(); + } + + public void testIsErr() { + cell1 = row3.createCell(0); + cell1.setCellFormula("ISERR(B1)"); // produces #DIV/0! + cell2 = row3.createCell(1); + cell2.setCellFormula("ISERR(B2)"); // produces #N/A + + CellValue cell1Value = evaluator.evaluate(cell1); + CellValue cell2Value = evaluator.evaluate(cell2); + + assertEquals(true, cell1Value.getBooleanValue()); + assertEquals(false, cell2Value.getBooleanValue()); + } + + public void testIsError() { + cell1 = row3.createCell(0); + cell1.setCellFormula("ISERROR(B1)"); // produces #DIV/0! + cell2 = row3.createCell(1); + cell2.setCellFormula("ISERROR(B2)"); // produces #N/A + + CellValue cell1Value = evaluator.evaluate(cell1); + CellValue cell2Value = evaluator.evaluate(cell2); + + assertEquals(true, cell1Value.getBooleanValue()); + assertEquals(true, cell2Value.getBooleanValue()); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestMatchFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestMatchFunctionsFromSpreadsheet.java index dce2927337..df3b52595e 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestMatchFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestMatchFunctionsFromSpreadsheet.java @@ -1,36 +1,36 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests Match functions as loaded from a test data spreadsheet.

    - * - * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class - * (TestXxxx) of the target (Xxxx) implementor, where execution can be observed - * more easily. - */ -public final class TestMatchFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestMatchFunctionsFromSpreadsheet.class, "MatchFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests Match functions as loaded from a test data spreadsheet.

    + * + * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class + * (TestXxxx) of the target (Xxxx) implementor, where execution can be observed + * more easily. + */ +public final class TestMatchFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestMatchFunctionsFromSpreadsheet.class, "MatchFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestMirr.java b/src/testcases/org/apache/poi/ss/formula/functions/TestMirr.java index 6a925511f1..f38bff7fc1 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestMirr.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestMirr.java @@ -1,168 +1,168 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.EvaluationException; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.CellValue; - -import junit.framework.AssertionFailedError; -import junit.framework.TestCase; - -/** - * Tests for {@link org.apache.poi.ss.formula.functions.Mirr} - * - * @author Carlos Delgado (carlos dot del dot est at gmail dot com) - * @author Cedric Walter (cedric dot walter at gmail dot com) - * @see {@link org.apache.poi.ss.formula.functions.TestIrr} - */ -public final class TestMirr extends TestCase { - - public void testMirr() { - Mirr mirr = new Mirr(); - double mirrValue; - - double financeRate = 0.12; - double reinvestRate = 0.1; - double[] values = {-120000d, 39000d, 30000d, 21000d, 37000d, 46000d, reinvestRate, financeRate}; - try { - mirrValue = mirr.evaluate(values); - } catch (EvaluationException e) { - throw new AssertionFailedError("MIRR should not failed with these parameters" + e); - } - assertEquals("mirr", 0.126094130366, mirrValue, 0.0000000001); - - reinvestRate = 0.05; - financeRate = 0.08; - values = new double[]{-7500d, 3000d, 5000d, 1200d, 4000d, reinvestRate, financeRate}; - try { - mirrValue = mirr.evaluate(values); - } catch (EvaluationException e) { - throw new AssertionFailedError("MIRR should not failed with these parameters" + e); - } - assertEquals("mirr", 0.18736225093, mirrValue, 0.0000000001); - - reinvestRate = 0.065; - financeRate = 0.1; - values = new double[]{-10000, 3400d, 6500d, 1000d, reinvestRate, financeRate}; - try { - mirrValue = mirr.evaluate(values); - } catch (EvaluationException e) { - throw new AssertionFailedError("MIRR should not failed with these parameters" + e); - } - assertEquals("mirr", 0.07039493966, mirrValue, 0.0000000001); - - reinvestRate = 0.07; - financeRate = 0.01; - values = new double[]{-10000d, -3400d, -6500d, -1000d, reinvestRate, financeRate}; - try { - mirrValue = mirr.evaluate(values); - } catch (EvaluationException e) { - throw new AssertionFailedError("MIRR should not failed with these parameters" + e); - } - assertEquals("mirr", -1, mirrValue, 0.0); - - } - - public void testMirrErrors_expectDIV0() { - Mirr mirr = new Mirr(); - - double reinvestRate = 0.05; - double financeRate = 0.08; - double[] incomes = {120000d, 39000d, 30000d, 21000d, 37000d, 46000d, reinvestRate, financeRate}; - try { - mirr.evaluate(incomes); - } catch (EvaluationException e) { - assertEquals(ErrorEval.DIV_ZERO, e.getErrorEval()); - return; - } - throw new AssertionFailedError("MIRR should failed with all these positives values"); - } - - - public void testEvaluateInSheet() { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("Sheet1"); - HSSFRow row = sheet.createRow(0); - - row.createCell(0).setCellValue(-7500d); - row.createCell(1).setCellValue(3000d); - row.createCell(2).setCellValue(5000d); - row.createCell(3).setCellValue(1200d); - row.createCell(4).setCellValue(4000d); - - row.createCell(5).setCellValue(0.05d); - row.createCell(6).setCellValue(0.08d); - - HSSFCell cell = row.createCell(7); - cell.setCellFormula("MIRR(A1:E1, F1, G1)"); - - HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); - fe.clearAllCachedResultValues(); - fe.evaluateFormulaCellEnum(cell); - double res = cell.getNumericCellValue(); - assertEquals(0.18736225093, res, 0.00000001); - } - - public void testMirrFromSpreadsheet() { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("mirrTest.xls"); - HSSFSheet sheet = wb.getSheet("Mirr"); - HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); - StringBuilder failures = new StringBuilder(); - int failureCount = 0; - int[] resultRows = {9, 19, 29, 45}; - - for (int rowNum : resultRows) { - HSSFRow row = sheet.getRow(rowNum); - HSSFCell cellA = row.getCell(0); - try { - CellValue cv = fe.evaluate(cellA); - assertFormulaResult(cv, cellA); - } catch (Throwable e) { - if (failures.length() > 0) failures.append('\n'); - failures.append("Row[").append(cellA.getRowIndex() + 1).append("]: ").append(cellA.getCellFormula()).append(" "); - failures.append(e.getMessage()); - failureCount++; - } - } - - HSSFRow row = sheet.getRow(37); - HSSFCell cellA = row.getCell(0); - CellValue cv = fe.evaluate(cellA); - assertEquals(ErrorEval.DIV_ZERO.getErrorCode(), cv.getErrorValue()); - - if (failures.length() > 0) { - throw new AssertionFailedError(failureCount + " IRR assertions failed:\n" + failures.toString()); - } - - } - - private static void assertFormulaResult(CellValue cv, HSSFCell cell) { - double actualValue = cv.getNumberValue(); - double expectedValue = cell.getNumericCellValue(); // cached formula result calculated by Excel - assertEquals("Invalid formula result: " + cv.toString(), CellType.NUMERIC, cv.getCellTypeEnum()); - assertEquals(expectedValue, actualValue, 1E-8); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CellValue; + +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; + +/** + * Tests for {@link org.apache.poi.ss.formula.functions.Mirr} + * + * @author Carlos Delgado (carlos dot del dot est at gmail dot com) + * @author Cedric Walter (cedric dot walter at gmail dot com) + * @see {@link org.apache.poi.ss.formula.functions.TestIrr} + */ +public final class TestMirr extends TestCase { + + public void testMirr() { + Mirr mirr = new Mirr(); + double mirrValue; + + double financeRate = 0.12; + double reinvestRate = 0.1; + double[] values = {-120000d, 39000d, 30000d, 21000d, 37000d, 46000d, reinvestRate, financeRate}; + try { + mirrValue = mirr.evaluate(values); + } catch (EvaluationException e) { + throw new AssertionFailedError("MIRR should not failed with these parameters" + e); + } + assertEquals("mirr", 0.126094130366, mirrValue, 0.0000000001); + + reinvestRate = 0.05; + financeRate = 0.08; + values = new double[]{-7500d, 3000d, 5000d, 1200d, 4000d, reinvestRate, financeRate}; + try { + mirrValue = mirr.evaluate(values); + } catch (EvaluationException e) { + throw new AssertionFailedError("MIRR should not failed with these parameters" + e); + } + assertEquals("mirr", 0.18736225093, mirrValue, 0.0000000001); + + reinvestRate = 0.065; + financeRate = 0.1; + values = new double[]{-10000, 3400d, 6500d, 1000d, reinvestRate, financeRate}; + try { + mirrValue = mirr.evaluate(values); + } catch (EvaluationException e) { + throw new AssertionFailedError("MIRR should not failed with these parameters" + e); + } + assertEquals("mirr", 0.07039493966, mirrValue, 0.0000000001); + + reinvestRate = 0.07; + financeRate = 0.01; + values = new double[]{-10000d, -3400d, -6500d, -1000d, reinvestRate, financeRate}; + try { + mirrValue = mirr.evaluate(values); + } catch (EvaluationException e) { + throw new AssertionFailedError("MIRR should not failed with these parameters" + e); + } + assertEquals("mirr", -1, mirrValue, 0.0); + + } + + public void testMirrErrors_expectDIV0() { + Mirr mirr = new Mirr(); + + double reinvestRate = 0.05; + double financeRate = 0.08; + double[] incomes = {120000d, 39000d, 30000d, 21000d, 37000d, 46000d, reinvestRate, financeRate}; + try { + mirr.evaluate(incomes); + } catch (EvaluationException e) { + assertEquals(ErrorEval.DIV_ZERO, e.getErrorEval()); + return; + } + throw new AssertionFailedError("MIRR should failed with all these positives values"); + } + + + public void testEvaluateInSheet() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("Sheet1"); + HSSFRow row = sheet.createRow(0); + + row.createCell(0).setCellValue(-7500d); + row.createCell(1).setCellValue(3000d); + row.createCell(2).setCellValue(5000d); + row.createCell(3).setCellValue(1200d); + row.createCell(4).setCellValue(4000d); + + row.createCell(5).setCellValue(0.05d); + row.createCell(6).setCellValue(0.08d); + + HSSFCell cell = row.createCell(7); + cell.setCellFormula("MIRR(A1:E1, F1, G1)"); + + HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); + fe.clearAllCachedResultValues(); + fe.evaluateFormulaCellEnum(cell); + double res = cell.getNumericCellValue(); + assertEquals(0.18736225093, res, 0.00000001); + } + + public void testMirrFromSpreadsheet() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("mirrTest.xls"); + HSSFSheet sheet = wb.getSheet("Mirr"); + HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb); + StringBuilder failures = new StringBuilder(); + int failureCount = 0; + int[] resultRows = {9, 19, 29, 45}; + + for (int rowNum : resultRows) { + HSSFRow row = sheet.getRow(rowNum); + HSSFCell cellA = row.getCell(0); + try { + CellValue cv = fe.evaluate(cellA); + assertFormulaResult(cv, cellA); + } catch (Throwable e) { + if (failures.length() > 0) failures.append('\n'); + failures.append("Row[").append(cellA.getRowIndex() + 1).append("]: ").append(cellA.getCellFormula()).append(" "); + failures.append(e.getMessage()); + failureCount++; + } + } + + HSSFRow row = sheet.getRow(37); + HSSFCell cellA = row.getCell(0); + CellValue cv = fe.evaluate(cellA); + assertEquals(ErrorEval.DIV_ZERO.getErrorCode(), cv.getErrorValue()); + + if (failures.length() > 0) { + throw new AssertionFailedError(failureCount + " IRR assertions failed:\n" + failures.toString()); + } + + } + + private static void assertFormulaResult(CellValue cv, HSSFCell cell) { + double actualValue = cv.getNumberValue(); + double expectedValue = cell.getNumericCellValue(); // cached formula result calculated by Excel + assertEquals("Invalid formula result: " + cv.toString(), CellType.NUMERIC, cv.getCellTypeEnum()); + assertEquals(expectedValue, actualValue, 1E-8); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java b/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java index 05c6a0aed8..dd6c30e1a9 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestQuotient.java @@ -1,64 +1,64 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.ss.formula.functions; - -import junit.framework.TestCase; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; - -/** - * Tests for {@link Quotient} - * - * @author cedric dot walter @ gmail dot com - */ -public class TestQuotient extends TestCase { - private static ValueEval invokeValue(String numerator, String denominator) { - ValueEval[] args = new ValueEval[]{new StringEval(numerator), new StringEval(denominator)}; - return new Quotient().evaluate(args, -1, -1); - } - - private static void confirmValue(String msg, String numerator, String denominator, String expected) { - ValueEval result = invokeValue(numerator, denominator); - assertEquals(NumberEval.class, result.getClass()); - assertEquals(msg, expected, ((NumberEval) result).getStringValue()); - } - - private static void confirmValueError(String msg, String numerator, String denominator, ErrorEval numError) { - ValueEval result = invokeValue(numerator, denominator); - assertEquals(ErrorEval.class, result.getClass()); - assertEquals(msg, numError, result); - } - - public void testBasic() { - confirmValue("Integer portion of 5/2 (2)", "5", "2", "2"); - confirmValue("Integer portion of 4.5/3.1 (1)", "4.5", "3.1", "1"); - - confirmValue("Integer portion of -10/3 (-3)", "-10", "3", "-3"); - confirmValue("Integer portion of -5.5/2 (-2)", "-5.5", "2", "-2"); - - confirmValue("Integer portion of Pi/Avogadro (0)", "3.14159", "6.02214179E+23", "0"); - } - - public void testErrors() { - confirmValueError("numerator is nonnumeric", "ABCD", "", ErrorEval.VALUE_INVALID); - confirmValueError("denominator is nonnumeric", "", "ABCD", ErrorEval.VALUE_INVALID); - - confirmValueError("dividing by zero", "3.14159", "0", ErrorEval.DIV_ZERO); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss.formula.functions; + +import junit.framework.TestCase; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Tests for {@link Quotient} + * + * @author cedric dot walter @ gmail dot com + */ +public class TestQuotient extends TestCase { + private static ValueEval invokeValue(String numerator, String denominator) { + ValueEval[] args = new ValueEval[]{new StringEval(numerator), new StringEval(denominator)}; + return new Quotient().evaluate(args, -1, -1); + } + + private static void confirmValue(String msg, String numerator, String denominator, String expected) { + ValueEval result = invokeValue(numerator, denominator); + assertEquals(NumberEval.class, result.getClass()); + assertEquals(msg, expected, ((NumberEval) result).getStringValue()); + } + + private static void confirmValueError(String msg, String numerator, String denominator, ErrorEval numError) { + ValueEval result = invokeValue(numerator, denominator); + assertEquals(ErrorEval.class, result.getClass()); + assertEquals(msg, numError, result); + } + + public void testBasic() { + confirmValue("Integer portion of 5/2 (2)", "5", "2", "2"); + confirmValue("Integer portion of 4.5/3.1 (1)", "4.5", "3.1", "1"); + + confirmValue("Integer portion of -10/3 (-3)", "-10", "3", "-3"); + confirmValue("Integer portion of -5.5/2 (-2)", "-5.5", "2", "-2"); + + confirmValue("Integer portion of Pi/Avogadro (0)", "3.14159", "6.02214179E+23", "0"); + } + + public void testErrors() { + confirmValueError("numerator is nonnumeric", "ABCD", "", ErrorEval.VALUE_INVALID); + confirmValueError("denominator is nonnumeric", "", "ABCD", ErrorEval.VALUE_INVALID); + + confirmValueError("dividing by zero", "3.14159", "0", ErrorEval.DIV_ZERO); + } } \ No newline at end of file diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestQuotientFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestQuotientFunctionsFromSpreadsheet.java index 62c4c10f2d..146e0cf908 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestQuotientFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestQuotientFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests QUOTIENT() as loaded from a test data spreadsheet.

    - */ -public class TestQuotientFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestQuotientFunctionsFromSpreadsheet.class, "QuotientFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests QUOTIENT() as loaded from a test data spreadsheet.

    + */ +public class TestQuotientFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestQuotientFunctionsFromSpreadsheet.class, "QuotientFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestReptFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestReptFunctionsFromSpreadsheet.java index c0c11eae6a..e1d26ff639 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestReptFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestReptFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests REPT() as loaded from a test data spreadsheet.

    - */ -public class TestReptFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestReptFunctionsFromSpreadsheet.class, "ReptFunctionTestCaseData.xls"); - } +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests REPT() as loaded from a test data spreadsheet.

    + */ +public class TestReptFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestReptFunctionsFromSpreadsheet.class, "ReptFunctionTestCaseData.xls"); + } } \ No newline at end of file diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java index 687c7b8319..7f6ca4ea67 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestRomanFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests Roman() as loaded from a test data spreadsheet.

    - */ -public class TestRomanFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestRomanFunctionsFromSpreadsheet.class, "RomanFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests Roman() as loaded from a test data spreadsheet.

    + */ +public class TestRomanFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestRomanFunctionsFromSpreadsheet.class, "RomanFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet.java index c2e41dd4a4..cf70a993d5 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests WeekNum() as loaded from a test data spreadsheet.

    - */ -public class TestWeekNumFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - return data(TestWeekNumFunctionsFromSpreadsheet.class, "WeekNumFunctionTestCaseData.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests WeekNum() as loaded from a test data spreadsheet.

    + */ +public class TestWeekNumFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + return data(TestWeekNumFunctionsFromSpreadsheet.class, "WeekNumFunctionTestCaseData.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet2013.java b/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet2013.java index b75a419080..6d104efcad 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet2013.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestWeekNumFunctionsFromSpreadsheet2013.java @@ -1,33 +1,33 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.functions; - -import java.util.Collection; - -import org.junit.runners.Parameterized.Parameters; - -/** - * Tests WeekNum() as loaded from a test data 2013 excel spreadsheet.

    - */ -public class TestWeekNumFunctionsFromSpreadsheet2013 extends BaseTestFunctionsFromSpreadsheet { - @Parameters(name="{0}") - public static Collection data() throws Exception { - //Only open this file with Excel 2013 to keep binary specific to that version - return data(TestWeekNumFunctionsFromSpreadsheet2013.class, "WeekNumFunctionTestCaseData2013.xls"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.util.Collection; + +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests WeekNum() as loaded from a test data 2013 excel spreadsheet.

    + */ +public class TestWeekNumFunctionsFromSpreadsheet2013 extends BaseTestFunctionsFromSpreadsheet { + @Parameters(name="{0}") + public static Collection data() throws Exception { + //Only open this file with Excel 2013 to keep binary specific to that version + return data(TestWeekNumFunctionsFromSpreadsheet2013.class, "WeekNumFunctionTestCaseData2013.xls"); + } +} diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java index 1111960f8c..d1b4290100 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java @@ -1,1436 +1,1436 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -package org.apache.poi.ss.usermodel; - -import org.apache.poi.hssf.usermodel.HSSFConditionalFormatting; -import org.apache.poi.hssf.usermodel.HSSFConditionalFormattingRule; -import org.apache.poi.ss.ITestDataProvider; -import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; -import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; -import org.apache.poi.ss.util.CellRangeAddress; -import org.junit.Test; - -import java.io.IOException; - -import static org.junit.Assert.*; - -/** - * Base tests for Conditional Formatting, for both HSSF and XSSF - */ -public abstract class BaseTestConditionalFormatting { - private final ITestDataProvider _testDataProvider; - - public BaseTestConditionalFormatting(ITestDataProvider testDataProvider){ - _testDataProvider = testDataProvider; - } - - protected abstract void assertColour(String hexExpected, Color actual); - - @Test - public void testBasic() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); - - assertEquals(0, sheetCF.getNumConditionalFormattings()); - try { - assertNull(sheetCF.getConditionalFormattingAt(0)); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); - } - - try { - sheetCF.removeConditionalFormatting(0); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); - } - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("1"); - ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule("2"); - ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule("3"); - ConditionalFormattingRule rule4 = sheetCF.createConditionalFormattingRule("4"); - try { - sheetCF.addConditionalFormatting(null, rule1); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("regions must not be null")); - } - try { - sheetCF.addConditionalFormatting( - new CellRangeAddress[]{ CellRangeAddress.valueOf("A1:A3") }, - (ConditionalFormattingRule)null); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("cfRules must not be null")); - } - - try { - sheetCF.addConditionalFormatting( - new CellRangeAddress[]{ CellRangeAddress.valueOf("A1:A3") }, - new ConditionalFormattingRule[0]); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("cfRules must not be empty")); - } - - try { - sheetCF.addConditionalFormatting( - new CellRangeAddress[]{ CellRangeAddress.valueOf("A1:A3") }, - new ConditionalFormattingRule[]{rule1, rule2, rule3, rule4}); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("Number of rules must not exceed 3")); - } - wb.close(); - } - - /** - * Test format conditions based on a boolean formula - */ - @Test - public void testBooleanFormulaConditions() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("SUM(A1:A5)>10"); - assertEquals(ConditionType.FORMULA, rule1.getConditionType()); - assertEquals("SUM(A1:A5)>10", rule1.getFormula1()); - int formatIndex1 = sheetCF.addConditionalFormatting( - new CellRangeAddress[]{ - CellRangeAddress.valueOf("B1"), - CellRangeAddress.valueOf("C3"), - }, rule1); - assertEquals(0, formatIndex1); - assertEquals(1, sheetCF.getNumConditionalFormattings()); - CellRangeAddress[] ranges1 = sheetCF.getConditionalFormattingAt(formatIndex1).getFormattingRanges(); - assertEquals(2, ranges1.length); - assertEquals("B1", ranges1[0].formatAsString()); - assertEquals("C3", ranges1[1].formatAsString()); - - // adjacent address are merged - int formatIndex2 = sheetCF.addConditionalFormatting( - new CellRangeAddress[]{ - CellRangeAddress.valueOf("B1"), - CellRangeAddress.valueOf("B2"), - CellRangeAddress.valueOf("B3"), - }, rule1); - assertEquals(1, formatIndex2); - assertEquals(2, sheetCF.getNumConditionalFormattings()); - CellRangeAddress[] ranges2 = sheetCF.getConditionalFormattingAt(formatIndex2).getFormattingRanges(); - assertEquals(1, ranges2.length); - assertEquals("B1:B3", ranges2[0].formatAsString()); - wb.close(); - } - - @Test - public void testSingleFormulaConditions() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.EQUAL, "SUM(A1:A5)+10"); - assertEquals(ConditionType.CELL_VALUE_IS, rule1.getConditionType()); - assertEquals("SUM(A1:A5)+10", rule1.getFormula1()); - assertEquals(ComparisonOperator.EQUAL, rule1.getComparisonOperation()); - - ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.NOT_EQUAL, "15"); - assertEquals(ConditionType.CELL_VALUE_IS, rule2.getConditionType()); - assertEquals("15", rule2.getFormula1()); - assertEquals(ComparisonOperator.NOT_EQUAL, rule2.getComparisonOperation()); - - ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.NOT_EQUAL, "15"); - assertEquals(ConditionType.CELL_VALUE_IS, rule3.getConditionType()); - assertEquals("15", rule3.getFormula1()); - assertEquals(ComparisonOperator.NOT_EQUAL, rule3.getComparisonOperation()); - - ConditionalFormattingRule rule4 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.GT, "0"); - assertEquals(ConditionType.CELL_VALUE_IS, rule4.getConditionType()); - assertEquals("0", rule4.getFormula1()); - assertEquals(ComparisonOperator.GT, rule4.getComparisonOperation()); - - ConditionalFormattingRule rule5 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.LT, "0"); - assertEquals(ConditionType.CELL_VALUE_IS, rule5.getConditionType()); - assertEquals("0", rule5.getFormula1()); - assertEquals(ComparisonOperator.LT, rule5.getComparisonOperation()); - - ConditionalFormattingRule rule6 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.GE, "0"); - assertEquals(ConditionType.CELL_VALUE_IS, rule6.getConditionType()); - assertEquals("0", rule6.getFormula1()); - assertEquals(ComparisonOperator.GE, rule6.getComparisonOperation()); - - ConditionalFormattingRule rule7 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.LE, "0"); - assertEquals(ConditionType.CELL_VALUE_IS, rule7.getConditionType()); - assertEquals("0", rule7.getFormula1()); - assertEquals(ComparisonOperator.LE, rule7.getComparisonOperation()); - - ConditionalFormattingRule rule8 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.BETWEEN, "0", "5"); - assertEquals(ConditionType.CELL_VALUE_IS, rule8.getConditionType()); - assertEquals("0", rule8.getFormula1()); - assertEquals("5", rule8.getFormula2()); - assertEquals(ComparisonOperator.BETWEEN, rule8.getComparisonOperation()); - - ConditionalFormattingRule rule9 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.NOT_BETWEEN, "0", "5"); - assertEquals(ConditionType.CELL_VALUE_IS, rule9.getConditionType()); - assertEquals("0", rule9.getFormula1()); - assertEquals("5", rule9.getFormula2()); - assertEquals(ComparisonOperator.NOT_BETWEEN, rule9.getComparisonOperation()); - - wb.close(); - } - - @Test - public void testCopy() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sheet1 = wb.createSheet(); - Sheet sheet2 = wb.createSheet(); - SheetConditionalFormatting sheet1CF = sheet1.getSheetConditionalFormatting(); - SheetConditionalFormatting sheet2CF = sheet2.getSheetConditionalFormatting(); - assertEquals(0, sheet1CF.getNumConditionalFormattings()); - assertEquals(0, sheet2CF.getNumConditionalFormattings()); - - ConditionalFormattingRule rule1 = sheet1CF.createConditionalFormattingRule( - ComparisonOperator.EQUAL, "SUM(A1:A5)+10"); - - ConditionalFormattingRule rule2 = sheet1CF.createConditionalFormattingRule( - ComparisonOperator.NOT_EQUAL, "15"); - - // adjacent address are merged - int formatIndex = sheet1CF.addConditionalFormatting( - new CellRangeAddress[]{ - CellRangeAddress.valueOf("A1:A5"), - CellRangeAddress.valueOf("C1:C5") - }, rule1, rule2); - assertEquals(0, formatIndex); - assertEquals(1, sheet1CF.getNumConditionalFormattings()); - - assertEquals(0, sheet2CF.getNumConditionalFormattings()); - sheet2CF.addConditionalFormatting(sheet1CF.getConditionalFormattingAt(formatIndex)); - assertEquals(1, sheet2CF.getNumConditionalFormattings()); - - ConditionalFormatting sheet2cf = sheet2CF.getConditionalFormattingAt(0); - assertEquals(2, sheet2cf.getNumberOfRules()); - assertEquals("SUM(A1:A5)+10", sheet2cf.getRule(0).getFormula1()); - assertEquals(ComparisonOperator.EQUAL, sheet2cf.getRule(0).getComparisonOperation()); - assertEquals(ConditionType.CELL_VALUE_IS, sheet2cf.getRule(0).getConditionType()); - assertEquals("15", sheet2cf.getRule(1).getFormula1()); - assertEquals(ComparisonOperator.NOT_EQUAL, sheet2cf.getRule(1).getComparisonOperation()); - assertEquals(ConditionType.CELL_VALUE_IS, sheet2cf.getRule(1).getConditionType()); - - wb.close(); - } - - @Test - public void testRemove() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sheet1 = wb.createSheet(); - SheetConditionalFormatting sheetCF = sheet1.getSheetConditionalFormatting(); - assertEquals(0, sheetCF.getNumConditionalFormattings()); - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.EQUAL, "SUM(A1:A5)"); - - // adjacent address are merged - int formatIndex = sheetCF.addConditionalFormatting( - new CellRangeAddress[]{ - CellRangeAddress.valueOf("A1:A5") - }, rule1); - assertEquals(0, formatIndex); - assertEquals(1, sheetCF.getNumConditionalFormattings()); - sheetCF.removeConditionalFormatting(0); - assertEquals(0, sheetCF.getNumConditionalFormattings()); - try { - assertNull(sheetCF.getConditionalFormattingAt(0)); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); - } - - formatIndex = sheetCF.addConditionalFormatting( - new CellRangeAddress[]{ - CellRangeAddress.valueOf("A1:A5") - }, rule1); - assertEquals(0, formatIndex); - assertEquals(1, sheetCF.getNumConditionalFormattings()); - sheetCF.removeConditionalFormatting(0); - assertEquals(0, sheetCF.getNumConditionalFormattings()); - try { - assertNull(sheetCF.getConditionalFormattingAt(0)); - fail("expected exception"); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); - } - - wb.close(); - } - - @Test - public void testCreateCF() throws IOException { - Workbook workbook = _testDataProvider.createWorkbook(); - Sheet sheet = workbook.createSheet(); - String formula = "7"; - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(formula); - FontFormatting fontFmt = rule1.createFontFormatting(); - fontFmt.setFontStyle(true, false); - - BorderFormatting bordFmt = rule1.createBorderFormatting(); - bordFmt.setBorderBottom(BorderStyle.THIN); - bordFmt.setBorderTop(BorderStyle.THICK); - bordFmt.setBorderLeft(BorderStyle.DASHED); - bordFmt.setBorderRight(BorderStyle.DOTTED); - - PatternFormatting patternFmt = rule1.createPatternFormatting(); - patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index); - - - ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2"); - ConditionalFormattingRule [] cfRules = - { - rule1, rule2 - }; - - short col = 1; - CellRangeAddress [] regions = { - new CellRangeAddress(0, 65535, col, col) - }; - - sheetCF.addConditionalFormatting(regions, cfRules); - sheetCF.addConditionalFormatting(regions, cfRules); - - // Verification - assertEquals(2, sheetCF.getNumConditionalFormattings()); - sheetCF.removeConditionalFormatting(1); - assertEquals(1, sheetCF.getNumConditionalFormattings()); - ConditionalFormatting cf = sheetCF.getConditionalFormattingAt(0); - assertNotNull(cf); - - regions = cf.getFormattingRanges(); - assertNotNull(regions); - assertEquals(1, regions.length); - CellRangeAddress r = regions[0]; - assertEquals(1, r.getFirstColumn()); - assertEquals(1, r.getLastColumn()); - assertEquals(0, r.getFirstRow()); - assertEquals(65535, r.getLastRow()); - - assertEquals(2, cf.getNumberOfRules()); - - rule1 = cf.getRule(0); - assertEquals("7",rule1.getFormula1()); - assertNull(rule1.getFormula2()); - - FontFormatting r1fp = rule1.getFontFormatting(); - assertNotNull(r1fp); - - assertTrue(r1fp.isItalic()); - assertFalse(r1fp.isBold()); - - BorderFormatting r1bf = rule1.getBorderFormatting(); - assertNotNull(r1bf); - assertEquals(BorderStyle.THIN, r1bf.getBorderBottomEnum()); - assertEquals(BorderStyle.THICK,r1bf.getBorderTopEnum()); - assertEquals(BorderStyle.DASHED,r1bf.getBorderLeftEnum()); - assertEquals(BorderStyle.DOTTED,r1bf.getBorderRightEnum()); - - PatternFormatting r1pf = rule1.getPatternFormatting(); - assertNotNull(r1pf); -// assertEquals(IndexedColors.YELLOW.index,r1pf.getFillBackgroundColor()); - - rule2 = cf.getRule(1); - assertEquals("2",rule2.getFormula2()); - assertEquals("1",rule2.getFormula1()); - - workbook.close(); - } - - @Test - public void testClone() throws IOException { - - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sheet = wb.createSheet(); - String formula = "7"; - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(formula); - FontFormatting fontFmt = rule1.createFontFormatting(); - fontFmt.setFontStyle(true, false); - - PatternFormatting patternFmt = rule1.createPatternFormatting(); - patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index); - - - ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2"); - ConditionalFormattingRule [] cfRules = - { - rule1, rule2 - }; - - short col = 1; - CellRangeAddress [] regions = { - new CellRangeAddress(0, 65535, col, col) - }; - - sheetCF.addConditionalFormatting(regions, cfRules); - - try { - wb.cloneSheet(0); - assertEquals(2, wb.getNumberOfSheets()); - } catch (RuntimeException e) { - if (e.getMessage().indexOf("needs to define a clone method") > 0) { - fail("Identified bug 45682"); - } - throw e; - } finally { - wb.close(); - } - } - - @Test - public void testShiftRows() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sheet = wb.createSheet(); - - SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); - - ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.BETWEEN, "SUM(A10:A15)", "1+SUM(B16:B30)"); - FontFormatting fontFmt = rule1.createFontFormatting(); - fontFmt.setFontStyle(true, false); - - PatternFormatting patternFmt = rule1.createPatternFormatting(); - patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index); - - ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule( - ComparisonOperator.BETWEEN, "SUM(A10:A15)", "1+SUM(B16:B30)"); - BorderFormatting borderFmt = rule2.createBorderFormatting(); - borderFmt.setBorderDiagonal(BorderStyle.MEDIUM); - - CellRangeAddress [] regions = { - new CellRangeAddress(2, 4, 0, 0), // A3:A5 - }; - sheetCF.addConditionalFormatting(regions, rule1); - sheetCF.addConditionalFormatting(regions, rule2); - - // This row-shift should destroy the CF region - sheet.shiftRows(10, 20, -9); - assertEquals(0, sheetCF.getNumConditionalFormattings()); - - // re-add the CF - sheetCF.addConditionalFormatting(regions, rule1); - sheetCF.addConditionalFormatting(regions, rule2); - - // This row shift should only affect the formulas - sheet.shiftRows(14, 17, 8); - ConditionalFormatting cf1 = sheetCF.getConditionalFormattingAt(0); - assertEquals("SUM(A10:A23)", cf1.getRule(0).getFormula1()); - assertEquals("1+SUM(B24:B30)", cf1.getRule(0).getFormula2()); - ConditionalFormatting cf2 = sheetCF.getConditionalFormattingAt(1); - assertEquals("SUM(A10:A23)", cf2.getRule(0).getFormula1()); - assertEquals("1+SUM(B24:B30)", cf2.getRule(0).getFormula2()); - - sheet.shiftRows(0, 8, 21); - cf1 = sheetCF.getConditionalFormattingAt(0); - assertEquals("SUM(A10:A21)", cf1.getRule(0).getFormula1()); - assertEquals("1+SUM(#REF!)", cf1.getRule(0).getFormula2()); - cf2 = sheetCF.getConditionalFormattingAt(1); - assertEquals("SUM(A10:A21)", cf2.getRule(0).getFormula1()); - assertEquals("1+SUM(#REF!)", cf2.getRule(0).getFormula2()); - - wb.close(); - } - - protected void testRead(String filename) throws IOException { - Workbook wb = _testDataProvider.openSampleWorkbook(filename); - Sheet sh = wb.getSheet("CF"); - SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); - assertEquals(3, sheetCF.getNumConditionalFormattings()); - - ConditionalFormatting cf1 = sheetCF.getConditionalFormattingAt(0); - assertEquals(2, cf1.getNumberOfRules()); - - CellRangeAddress[] regions1 = cf1.getFormattingRanges(); - assertEquals(1, regions1.length); - assertEquals("A1:A8", regions1[0].formatAsString()); - - // CF1 has two rules: values less than -3 are bold-italic red, values greater than 3 are green - ConditionalFormattingRule rule1 = cf1.getRule(0); - assertEquals(ConditionType.CELL_VALUE_IS, rule1.getConditionType()); - assertEquals(ComparisonOperator.GT, rule1.getComparisonOperation()); - assertEquals("3", rule1.getFormula1()); - assertNull(rule1.getFormula2()); - // fills and borders are not set - assertNull(rule1.getPatternFormatting()); - assertNull(rule1.getBorderFormatting()); - - FontFormatting fmt1 = rule1.getFontFormatting(); -// assertEquals(IndexedColors.GREEN.index, fmt1.getFontColorIndex()); - assertTrue(fmt1.isBold()); - assertFalse(fmt1.isItalic()); - - ConditionalFormattingRule rule2 = cf1.getRule(1); - assertEquals(ConditionType.CELL_VALUE_IS, rule2.getConditionType()); - assertEquals(ComparisonOperator.LT, rule2.getComparisonOperation()); - assertEquals("-3", rule2.getFormula1()); - assertNull(rule2.getFormula2()); - assertNull(rule2.getPatternFormatting()); - assertNull(rule2.getBorderFormatting()); - - FontFormatting fmt2 = rule2.getFontFormatting(); -// assertEquals(IndexedColors.RED.index, fmt2.getFontColorIndex()); - assertTrue(fmt2.isBold()); - assertTrue(fmt2.isItalic()); - - - ConditionalFormatting cf2 = sheetCF.getConditionalFormattingAt(1); - assertEquals(1, cf2.getNumberOfRules()); - CellRangeAddress[] regions2 = cf2.getFormattingRanges(); - assertEquals(1, regions2.length); - assertEquals("B9", regions2[0].formatAsString()); - - ConditionalFormattingRule rule3 = cf2.getRule(0); - assertEquals(ConditionType.FORMULA, rule3.getConditionType()); - assertEquals(ComparisonOperator.NO_COMPARISON, rule3.getComparisonOperation()); - assertEquals("$A$8>5", rule3.getFormula1()); - assertNull(rule3.getFormula2()); - - FontFormatting fmt3 = rule3.getFontFormatting(); -// assertEquals(IndexedColors.RED.index, fmt3.getFontColorIndex()); - assertTrue(fmt3.isBold()); - assertTrue(fmt3.isItalic()); - - PatternFormatting fmt4 = rule3.getPatternFormatting(); -// assertEquals(IndexedColors.LIGHT_CORNFLOWER_BLUE.index, fmt4.getFillBackgroundColor()); -// assertEquals(IndexedColors.AUTOMATIC.index, fmt4.getFillForegroundColor()); - assertEquals(PatternFormatting.NO_FILL, fmt4.getFillPattern()); - // borders are not set - assertNull(rule3.getBorderFormatting()); - - ConditionalFormatting cf3 = sheetCF.getConditionalFormattingAt(2); - CellRangeAddress[] regions3 = cf3.getFormattingRanges(); - assertEquals(1, regions3.length); - assertEquals("B1:B7", regions3[0].formatAsString()); - assertEquals(2, cf3.getNumberOfRules()); - - ConditionalFormattingRule rule4 = cf3.getRule(0); - assertEquals(ConditionType.CELL_VALUE_IS, rule4.getConditionType()); - assertEquals(ComparisonOperator.LE, rule4.getComparisonOperation()); - assertEquals("\"AAA\"", rule4.getFormula1()); - assertNull(rule4.getFormula2()); - - ConditionalFormattingRule rule5 = cf3.getRule(1); - assertEquals(ConditionType.CELL_VALUE_IS, rule5.getConditionType()); - assertEquals(ComparisonOperator.BETWEEN, rule5.getComparisonOperation()); - assertEquals("\"A\"", rule5.getFormula1()); - assertEquals("\"AAA\"", rule5.getFormula2()); - - wb.close(); - } - - public void testReadOffice2007(String filename) throws IOException { - Workbook wb = _testDataProvider.openSampleWorkbook(filename); - Sheet s = wb.getSheet("CF"); - - // Sanity check data - assertEquals("Values", s.getRow(0).getCell(0).toString()); - assertEquals("10.0", s.getRow(2).getCell(0).toString()); - - // Check we found all the conditional formatting rules we should have - SheetConditionalFormatting sheetCF = s.getSheetConditionalFormatting(); - int numCF = 3; - int numCF12 = 15; - int numCFEX = 0; // TODO This should be 2, but we don't support CFEX formattings yet, see #58149 - assertEquals(numCF+numCF12+numCFEX, sheetCF.getNumConditionalFormattings()); - - int fCF = 0, fCF12 = 0, fCFEX = 0; - for (int i=0; iYellow->Green - Column F - cf = sheetCF.getConditionalFormattingAt(3); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("F2:F17", cf.getFormattingRanges()[0].formatAsString()); - assertColorScale(cf, "F8696B", "FFEB84", "63BE7B"); - - - // Colours Blue->White->Red - Column G - cf = sheetCF.getConditionalFormattingAt(4); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("G2:G17", cf.getFormattingRanges()[0].formatAsString()); - assertColorScale(cf, "5A8AC6", "FCFCFF", "F8696B"); - - - // Icons : Default - Column H, percentage thresholds - cf = sheetCF.getConditionalFormattingAt(5); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("H2:H17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_TRAFFIC_LIGHTS, 0d, 33d, 67d); - - - // Icons : 3 signs - Column I - cf = sheetCF.getConditionalFormattingAt(6); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("I2:I17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_SHAPES, 0d, 33d, 67d); - - - // Icons : 3 traffic lights 2 - Column J - cf = sheetCF.getConditionalFormattingAt(7); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("J2:J17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_TRAFFIC_LIGHTS_BOX, 0d, 33d, 67d); - - - // Icons : 4 traffic lights - Column K - cf = sheetCF.getConditionalFormattingAt(8); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("K2:K17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYRB_4_TRAFFIC_LIGHTS, 0d, 25d, 50d, 75d); - - - // Icons : 3 symbols with backgrounds - Column L - cf = sheetCF.getConditionalFormattingAt(9); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("L2:L17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_SYMBOLS_CIRCLE, 0d, 33d, 67d); - - - // Icons : 3 flags - Column M2 Only - cf = sheetCF.getConditionalFormattingAt(10); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("M2", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_FLAGS, 0d, 33d, 67d); - - // Icons : 3 flags - Column M (all) - cf = sheetCF.getConditionalFormattingAt(11); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("M2:M17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_FLAGS, 0d, 33d, 67d); - - - // Icons : 3 symbols 2 (no background) - Column N - cf = sheetCF.getConditionalFormattingAt(12); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("N2:N17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_SYMBOLS, 0d, 33d, 67d); - - - // Icons : 3 arrows - Column O - cf = sheetCF.getConditionalFormattingAt(13); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("O2:O17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GYR_3_ARROW, 0d, 33d, 67d); - - - // Icons : 5 arrows grey - Column P - cf = sheetCF.getConditionalFormattingAt(14); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("P2:P17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.GREY_5_ARROWS, 0d, 20d, 40d, 60d, 80d); - - - // Icons : 3 stars (ext) - Column Q - // TODO Support EXT formattings - - - // Icons : 4 ratings - Column R - cf = sheetCF.getConditionalFormattingAt(15); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("R2:R17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.RATINGS_4, 0d, 25d, 50d, 75d); - - - // Icons : 5 ratings - Column S - cf = sheetCF.getConditionalFormattingAt(16); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("S2:S17", cf.getFormattingRanges()[0].formatAsString()); - assertIconSetPercentages(cf, IconSet.RATINGS_5, 0d, 20d, 40d, 60d, 80d); - - - // Custom Icon+Format - Column T - cf = sheetCF.getConditionalFormattingAt(17); - assertEquals(1, cf.getFormattingRanges().length); - assertEquals("T2:T17", cf.getFormattingRanges()[0].formatAsString()); - - // TODO Support IconSet + Other CFs with 2 rules -// assertEquals(2, cf.getNumberOfRules()); -// cr = cf.getRule(0); -// assertIconSetPercentages(cr, IconSet.GYR_3_TRAFFIC_LIGHTS_BOX, 0d, 33d, 67d); -// cr = cf.getRule(1); -// assertEquals(ConditionType.FORMULA, cr.getConditionType()); -// assertEquals(ComparisonOperator.NO_COMPARISON, cr.getComparisonOperation()); -// // TODO Why aren't these two the same between formats? -// if (cr instanceof HSSFConditionalFormattingRule) { -// assertEquals("MOD(ROW($T1),2)=1", cr.getFormula1()); -// } else { -// assertEquals("MOD(ROW($T2),2)=1", cr.getFormula1()); -// } -// assertEquals(null, cr.getFormula2()); - - - // Mixed icons - Column U - // TODO Support EXT formattings - - wb.close(); - } - - private void assertDataBar(ConditionalFormatting cf, String color) { - assertEquals(1, cf.getNumberOfRules()); - ConditionalFormattingRule cr = cf.getRule(0); - assertDataBar(cr, color); - } - private void assertDataBar(ConditionalFormattingRule cr, String color) { - assertEquals(ConditionType.DATA_BAR, cr.getConditionType()); - assertEquals(ComparisonOperator.NO_COMPARISON, cr.getComparisonOperation()); - assertEquals(null, cr.getFormula1()); - assertEquals(null, cr.getFormula2()); - - DataBarFormatting databar = cr.getDataBarFormatting(); - assertNotNull(databar); - assertEquals(false, databar.isIconOnly()); - assertEquals(true, databar.isLeftToRight()); - assertEquals(0, databar.getWidthMin()); - assertEquals(100, databar.getWidthMax()); - - assertColour(color, databar.getColor()); - - ConditionalFormattingThreshold th; - th = databar.getMinThreshold(); - assertEquals(RangeType.MIN, th.getRangeType()); - assertEquals(null, th.getValue()); - assertEquals(null, th.getFormula()); - th = databar.getMaxThreshold(); - assertEquals(RangeType.MAX, th.getRangeType()); - assertEquals(null, th.getValue()); - assertEquals(null, th.getFormula()); - } - - private void assertIconSetPercentages(ConditionalFormatting cf, IconSet iconset, Double...vals) { - assertEquals(1, cf.getNumberOfRules()); - ConditionalFormattingRule cr = cf.getRule(0); - assertIconSetPercentages(cr, iconset, vals); - } - private void assertIconSetPercentages(ConditionalFormattingRule cr, IconSet iconset, Double...vals) { - assertEquals(ConditionType.ICON_SET, cr.getConditionType()); - assertEquals(ComparisonOperator.NO_COMPARISON, cr.getComparisonOperation()); - assertEquals(null, cr.getFormula1()); - assertEquals(null, cr.getFormula2()); - - IconMultiStateFormatting icon = cr.getMultiStateFormatting(); - assertNotNull(icon); - assertEquals(iconset, icon.getIconSet()); - assertEquals(false, icon.isIconOnly()); - assertEquals(false, icon.isReversed()); - - assertNotNull(icon.getThresholds()); - assertEquals(vals.length, icon.getThresholds().length); - for (int i=0; i0"); - sheet.getSheetConditionalFormatting().addConditionalFormatting(ranges, rule); - wb.close(); - } - - @Test - public void testSetCellRangeAddresswithSingleRange() throws Exception { - Workbook wb = _testDataProvider.createWorkbook(); - final Sheet sheet = wb.createSheet("S1"); - final SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting(); - assertEquals(0, cf.getNumConditionalFormattings()); - ConditionalFormattingRule rule1 = cf.createConditionalFormattingRule("$A$1>0"); - cf.addConditionalFormatting(new CellRangeAddress[] { - CellRangeAddress.valueOf("A1:A5") - }, rule1); - - assertEquals(1, cf.getNumConditionalFormattings()); - ConditionalFormatting readCf = cf.getConditionalFormattingAt(0); - CellRangeAddress[] formattingRanges = readCf.getFormattingRanges(); - assertEquals(1, formattingRanges.length); - CellRangeAddress formattingRange = formattingRanges[0]; - assertEquals("A1:A5", formattingRange.formatAsString()); - - readCf.setFormattingRanges(new CellRangeAddress[] { - CellRangeAddress.valueOf("A1:A6") - }); - - readCf = cf.getConditionalFormattingAt(0); - formattingRanges = readCf.getFormattingRanges(); - assertEquals(1, formattingRanges.length); - formattingRange = formattingRanges[0]; - assertEquals("A1:A6", formattingRange.formatAsString()); - } - - @Test - public void testSetCellRangeAddressWithMultipleRanges() throws Exception { - Workbook wb = _testDataProvider.createWorkbook(); - final Sheet sheet = wb.createSheet("S1"); - final SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting(); - assertEquals(0, cf.getNumConditionalFormattings()); - ConditionalFormattingRule rule1 = cf.createConditionalFormattingRule("$A$1>0"); - cf.addConditionalFormatting(new CellRangeAddress[] { - CellRangeAddress.valueOf("A1:A5") - }, rule1); - - assertEquals(1, cf.getNumConditionalFormattings()); - ConditionalFormatting readCf = cf.getConditionalFormattingAt(0); - CellRangeAddress[] formattingRanges = readCf.getFormattingRanges(); - assertEquals(1, formattingRanges.length); - CellRangeAddress formattingRange = formattingRanges[0]; - assertEquals("A1:A5", formattingRange.formatAsString()); - - readCf.setFormattingRanges(new CellRangeAddress[] { - CellRangeAddress.valueOf("A1:A6"), - CellRangeAddress.valueOf("B1:B6") - }); - - readCf = cf.getConditionalFormattingAt(0); - formattingRanges = readCf.getFormattingRanges(); - assertEquals(2, formattingRanges.length); - formattingRange = formattingRanges[0]; - assertEquals("A1:A6", formattingRange.formatAsString()); - formattingRange = formattingRanges[1]; - assertEquals("B1:B6", formattingRange.formatAsString()); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetCellRangeAddressWithNullRanges() throws Exception { - Workbook wb = _testDataProvider.createWorkbook(); - final Sheet sheet = wb.createSheet("S1"); - final SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting(); - assertEquals(0, cf.getNumConditionalFormattings()); - ConditionalFormattingRule rule1 = cf.createConditionalFormattingRule("$A$1>0"); - cf.addConditionalFormatting(new CellRangeAddress[] { - CellRangeAddress.valueOf("A1:A5") - }, rule1); - - assertEquals(1, cf.getNumConditionalFormattings()); - ConditionalFormatting readCf = cf.getConditionalFormattingAt(0); - readCf.setFormattingRanges(null); - } - - - @SuppressWarnings("deprecation") - @Test - public void test52122() throws Exception { - Workbook workbook = _testDataProvider.createWorkbook(); - Sheet sheet = workbook.createSheet("Conditional Formatting Test"); - sheet.setColumnWidth(0, 256 * 10); - sheet.setColumnWidth(1, 256 * 10); - sheet.setColumnWidth(2, 256 * 10); - - // Create some content. - // row 0 - Row row = sheet.createRow(0); - - Cell cell0 = row.createCell(0); - cell0.setCellType(CellType.NUMERIC); - cell0.setCellValue(100); - - Cell cell1 = row.createCell(1); - cell1.setCellType(CellType.NUMERIC); - cell1.setCellValue(120); - - Cell cell2 = row.createCell(2); - cell2.setCellType(CellType.NUMERIC); - cell2.setCellValue(130); - - // row 1 - row = sheet.createRow(1); - - cell0 = row.createCell(0); - cell0.setCellType(CellType.NUMERIC); - cell0.setCellValue(200); - - cell1 = row.createCell(1); - cell1.setCellType(CellType.NUMERIC); - cell1.setCellValue(220); - - cell2 = row.createCell(2); - cell2.setCellType(CellType.NUMERIC); - cell2.setCellValue(230); - - // row 2 - row = sheet.createRow(2); - - cell0 = row.createCell(0); - cell0.setCellType(CellType.NUMERIC); - cell0.setCellValue(300); - - cell1 = row.createCell(1); - cell1.setCellType(CellType.NUMERIC); - cell1.setCellValue(320); - - cell2 = row.createCell(2); - cell2.setCellType(CellType.NUMERIC); - cell2.setCellValue(330); - - // Create conditional formatting, CELL1 should be yellow if CELL0 is not blank. - SheetConditionalFormatting formatting = sheet.getSheetConditionalFormatting(); - - ConditionalFormattingRule rule = formatting.createConditionalFormattingRule("$A$1>75"); - - PatternFormatting pattern = rule.createPatternFormatting(); - pattern.setFillBackgroundColor(IndexedColors.BLUE.index); - pattern.setFillPattern(PatternFormatting.SOLID_FOREGROUND); - - CellRangeAddress[] range = {CellRangeAddress.valueOf("B2:C2")}; - CellRangeAddress[] range2 = {CellRangeAddress.valueOf("B1:C1")}; - - formatting.addConditionalFormatting(range, rule); - formatting.addConditionalFormatting(range2, rule); - - // Write file. - /*FileOutputStream fos = new FileOutputStream("c:\\temp\\52122_conditional-sheet.xls"); - try { - workbook.write(fos); - } finally { - fos.close(); - }*/ - - Workbook wbBack = _testDataProvider.writeOutAndReadBack(workbook); - Sheet sheetBack = wbBack.getSheetAt(0); - final SheetConditionalFormatting sheetConditionalFormattingBack = sheetBack.getSheetConditionalFormatting(); - assertNotNull(sheetConditionalFormattingBack); - final ConditionalFormatting formattingBack = sheetConditionalFormattingBack.getConditionalFormattingAt(0); - assertNotNull(formattingBack); - final ConditionalFormattingRule ruleBack = formattingBack.getRule(0); - assertNotNull(ruleBack); - final PatternFormatting patternFormattingBack1 = ruleBack.getPatternFormatting(); - assertNotNull(patternFormattingBack1); - assertEquals(IndexedColors.BLUE.index, patternFormattingBack1.getFillBackgroundColor()); - assertEquals(PatternFormatting.SOLID_FOREGROUND, patternFormattingBack1.getFillPattern()); - } +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import org.apache.poi.hssf.usermodel.HSSFConditionalFormatting; +import org.apache.poi.hssf.usermodel.HSSFConditionalFormattingRule; +import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; +import org.apache.poi.ss.util.CellRangeAddress; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +/** + * Base tests for Conditional Formatting, for both HSSF and XSSF + */ +public abstract class BaseTestConditionalFormatting { + private final ITestDataProvider _testDataProvider; + + public BaseTestConditionalFormatting(ITestDataProvider testDataProvider){ + _testDataProvider = testDataProvider; + } + + protected abstract void assertColour(String hexExpected, Color actual); + + @Test + public void testBasic() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); + + assertEquals(0, sheetCF.getNumConditionalFormattings()); + try { + assertNull(sheetCF.getConditionalFormattingAt(0)); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); + } + + try { + sheetCF.removeConditionalFormatting(0); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); + } + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("1"); + ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule("2"); + ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule("3"); + ConditionalFormattingRule rule4 = sheetCF.createConditionalFormattingRule("4"); + try { + sheetCF.addConditionalFormatting(null, rule1); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("regions must not be null")); + } + try { + sheetCF.addConditionalFormatting( + new CellRangeAddress[]{ CellRangeAddress.valueOf("A1:A3") }, + (ConditionalFormattingRule)null); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("cfRules must not be null")); + } + + try { + sheetCF.addConditionalFormatting( + new CellRangeAddress[]{ CellRangeAddress.valueOf("A1:A3") }, + new ConditionalFormattingRule[0]); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("cfRules must not be empty")); + } + + try { + sheetCF.addConditionalFormatting( + new CellRangeAddress[]{ CellRangeAddress.valueOf("A1:A3") }, + new ConditionalFormattingRule[]{rule1, rule2, rule3, rule4}); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("Number of rules must not exceed 3")); + } + wb.close(); + } + + /** + * Test format conditions based on a boolean formula + */ + @Test + public void testBooleanFormulaConditions() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("SUM(A1:A5)>10"); + assertEquals(ConditionType.FORMULA, rule1.getConditionType()); + assertEquals("SUM(A1:A5)>10", rule1.getFormula1()); + int formatIndex1 = sheetCF.addConditionalFormatting( + new CellRangeAddress[]{ + CellRangeAddress.valueOf("B1"), + CellRangeAddress.valueOf("C3"), + }, rule1); + assertEquals(0, formatIndex1); + assertEquals(1, sheetCF.getNumConditionalFormattings()); + CellRangeAddress[] ranges1 = sheetCF.getConditionalFormattingAt(formatIndex1).getFormattingRanges(); + assertEquals(2, ranges1.length); + assertEquals("B1", ranges1[0].formatAsString()); + assertEquals("C3", ranges1[1].formatAsString()); + + // adjacent address are merged + int formatIndex2 = sheetCF.addConditionalFormatting( + new CellRangeAddress[]{ + CellRangeAddress.valueOf("B1"), + CellRangeAddress.valueOf("B2"), + CellRangeAddress.valueOf("B3"), + }, rule1); + assertEquals(1, formatIndex2); + assertEquals(2, sheetCF.getNumConditionalFormattings()); + CellRangeAddress[] ranges2 = sheetCF.getConditionalFormattingAt(formatIndex2).getFormattingRanges(); + assertEquals(1, ranges2.length); + assertEquals("B1:B3", ranges2[0].formatAsString()); + wb.close(); + } + + @Test + public void testSingleFormulaConditions() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.EQUAL, "SUM(A1:A5)+10"); + assertEquals(ConditionType.CELL_VALUE_IS, rule1.getConditionType()); + assertEquals("SUM(A1:A5)+10", rule1.getFormula1()); + assertEquals(ComparisonOperator.EQUAL, rule1.getComparisonOperation()); + + ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.NOT_EQUAL, "15"); + assertEquals(ConditionType.CELL_VALUE_IS, rule2.getConditionType()); + assertEquals("15", rule2.getFormula1()); + assertEquals(ComparisonOperator.NOT_EQUAL, rule2.getComparisonOperation()); + + ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.NOT_EQUAL, "15"); + assertEquals(ConditionType.CELL_VALUE_IS, rule3.getConditionType()); + assertEquals("15", rule3.getFormula1()); + assertEquals(ComparisonOperator.NOT_EQUAL, rule3.getComparisonOperation()); + + ConditionalFormattingRule rule4 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.GT, "0"); + assertEquals(ConditionType.CELL_VALUE_IS, rule4.getConditionType()); + assertEquals("0", rule4.getFormula1()); + assertEquals(ComparisonOperator.GT, rule4.getComparisonOperation()); + + ConditionalFormattingRule rule5 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.LT, "0"); + assertEquals(ConditionType.CELL_VALUE_IS, rule5.getConditionType()); + assertEquals("0", rule5.getFormula1()); + assertEquals(ComparisonOperator.LT, rule5.getComparisonOperation()); + + ConditionalFormattingRule rule6 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.GE, "0"); + assertEquals(ConditionType.CELL_VALUE_IS, rule6.getConditionType()); + assertEquals("0", rule6.getFormula1()); + assertEquals(ComparisonOperator.GE, rule6.getComparisonOperation()); + + ConditionalFormattingRule rule7 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.LE, "0"); + assertEquals(ConditionType.CELL_VALUE_IS, rule7.getConditionType()); + assertEquals("0", rule7.getFormula1()); + assertEquals(ComparisonOperator.LE, rule7.getComparisonOperation()); + + ConditionalFormattingRule rule8 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.BETWEEN, "0", "5"); + assertEquals(ConditionType.CELL_VALUE_IS, rule8.getConditionType()); + assertEquals("0", rule8.getFormula1()); + assertEquals("5", rule8.getFormula2()); + assertEquals(ComparisonOperator.BETWEEN, rule8.getComparisonOperation()); + + ConditionalFormattingRule rule9 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.NOT_BETWEEN, "0", "5"); + assertEquals(ConditionType.CELL_VALUE_IS, rule9.getConditionType()); + assertEquals("0", rule9.getFormula1()); + assertEquals("5", rule9.getFormula2()); + assertEquals(ComparisonOperator.NOT_BETWEEN, rule9.getComparisonOperation()); + + wb.close(); + } + + @Test + public void testCopy() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet1 = wb.createSheet(); + Sheet sheet2 = wb.createSheet(); + SheetConditionalFormatting sheet1CF = sheet1.getSheetConditionalFormatting(); + SheetConditionalFormatting sheet2CF = sheet2.getSheetConditionalFormatting(); + assertEquals(0, sheet1CF.getNumConditionalFormattings()); + assertEquals(0, sheet2CF.getNumConditionalFormattings()); + + ConditionalFormattingRule rule1 = sheet1CF.createConditionalFormattingRule( + ComparisonOperator.EQUAL, "SUM(A1:A5)+10"); + + ConditionalFormattingRule rule2 = sheet1CF.createConditionalFormattingRule( + ComparisonOperator.NOT_EQUAL, "15"); + + // adjacent address are merged + int formatIndex = sheet1CF.addConditionalFormatting( + new CellRangeAddress[]{ + CellRangeAddress.valueOf("A1:A5"), + CellRangeAddress.valueOf("C1:C5") + }, rule1, rule2); + assertEquals(0, formatIndex); + assertEquals(1, sheet1CF.getNumConditionalFormattings()); + + assertEquals(0, sheet2CF.getNumConditionalFormattings()); + sheet2CF.addConditionalFormatting(sheet1CF.getConditionalFormattingAt(formatIndex)); + assertEquals(1, sheet2CF.getNumConditionalFormattings()); + + ConditionalFormatting sheet2cf = sheet2CF.getConditionalFormattingAt(0); + assertEquals(2, sheet2cf.getNumberOfRules()); + assertEquals("SUM(A1:A5)+10", sheet2cf.getRule(0).getFormula1()); + assertEquals(ComparisonOperator.EQUAL, sheet2cf.getRule(0).getComparisonOperation()); + assertEquals(ConditionType.CELL_VALUE_IS, sheet2cf.getRule(0).getConditionType()); + assertEquals("15", sheet2cf.getRule(1).getFormula1()); + assertEquals(ComparisonOperator.NOT_EQUAL, sheet2cf.getRule(1).getComparisonOperation()); + assertEquals(ConditionType.CELL_VALUE_IS, sheet2cf.getRule(1).getConditionType()); + + wb.close(); + } + + @Test + public void testRemove() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet1 = wb.createSheet(); + SheetConditionalFormatting sheetCF = sheet1.getSheetConditionalFormatting(); + assertEquals(0, sheetCF.getNumConditionalFormattings()); + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.EQUAL, "SUM(A1:A5)"); + + // adjacent address are merged + int formatIndex = sheetCF.addConditionalFormatting( + new CellRangeAddress[]{ + CellRangeAddress.valueOf("A1:A5") + }, rule1); + assertEquals(0, formatIndex); + assertEquals(1, sheetCF.getNumConditionalFormattings()); + sheetCF.removeConditionalFormatting(0); + assertEquals(0, sheetCF.getNumConditionalFormattings()); + try { + assertNull(sheetCF.getConditionalFormattingAt(0)); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); + } + + formatIndex = sheetCF.addConditionalFormatting( + new CellRangeAddress[]{ + CellRangeAddress.valueOf("A1:A5") + }, rule1); + assertEquals(0, formatIndex); + assertEquals(1, sheetCF.getNumConditionalFormattings()); + sheetCF.removeConditionalFormatting(0); + assertEquals(0, sheetCF.getNumConditionalFormattings()); + try { + assertNull(sheetCF.getConditionalFormattingAt(0)); + fail("expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().startsWith("Specified CF index 0 is outside the allowable range")); + } + + wb.close(); + } + + @Test + public void testCreateCF() throws IOException { + Workbook workbook = _testDataProvider.createWorkbook(); + Sheet sheet = workbook.createSheet(); + String formula = "7"; + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(formula); + FontFormatting fontFmt = rule1.createFontFormatting(); + fontFmt.setFontStyle(true, false); + + BorderFormatting bordFmt = rule1.createBorderFormatting(); + bordFmt.setBorderBottom(BorderStyle.THIN); + bordFmt.setBorderTop(BorderStyle.THICK); + bordFmt.setBorderLeft(BorderStyle.DASHED); + bordFmt.setBorderRight(BorderStyle.DOTTED); + + PatternFormatting patternFmt = rule1.createPatternFormatting(); + patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index); + + + ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2"); + ConditionalFormattingRule [] cfRules = + { + rule1, rule2 + }; + + short col = 1; + CellRangeAddress [] regions = { + new CellRangeAddress(0, 65535, col, col) + }; + + sheetCF.addConditionalFormatting(regions, cfRules); + sheetCF.addConditionalFormatting(regions, cfRules); + + // Verification + assertEquals(2, sheetCF.getNumConditionalFormattings()); + sheetCF.removeConditionalFormatting(1); + assertEquals(1, sheetCF.getNumConditionalFormattings()); + ConditionalFormatting cf = sheetCF.getConditionalFormattingAt(0); + assertNotNull(cf); + + regions = cf.getFormattingRanges(); + assertNotNull(regions); + assertEquals(1, regions.length); + CellRangeAddress r = regions[0]; + assertEquals(1, r.getFirstColumn()); + assertEquals(1, r.getLastColumn()); + assertEquals(0, r.getFirstRow()); + assertEquals(65535, r.getLastRow()); + + assertEquals(2, cf.getNumberOfRules()); + + rule1 = cf.getRule(0); + assertEquals("7",rule1.getFormula1()); + assertNull(rule1.getFormula2()); + + FontFormatting r1fp = rule1.getFontFormatting(); + assertNotNull(r1fp); + + assertTrue(r1fp.isItalic()); + assertFalse(r1fp.isBold()); + + BorderFormatting r1bf = rule1.getBorderFormatting(); + assertNotNull(r1bf); + assertEquals(BorderStyle.THIN, r1bf.getBorderBottomEnum()); + assertEquals(BorderStyle.THICK,r1bf.getBorderTopEnum()); + assertEquals(BorderStyle.DASHED,r1bf.getBorderLeftEnum()); + assertEquals(BorderStyle.DOTTED,r1bf.getBorderRightEnum()); + + PatternFormatting r1pf = rule1.getPatternFormatting(); + assertNotNull(r1pf); +// assertEquals(IndexedColors.YELLOW.index,r1pf.getFillBackgroundColor()); + + rule2 = cf.getRule(1); + assertEquals("2",rule2.getFormula2()); + assertEquals("1",rule2.getFormula1()); + + workbook.close(); + } + + @Test + public void testClone() throws IOException { + + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet = wb.createSheet(); + String formula = "7"; + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(formula); + FontFormatting fontFmt = rule1.createFontFormatting(); + fontFmt.setFontStyle(true, false); + + PatternFormatting patternFmt = rule1.createPatternFormatting(); + patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index); + + + ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.BETWEEN, "1", "2"); + ConditionalFormattingRule [] cfRules = + { + rule1, rule2 + }; + + short col = 1; + CellRangeAddress [] regions = { + new CellRangeAddress(0, 65535, col, col) + }; + + sheetCF.addConditionalFormatting(regions, cfRules); + + try { + wb.cloneSheet(0); + assertEquals(2, wb.getNumberOfSheets()); + } catch (RuntimeException e) { + if (e.getMessage().indexOf("needs to define a clone method") > 0) { + fail("Identified bug 45682"); + } + throw e; + } finally { + wb.close(); + } + } + + @Test + public void testShiftRows() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet = wb.createSheet(); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.BETWEEN, "SUM(A10:A15)", "1+SUM(B16:B30)"); + FontFormatting fontFmt = rule1.createFontFormatting(); + fontFmt.setFontStyle(true, false); + + PatternFormatting patternFmt = rule1.createPatternFormatting(); + patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index); + + ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule( + ComparisonOperator.BETWEEN, "SUM(A10:A15)", "1+SUM(B16:B30)"); + BorderFormatting borderFmt = rule2.createBorderFormatting(); + borderFmt.setBorderDiagonal(BorderStyle.MEDIUM); + + CellRangeAddress [] regions = { + new CellRangeAddress(2, 4, 0, 0), // A3:A5 + }; + sheetCF.addConditionalFormatting(regions, rule1); + sheetCF.addConditionalFormatting(regions, rule2); + + // This row-shift should destroy the CF region + sheet.shiftRows(10, 20, -9); + assertEquals(0, sheetCF.getNumConditionalFormattings()); + + // re-add the CF + sheetCF.addConditionalFormatting(regions, rule1); + sheetCF.addConditionalFormatting(regions, rule2); + + // This row shift should only affect the formulas + sheet.shiftRows(14, 17, 8); + ConditionalFormatting cf1 = sheetCF.getConditionalFormattingAt(0); + assertEquals("SUM(A10:A23)", cf1.getRule(0).getFormula1()); + assertEquals("1+SUM(B24:B30)", cf1.getRule(0).getFormula2()); + ConditionalFormatting cf2 = sheetCF.getConditionalFormattingAt(1); + assertEquals("SUM(A10:A23)", cf2.getRule(0).getFormula1()); + assertEquals("1+SUM(B24:B30)", cf2.getRule(0).getFormula2()); + + sheet.shiftRows(0, 8, 21); + cf1 = sheetCF.getConditionalFormattingAt(0); + assertEquals("SUM(A10:A21)", cf1.getRule(0).getFormula1()); + assertEquals("1+SUM(#REF!)", cf1.getRule(0).getFormula2()); + cf2 = sheetCF.getConditionalFormattingAt(1); + assertEquals("SUM(A10:A21)", cf2.getRule(0).getFormula1()); + assertEquals("1+SUM(#REF!)", cf2.getRule(0).getFormula2()); + + wb.close(); + } + + protected void testRead(String filename) throws IOException { + Workbook wb = _testDataProvider.openSampleWorkbook(filename); + Sheet sh = wb.getSheet("CF"); + SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); + assertEquals(3, sheetCF.getNumConditionalFormattings()); + + ConditionalFormatting cf1 = sheetCF.getConditionalFormattingAt(0); + assertEquals(2, cf1.getNumberOfRules()); + + CellRangeAddress[] regions1 = cf1.getFormattingRanges(); + assertEquals(1, regions1.length); + assertEquals("A1:A8", regions1[0].formatAsString()); + + // CF1 has two rules: values less than -3 are bold-italic red, values greater than 3 are green + ConditionalFormattingRule rule1 = cf1.getRule(0); + assertEquals(ConditionType.CELL_VALUE_IS, rule1.getConditionType()); + assertEquals(ComparisonOperator.GT, rule1.getComparisonOperation()); + assertEquals("3", rule1.getFormula1()); + assertNull(rule1.getFormula2()); + // fills and borders are not set + assertNull(rule1.getPatternFormatting()); + assertNull(rule1.getBorderFormatting()); + + FontFormatting fmt1 = rule1.getFontFormatting(); +// assertEquals(IndexedColors.GREEN.index, fmt1.getFontColorIndex()); + assertTrue(fmt1.isBold()); + assertFalse(fmt1.isItalic()); + + ConditionalFormattingRule rule2 = cf1.getRule(1); + assertEquals(ConditionType.CELL_VALUE_IS, rule2.getConditionType()); + assertEquals(ComparisonOperator.LT, rule2.getComparisonOperation()); + assertEquals("-3", rule2.getFormula1()); + assertNull(rule2.getFormula2()); + assertNull(rule2.getPatternFormatting()); + assertNull(rule2.getBorderFormatting()); + + FontFormatting fmt2 = rule2.getFontFormatting(); +// assertEquals(IndexedColors.RED.index, fmt2.getFontColorIndex()); + assertTrue(fmt2.isBold()); + assertTrue(fmt2.isItalic()); + + + ConditionalFormatting cf2 = sheetCF.getConditionalFormattingAt(1); + assertEquals(1, cf2.getNumberOfRules()); + CellRangeAddress[] regions2 = cf2.getFormattingRanges(); + assertEquals(1, regions2.length); + assertEquals("B9", regions2[0].formatAsString()); + + ConditionalFormattingRule rule3 = cf2.getRule(0); + assertEquals(ConditionType.FORMULA, rule3.getConditionType()); + assertEquals(ComparisonOperator.NO_COMPARISON, rule3.getComparisonOperation()); + assertEquals("$A$8>5", rule3.getFormula1()); + assertNull(rule3.getFormula2()); + + FontFormatting fmt3 = rule3.getFontFormatting(); +// assertEquals(IndexedColors.RED.index, fmt3.getFontColorIndex()); + assertTrue(fmt3.isBold()); + assertTrue(fmt3.isItalic()); + + PatternFormatting fmt4 = rule3.getPatternFormatting(); +// assertEquals(IndexedColors.LIGHT_CORNFLOWER_BLUE.index, fmt4.getFillBackgroundColor()); +// assertEquals(IndexedColors.AUTOMATIC.index, fmt4.getFillForegroundColor()); + assertEquals(PatternFormatting.NO_FILL, fmt4.getFillPattern()); + // borders are not set + assertNull(rule3.getBorderFormatting()); + + ConditionalFormatting cf3 = sheetCF.getConditionalFormattingAt(2); + CellRangeAddress[] regions3 = cf3.getFormattingRanges(); + assertEquals(1, regions3.length); + assertEquals("B1:B7", regions3[0].formatAsString()); + assertEquals(2, cf3.getNumberOfRules()); + + ConditionalFormattingRule rule4 = cf3.getRule(0); + assertEquals(ConditionType.CELL_VALUE_IS, rule4.getConditionType()); + assertEquals(ComparisonOperator.LE, rule4.getComparisonOperation()); + assertEquals("\"AAA\"", rule4.getFormula1()); + assertNull(rule4.getFormula2()); + + ConditionalFormattingRule rule5 = cf3.getRule(1); + assertEquals(ConditionType.CELL_VALUE_IS, rule5.getConditionType()); + assertEquals(ComparisonOperator.BETWEEN, rule5.getComparisonOperation()); + assertEquals("\"A\"", rule5.getFormula1()); + assertEquals("\"AAA\"", rule5.getFormula2()); + + wb.close(); + } + + public void testReadOffice2007(String filename) throws IOException { + Workbook wb = _testDataProvider.openSampleWorkbook(filename); + Sheet s = wb.getSheet("CF"); + + // Sanity check data + assertEquals("Values", s.getRow(0).getCell(0).toString()); + assertEquals("10.0", s.getRow(2).getCell(0).toString()); + + // Check we found all the conditional formatting rules we should have + SheetConditionalFormatting sheetCF = s.getSheetConditionalFormatting(); + int numCF = 3; + int numCF12 = 15; + int numCFEX = 0; // TODO This should be 2, but we don't support CFEX formattings yet, see #58149 + assertEquals(numCF+numCF12+numCFEX, sheetCF.getNumConditionalFormattings()); + + int fCF = 0, fCF12 = 0, fCFEX = 0; + for (int i=0; iYellow->Green - Column F + cf = sheetCF.getConditionalFormattingAt(3); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("F2:F17", cf.getFormattingRanges()[0].formatAsString()); + assertColorScale(cf, "F8696B", "FFEB84", "63BE7B"); + + + // Colours Blue->White->Red - Column G + cf = sheetCF.getConditionalFormattingAt(4); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("G2:G17", cf.getFormattingRanges()[0].formatAsString()); + assertColorScale(cf, "5A8AC6", "FCFCFF", "F8696B"); + + + // Icons : Default - Column H, percentage thresholds + cf = sheetCF.getConditionalFormattingAt(5); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("H2:H17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_TRAFFIC_LIGHTS, 0d, 33d, 67d); + + + // Icons : 3 signs - Column I + cf = sheetCF.getConditionalFormattingAt(6); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("I2:I17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_SHAPES, 0d, 33d, 67d); + + + // Icons : 3 traffic lights 2 - Column J + cf = sheetCF.getConditionalFormattingAt(7); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("J2:J17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_TRAFFIC_LIGHTS_BOX, 0d, 33d, 67d); + + + // Icons : 4 traffic lights - Column K + cf = sheetCF.getConditionalFormattingAt(8); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("K2:K17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYRB_4_TRAFFIC_LIGHTS, 0d, 25d, 50d, 75d); + + + // Icons : 3 symbols with backgrounds - Column L + cf = sheetCF.getConditionalFormattingAt(9); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("L2:L17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_SYMBOLS_CIRCLE, 0d, 33d, 67d); + + + // Icons : 3 flags - Column M2 Only + cf = sheetCF.getConditionalFormattingAt(10); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("M2", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_FLAGS, 0d, 33d, 67d); + + // Icons : 3 flags - Column M (all) + cf = sheetCF.getConditionalFormattingAt(11); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("M2:M17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_FLAGS, 0d, 33d, 67d); + + + // Icons : 3 symbols 2 (no background) - Column N + cf = sheetCF.getConditionalFormattingAt(12); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("N2:N17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_SYMBOLS, 0d, 33d, 67d); + + + // Icons : 3 arrows - Column O + cf = sheetCF.getConditionalFormattingAt(13); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("O2:O17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_ARROW, 0d, 33d, 67d); + + + // Icons : 5 arrows grey - Column P + cf = sheetCF.getConditionalFormattingAt(14); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("P2:P17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GREY_5_ARROWS, 0d, 20d, 40d, 60d, 80d); + + + // Icons : 3 stars (ext) - Column Q + // TODO Support EXT formattings + + + // Icons : 4 ratings - Column R + cf = sheetCF.getConditionalFormattingAt(15); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("R2:R17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.RATINGS_4, 0d, 25d, 50d, 75d); + + + // Icons : 5 ratings - Column S + cf = sheetCF.getConditionalFormattingAt(16); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("S2:S17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.RATINGS_5, 0d, 20d, 40d, 60d, 80d); + + + // Custom Icon+Format - Column T + cf = sheetCF.getConditionalFormattingAt(17); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("T2:T17", cf.getFormattingRanges()[0].formatAsString()); + + // TODO Support IconSet + Other CFs with 2 rules +// assertEquals(2, cf.getNumberOfRules()); +// cr = cf.getRule(0); +// assertIconSetPercentages(cr, IconSet.GYR_3_TRAFFIC_LIGHTS_BOX, 0d, 33d, 67d); +// cr = cf.getRule(1); +// assertEquals(ConditionType.FORMULA, cr.getConditionType()); +// assertEquals(ComparisonOperator.NO_COMPARISON, cr.getComparisonOperation()); +// // TODO Why aren't these two the same between formats? +// if (cr instanceof HSSFConditionalFormattingRule) { +// assertEquals("MOD(ROW($T1),2)=1", cr.getFormula1()); +// } else { +// assertEquals("MOD(ROW($T2),2)=1", cr.getFormula1()); +// } +// assertEquals(null, cr.getFormula2()); + + + // Mixed icons - Column U + // TODO Support EXT formattings + + wb.close(); + } + + private void assertDataBar(ConditionalFormatting cf, String color) { + assertEquals(1, cf.getNumberOfRules()); + ConditionalFormattingRule cr = cf.getRule(0); + assertDataBar(cr, color); + } + private void assertDataBar(ConditionalFormattingRule cr, String color) { + assertEquals(ConditionType.DATA_BAR, cr.getConditionType()); + assertEquals(ComparisonOperator.NO_COMPARISON, cr.getComparisonOperation()); + assertEquals(null, cr.getFormula1()); + assertEquals(null, cr.getFormula2()); + + DataBarFormatting databar = cr.getDataBarFormatting(); + assertNotNull(databar); + assertEquals(false, databar.isIconOnly()); + assertEquals(true, databar.isLeftToRight()); + assertEquals(0, databar.getWidthMin()); + assertEquals(100, databar.getWidthMax()); + + assertColour(color, databar.getColor()); + + ConditionalFormattingThreshold th; + th = databar.getMinThreshold(); + assertEquals(RangeType.MIN, th.getRangeType()); + assertEquals(null, th.getValue()); + assertEquals(null, th.getFormula()); + th = databar.getMaxThreshold(); + assertEquals(RangeType.MAX, th.getRangeType()); + assertEquals(null, th.getValue()); + assertEquals(null, th.getFormula()); + } + + private void assertIconSetPercentages(ConditionalFormatting cf, IconSet iconset, Double...vals) { + assertEquals(1, cf.getNumberOfRules()); + ConditionalFormattingRule cr = cf.getRule(0); + assertIconSetPercentages(cr, iconset, vals); + } + private void assertIconSetPercentages(ConditionalFormattingRule cr, IconSet iconset, Double...vals) { + assertEquals(ConditionType.ICON_SET, cr.getConditionType()); + assertEquals(ComparisonOperator.NO_COMPARISON, cr.getComparisonOperation()); + assertEquals(null, cr.getFormula1()); + assertEquals(null, cr.getFormula2()); + + IconMultiStateFormatting icon = cr.getMultiStateFormatting(); + assertNotNull(icon); + assertEquals(iconset, icon.getIconSet()); + assertEquals(false, icon.isIconOnly()); + assertEquals(false, icon.isReversed()); + + assertNotNull(icon.getThresholds()); + assertEquals(vals.length, icon.getThresholds().length); + for (int i=0; i0"); + sheet.getSheetConditionalFormatting().addConditionalFormatting(ranges, rule); + wb.close(); + } + + @Test + public void testSetCellRangeAddresswithSingleRange() throws Exception { + Workbook wb = _testDataProvider.createWorkbook(); + final Sheet sheet = wb.createSheet("S1"); + final SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting(); + assertEquals(0, cf.getNumConditionalFormattings()); + ConditionalFormattingRule rule1 = cf.createConditionalFormattingRule("$A$1>0"); + cf.addConditionalFormatting(new CellRangeAddress[] { + CellRangeAddress.valueOf("A1:A5") + }, rule1); + + assertEquals(1, cf.getNumConditionalFormattings()); + ConditionalFormatting readCf = cf.getConditionalFormattingAt(0); + CellRangeAddress[] formattingRanges = readCf.getFormattingRanges(); + assertEquals(1, formattingRanges.length); + CellRangeAddress formattingRange = formattingRanges[0]; + assertEquals("A1:A5", formattingRange.formatAsString()); + + readCf.setFormattingRanges(new CellRangeAddress[] { + CellRangeAddress.valueOf("A1:A6") + }); + + readCf = cf.getConditionalFormattingAt(0); + formattingRanges = readCf.getFormattingRanges(); + assertEquals(1, formattingRanges.length); + formattingRange = formattingRanges[0]; + assertEquals("A1:A6", formattingRange.formatAsString()); + } + + @Test + public void testSetCellRangeAddressWithMultipleRanges() throws Exception { + Workbook wb = _testDataProvider.createWorkbook(); + final Sheet sheet = wb.createSheet("S1"); + final SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting(); + assertEquals(0, cf.getNumConditionalFormattings()); + ConditionalFormattingRule rule1 = cf.createConditionalFormattingRule("$A$1>0"); + cf.addConditionalFormatting(new CellRangeAddress[] { + CellRangeAddress.valueOf("A1:A5") + }, rule1); + + assertEquals(1, cf.getNumConditionalFormattings()); + ConditionalFormatting readCf = cf.getConditionalFormattingAt(0); + CellRangeAddress[] formattingRanges = readCf.getFormattingRanges(); + assertEquals(1, formattingRanges.length); + CellRangeAddress formattingRange = formattingRanges[0]; + assertEquals("A1:A5", formattingRange.formatAsString()); + + readCf.setFormattingRanges(new CellRangeAddress[] { + CellRangeAddress.valueOf("A1:A6"), + CellRangeAddress.valueOf("B1:B6") + }); + + readCf = cf.getConditionalFormattingAt(0); + formattingRanges = readCf.getFormattingRanges(); + assertEquals(2, formattingRanges.length); + formattingRange = formattingRanges[0]; + assertEquals("A1:A6", formattingRange.formatAsString()); + formattingRange = formattingRanges[1]; + assertEquals("B1:B6", formattingRange.formatAsString()); + } + + @Test(expected = IllegalArgumentException.class) + public void testSetCellRangeAddressWithNullRanges() throws Exception { + Workbook wb = _testDataProvider.createWorkbook(); + final Sheet sheet = wb.createSheet("S1"); + final SheetConditionalFormatting cf = sheet.getSheetConditionalFormatting(); + assertEquals(0, cf.getNumConditionalFormattings()); + ConditionalFormattingRule rule1 = cf.createConditionalFormattingRule("$A$1>0"); + cf.addConditionalFormatting(new CellRangeAddress[] { + CellRangeAddress.valueOf("A1:A5") + }, rule1); + + assertEquals(1, cf.getNumConditionalFormattings()); + ConditionalFormatting readCf = cf.getConditionalFormattingAt(0); + readCf.setFormattingRanges(null); + } + + + @SuppressWarnings("deprecation") + @Test + public void test52122() throws Exception { + Workbook workbook = _testDataProvider.createWorkbook(); + Sheet sheet = workbook.createSheet("Conditional Formatting Test"); + sheet.setColumnWidth(0, 256 * 10); + sheet.setColumnWidth(1, 256 * 10); + sheet.setColumnWidth(2, 256 * 10); + + // Create some content. + // row 0 + Row row = sheet.createRow(0); + + Cell cell0 = row.createCell(0); + cell0.setCellType(CellType.NUMERIC); + cell0.setCellValue(100); + + Cell cell1 = row.createCell(1); + cell1.setCellType(CellType.NUMERIC); + cell1.setCellValue(120); + + Cell cell2 = row.createCell(2); + cell2.setCellType(CellType.NUMERIC); + cell2.setCellValue(130); + + // row 1 + row = sheet.createRow(1); + + cell0 = row.createCell(0); + cell0.setCellType(CellType.NUMERIC); + cell0.setCellValue(200); + + cell1 = row.createCell(1); + cell1.setCellType(CellType.NUMERIC); + cell1.setCellValue(220); + + cell2 = row.createCell(2); + cell2.setCellType(CellType.NUMERIC); + cell2.setCellValue(230); + + // row 2 + row = sheet.createRow(2); + + cell0 = row.createCell(0); + cell0.setCellType(CellType.NUMERIC); + cell0.setCellValue(300); + + cell1 = row.createCell(1); + cell1.setCellType(CellType.NUMERIC); + cell1.setCellValue(320); + + cell2 = row.createCell(2); + cell2.setCellType(CellType.NUMERIC); + cell2.setCellValue(330); + + // Create conditional formatting, CELL1 should be yellow if CELL0 is not blank. + SheetConditionalFormatting formatting = sheet.getSheetConditionalFormatting(); + + ConditionalFormattingRule rule = formatting.createConditionalFormattingRule("$A$1>75"); + + PatternFormatting pattern = rule.createPatternFormatting(); + pattern.setFillBackgroundColor(IndexedColors.BLUE.index); + pattern.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + CellRangeAddress[] range = {CellRangeAddress.valueOf("B2:C2")}; + CellRangeAddress[] range2 = {CellRangeAddress.valueOf("B1:C1")}; + + formatting.addConditionalFormatting(range, rule); + formatting.addConditionalFormatting(range2, rule); + + // Write file. + /*FileOutputStream fos = new FileOutputStream("c:\\temp\\52122_conditional-sheet.xls"); + try { + workbook.write(fos); + } finally { + fos.close(); + }*/ + + Workbook wbBack = _testDataProvider.writeOutAndReadBack(workbook); + Sheet sheetBack = wbBack.getSheetAt(0); + final SheetConditionalFormatting sheetConditionalFormattingBack = sheetBack.getSheetConditionalFormatting(); + assertNotNull(sheetConditionalFormattingBack); + final ConditionalFormatting formattingBack = sheetConditionalFormattingBack.getConditionalFormattingAt(0); + assertNotNull(formattingBack); + final ConditionalFormattingRule ruleBack = formattingBack.getRule(0); + assertNotNull(ruleBack); + final PatternFormatting patternFormattingBack1 = ruleBack.getPatternFormatting(); + assertNotNull(patternFormattingBack1); + assertEquals(IndexedColors.BLUE.index, patternFormattingBack1.getFillBackgroundColor()); + assertEquals(PatternFormatting.SOLID_FOREGROUND, patternFormattingBack1.getFillPattern()); + } } \ No newline at end of file diff --git a/src/testcases/org/apache/poi/ss/util/BaseTestCellUtil.java b/src/testcases/org/apache/poi/ss/util/BaseTestCellUtil.java index 29bc3cd8a7..ac88fdad48 100644 --- a/src/testcases/org/apache/poi/ss/util/BaseTestCellUtil.java +++ b/src/testcases/org/apache/poi/ss/util/BaseTestCellUtil.java @@ -1,416 +1,416 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ==================================================================== */ - -package org.apache.poi.ss.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.apache.poi.ss.ITestDataProvider; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.ss.usermodel.Workbook; -import org.junit.Test; - -/** - * Tests Spreadsheet CellUtil - * - * @see org.apache.poi.ss.util.CellUtil - */ -public class BaseTestCellUtil { - protected final ITestDataProvider _testDataProvider; - - protected BaseTestCellUtil(ITestDataProvider testDataProvider) { - _testDataProvider = testDataProvider; - } - - @Test - public void setCellStyleProperty() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet s = wb.createSheet(); - Row r = s.createRow(0); - Cell c = r.createCell(0); - - // Add a border should create a new style - int styCnt1 = wb.getNumCellStyles(); - CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, BorderStyle.THIN); - int styCnt2 = wb.getNumCellStyles(); - assertEquals(styCnt1+1, styCnt2); - - // Add same border to another cell, should not create another style - c = r.createCell(1); - CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, BorderStyle.THIN); - int styCnt3 = wb.getNumCellStyles(); - assertEquals(styCnt2, styCnt3); - - wb.close(); - } - - @Test(expected=RuntimeException.class) - public void setCellStylePropertyWithInvalidValue() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - try { - Sheet s = wb.createSheet(); - Row r = s.createRow(0); - Cell c = r.createCell(0); - - // An invalid BorderStyle constant - CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, 42); - } finally { - wb.close(); - } - } - - @Test() - public void setCellStylePropertyBorderWithShortAndEnum() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet s = wb.createSheet(); - Row r = s.createRow(0); - Cell c = r.createCell(0); - - // A valid BorderStyle constant, as a Short - CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, BorderStyle.DASH_DOT.getCode()); - assertEquals(BorderStyle.DASH_DOT, c.getCellStyle().getBorderBottomEnum()); - - // A valid BorderStyle constant, as an Enum - CellUtil.setCellStyleProperty(c, CellUtil.BORDER_TOP, BorderStyle.MEDIUM_DASH_DOT); - assertEquals(BorderStyle.MEDIUM_DASH_DOT, c.getCellStyle().getBorderTopEnum()); - - wb.close(); - } - - @Test - public void setCellStyleProperties() throws IOException { - System.out.println("setCellStyleProps start"); - Workbook wb = _testDataProvider.createWorkbook(); - Sheet s = wb.createSheet(); - Row r = s.createRow(0); - Cell c = r.createCell(0); - - // Add multiple border properties to cell should create a single new style - int styCnt1 = wb.getNumCellStyles(); - Map props = new HashMap(); - props.put(CellUtil.BORDER_TOP, BorderStyle.THIN); - props.put(CellUtil.BORDER_BOTTOM, BorderStyle.THIN); - props.put(CellUtil.BORDER_LEFT, BorderStyle.THIN); - props.put(CellUtil.BORDER_RIGHT, BorderStyle.THIN); - props.put(CellUtil.ALIGNMENT, HorizontalAlignment.CENTER.getCode()); // try it both with a Short (deprecated) - props.put(CellUtil.VERTICAL_ALIGNMENT, VerticalAlignment.CENTER); // and with an enum - CellUtil.setCellStyleProperties(c, props); - int styCnt2 = wb.getNumCellStyles(); - assertEquals("Only one additional style should have been created", styCnt1 + 1, styCnt2); - - // Add same border another to same cell, should not create another style - c = r.createCell(1); - CellUtil.setCellStyleProperties(c, props); - int styCnt3 = wb.getNumCellStyles(); - System.out.println("setCellStyleProps nearing end"); - assertEquals("No additional styles should have been created", styCnt2, styCnt3); - - wb.close(); - - } - - @Test - public void getRow() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - Row row1 = sh.createRow(0); - - // Get row that already exists - Row r1 = CellUtil.getRow(0, sh); - assertNotNull(r1); - assertSame("An existing row should not be recreated", row1, r1); - - // Get row that does not exist yet - assertNotNull(CellUtil.getRow(1, sh)); - - wb.close(); - } - - @Test - public void getCell() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - Row row = sh.createRow(0); - Cell A1 = row.createCell(0); - - // Get cell that already exists - Cell a1 = CellUtil.getCell(row, 0); - assertNotNull(a1); - assertSame("An existing cell should not be recreated", A1, a1); - - // Get cell that does not exist yet - assertNotNull(CellUtil.getCell(row, 1)); - - wb.close(); - } - - @Test - public void createCell() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - Row row = sh.createRow(0); - - CellStyle style = wb.createCellStyle(); - style.setWrapText(true); - - // calling createCell on a non-existing cell should create a cell and set the cell value and style. - Cell F1 = CellUtil.createCell(row, 5, "Cell Value", style); - - assertSame(row.getCell(5), F1); - assertEquals("Cell Value", F1.getStringCellValue()); - assertEquals(style, F1.getCellStyle()); - // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. - // HSSFCellStyle wraps an underlying style record, and the underlying - // style record is the same between multiple getCellStyle() calls. - - // calling createCell on an existing cell should return the existing cell and modify the cell value and style. - Cell f1 = CellUtil.createCell(row, 5, "Overwritten cell value", null); - assertSame(row.getCell(5), f1); - assertSame(F1, f1); - assertEquals("Overwritten cell value", f1.getStringCellValue()); - assertEquals("Overwritten cell value", F1.getStringCellValue()); - assertEquals("cell style should be unchanged with createCell(..., null)", style, f1.getCellStyle()); - assertEquals("cell style should be unchanged with createCell(..., null)", style, F1.getCellStyle()); - - // test createCell(row, column, value) (no CellStyle) - f1 = CellUtil.createCell(row, 5, "Overwritten cell with default style"); - assertSame(F1, f1); - - wb.close(); - - } - - /** - * @deprecated by {@link #setAlignmentEnum()} - * - * @throws IOException - * - */ - @Deprecated - @SuppressWarnings("deprecated") - @Test - public void setAlignment() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - Row row = sh.createRow(0); - Cell A1 = row.createCell(0); - Cell B1 = row.createCell(1); - - // Assumptions - assertEquals(A1.getCellStyle(), B1.getCellStyle()); - // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. - // HSSFCellStyle wraps an underlying style record, and the underlying - // style record is the same between multiple getCellStyle() calls. - assertEquals(CellStyle.ALIGN_GENERAL, A1.getCellStyle().getAlignment()); - assertEquals(CellStyle.ALIGN_GENERAL, B1.getCellStyle().getAlignment()); - - // get/set alignment modifies the cell's style - CellUtil.setAlignment(A1, null, CellStyle.ALIGN_RIGHT); - assertEquals(CellStyle.ALIGN_RIGHT, A1.getCellStyle().getAlignment()); - - // get/set alignment doesn't affect the style of cells with - // the same style prior to modifying the style - assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); - assertEquals(CellStyle.ALIGN_GENERAL, B1.getCellStyle().getAlignment()); - - wb.close(); - } - - @Test - public void setAlignmentEnum() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - Row row = sh.createRow(0); - Cell A1 = row.createCell(0); - Cell B1 = row.createCell(1); - - // Assumptions - assertEquals(A1.getCellStyle(), B1.getCellStyle()); - // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. - // HSSFCellStyle wraps an underlying style record, and the underlying - // style record is the same between multiple getCellStyle() calls. - assertEquals(HorizontalAlignment.GENERAL, A1.getCellStyle().getAlignmentEnum()); - assertEquals(HorizontalAlignment.GENERAL, B1.getCellStyle().getAlignmentEnum()); - - // get/set alignment modifies the cell's style - CellUtil.setAlignment(A1, HorizontalAlignment.RIGHT); - assertEquals(HorizontalAlignment.RIGHT, A1.getCellStyle().getAlignmentEnum()); - - // get/set alignment doesn't affect the style of cells with - // the same style prior to modifying the style - assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); - assertEquals(HorizontalAlignment.GENERAL, B1.getCellStyle().getAlignmentEnum()); - - wb.close(); - } - - @Test - public void setVerticalAlignmentEnum() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - Row row = sh.createRow(0); - Cell A1 = row.createCell(0); - Cell B1 = row.createCell(1); - - // Assumptions - assertEquals(A1.getCellStyle(), B1.getCellStyle()); - // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. - // HSSFCellStyle wraps an underlying style record, and the underlying - // style record is the same between multiple getCellStyle() calls. - assertEquals(VerticalAlignment.BOTTOM, A1.getCellStyle().getVerticalAlignmentEnum()); - assertEquals(VerticalAlignment.BOTTOM, B1.getCellStyle().getVerticalAlignmentEnum()); - - // get/set alignment modifies the cell's style - CellUtil.setVerticalAlignment(A1, VerticalAlignment.TOP); - assertEquals(VerticalAlignment.TOP, A1.getCellStyle().getVerticalAlignmentEnum()); - - // get/set alignment doesn't affect the style of cells with - // the same style prior to modifying the style - assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); - assertEquals(VerticalAlignment.BOTTOM, B1.getCellStyle().getVerticalAlignmentEnum()); - - wb.close(); - } - - @Test - public void setFont() throws IOException { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh = wb.createSheet(); - Row row = sh.createRow(0); - Cell A1 = row.createCell(0); - Cell B1 = row.createCell(1); - final short defaultFontIndex = 0; - Font font = wb.createFont(); - font.setItalic(true); - final short customFontIndex = font.getIndex(); - - // Assumptions - assertNotEquals(defaultFontIndex, customFontIndex); - assertEquals(A1.getCellStyle(), B1.getCellStyle()); - // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. - // HSSFCellStyle wraps an underlying style record, and the underlying - // style record is the same between multiple getCellStyle() calls. - assertEquals(defaultFontIndex, A1.getCellStyle().getFontIndex()); - assertEquals(defaultFontIndex, B1.getCellStyle().getFontIndex()); - - // get/set alignment modifies the cell's style - CellUtil.setFont(A1, font); - assertEquals(customFontIndex, A1.getCellStyle().getFontIndex()); - - // get/set alignment doesn't affect the style of cells with - // the same style prior to modifying the style - assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); - assertEquals(defaultFontIndex, B1.getCellStyle().getFontIndex()); - - wb.close(); - } - - @Test - public void setFontFromDifferentWorkbook() throws IOException { - Workbook wb1 = _testDataProvider.createWorkbook(); - Workbook wb2 = _testDataProvider.createWorkbook(); - Font font1 = wb1.createFont(); - Font font2 = wb2.createFont(); - // do something to make font1 and font2 different - // so they are not same or equal. - font1.setItalic(true); - Cell A1 = wb1.createSheet().createRow(0).createCell(0); - - // okay - CellUtil.setFont(A1, font1); - - // font belongs to different workbook - try { - CellUtil.setFont(A1, font2); - fail("setFont not allowed if font belongs to a different workbook"); - } catch (final IllegalArgumentException e) { - // one specific message is expected - if (!e.getMessage().startsWith("Font does not belong to this workbook")) { - throw e; - } - } finally { - wb1.close(); - wb2.close(); - } - } - - /** - * bug 55555 - * @deprecated Replaced by {@link #setFillForegroundColorBeforeFillBackgroundColorEnum()} - * @since POI 3.15 beta 3 - */ - @Deprecated - // bug 55555 - @Test - public void setFillForegroundColorBeforeFillBackgroundColor() throws IOException { - Workbook wb1 = _testDataProvider.createWorkbook(); - Cell A1 = wb1.createSheet().createRow(0).createCell(0); - Map properties = new HashMap(); - // FIXME: Use FillPatternType.BRICKS enum - properties.put(CellUtil.FILL_PATTERN, CellStyle.BRICKS); - properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.BLUE.index); - properties.put(CellUtil.FILL_BACKGROUND_COLOR, IndexedColors.RED.index); - - CellUtil.setCellStyleProperties(A1, properties); - CellStyle style = A1.getCellStyle(); - // FIXME: Use FillPatternType.BRICKS enum - assertEquals("fill pattern", CellStyle.BRICKS, style.getFillPattern()); - assertEquals("fill foreground color", IndexedColors.BLUE, IndexedColors.fromInt(style.getFillForegroundColor())); - assertEquals("fill background color", IndexedColors.RED, IndexedColors.fromInt(style.getFillBackgroundColor())); - wb1.close(); - } - /** - * bug 55555 - * @since POI 3.15 beta 3 - */ - @Test - public void setFillForegroundColorBeforeFillBackgroundColorEnum() throws IOException { - Workbook wb1 = _testDataProvider.createWorkbook(); - Cell A1 = wb1.createSheet().createRow(0).createCell(0); - Map properties = new HashMap(); - // FIXME: Use FillPatternType.BRICKS enum - properties.put(CellUtil.FILL_PATTERN, FillPatternType.BRICKS); - properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.BLUE.index); - properties.put(CellUtil.FILL_BACKGROUND_COLOR, IndexedColors.RED.index); - - CellUtil.setCellStyleProperties(A1, properties); - CellStyle style = A1.getCellStyle(); - // FIXME: Use FillPatternType.BRICKS enum - assertEquals("fill pattern", FillPatternType.BRICKS, style.getFillPatternEnum()); - assertEquals("fill foreground color", IndexedColors.BLUE, IndexedColors.fromInt(style.getFillForegroundColor())); - assertEquals("fill background color", IndexedColors.RED, IndexedColors.fromInt(style.getFillBackgroundColor())); - - wb1.close(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==================================================================== */ + +package org.apache.poi.ss.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.junit.Test; + +/** + * Tests Spreadsheet CellUtil + * + * @see org.apache.poi.ss.util.CellUtil + */ +public class BaseTestCellUtil { + protected final ITestDataProvider _testDataProvider; + + protected BaseTestCellUtil(ITestDataProvider testDataProvider) { + _testDataProvider = testDataProvider; + } + + @Test + public void setCellStyleProperty() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet s = wb.createSheet(); + Row r = s.createRow(0); + Cell c = r.createCell(0); + + // Add a border should create a new style + int styCnt1 = wb.getNumCellStyles(); + CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, BorderStyle.THIN); + int styCnt2 = wb.getNumCellStyles(); + assertEquals(styCnt1+1, styCnt2); + + // Add same border to another cell, should not create another style + c = r.createCell(1); + CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, BorderStyle.THIN); + int styCnt3 = wb.getNumCellStyles(); + assertEquals(styCnt2, styCnt3); + + wb.close(); + } + + @Test(expected=RuntimeException.class) + public void setCellStylePropertyWithInvalidValue() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + try { + Sheet s = wb.createSheet(); + Row r = s.createRow(0); + Cell c = r.createCell(0); + + // An invalid BorderStyle constant + CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, 42); + } finally { + wb.close(); + } + } + + @Test() + public void setCellStylePropertyBorderWithShortAndEnum() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet s = wb.createSheet(); + Row r = s.createRow(0); + Cell c = r.createCell(0); + + // A valid BorderStyle constant, as a Short + CellUtil.setCellStyleProperty(c, CellUtil.BORDER_BOTTOM, BorderStyle.DASH_DOT.getCode()); + assertEquals(BorderStyle.DASH_DOT, c.getCellStyle().getBorderBottomEnum()); + + // A valid BorderStyle constant, as an Enum + CellUtil.setCellStyleProperty(c, CellUtil.BORDER_TOP, BorderStyle.MEDIUM_DASH_DOT); + assertEquals(BorderStyle.MEDIUM_DASH_DOT, c.getCellStyle().getBorderTopEnum()); + + wb.close(); + } + + @Test + public void setCellStyleProperties() throws IOException { + System.out.println("setCellStyleProps start"); + Workbook wb = _testDataProvider.createWorkbook(); + Sheet s = wb.createSheet(); + Row r = s.createRow(0); + Cell c = r.createCell(0); + + // Add multiple border properties to cell should create a single new style + int styCnt1 = wb.getNumCellStyles(); + Map props = new HashMap(); + props.put(CellUtil.BORDER_TOP, BorderStyle.THIN); + props.put(CellUtil.BORDER_BOTTOM, BorderStyle.THIN); + props.put(CellUtil.BORDER_LEFT, BorderStyle.THIN); + props.put(CellUtil.BORDER_RIGHT, BorderStyle.THIN); + props.put(CellUtil.ALIGNMENT, HorizontalAlignment.CENTER.getCode()); // try it both with a Short (deprecated) + props.put(CellUtil.VERTICAL_ALIGNMENT, VerticalAlignment.CENTER); // and with an enum + CellUtil.setCellStyleProperties(c, props); + int styCnt2 = wb.getNumCellStyles(); + assertEquals("Only one additional style should have been created", styCnt1 + 1, styCnt2); + + // Add same border another to same cell, should not create another style + c = r.createCell(1); + CellUtil.setCellStyleProperties(c, props); + int styCnt3 = wb.getNumCellStyles(); + System.out.println("setCellStyleProps nearing end"); + assertEquals("No additional styles should have been created", styCnt2, styCnt3); + + wb.close(); + + } + + @Test + public void getRow() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + Row row1 = sh.createRow(0); + + // Get row that already exists + Row r1 = CellUtil.getRow(0, sh); + assertNotNull(r1); + assertSame("An existing row should not be recreated", row1, r1); + + // Get row that does not exist yet + assertNotNull(CellUtil.getRow(1, sh)); + + wb.close(); + } + + @Test + public void getCell() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + Row row = sh.createRow(0); + Cell A1 = row.createCell(0); + + // Get cell that already exists + Cell a1 = CellUtil.getCell(row, 0); + assertNotNull(a1); + assertSame("An existing cell should not be recreated", A1, a1); + + // Get cell that does not exist yet + assertNotNull(CellUtil.getCell(row, 1)); + + wb.close(); + } + + @Test + public void createCell() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + Row row = sh.createRow(0); + + CellStyle style = wb.createCellStyle(); + style.setWrapText(true); + + // calling createCell on a non-existing cell should create a cell and set the cell value and style. + Cell F1 = CellUtil.createCell(row, 5, "Cell Value", style); + + assertSame(row.getCell(5), F1); + assertEquals("Cell Value", F1.getStringCellValue()); + assertEquals(style, F1.getCellStyle()); + // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. + // HSSFCellStyle wraps an underlying style record, and the underlying + // style record is the same between multiple getCellStyle() calls. + + // calling createCell on an existing cell should return the existing cell and modify the cell value and style. + Cell f1 = CellUtil.createCell(row, 5, "Overwritten cell value", null); + assertSame(row.getCell(5), f1); + assertSame(F1, f1); + assertEquals("Overwritten cell value", f1.getStringCellValue()); + assertEquals("Overwritten cell value", F1.getStringCellValue()); + assertEquals("cell style should be unchanged with createCell(..., null)", style, f1.getCellStyle()); + assertEquals("cell style should be unchanged with createCell(..., null)", style, F1.getCellStyle()); + + // test createCell(row, column, value) (no CellStyle) + f1 = CellUtil.createCell(row, 5, "Overwritten cell with default style"); + assertSame(F1, f1); + + wb.close(); + + } + + /** + * @deprecated by {@link #setAlignmentEnum()} + * + * @throws IOException + * + */ + @Deprecated + @SuppressWarnings("deprecated") + @Test + public void setAlignment() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + Row row = sh.createRow(0); + Cell A1 = row.createCell(0); + Cell B1 = row.createCell(1); + + // Assumptions + assertEquals(A1.getCellStyle(), B1.getCellStyle()); + // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. + // HSSFCellStyle wraps an underlying style record, and the underlying + // style record is the same between multiple getCellStyle() calls. + assertEquals(CellStyle.ALIGN_GENERAL, A1.getCellStyle().getAlignment()); + assertEquals(CellStyle.ALIGN_GENERAL, B1.getCellStyle().getAlignment()); + + // get/set alignment modifies the cell's style + CellUtil.setAlignment(A1, null, CellStyle.ALIGN_RIGHT); + assertEquals(CellStyle.ALIGN_RIGHT, A1.getCellStyle().getAlignment()); + + // get/set alignment doesn't affect the style of cells with + // the same style prior to modifying the style + assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); + assertEquals(CellStyle.ALIGN_GENERAL, B1.getCellStyle().getAlignment()); + + wb.close(); + } + + @Test + public void setAlignmentEnum() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + Row row = sh.createRow(0); + Cell A1 = row.createCell(0); + Cell B1 = row.createCell(1); + + // Assumptions + assertEquals(A1.getCellStyle(), B1.getCellStyle()); + // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. + // HSSFCellStyle wraps an underlying style record, and the underlying + // style record is the same between multiple getCellStyle() calls. + assertEquals(HorizontalAlignment.GENERAL, A1.getCellStyle().getAlignmentEnum()); + assertEquals(HorizontalAlignment.GENERAL, B1.getCellStyle().getAlignmentEnum()); + + // get/set alignment modifies the cell's style + CellUtil.setAlignment(A1, HorizontalAlignment.RIGHT); + assertEquals(HorizontalAlignment.RIGHT, A1.getCellStyle().getAlignmentEnum()); + + // get/set alignment doesn't affect the style of cells with + // the same style prior to modifying the style + assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); + assertEquals(HorizontalAlignment.GENERAL, B1.getCellStyle().getAlignmentEnum()); + + wb.close(); + } + + @Test + public void setVerticalAlignmentEnum() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + Row row = sh.createRow(0); + Cell A1 = row.createCell(0); + Cell B1 = row.createCell(1); + + // Assumptions + assertEquals(A1.getCellStyle(), B1.getCellStyle()); + // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. + // HSSFCellStyle wraps an underlying style record, and the underlying + // style record is the same between multiple getCellStyle() calls. + assertEquals(VerticalAlignment.BOTTOM, A1.getCellStyle().getVerticalAlignmentEnum()); + assertEquals(VerticalAlignment.BOTTOM, B1.getCellStyle().getVerticalAlignmentEnum()); + + // get/set alignment modifies the cell's style + CellUtil.setVerticalAlignment(A1, VerticalAlignment.TOP); + assertEquals(VerticalAlignment.TOP, A1.getCellStyle().getVerticalAlignmentEnum()); + + // get/set alignment doesn't affect the style of cells with + // the same style prior to modifying the style + assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); + assertEquals(VerticalAlignment.BOTTOM, B1.getCellStyle().getVerticalAlignmentEnum()); + + wb.close(); + } + + @Test + public void setFont() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sh = wb.createSheet(); + Row row = sh.createRow(0); + Cell A1 = row.createCell(0); + Cell B1 = row.createCell(1); + final short defaultFontIndex = 0; + Font font = wb.createFont(); + font.setItalic(true); + final short customFontIndex = font.getIndex(); + + // Assumptions + assertNotEquals(defaultFontIndex, customFontIndex); + assertEquals(A1.getCellStyle(), B1.getCellStyle()); + // should be assertSame, but a new HSSFCellStyle is returned for each getCellStyle() call. + // HSSFCellStyle wraps an underlying style record, and the underlying + // style record is the same between multiple getCellStyle() calls. + assertEquals(defaultFontIndex, A1.getCellStyle().getFontIndex()); + assertEquals(defaultFontIndex, B1.getCellStyle().getFontIndex()); + + // get/set alignment modifies the cell's style + CellUtil.setFont(A1, font); + assertEquals(customFontIndex, A1.getCellStyle().getFontIndex()); + + // get/set alignment doesn't affect the style of cells with + // the same style prior to modifying the style + assertNotEquals(A1.getCellStyle(), B1.getCellStyle()); + assertEquals(defaultFontIndex, B1.getCellStyle().getFontIndex()); + + wb.close(); + } + + @Test + public void setFontFromDifferentWorkbook() throws IOException { + Workbook wb1 = _testDataProvider.createWorkbook(); + Workbook wb2 = _testDataProvider.createWorkbook(); + Font font1 = wb1.createFont(); + Font font2 = wb2.createFont(); + // do something to make font1 and font2 different + // so they are not same or equal. + font1.setItalic(true); + Cell A1 = wb1.createSheet().createRow(0).createCell(0); + + // okay + CellUtil.setFont(A1, font1); + + // font belongs to different workbook + try { + CellUtil.setFont(A1, font2); + fail("setFont not allowed if font belongs to a different workbook"); + } catch (final IllegalArgumentException e) { + // one specific message is expected + if (!e.getMessage().startsWith("Font does not belong to this workbook")) { + throw e; + } + } finally { + wb1.close(); + wb2.close(); + } + } + + /** + * bug 55555 + * @deprecated Replaced by {@link #setFillForegroundColorBeforeFillBackgroundColorEnum()} + * @since POI 3.15 beta 3 + */ + @Deprecated + // bug 55555 + @Test + public void setFillForegroundColorBeforeFillBackgroundColor() throws IOException { + Workbook wb1 = _testDataProvider.createWorkbook(); + Cell A1 = wb1.createSheet().createRow(0).createCell(0); + Map properties = new HashMap(); + // FIXME: Use FillPatternType.BRICKS enum + properties.put(CellUtil.FILL_PATTERN, CellStyle.BRICKS); + properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.BLUE.index); + properties.put(CellUtil.FILL_BACKGROUND_COLOR, IndexedColors.RED.index); + + CellUtil.setCellStyleProperties(A1, properties); + CellStyle style = A1.getCellStyle(); + // FIXME: Use FillPatternType.BRICKS enum + assertEquals("fill pattern", CellStyle.BRICKS, style.getFillPattern()); + assertEquals("fill foreground color", IndexedColors.BLUE, IndexedColors.fromInt(style.getFillForegroundColor())); + assertEquals("fill background color", IndexedColors.RED, IndexedColors.fromInt(style.getFillBackgroundColor())); + wb1.close(); + } + /** + * bug 55555 + * @since POI 3.15 beta 3 + */ + @Test + public void setFillForegroundColorBeforeFillBackgroundColorEnum() throws IOException { + Workbook wb1 = _testDataProvider.createWorkbook(); + Cell A1 = wb1.createSheet().createRow(0).createCell(0); + Map properties = new HashMap(); + // FIXME: Use FillPatternType.BRICKS enum + properties.put(CellUtil.FILL_PATTERN, FillPatternType.BRICKS); + properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.BLUE.index); + properties.put(CellUtil.FILL_BACKGROUND_COLOR, IndexedColors.RED.index); + + CellUtil.setCellStyleProperties(A1, properties); + CellStyle style = A1.getCellStyle(); + // FIXME: Use FillPatternType.BRICKS enum + assertEquals("fill pattern", FillPatternType.BRICKS, style.getFillPatternEnum()); + assertEquals("fill foreground color", IndexedColors.BLUE, IndexedColors.fromInt(style.getFillForegroundColor())); + assertEquals("fill background color", IndexedColors.RED, IndexedColors.fromInt(style.getFillBackgroundColor())); + + wb1.close(); + } +} -- 2.39.5