aboutsummaryrefslogtreecommitdiffstats
path: root/src/java
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2008-12-09 15:00:35 +0000
committerJeremias Maerki <jeremias@apache.org>2008-12-09 15:00:35 +0000
commita6ddced309701a1ca8d79a9e7bec3288afba2cc8 (patch)
treec3d2bcfe7277246d9a2acc3675721a99f4de5727 /src/java
parent9d339f0968314f0cfcc4a720628fed1845292ce1 (diff)
parentf9d4720b99f5e0fb423b097d7207dfab446d911c (diff)
downloadxmlgraphics-fop-a6ddced309701a1ca8d79a9e7bec3288afba2cc8.tar.gz
xmlgraphics-fop-a6ddced309701a1ca8d79a9e7bec3288afba2cc8.zip
Merge from Trunk revisions 719662 - 724689.
Conflict for ImageHandler interface resolved by renaming Trunk's ImageHandler to ImageHandlerBase and extending the other ImageHandler from that. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@724729 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
-rw-r--r--src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler5
-rw-r--r--src/java/org/apache/fop/afp/AFPBorderPainter.java194
-rw-r--r--src/java/org/apache/fop/afp/AFPConstants.java (renamed from src/java/org/apache/fop/render/afp/modca/AFPConstants.java)18
-rw-r--r--src/java/org/apache/fop/afp/AFPDataObjectFactory.java272
-rw-r--r--src/java/org/apache/fop/afp/AFPDataObjectInfo.java247
-rw-r--r--src/java/org/apache/fop/afp/AFPEventProducer.java (renamed from src/java/org/apache/fop/render/afp/AFPEventProducer.java)22
-rw-r--r--src/java/org/apache/fop/afp/AFPEventProducer.xml6
-rw-r--r--src/java/org/apache/fop/afp/AFPGraphics2D.java698
-rw-r--r--src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java109
-rw-r--r--src/java/org/apache/fop/afp/AFPImageObjectInfo.java115
-rw-r--r--src/java/org/apache/fop/afp/AFPLineDataInfo.java192
-rw-r--r--src/java/org/apache/fop/afp/AFPObjectAreaInfo.java172
-rw-r--r--src/java/org/apache/fop/afp/AFPPaintingState.java495
-rw-r--r--src/java/org/apache/fop/afp/AFPRectanglePainter.java84
-rw-r--r--src/java/org/apache/fop/afp/AFPResourceInfo.java141
-rw-r--r--src/java/org/apache/fop/afp/AFPResourceLevel.java201
-rw-r--r--src/java/org/apache/fop/afp/AFPResourceManager.java179
-rw-r--r--src/java/org/apache/fop/afp/AFPStreamer.java215
-rw-r--r--src/java/org/apache/fop/afp/AFPTextDataInfo.java232
-rw-r--r--src/java/org/apache/fop/afp/AFPUnitConverter.java121
-rw-r--r--src/java/org/apache/fop/afp/AbstractAFPPainter.java53
-rw-r--r--src/java/org/apache/fop/afp/BorderPaintingInfo.java121
-rw-r--r--src/java/org/apache/fop/afp/Completable.java40
-rw-r--r--src/java/org/apache/fop/afp/DataStream.java602
-rw-r--r--src/java/org/apache/fop/afp/Factory.java635
-rw-r--r--src/java/org/apache/fop/afp/PaintingInfo.java27
-rw-r--r--src/java/org/apache/fop/afp/RectanglePaintingInfo.java84
-rw-r--r--src/java/org/apache/fop/afp/Startable.java40
-rw-r--r--src/java/org/apache/fop/afp/Streamable.java38
-rw-r--r--src/java/org/apache/fop/afp/StructuredData.java33
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java157
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFont.java (renamed from src/java/org/apache/fop/render/afp/fonts/AFPFont.java)8
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java (renamed from src/java/org/apache/fop/render/afp/AFPFontAttributes.java)44
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontCollection.java92
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontInfo.java (renamed from src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java)18
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontReader.java (renamed from src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java)8
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPPageFonts.java64
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSet.java (renamed from src/java/org/apache/fop/render/afp/fonts/CharacterSet.java)10
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java (renamed from src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java)2
-rw-r--r--src/java/org/apache/fop/afp/fonts/FontRuntimeException.java (renamed from src/java/org/apache/fop/render/afp/exceptions/FontRuntimeException.java)6
-rw-r--r--src/java/org/apache/fop/afp/fonts/FopCharacterSet.java (renamed from src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java)16
-rw-r--r--src/java/org/apache/fop/afp/fonts/OutlineFont.java (renamed from src/java/org/apache/fop/render/afp/fonts/OutlineFont.java)15
-rw-r--r--src/java/org/apache/fop/afp/fonts/RasterFont.java (renamed from src/java/org/apache/fop/render/afp/fonts/RasterFont.java)30
-rw-r--r--src/java/org/apache/fop/afp/fonts/package.html23
-rw-r--r--src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java149
-rw-r--r--src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrder.java60
-rw-r--r--src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrderContainer.java158
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsAreaBegin.java69
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsAreaEnd.java53
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsBox.java63
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsChainedSegment.java112
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java114
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsData.java126
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsFillet.java46
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsFullArc.java85
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsImage.java120
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsLine.java56
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetArcParameters.java51
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetCharacterSet.java66
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetCurrentPosition.java40
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetLineType.java97
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java65
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetMix.java69
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetPatternSymbol.java117
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java104
-rw-r--r--src/java/org/apache/fop/afp/goca/package.html23
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageCellPosition.java (renamed from src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java)65
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageContent.java267
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageInputDescriptor.java (renamed from src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java)31
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageOutputControl.java (renamed from src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java)25
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageRasterData.java (renamed from src/java/org/apache/fop/render/afp/modca/ImageRasterData.java)41
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageRasterPattern.java (renamed from src/java/org/apache/fop/render/afp/modca/ImageRasterPattern.java)2
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageSegment.java161
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageSizeParameter.java (renamed from src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java)29
-rw-r--r--src/java/org/apache/fop/afp/ioca/package.html23
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractAFPObject.java321
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractDataObject.java140
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractDescriptor.java (renamed from src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java)53
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java101
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractNamedAFPObject.java122
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractPageObject.java350
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractResourceEnvironmentGroupContainer.java99
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractResourceGroupContainer.java168
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractStructuredObject.java69
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java181
-rw-r--r--src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java221
-rw-r--r--src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java84
-rw-r--r--src/java/org/apache/fop/afp/modca/Document.java96
-rw-r--r--src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java152
-rw-r--r--src/java/org/apache/fop/afp/modca/GraphicsObject.java385
-rw-r--r--src/java/org/apache/fop/afp/modca/IMImageObject.java (renamed from src/java/org/apache/fop/render/afp/modca/IMImageObject.java)98
-rw-r--r--src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java78
-rw-r--r--src/java/org/apache/fop/afp/modca/ImageObject.java155
-rw-r--r--src/java/org/apache/fop/afp/modca/IncludeObject.java301
-rw-r--r--src/java/org/apache/fop/afp/modca/IncludePageOverlay.java (renamed from src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java)50
-rw-r--r--src/java/org/apache/fop/afp/modca/IncludePageSegment.java (renamed from src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java)70
-rw-r--r--src/java/org/apache/fop/afp/modca/InterchangeSet.java115
-rw-r--r--src/java/org/apache/fop/afp/modca/InvokeMediumMap.java (renamed from src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java)48
-rw-r--r--src/java/org/apache/fop/afp/modca/MapCodedFont.java (renamed from src/java/org/apache/fop/render/afp/modca/MapCodedFont.java)102
-rw-r--r--src/java/org/apache/fop/afp/modca/MapContainerData.java59
-rw-r--r--src/java/org/apache/fop/afp/modca/MapDataResource.java58
-rw-r--r--src/java/org/apache/fop/afp/modca/MapPageOverlay.java (renamed from src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java)39
-rw-r--r--src/java/org/apache/fop/afp/modca/MaximumSizeExceededException.java (renamed from src/java/org/apache/fop/render/afp/modca/MaximumSizeExceededException.java)2
-rw-r--r--src/java/org/apache/fop/afp/modca/NoOperation.java (renamed from src/java/org/apache/fop/render/afp/modca/NoOperation.java)7
-rw-r--r--src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java72
-rw-r--r--src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java112
-rw-r--r--src/java/org/apache/fop/afp/modca/ObjectContainer.java123
-rw-r--r--src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java184
-rw-r--r--src/java/org/apache/fop/afp/modca/Overlay.java87
-rw-r--r--src/java/org/apache/fop/afp/modca/PageDescriptor.java (renamed from src/java/org/apache/fop/render/afp/modca/PageDescriptor.java)43
-rw-r--r--src/java/org/apache/fop/afp/modca/PageGroup.java105
-rw-r--r--src/java/org/apache/fop/afp/modca/PageObject.java219
-rw-r--r--src/java/org/apache/fop/afp/modca/PageSegment.java90
-rw-r--r--src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java144
-rw-r--r--src/java/org/apache/fop/afp/modca/PresentationEnvironmentControl.java98
-rw-r--r--src/java/org/apache/fop/afp/modca/PresentationTextData.java (renamed from src/java/org/apache/fop/render/afp/modca/PresentationTextData.java)495
-rw-r--r--src/java/org/apache/fop/afp/modca/PresentationTextDescriptor.java (renamed from src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java)42
-rw-r--r--src/java/org/apache/fop/afp/modca/PresentationTextObject.java174
-rw-r--r--src/java/org/apache/fop/afp/modca/Registry.java288
-rw-r--r--src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java128
-rw-r--r--src/java/org/apache/fop/afp/modca/ResourceGroup.java107
-rw-r--r--src/java/org/apache/fop/afp/modca/ResourceObject.java150
-rw-r--r--src/java/org/apache/fop/afp/modca/StreamedResourceGroup.java96
-rw-r--r--src/java/org/apache/fop/afp/modca/TagLogicalElement.java (renamed from src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java)73
-rw-r--r--src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java (renamed from src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java)5
-rw-r--r--src/java/org/apache/fop/afp/modca/package.html23
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java120
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/CommentTriplet.java52
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/DescriptorPositionTriplet.java53
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/ExtendedResourceLocalIdentifierTriplet.java75
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java208
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/MappingOptionTriplet.java87
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/MeasurementUnitsTriplet.java72
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/ObjectAreaSizeTriplet.java84
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/ObjectByteExtentTriplet.java56
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/ObjectClassificationTriplet.java214
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceMixingRulesTriplet.java80
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceResetMixingTriplet.java66
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/ResourceObjectTypeTriplet.java54
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/package.html23
-rw-r--r--src/java/org/apache/fop/afp/package.html23
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPBridgeContext.java108
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java150
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java80
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java40
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java42
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPTextHandler.java145
-rw-r--r--src/java/org/apache/fop/afp/svg/AFPTextPainter.java44
-rw-r--r--src/java/org/apache/fop/afp/svg/package.html23
-rw-r--r--src/java/org/apache/fop/afp/util/BinaryUtils.java (renamed from src/java/org/apache/fop/render/afp/tools/BinaryUtils.java)2
-rw-r--r--src/java/org/apache/fop/afp/util/DTDEntityResolver.java (renamed from src/java/org/apache/fop/render/afp/tools/DTDEntityResolver.java)4
-rw-r--r--src/java/org/apache/fop/afp/util/StringUtils.java (renamed from src/java/org/apache/fop/render/afp/tools/StringUtils.java)2
-rw-r--r--src/java/org/apache/fop/afp/util/StructuredFieldReader.java (renamed from src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java)2
-rw-r--r--src/java/org/apache/fop/afp/util/package.html23
-rw-r--r--src/java/org/apache/fop/apps/MimeConstants.java48
-rw-r--r--src/java/org/apache/fop/area/Area.java20
-rw-r--r--src/java/org/apache/fop/area/AreaTreeHandler.java32
-rw-r--r--src/java/org/apache/fop/area/AreaTreeModel.java10
-rw-r--r--src/java/org/apache/fop/area/AreaTreeObject.java21
-rw-r--r--src/java/org/apache/fop/area/IDTracker.java14
-rw-r--r--src/java/org/apache/fop/area/PageViewport.java7
-rw-r--r--src/java/org/apache/fop/area/RegionReference.java9
-rw-r--r--src/java/org/apache/fop/area/RenderPagesModel.java8
-rw-r--r--src/java/org/apache/fop/area/inline/FilledArea.java10
-rw-r--r--src/java/org/apache/fop/area/inline/Image.java10
-rw-r--r--src/java/org/apache/fop/area/inline/InlineArea.java2
-rw-r--r--src/java/org/apache/fop/area/inline/TextArea.java7
-rw-r--r--src/java/org/apache/fop/area/inline/Viewport.java18
-rw-r--r--src/java/org/apache/fop/cli/InputHandler.java3
-rw-r--r--src/java/org/apache/fop/events/EventFormatter.xml4
-rw-r--r--src/java/org/apache/fop/fo/ElementMapping.java1
-rw-r--r--src/java/org/apache/fop/fo/FObj.java5
-rw-r--r--src/java/org/apache/fop/fo/flow/Marker.java31
-rw-r--r--src/java/org/apache/fop/fo/properties/PropertyCache.java17
-rw-r--r--src/java/org/apache/fop/fonts/Base14Font.java1
-rw-r--r--src/java/org/apache/fop/fonts/CIDFont.java2
-rw-r--r--src/java/org/apache/fop/fonts/CustomFont.java1
-rw-r--r--src/java/org/apache/fop/fonts/Font.java1
-rw-r--r--src/java/org/apache/fop/fonts/FontCollection.java1
-rw-r--r--src/java/org/apache/fop/fonts/FontDescriptor.java1
-rw-r--r--src/java/org/apache/fop/fonts/FontEventListener.java1
-rw-r--r--src/java/org/apache/fop/fonts/FontInfo.java85
-rw-r--r--src/java/org/apache/fop/fonts/FontMetrics.java1
-rw-r--r--src/java/org/apache/fop/fonts/FontTriplet.java1
-rw-r--r--src/java/org/apache/fop/fonts/FontType.java28
-rw-r--r--src/java/org/apache/fop/fonts/FontUtil.java1
-rw-r--r--src/java/org/apache/fop/fonts/MultiByteFont.java1
-rw-r--r--src/java/org/apache/fop/fonts/MutableFont.java1
-rw-r--r--src/java/org/apache/fop/fonts/Typeface.java5
-rw-r--r--src/java/org/apache/fop/fonts/package.html17
-rw-r--r--src/java/org/apache/fop/image/loader/batik/BatikUtil.java19
-rw-r--r--src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java67
-rw-r--r--src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java61
-rw-r--r--src/java/org/apache/fop/layoutmgr/TraitSetter.java1
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java6
-rw-r--r--src/java/org/apache/fop/pdf/PDFDocument.java411
-rw-r--r--src/java/org/apache/fop/pdf/PDFPaintingState.java229
-rw-r--r--src/java/org/apache/fop/pdf/PDFState.java417
-rw-r--r--src/java/org/apache/fop/pdf/package.html17
-rw-r--r--src/java/org/apache/fop/render/AbstractGenericSVGHandler.java126
-rw-r--r--src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java15
-rw-r--r--src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java209
-rw-r--r--src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java193
-rw-r--r--src/java/org/apache/fop/render/AbstractRenderer.java6
-rw-r--r--src/java/org/apache/fop/render/ImageHandler.java25
-rw-r--r--src/java/org/apache/fop/render/ImageHandlerBase.java50
-rw-r--r--src/java/org/apache/fop/render/PrintRenderer.java14
-rw-r--r--src/java/org/apache/fop/render/RendererContext.java52
-rw-r--r--src/java/org/apache/fop/render/afp/AFPEventProducer.xml4
-rw-r--r--src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java128
-rw-r--r--src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java73
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandler.java104
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java110
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java72
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java55
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java42
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java116
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java77
-rw-r--r--src/java/org/apache/fop/render/afp/AFPInfo.java310
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRenderer.java1858
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java95
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererContext.java83
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java8
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java162
-rw-r--r--src/java/org/apache/fop/render/afp/AFPSVGHandler.java201
-rw-r--r--src/java/org/apache/fop/render/afp/AbstractAFPImageHandlerRawStream.java79
-rwxr-xr-xsrc/java/org/apache/fop/render/afp/extensions/AFPAttribute.java4
-rwxr-xr-xsrc/java/org/apache/fop/render/afp/extensions/AFPElement.java9
-rwxr-xr-xsrc/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java32
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java155
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java2
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java100
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java9
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java79
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/AFPFontCollection.java110
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AFPDataStream.java701
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java66
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java69
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java435
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java353
-rw-r--r--src/java/org/apache/fop/render/afp/modca/Document.java213
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageContent.java295
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java109
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageObject.java275
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageSegment.java214
-rw-r--r--src/java/org/apache/fop/render/afp/modca/IncludeObject.java171
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java102
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java112
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java198
-rw-r--r--src/java/org/apache/fop/render/afp/modca/Overlay.java139
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PageGroup.java208
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PageObject.java191
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java337
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ResourceGroup.java154
-rw-r--r--src/java/org/apache/fop/render/afp/package.html23
-rw-r--r--src/java/org/apache/fop/render/awt/AWTRenderer.java9
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DRenderer.java80
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java37
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLRenderer.java2
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFContentGenerator.java12
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java2
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFImageHandler.java24
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java2
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java163
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java6
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java8
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java41
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java10
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java3
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFSVGHandler.java30
-rw-r--r--src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java1
-rw-r--r--src/java/org/apache/fop/render/ps/PSSVGHandler.java10
-rw-r--r--src/java/org/apache/fop/render/ps/PSTextPainter.java44
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java2
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java2
-rw-r--r--src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java4
-rw-r--r--src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java142
-rw-r--r--src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java284
-rw-r--r--src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java113
-rw-r--r--src/java/org/apache/fop/svg/AbstractFOPTextPainter.java528
-rw-r--r--src/java/org/apache/fop/svg/FOPTextHandler.java27
-rw-r--r--src/java/org/apache/fop/svg/GraphicsConfiguration.java1
-rw-r--r--src/java/org/apache/fop/svg/NativeImageHandler.java40
-rw-r--r--src/java/org/apache/fop/svg/PDFBridgeContext.java106
-rw-r--r--src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java40
-rw-r--r--src/java/org/apache/fop/svg/PDFGraphics2D.java97
-rw-r--r--src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java1
-rw-r--r--src/java/org/apache/fop/svg/PDFImageElementBridge.java233
-rw-r--r--src/java/org/apache/fop/svg/PDFTextElementBridge.java42
-rw-r--r--src/java/org/apache/fop/svg/PDFTextPainter.java24
-rw-r--r--src/java/org/apache/fop/util/AbstractPaintingState.java531
291 files changed, 21696 insertions, 8675 deletions
diff --git a/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler b/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler
new file mode 100644
index 000000000..deab7d259
--- /dev/null
+++ b/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler
@@ -0,0 +1,5 @@
+org.apache.fop.render.afp.AFPImageHandlerRenderedImage
+org.apache.fop.render.afp.AFPImageHandlerRawCCITTFax
+org.apache.fop.render.afp.AFPImageHandlerRawStream
+org.apache.fop.render.afp.AFPImageHandlerGraphics2D
+org.apache.fop.render.afp.AFPImageHandlerXML
diff --git a/src/java/org/apache/fop/afp/AFPBorderPainter.java b/src/java/org/apache/fop/afp/AFPBorderPainter.java
new file mode 100644
index 000000000..4c56c0def
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPBorderPainter.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.geom.AffineTransform;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.util.ColorUtil;
+
+/**
+ * Handles the drawing of borders/lines in AFP
+ */
+public class AFPBorderPainter extends AbstractAFPPainter {
+
+ /**
+ * Main constructor
+ *
+ * @param paintingState the AFP painting state converter
+ * @param dataStream the AFP datastream
+ */
+ public AFPBorderPainter(AFPPaintingState paintingState, DataStream dataStream) {
+ super(paintingState, dataStream);
+ }
+
+ /** {@inheritDoc} */
+ public void paint(PaintingInfo paintInfo) {
+ BorderPaintingInfo borderPaintInfo = (BorderPaintingInfo)paintInfo;
+ float w = borderPaintInfo.getX2() - borderPaintInfo.getX1();
+ float h = borderPaintInfo.getY2() - borderPaintInfo.getY1();
+ if ((w < 0) || (h < 0)) {
+ log.error("Negative extent received. Border won't be painted.");
+ return;
+ }
+
+ int pageWidth = dataStream.getCurrentPage().getWidth();
+ int pageHeight = dataStream.getCurrentPage().getHeight();
+ AFPUnitConverter unitConv = paintingState.getUnitConverter();
+ AffineTransform at = paintingState.getData().getTransform();
+
+ float x1 = unitConv.pt2units(borderPaintInfo.getX1());
+ float y1 = unitConv.pt2units(borderPaintInfo.getY1());
+ float x2 = unitConv.pt2units(borderPaintInfo.getX2());
+ float y2 = unitConv.pt2units(borderPaintInfo.getY2());
+
+ switch (paintingState.getRotation()) {
+ case 0:
+ x1 += at.getTranslateX();
+ y1 += at.getTranslateY();
+ x2 += at.getTranslateX();
+ y2 += at.getTranslateY();
+ break;
+ case 90:
+ x1 += at.getTranslateY();
+ y1 += (float) (pageWidth - at.getTranslateX());
+ x2 += at.getTranslateY();
+ y2 += (float) (pageWidth - at.getTranslateX());
+ break;
+ case 180:
+ x1 += (float) (pageWidth - at.getTranslateX());
+ y1 += (float) (pageHeight - at.getTranslateY());
+ x2 += (float) (pageWidth - at.getTranslateX());
+ y2 += (float) (pageHeight - at.getTranslateY());
+ break;
+ case 270:
+ x1 = (float) (pageHeight - at.getTranslateY());
+ y1 += (float) at.getTranslateX();
+ x2 += x1;
+ y2 += (float) at.getTranslateX();
+ break;
+ }
+
+ AFPLineDataInfo lineDataInfo = new AFPLineDataInfo();
+ lineDataInfo.setColor(borderPaintInfo.getColor());
+ lineDataInfo.setRotation(paintingState.getRotation());
+ lineDataInfo.x1 = Math.round(x1);
+ lineDataInfo.y1 = Math.round(y1);
+ if (borderPaintInfo.isHorizontal()) {
+ lineDataInfo.setThickness(Math.round(y2 - y1));
+ } else {
+ lineDataInfo.setThickness(Math.round(x2 - x1));
+ }
+
+ // handle border-*-style
+ switch (borderPaintInfo.getStyle()) {
+ case Constants.EN_DOUBLE:
+ if (borderPaintInfo.isHorizontal()) {
+ lineDataInfo.x2 = Math.round(x2);
+ lineDataInfo.y2 = lineDataInfo.y1;
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.y1 += Math.round((lineDataInfo.thickness / 3) * 2);
+ dataStream.createLine(lineDataInfo);
+ } else {
+ lineDataInfo.x2 = lineDataInfo.x1;
+ lineDataInfo.y2 = Math.round(y2);
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.x1 += Math.round((lineDataInfo.thickness / 3) * 2);
+ dataStream.createLine(lineDataInfo);
+ }
+ break;
+ case Constants.EN_DASHED:
+ int thick = lineDataInfo.thickness * 3;
+ if (borderPaintInfo.isHorizontal()) {
+ lineDataInfo.x2 = lineDataInfo.x1 + thick;
+ lineDataInfo.y2 = lineDataInfo.y1;
+ int ex2 = Math.round(x2);
+ while (lineDataInfo.x1 + thick < ex2) {
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.x1 += 2 * thick;
+ lineDataInfo.x2 = lineDataInfo.x1 + thick;
+ }
+ } else {
+ lineDataInfo.x2 = lineDataInfo.x1;
+ lineDataInfo.y2 = lineDataInfo.y1 + thick;
+ int ey2 = Math.round(y2);
+ while (lineDataInfo.y1 + thick < ey2) {
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.y1 += 2 * thick;
+ lineDataInfo.y2 = lineDataInfo.y1 + thick;
+ }
+ }
+ break;
+ case Constants.EN_DOTTED:
+ if (borderPaintInfo.isHorizontal()) {
+ lineDataInfo.x2 = lineDataInfo.x1 + lineDataInfo.thickness;
+ lineDataInfo.y2 = lineDataInfo.y1;
+ int ex2 = Math.round(x2);
+ while (lineDataInfo.x1 + lineDataInfo.thickness < ex2) {
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.x1 += 3 * lineDataInfo.thickness;
+ lineDataInfo.x2 = lineDataInfo.x1 + lineDataInfo.thickness;
+ }
+ } else {
+ lineDataInfo.x2 = lineDataInfo.x1;
+ lineDataInfo.y2 = lineDataInfo.y1 + lineDataInfo.thickness;
+ int ey2 = Math.round(y2);
+ while (lineDataInfo.y1 + lineDataInfo.thickness < ey2) {
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.y1 += 3 * lineDataInfo.thickness;
+ lineDataInfo.y2 = lineDataInfo.y1 + lineDataInfo.thickness;
+ }
+ }
+ break;
+ case Constants.EN_GROOVE:
+ case Constants.EN_RIDGE:
+ //TODO
+ lineDataInfo.x2 = Math.round(x2);
+ float colFactor = (borderPaintInfo.getStyle() == Constants.EN_GROOVE ? 0.4f : -0.4f);
+ float h3 = (y2 - y1) / 3;
+ lineDataInfo.color = ColorUtil.lightenColor(borderPaintInfo.getColor(), -colFactor);
+ lineDataInfo.thickness = Math.round(h3);
+ lineDataInfo.y1 = lineDataInfo.y2 = Math.round(y1);
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.color = borderPaintInfo.getColor();
+ lineDataInfo.y1 = lineDataInfo.y2 = Math.round(y1 + h3);
+ dataStream.createLine(lineDataInfo);
+ lineDataInfo.color = ColorUtil.lightenColor(borderPaintInfo.getColor(), colFactor);
+ lineDataInfo.y1 = lineDataInfo.y2 = Math.round(y1 + h3 + h3);
+ dataStream.createLine(lineDataInfo);
+ break;
+ case Constants.EN_HIDDEN:
+ break;
+ case Constants.EN_INSET:
+ case Constants.EN_OUTSET:
+ case Constants.EN_SOLID:
+ default:
+ if (borderPaintInfo.isHorizontal()) {
+ lineDataInfo.x2 = Math.round(x2);
+ lineDataInfo.y2 = lineDataInfo.y1;
+ } else {
+ lineDataInfo.x2 = lineDataInfo.x1;
+ lineDataInfo.y2 = Math.round(y2);
+ }
+ dataStream.createLine(lineDataInfo);
+ }
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/AFPConstants.java b/src/java/org/apache/fop/afp/AFPConstants.java
index 73c39f2f0..3462ddfe6 100644
--- a/src/java/org/apache/fop/render/afp/modca/AFPConstants.java
+++ b/src/java/org/apache/fop/afp/AFPConstants.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp;
/**
* Constants used by the AFP renderer.
@@ -34,4 +34,20 @@ public interface AFPConstants {
* The encoding to use to convert to ASCII
*/
String ASCII_ENCODING = "Cp1252";
+
+ /**
+ * The encoding to use to convert to US ASCII (7 bit)
+ */
+ String US_ASCII_ENCODING = "US-ASCII";
+
+ /**
+ * The scaling of the default transform is set to
+ * approximately 72 user space coordinates per square inch
+ */
+ int DPI_72 = 72;
+
+ /**
+ * 72dpi in millipoints
+ */
+ int DPI_72_MPTS = DPI_72 * 1000;
}
diff --git a/src/java/org/apache/fop/afp/AFPDataObjectFactory.java b/src/java/org/apache/fop/afp/AFPDataObjectFactory.java
new file mode 100644
index 000000000..80cb40713
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPDataObjectFactory.java
@@ -0,0 +1,272 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.geom.Rectangle2D;
+
+import org.apache.fop.afp.ioca.ImageContent;
+import org.apache.fop.afp.modca.AbstractDataObject;
+import org.apache.fop.afp.modca.AbstractNamedAFPObject;
+import org.apache.fop.afp.modca.Document;
+import org.apache.fop.afp.modca.GraphicsObject;
+import org.apache.fop.afp.modca.ImageObject;
+import org.apache.fop.afp.modca.IncludeObject;
+import org.apache.fop.afp.modca.ObjectContainer;
+import org.apache.fop.afp.modca.Overlay;
+import org.apache.fop.afp.modca.PageSegment;
+import org.apache.fop.afp.modca.Registry;
+import org.apache.fop.afp.modca.ResourceObject;
+import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
+import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet;
+import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+
+/**
+ * Factory for high level data objects (Image/Graphics etc)
+ */
+public class AFPDataObjectFactory {
+
+ private final Factory factory;
+
+ /**
+ * Main constructor
+ *
+ * @param factory an object factory
+ */
+ public AFPDataObjectFactory(Factory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * Creates and configures an ObjectContainer.
+ *
+ * @param dataObjectInfo the object container info
+ * @return a newly created Object Container
+ */
+ public ObjectContainer createObjectContainer(AFPDataObjectInfo dataObjectInfo) {
+ ObjectContainer objectContainer = factory.createObjectContainer();
+
+ // set data object viewport (i.e. position, rotation, dimension, resolution)
+ objectContainer.setViewport(dataObjectInfo);
+
+ // set object classification
+ Registry.ObjectType objectType = dataObjectInfo.getObjectType();
+ AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
+ AFPResourceLevel resourceLevel = resourceInfo.getLevel();
+ final boolean dataInContainer = true;
+ final boolean containerHasOEG = resourceLevel.isInline();
+ final boolean dataInOCD = true;
+ objectContainer.setObjectClassification(
+ ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT,
+ objectType, dataInContainer, containerHasOEG, dataInOCD);
+
+ objectContainer.setData(dataObjectInfo.getData());
+ return objectContainer;
+ }
+
+ /**
+ * Creates and configures an IOCA Image Object.
+ *
+ * @param imageObjectInfo the image object info
+ * @return a newly created IOCA Image Object
+ */
+ public ImageObject createImage(AFPImageObjectInfo imageObjectInfo) {
+ // IOCA bitmap image
+ ImageObject imageObj = factory.createImageObject();
+
+ // set data object viewport (i.e. position, rotation, dimension, resolution)
+ imageObj.setViewport(imageObjectInfo);
+
+ if (imageObjectInfo.hasCompression()) {
+ int compression = imageObjectInfo.getCompression();
+ switch (compression) {
+ case TIFFImage.COMP_FAX_G3_1D:
+ imageObj.setEncoding(ImageContent.COMPID_G3_MH);
+ break;
+ case TIFFImage.COMP_FAX_G3_2D:
+ imageObj.setEncoding(ImageContent.COMPID_G3_MR);
+ break;
+ case TIFFImage.COMP_FAX_G4_2D:
+ imageObj.setEncoding(ImageContent.COMPID_G3_MMR);
+ break;
+ default:
+ throw new IllegalStateException(
+ "Invalid compression scheme: " + compression);
+ }
+ }
+
+ if (imageObjectInfo.isColor()) {
+ imageObj.setIDESize((byte) 24);
+ } else {
+ imageObj.setIDESize((byte) imageObjectInfo.getBitsPerPixel());
+ }
+
+ imageObj.setData(imageObjectInfo.getData());
+
+ return imageObj;
+ }
+
+ /**
+ * Creates and returns a new graphics object.
+ *
+ * @param graphicsObjectInfo the graphics object info
+ * @return a new graphics object
+ */
+ public GraphicsObject createGraphic(AFPGraphicsObjectInfo graphicsObjectInfo) {
+ // set newly created graphics object in g2d
+ GraphicsObject graphicsObj = factory.createGraphicsObject();
+
+ // set data object viewport (i.e. position, rotation, dimension, resolution)
+ graphicsObj.setViewport(graphicsObjectInfo);
+
+ AFPGraphics2D g2d = graphicsObjectInfo.getGraphics2D();
+ g2d.setGraphicsObject(graphicsObj);
+
+ // paint to graphics object
+ Graphics2DImagePainter painter = graphicsObjectInfo.getPainter();
+ Rectangle2D area = graphicsObjectInfo.getArea();
+ g2d.scale(1, -1);
+ g2d.translate(0, -area.getHeight());
+
+ painter.paint(g2d, area);
+
+ graphicsObj.setComplete(true);
+
+ // return painted graphics object
+ return graphicsObj;
+ }
+
+ /**
+ * Creates and returns a new include object.
+ *
+ * @param includeName the include name
+ * @param dataObjectInfo a data object info
+ *
+ * @return a new include object
+ */
+ public IncludeObject createInclude(String includeName, AFPDataObjectInfo dataObjectInfo) {
+ IncludeObject includeObj = factory.createInclude(includeName);
+
+ if (dataObjectInfo instanceof AFPImageObjectInfo) {
+ // IOCA image object
+ includeObj.setObjectType(IncludeObject.TYPE_IMAGE);
+ } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) {
+ // graphics object
+ includeObj.setObjectType(IncludeObject.TYPE_GRAPHIC);
+ } else {
+ // object container
+ includeObj.setObjectType(IncludeObject.TYPE_OTHER);
+
+ // set mandatory object classification (type other)
+ Registry.ObjectType objectType = dataObjectInfo.getObjectType();
+ if (objectType != null) {
+ // set object classification
+ final boolean dataInContainer = true;
+ final boolean containerHasOEG = false; // environment parameters set in include
+ final boolean dataInOCD = true;
+ includeObj.setObjectClassification(
+ // object scope not defined
+ ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT,
+ objectType, dataInContainer, containerHasOEG, dataInOCD);
+ } else {
+ throw new IllegalStateException(
+ "Failed to set Object Classification Triplet on Object Container.");
+ }
+ }
+
+ AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
+
+ int xOffset = objectAreaInfo.getX();
+ int yOffset = objectAreaInfo.getY();
+ includeObj.setObjectAreaOffset(xOffset, yOffset);
+
+ int width = objectAreaInfo.getWidth();
+ int height = objectAreaInfo.getHeight();
+ includeObj.setObjectAreaSize(width, height);
+
+ int rotation = objectAreaInfo.getRotation();
+ includeObj.setObjectAreaOrientation(rotation);
+
+ int widthRes = objectAreaInfo.getWidthRes();
+ int heightRes = objectAreaInfo.getHeightRes();
+ includeObj.setMeasurementUnits(widthRes, heightRes);
+
+ includeObj.setMappingOption(MappingOptionTriplet.SCALE_TO_FIT);
+
+ return includeObj;
+ }
+
+ /**
+ * Creates a resource object wrapper for named includable data objects
+ *
+ * @param namedObj an named object
+ * @param resourceInfo resource information
+ * @param objectType the object type
+ * @return a new resource object wrapper
+ */
+ public ResourceObject createResource(AbstractNamedAFPObject namedObj,
+ AFPResourceInfo resourceInfo, Registry.ObjectType objectType) {
+ ResourceObject resourceObj = null;
+ String resourceName = resourceInfo.getName();
+ if (resourceName != null) {
+ resourceObj = factory.createResource(resourceName);
+ } else {
+ resourceObj = factory.createResource();
+ }
+
+ if (namedObj instanceof Document) {
+ resourceObj.setType(ResourceObject.TYPE_DOCUMENT);
+ } else if (namedObj instanceof PageSegment) {
+ resourceObj.setType(ResourceObject.TYPE_PAGE_SEGMENT);
+ } else if (namedObj instanceof Overlay) {
+ resourceObj.setType(ResourceObject.TYPE_OVERLAY_OBJECT);
+ } else if (namedObj instanceof AbstractDataObject) {
+ AbstractDataObject dataObj = (AbstractDataObject)namedObj;
+ if (namedObj instanceof ObjectContainer) {
+ resourceObj.setType(ResourceObject.TYPE_OBJECT_CONTAINER);
+
+ // set object classification
+ final boolean dataInContainer = true;
+ final boolean containerHasOEG = false; // must be included
+ final boolean dataInOCD = true;
+ // mandatory triplet for object container
+ resourceObj.setObjectClassification(
+ ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT,
+ objectType, dataInContainer, containerHasOEG, dataInOCD);
+ } else if (namedObj instanceof ImageObject) {
+ // ioca image type
+ resourceObj.setType(ResourceObject.TYPE_IMAGE);
+ } else if (namedObj instanceof GraphicsObject) {
+ resourceObj.setType(ResourceObject.TYPE_GRAPHIC);
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported resource object for data object type " + dataObj);
+ }
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported resource object type " + namedObj);
+ }
+
+ // set the resource information/classification on the data object
+ resourceObj.setDataObject(namedObj);
+ return resourceObj;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/AFPDataObjectInfo.java b/src/java/org/apache/fop/afp/AFPDataObjectInfo.java
new file mode 100644
index 000000000..f6ff0046a
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPDataObjectInfo.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.modca.Registry;
+
+/**
+ * A list of parameters associated with an AFP data objects
+ */
+public class AFPDataObjectInfo {
+ private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
+
+ /** the object area info */
+ private AFPObjectAreaInfo objectAreaInfo;
+
+ /** resource info */
+ private AFPResourceInfo resourceInfo;
+
+ /** the data object width */
+ private int dataWidth;
+
+ /** the data object height */
+ private int dataHeight;
+
+ /** the object registry mimetype */
+ private String mimeType;
+
+ /** the object data in a byte array */
+ private byte[] data;
+
+ /** the object data height resolution */
+ private int dataHeightRes;
+
+ /** the object data width resolution */
+ private int dataWidthRes;
+
+ /**
+ * Default constructor
+ */
+ public AFPDataObjectInfo() {
+ }
+
+ /**
+ * Sets the image mime type
+ *
+ * @param mimeType the image mime type
+ */
+ public void setMimeType(String mimeType) {
+ this.mimeType = mimeType;
+ }
+
+ /**
+ * Returns the mime type of this data object
+ *
+ * @return the mime type of this data object
+ */
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ /**
+ * Convenience method to return the object type
+ *
+ * @return the object type
+ */
+ public Registry.ObjectType getObjectType() {
+ return Registry.getInstance().getObjectType(getMimeType());
+ }
+
+ /**
+ * Returns the resource level at which this data object should reside
+ *
+ * @return the resource level at which this data object should reside
+ */
+ public AFPResourceInfo getResourceInfo() {
+ if (resourceInfo == null) {
+ this.resourceInfo = new AFPResourceInfo();
+ }
+ return resourceInfo;
+ }
+
+ /**
+ * Sets the resource level at which this object should reside
+ *
+ * @param resourceInfo the resource level at which this data object should reside
+ */
+ public void setResourceInfo(AFPResourceInfo resourceInfo) {
+ this.resourceInfo = resourceInfo;
+ }
+
+ /**
+ * Sets the object area info
+ *
+ * @param objectAreaInfo the object area info
+ */
+ public void setObjectAreaInfo(AFPObjectAreaInfo objectAreaInfo) {
+ this.objectAreaInfo = objectAreaInfo;
+ }
+
+ /**
+ * Returns the object area info
+ *
+ * @return the object area info
+ */
+ public AFPObjectAreaInfo getObjectAreaInfo() {
+ return this.objectAreaInfo;
+ }
+
+ /**
+ * Returns the uri of this data object
+ *
+ * @return the uri of this data object
+ */
+ public String getUri() {
+ return getResourceInfo().getUri();
+ }
+
+ /**
+ * Sets the data object uri
+ *
+ * @param uri the data object uri
+ */
+ public void setUri(String uri) {
+ getResourceInfo().setUri(uri);
+ }
+
+ /**
+ * Returns the image data width
+ *
+ * @return the image data width
+ */
+ public int getDataWidth() {
+ return dataWidth;
+ }
+
+ /**
+ * Sets the image data width
+ *
+ * @param imageDataWidth the image data width
+ */
+ public void setDataWidth(int imageDataWidth) {
+ this.dataWidth = imageDataWidth;
+ }
+
+ /**
+ * Returns the image data height
+ *
+ * @return the image data height
+ */
+ public int getDataHeight() {
+ return dataHeight;
+ }
+
+ /**
+ * Sets the image data height
+ *
+ * @param imageDataHeight the image data height
+ */
+ public void setDataHeight(int imageDataHeight) {
+ this.dataHeight = imageDataHeight;
+ }
+
+ /**
+ * Returns the data height resolution
+ *
+ * @return the data height resolution
+ */
+ public int getDataHeightRes() {
+ return this.dataHeightRes;
+ }
+
+ /**
+ * Sets the data width resolution
+ *
+ * @param dataWidthRes the data width resolution
+ */
+ public void setDataHeightRes(int dataHeightRes) {
+ this.dataHeightRes = dataHeightRes;
+ }
+
+ /**
+ * Returns the data width resolution
+ *
+ * @return the data width resolution
+ */
+ public int getDataWidthRes() {
+ return this.dataWidthRes;
+ }
+
+ /**
+ * Sets the data width resolution
+ *
+ * @param dataWidthRes the data width resolution
+ */
+ public void setDataWidthRes(int dataWidthRes) {
+ this.dataWidthRes = dataWidthRes;
+ }
+
+ /**
+ * Sets the object data
+ *
+ * @param data the object data
+ */
+ public void setData(byte[] data) {
+ this.data = data;
+ }
+
+ /**
+ * Returns the object data
+ *
+ * @return the object data
+ */
+ public byte[] getData() {
+ return this.data;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPDataObjectInfo{"
+ + "mimeType=" + mimeType
+ + ", dataWidth=" + dataWidth
+ + ", dataHeight=" + dataHeight
+ + ", dataWidthRes=" + dataWidthRes
+ + ", dataHeightRes=" + dataHeightRes
+ + (objectAreaInfo != null ? ", objectAreaInfo=" + objectAreaInfo : "")
+ + (resourceInfo != null ? ", resourceInfo=" + resourceInfo : "");
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPEventProducer.java b/src/java/org/apache/fop/afp/AFPEventProducer.java
index 08641b20e..49792183f 100644
--- a/src/java/org/apache/fop/render/afp/AFPEventProducer.java
+++ b/src/java/org/apache/fop/afp/AFPEventProducer.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp;
+package org.apache.fop.afp;
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.events.EventProducer;
@@ -55,9 +55,29 @@ public interface AFPEventProducer extends EventProducer {
/**
* Warn about using default font setup.
+ *
* @param source the event source
* @event.severity WARN
*/
void warnDefaultFontSetup(Object source);
+ /**
+ * Warn about a missing default "any" font configuration.
+ *
+ * @param source the event source
+ * @param style the font style
+ * @param weight the font weight
+ * @event.severity WARN
+ */
+ void warnMissingDefaultFont(Object source, String style, int weight);
+
+ /**
+ * A character set encoding error occurred.
+ *
+ * @param source the event source
+ * @param charSetName the character set name
+ * @param encoding the encoding
+ * @event.severity ERROR
+ */
+ void characterSetEncodingError(Object source, String charSetName, String encoding);
}
diff --git a/src/java/org/apache/fop/afp/AFPEventProducer.xml b/src/java/org/apache/fop/afp/AFPEventProducer.xml
new file mode 100644
index 000000000..8e6bb5429
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPEventProducer.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<catalogue xml:lang="en">
+ <message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup">No AFP fonts configured. Using default setup.</message>
+ <message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont">No AFP default "any", {style}, {weight} font configured.</message>
+ <message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError">An error occurred when attempting to encode character set {charSetName} with encoding scheme {encoding}.</message>
+</catalogue>
diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java
new file mode 100644
index 000000000..ee160feca
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java
@@ -0,0 +1,698 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.TexturePaint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Line2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.io.IOException;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.goca.GraphicsSetLineType;
+import org.apache.fop.afp.modca.GraphicsObject;
+import org.apache.fop.afp.svg.AFPGraphicsConfiguration;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.svg.NativeImageHandler;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
+import org.apache.xmlgraphics.java2d.GraphicContext;
+import org.apache.xmlgraphics.java2d.StrokingTextHandler;
+import org.apache.xmlgraphics.java2d.TextHandler;
+import org.apache.xmlgraphics.ps.ImageEncodingHelper;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * This is a concrete implementation of <tt>AbstractGraphics2D</tt> (and
+ * therefore of <tt>Graphics2D</tt>) which is able to generate GOCA byte
+ * codes.
+ *
+ * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D
+ */
+public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHandler {
+
+ private static final Log log = LogFactory.getLog(AFPGraphics2D.class);
+
+ private static final int X = 0;
+
+ private static final int Y = 1;
+
+ private static final int X1 = 0;
+
+ private static final int Y1 = 1;
+
+ private static final int X2 = 2;
+
+ private static final int Y2 = 3;
+
+ private static final int X3 = 4;
+
+ private static final int Y3 = 5;
+
+ /** graphics object */
+ private GraphicsObject graphicsObj = null;
+
+ /** Fallback text handler */
+ protected TextHandler fallbackTextHandler = new StrokingTextHandler();
+
+ /** Custom text handler */
+ protected TextHandler customTextHandler = null;
+
+ /** AFP resource manager */
+ private AFPResourceManager resourceManager = null;
+
+ /** AFP resource info */
+ private AFPResourceInfo resourceInfo = null;
+
+ /** Current AFP state */
+ private AFPPaintingState paintingState = null;
+
+ /** AFP graphics configuration */
+ private final AFPGraphicsConfiguration graphicsConfig = new AFPGraphicsConfiguration();
+
+ /** The AFP FontInfo */
+ private FontInfo fontInfo;
+
+ /**
+ * Main constructor
+ *
+ * @param textAsShapes
+ * if true, all text is turned into shapes in the convertion. No
+ * text is output.
+ * @param paintingState painting state
+ * @param resourceManager resource manager
+ * @param resourceInfo resource info
+ * @param fontInfo font info
+ */
+ public AFPGraphics2D(boolean textAsShapes, AFPPaintingState paintingState,
+ AFPResourceManager resourceManager, AFPResourceInfo resourceInfo,
+ FontInfo fontInfo) {
+ super(textAsShapes);
+ this.paintingState = paintingState;
+ this.resourceManager = resourceManager;
+ this.resourceInfo = resourceInfo;
+ this.fontInfo = fontInfo;
+ }
+
+ /**
+ * Copy Constructor
+ *
+ * @param g2d
+ * a AFPGraphics2D whose properties should be copied
+ */
+ public AFPGraphics2D(AFPGraphics2D g2d) {
+ super(g2d);
+ this.paintingState = g2d.paintingState;
+ this.resourceManager = g2d.resourceManager;
+ this.resourceInfo = g2d.resourceInfo;
+ this.fontInfo = g2d.fontInfo;
+
+ this.graphicsObj = g2d.graphicsObj;
+ this.fallbackTextHandler = g2d.fallbackTextHandler;
+ this.customTextHandler = g2d.customTextHandler;
+ }
+
+ /**
+ * Sets the AFP resource manager
+ *
+ * @param resourceManager the AFP resource manager
+ */
+ public void setResourceManager(AFPResourceManager resourceManager) {
+ this.resourceManager = resourceManager;
+ }
+
+ /**
+ * Sets the AFP resource info
+ *
+ * @param resourceInfo the AFP resource info
+ */
+ public void setResourceInfo(AFPResourceInfo resourceInfo) {
+ this.resourceInfo = resourceInfo;
+ }
+
+ /**
+ * Sets the GraphicContext
+ *
+ * @param gc
+ * GraphicContext to use
+ */
+ public void setGraphicContext(GraphicContext gc) {
+ this.gc = gc;
+ }
+
+ /**
+ * Apply the stroke to the AFP graphics object.
+ * This takes the java stroke and outputs the appropriate settings
+ * to the AFP graphics object so that the stroke attributes are handled.
+ *
+ * @param stroke the java stroke
+ */
+ protected void applyStroke(Stroke stroke) {
+ if (stroke instanceof BasicStroke) {
+ BasicStroke basicStroke = (BasicStroke) stroke;
+
+ // set line width
+ float lineWidth = basicStroke.getLineWidth();
+ graphicsObj.setLineWidth(Math.round(lineWidth / 2));
+
+ // set line type/style (note: this is an approximation at best!)
+ float[] dashArray = basicStroke.getDashArray();
+ if (paintingState.setDashArray(dashArray)) {
+ byte type = GraphicsSetLineType.DEFAULT; // normally SOLID
+ if (dashArray != null) {
+ type = GraphicsSetLineType.DOTTED; // default to plain DOTTED if dashed line
+ // float offset = basicStroke.getDashPhase();
+ if (dashArray.length == 2) {
+ if (dashArray[0] < dashArray[1]) {
+ type = GraphicsSetLineType.SHORT_DASHED;
+ } else if (dashArray[0] > dashArray[1]) {
+ type = GraphicsSetLineType.LONG_DASHED;
+ }
+ } else if (dashArray.length == 4) {
+ if (dashArray[0] > dashArray[1]
+ && dashArray[2] < dashArray[3]) {
+ type = GraphicsSetLineType.DASH_DOT;
+ } else if (dashArray[0] < dashArray[1]
+ && dashArray[2] < dashArray[3]) {
+ type = GraphicsSetLineType.DOUBLE_DOTTED;
+ }
+ } else if (dashArray.length == 6) {
+ if (dashArray[0] > dashArray[1]
+ && dashArray[2] < dashArray[3]
+ && dashArray[4] < dashArray[5]) {
+ type = GraphicsSetLineType.DASH_DOUBLE_DOTTED;
+ }
+ }
+ }
+ graphicsObj.setLineType(type);
+ }
+ } else {
+ log.warn("Unsupported Stroke: " + stroke.getClass().getName());
+ }
+ }
+
+ /**
+ * Apply the java paint to the AFP.
+ * This takes the java paint sets up the appropriate AFP commands
+ * for the drawing with that paint.
+ * Currently this supports the gradients and patterns from batik.
+ *
+ * @param paint the paint to convert to AFP
+ * @param fill true if the paint should be set for filling
+ * @return true if the paint is handled natively, false if the paint should be rasterized
+ */
+ private boolean applyPaint(Paint paint, boolean fill) {
+ if (paint instanceof Color) {
+ return true;
+ }
+ log.debug("NYI: applyPaint() " + paint + " fill=" + fill);
+ if (paint instanceof TexturePaint) {
+// TexturePaint texturePaint = (TexturePaint)paint;
+// BufferedImage bufferedImage = texturePaint.getImage();
+// AffineTransform at = paintingState.getTransform();
+// int x = (int)Math.round(at.getTranslateX());
+// int y = (int)Math.round(at.getTranslateY());
+// drawImage(bufferedImage, x, y, null);
+ }
+ return false;
+ }
+
+
+ /**
+ * Handle the Batik drawing event
+ *
+ * @param shape
+ * the shape to draw
+ * @param fill
+ * true if the shape is to be drawn filled
+ */
+ private void doDrawing(Shape shape, boolean fill) {
+ if (!fill) {
+ graphicsObj.newSegment();
+ }
+
+ graphicsObj.setColor(gc.getColor());
+
+ applyPaint(gc.getPaint(), fill);
+
+ if (fill) {
+ graphicsObj.beginArea();
+ } else {
+ applyStroke(gc.getStroke());
+ }
+
+ AffineTransform trans = gc.getTransform();
+ PathIterator iter = shape.getPathIterator(trans);
+ if (shape instanceof Line2D) {
+ double[] dstPts = new double[6];
+ iter.currentSegment(dstPts);
+ int[] coords = new int[4];
+ coords[X1] = (int) Math.round(dstPts[X]);
+ coords[Y1] = (int) Math.round(dstPts[Y]);
+ iter.next();
+ iter.currentSegment(dstPts);
+ coords[X2] = (int) Math.round(dstPts[X]);
+ coords[Y2] = (int) Math.round(dstPts[Y]);
+ graphicsObj.addLine(coords);
+ } else if (shape instanceof Rectangle2D) {
+ double[] dstPts = new double[6];
+ iter.currentSegment(dstPts);
+ int[] coords = new int[4];
+ coords[X2] = (int) Math.round(dstPts[X]);
+ coords[Y2] = (int) Math.round(dstPts[Y]);
+ iter.next();
+ iter.next();
+ iter.currentSegment(dstPts);
+ coords[X1] = (int) Math.round(dstPts[X]);
+ coords[Y1] = (int) Math.round(dstPts[Y]);
+ graphicsObj.addBox(coords);
+ } else if (shape instanceof Ellipse2D) {
+ double[] dstPts = new double[6];
+ Ellipse2D elip = (Ellipse2D) shape;
+ double scale = trans.getScaleX();
+ double radiusWidth = elip.getWidth() / 2;
+ double radiusHeight = elip.getHeight() / 2;
+ graphicsObj.setArcParams(
+ (int)Math.round(radiusWidth * scale),
+ (int)Math.round(radiusHeight * scale),
+ 0,
+ 0
+ );
+ double[] srcPts = new double[] {elip.getCenterX(), elip.getCenterY()};
+ trans.transform(srcPts, 0, dstPts, 0, 1);
+ final int mh = 1;
+ final int mhr = 0;
+ graphicsObj.addFullArc(
+ (int)Math.round(dstPts[X]),
+ (int)Math.round(dstPts[Y]),
+ mh,
+ mhr
+ );
+ } else {
+ processPathIterator(iter);
+ }
+
+ if (fill) {
+ graphicsObj.endArea();
+ }
+ }
+
+ /**
+ * Processes a path iterator generating the necessary painting operations.
+ *
+ * @param iter PathIterator to process
+ */
+ private void processPathIterator(PathIterator iter) {
+ double[] dstPts = new double[6];
+ for (int[] openingCoords = new int[2]; !iter.isDone(); iter.next()) {
+ switch (iter.currentSegment(dstPts)) {
+ case PathIterator.SEG_LINETO:
+ graphicsObj.addLine(new int[] {
+ (int)Math.round(dstPts[X]),
+ (int)Math.round(dstPts[Y])
+ }, true);
+ break;
+ case PathIterator.SEG_QUADTO:
+ graphicsObj.addFillet(new int[] {
+ (int)Math.round(dstPts[X1]),
+ (int)Math.round(dstPts[Y1]),
+ (int)Math.round(dstPts[X2]),
+ (int)Math.round(dstPts[Y2])
+ }, true);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ graphicsObj.addFillet(new int[] {
+ (int)Math.round(dstPts[X1]),
+ (int)Math.round(dstPts[Y1]),
+ (int)Math.round(dstPts[X2]),
+ (int)Math.round(dstPts[Y2]),
+ (int)Math.round(dstPts[X3]),
+ (int)Math.round(dstPts[Y3])
+ }, true);
+ break;
+ case PathIterator.SEG_MOVETO:
+ openingCoords = new int[] {
+ (int)Math.round(dstPts[X]),
+ (int)Math.round(dstPts[Y])
+ };
+ graphicsObj.setCurrentPosition(openingCoords);
+ break;
+ case PathIterator.SEG_CLOSE:
+ graphicsObj.addLine(openingCoords, true);
+ break;
+ default:
+ log.debug("Unrecognised path iterator type");
+ break;
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void draw(Shape shape) {
+ log.debug("draw() shape=" + shape);
+ doDrawing(shape, false);
+ }
+
+ /** {@inheritDoc} */
+ public void fill(Shape shape) {
+ log.debug("fill() shape=" + shape);
+ doDrawing(shape, true);
+ }
+
+ /**
+ * Central handler for IOExceptions for this class.
+ *
+ * @param ioe
+ * IOException to handle
+ */
+ public void handleIOException(IOException ioe) {
+ // TODO Surely, there's a better way to do this.
+ log.error(ioe.getMessage());
+ ioe.printStackTrace();
+ }
+
+ /** {@inheritDoc} */
+ public void drawString(String str, float x, float y) {
+ try {
+ if (customTextHandler != null && !textAsShapes) {
+ customTextHandler.drawString(this, str, x, y);
+ } else {
+ fallbackTextHandler.drawString(this, str, x, y);
+ }
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return graphicsConfig;
+ }
+
+ /** {@inheritDoc} */
+ public Graphics create() {
+ return new AFPGraphics2D(this);
+ }
+
+ /** {@inheritDoc} */
+ public void dispose() {
+ this.graphicsObj = null;
+ }
+
+ /** {@inheritDoc} */
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+ return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), observer);
+ }
+
+ private BufferedImage buildBufferedImage(Dimension size) {
+ return new BufferedImage(size.width, size.height,
+ BufferedImage.TYPE_INT_ARGB);
+ }
+
+ private AFPImageObjectInfo createImageObjectInfo(
+ RenderedImage img, int x, int y, int width, int height) throws IOException {
+ ImageInfo imageInfo = new ImageInfo(null, "image/unknown");
+ ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72);
+ imageInfo.setSize(size);
+
+ ImageRendered imageRendered = new ImageRendered(imageInfo, img, null);
+ RenderedImage renderedImage = imageRendered.getRenderedImage();
+
+ // create image object info
+ AFPImageObjectInfo imageObjectInfo = new AFPImageObjectInfo();
+
+ imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
+
+ int bitsPerPixel = paintingState.getBitsPerPixel();
+ imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+
+ imageObjectInfo.setResourceInfo(resourceInfo);
+
+ int dataHeight = renderedImage.getHeight();
+ imageObjectInfo.setDataHeight(dataHeight);
+
+ int dataWidth = renderedImage.getWidth();
+ imageObjectInfo.setDataWidth(dataWidth);
+
+ boolean colorImages = paintingState.isColorImages();
+ imageObjectInfo.setColor(colorImages);
+
+ ByteArrayOutputStream boas = new ByteArrayOutputStream();
+ ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, boas);
+ byte[] imageData = boas.toByteArray();
+
+ // convert to grayscale
+ if (!colorImages) {
+ boas.reset();
+ imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+ ImageEncodingHelper.encodeRGBAsGrayScale(
+ imageData, dataWidth, dataHeight, bitsPerPixel, boas);
+ imageData = boas.toByteArray();
+ }
+ imageObjectInfo.setData(imageData);
+
+ if (imageInfo != null) {
+ imageObjectInfo.setUri(imageInfo.getOriginalURI());
+ }
+
+ // create object area info
+ AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
+ objectAreaInfo.setX(x);
+ objectAreaInfo.setY(y);
+ objectAreaInfo.setWidth(width);
+ objectAreaInfo.setHeight(height);
+
+ int resolution = paintingState.getResolution();
+ objectAreaInfo.setWidthRes(resolution);
+ objectAreaInfo.setHeightRes(resolution);
+
+ imageObjectInfo.setObjectAreaInfo(objectAreaInfo);
+
+ return imageObjectInfo;
+ }
+
+ /**
+ * Draws an AWT image into a BufferedImage using an AWT Graphics2D implementation
+ *
+ * @param img the AWT image
+ * @param bufferedImage the AWT buffered image
+ * @param width the image width
+ * @param height the image height
+ * @param observer the image observer
+ * @return true if the image was drawn
+ */
+ private boolean drawBufferedImage(Image img, BufferedImage bufferedImage,
+ int width, int height, ImageObserver observer) {
+
+ java.awt.Graphics2D g2d = bufferedImage.createGraphics();
+ try {
+ g2d.setComposite(AlphaComposite.SrcOver);
+
+ Color color = new Color(1, 1, 1, 0);
+ g2d.setBackground(color);
+ g2d.setPaint(color);
+
+ g2d.fillRect(0, 0, width, height);
+
+ int imageWidth = bufferedImage.getWidth();
+ int imageHeight = bufferedImage.getHeight();
+ Rectangle clipRect = new Rectangle(0, 0, imageWidth, imageHeight);
+ g2d.clip(clipRect);
+
+ g2d.setComposite(gc.getComposite());
+
+ return g2d.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
+ } finally {
+ g2d.dispose(); //drawn so dispose immediately to free system resource
+ }
+ }
+
+ /** {@inheritDoc} */
+ public boolean drawImage(Image img, int x, int y, int width, int height,
+ ImageObserver observer) {
+
+ // draw with AWT Graphics2D
+ Dimension imageSize = new Dimension(width, height);
+ BufferedImage bufferedImage = buildBufferedImage(imageSize);
+
+ boolean drawn = drawBufferedImage(img, bufferedImage, width, height, observer);
+ if (drawn) {
+ AffineTransform at = gc.getTransform();
+ float[] srcPts = new float[] {x, y};
+ float[] dstPts = new float[srcPts.length];
+ at.transform(srcPts, 0, dstPts, 0, 1);
+ x = Math.round(dstPts[X]);
+ y = Math.round(dstPts[Y]);
+ try {
+ // get image object info
+ AFPImageObjectInfo imageObjectInfo
+ = createImageObjectInfo(bufferedImage, x, y, width, height);
+
+ // create image resource
+ resourceManager.createObject(imageObjectInfo);
+ return true;
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
+ int imgWidth = img.getWidth();
+ int imgHeight = img.getHeight();
+
+ AffineTransform at = paintingState.getData().getTransform();
+ AffineTransform gat = gc.getTransform();
+ int graphicsObjectHeight
+ = graphicsObj.getObjectEnvironmentGroup().getObjectAreaDescriptor().getHeight();
+ int x = (int)Math.round(at.getTranslateX() + gat.getTranslateX());
+ int y = (int)Math.round(at.getTranslateY() - (gat.getTranslateY() - graphicsObjectHeight));
+ int width = (int)Math.round(imgWidth * gat.getScaleX());
+ int height = (int)Math.round(imgHeight * -gat.getScaleY());
+ try {
+ // get image object info
+ AFPImageObjectInfo imageObjectInfo
+ = createImageObjectInfo(img, x, y, width, height);
+ // create image resource
+ resourceManager.createObject(imageObjectInfo);
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
+ }
+
+ /**
+ * Sets a custom TextHandler implementation that is responsible for painting
+ * text. The default TextHandler paints all text as shapes. A custom
+ * implementation can implement text painting using text painting operators.
+ *
+ * @param handler
+ * the custom TextHandler implementation
+ */
+ public void setCustomTextHandler(TextHandler handler) {
+ this.customTextHandler = handler;
+ }
+
+ /**
+ * Returns the GOCA graphics object
+ *
+ * @return the GOCA graphics object
+ */
+ public GraphicsObject getGraphicsObject() {
+ return this.graphicsObj;
+ }
+
+ /**
+ * Sets the GOCA graphics object
+ *
+ * @param obj the GOCA graphics object
+ */
+ public void setGraphicsObject(GraphicsObject obj) {
+ this.graphicsObj = obj;
+ }
+
+ /**
+ * Sets the AFP painting state
+ *
+ * @param paintingState the AFP painting state
+ */
+ public void setPaintingState(AFPPaintingState paintingState) {
+ this.paintingState = paintingState;
+ }
+
+ /**
+ * Returns the AFP painting state
+ *
+ * @return the AFP painting state
+ */
+ public AFPPaintingState getPaintingState() {
+ return this.paintingState;
+ }
+
+ /**
+ * Sets the FontInfo
+ *
+ * @param the FontInfo
+ */
+ public void setFontInfo(FontInfo fontInfo) {
+ this.fontInfo = fontInfo;
+ }
+
+ /**
+ * Returns the FontInfo
+ *
+ * @return the FontInfo
+ */
+ public FontInfo getFontInfo() {
+ return this.fontInfo;
+ }
+
+ /** {@inheritDoc} */
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+ log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform);
+ }
+
+ /** {@inheritDoc} */
+ public FontMetrics getFontMetrics(Font f) {
+ log.debug("getFontMetrics() NYI: f=" + f);
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ public void setXORMode(Color col) {
+ log.debug("setXORMode() NYI: col=" + col);
+ }
+
+ /** {@inheritDoc} */
+ public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image,
+ float x, float y, float width, float height) {
+ log.debug("NYI: addNativeImage() "+ "image=" + image
+ + ",x=" + x + ",y=" + y + ",width=" + width + ",height=" + height);
+ }
+
+ /** {@inheritDoc} */
+ public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+ log.debug("copyArea() NYI: ");
+ }
+}
diff --git a/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java b/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java
new file mode 100644
index 000000000..cd8c7c303
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * A graphics object info which contains necessary painting objects
+ */
+public class AFPGraphicsObjectInfo extends AFPDataObjectInfo {
+
+ /** the graphics object painter implementation */
+ private Graphics2DImagePainter painter;
+
+ /** the graphics object area */
+ private Rectangle2D area;
+
+ /** the AFP graphics 2d implementation */
+ private AFPGraphics2D g2d;
+
+ /**
+ * Returns the graphics painter
+ *
+ * @return the graphics painter
+ */
+ public Graphics2DImagePainter getPainter() {
+ return this.painter;
+ }
+
+ /**
+ * Sets the graphics painter
+ *
+ * @param graphicsPainter the graphics painter
+ */
+ public void setPainter(Graphics2DImagePainter graphicsPainter) {
+ this.painter = graphicsPainter;
+ }
+
+ /**
+ * Returns the graphics area
+ *
+ * @return the graphics area
+ */
+ public Rectangle2D getArea() {
+ AFPObjectAreaInfo objectAreaInfo = getObjectAreaInfo();
+ int width = objectAreaInfo.getWidth();
+ int height = objectAreaInfo.getHeight();
+ return new Rectangle(width, height);
+ }
+
+ /**
+ * Sets the graphics area area
+ *
+ * @param area the graphics object area
+ */
+ public void setArea(Rectangle2D area) {
+ this.area = area;
+ }
+
+ /**
+ * Sets the AFP graphics 2D implementation
+ *
+ * @param g2d the AFP graphics 2D implementation
+ */
+ public void setGraphics2D(AFPGraphics2D g2d) {
+ this.g2d = g2d;
+ }
+
+ /**
+ * Returns the AFP graphics 2D implementation
+ *
+ * @return the AFP graphics 2D implementation
+ */
+ public AFPGraphics2D getGraphics2D() {
+ return this.g2d;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsObjectInfo{" + super.toString() + "}";
+ }
+
+ /** {@inheritDoc} */
+ public String getMimeType() {
+ return MimeConstants.MIME_SVG;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/AFPImageObjectInfo.java b/src/java/org/apache/fop/afp/AFPImageObjectInfo.java
new file mode 100644
index 000000000..f3677534f
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPImageObjectInfo.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp;
+
+
+/**
+ * A list of parameters associated with an image
+ */
+public class AFPImageObjectInfo extends AFPDataObjectInfo {
+
+ /** number of bits per pixel used */
+ private int bitsPerPixel;
+
+ /** is this a color image? */
+ private boolean color;
+
+ /** compression type if any */
+ private int compression = -1;
+
+ /**
+ * Default constructor
+ */
+ public AFPImageObjectInfo() {
+ super();
+ }
+
+ /**
+ * Sets the number of bits per pixel
+ *
+ * @param bitsPerPixel the number of bits per pixel
+ */
+ public void setBitsPerPixel(int bitsPerPixel) {
+ this.bitsPerPixel = bitsPerPixel;
+ }
+
+ /**
+ * Sets if this image is color
+ *
+ * @param color true if this is a color image
+ */
+ public void setColor(boolean color) {
+ this.color = color;
+ }
+
+ /**
+ * Returns the number of bits used per pixel
+ *
+ * @return the number of bits used per pixel
+ */
+ public int getBitsPerPixel() {
+ return bitsPerPixel;
+ }
+
+ /**
+ * Returns true if this is a color image
+ *
+ * @return true if this is a color image
+ */
+ public boolean isColor() {
+ return color;
+ }
+
+ /**
+ * Returns true if this image uses compression
+ *
+ * @return true if this image uses compression
+ */
+ public boolean hasCompression() {
+ return compression > -1;
+ }
+
+ /**
+ * Returns the compression type
+ *
+ * @return the compression type
+ */
+ public int getCompression() {
+ return compression;
+ }
+
+ /**
+ * Sets the compression used with this image
+ *
+ * @param compression the type of compression used with this image
+ */
+ public void setCompression(int compression) {
+ this.compression = compression;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPImageObjectInfo{" + super.toString()
+ + ", compression=" + compression
+ + ", color=" + color
+ + ", bitsPerPixel=" + bitsPerPixel
+ + "}";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPLineDataInfo.java b/src/java/org/apache/fop/afp/AFPLineDataInfo.java
new file mode 100644
index 000000000..f3acf4f71
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPLineDataInfo.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.Color;
+
+/** Line data information */
+public class AFPLineDataInfo {
+
+ /** the x1 coordinate */
+ int x1;
+
+ /** the y1 coordinate */
+ int y1;
+
+ /** the x2 coordinate */
+ int x2;
+
+ /** the y2 coordinate */
+ int y2;
+
+ /** the thickness */
+ int thickness;
+
+ /** the painting color */
+ Color color;
+
+ /** the rotation */
+ int rotation = 0;
+
+ /**
+ * Default constructor
+ */
+ public AFPLineDataInfo() {
+ }
+
+ /**
+ * Returns the X1 coordinate
+ *
+ * @return the X1 coordinate
+ */
+ public int getX1() {
+ return x1;
+ }
+
+ /**
+ * Sets the X1 coordinate
+ *
+ * @param x1 the X1 coordinate
+ */
+ public void setX1(int x1) {
+ this.x1 = x1;
+ }
+
+ /**
+ * Returns the Y1 coordinate
+ *
+ * @return the Y1 coordinate
+ */
+ public int getY1() {
+ return y1;
+ }
+
+ /**
+ * Sets the Y1 coordinate
+ *
+ * @param y1 the Y1 coordinate
+ */
+ public void setY1(int y1) {
+ this.y1 = y1;
+ }
+
+ /**
+ * Returns the X2 coordinate
+ *
+ * @return the X2 coordinate
+ */
+ public int getX2() {
+ return x2;
+ }
+
+ /**
+ * Sets the X2 coordinate
+ *
+ * @param x2 the X2 coordinate
+ */
+ public void setX2(int x2) {
+ this.x2 = x2;
+ }
+
+ /**
+ * Returns the Y2 coordinate
+ *
+ * @return the Y2 coordinate
+ */
+ public int getY2() {
+ return y2;
+ }
+
+ /**
+ * Sets the Y2 coordinate
+ *
+ * @param y2 the Y2 coordinate
+ */
+ public void setY2(int y2) {
+ this.y2 = y2;
+ }
+
+ /**
+ * Returns the line thickness
+ *
+ * @return the line thickness
+ */
+ public int getThickness() {
+ return thickness;
+ }
+
+ /**
+ * Sets the line thickness
+ *
+ * @param thickness the line thickness
+ */
+ public void setThickness(int thickness) {
+ this.thickness = thickness;
+ }
+
+ /**
+ * Returns line color
+ *
+ * @return the line color
+ */
+ public Color getColor() {
+ return color;
+ }
+
+ /**
+ * Sets the line color
+ *
+ * @param color the line color
+ */
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ /**
+ * Returns line rotation
+ *
+ * @return the line rotation
+ */
+ public int getRotation() {
+ return rotation;
+ }
+
+ /**
+ * Sets the line rotation
+ *
+ * @param rotation the line rotation
+ */
+ public void setRotation(int rotation) {
+ this.rotation = rotation;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPLineDataInfo{x1=" + x1
+ + ", y1=" + y1
+ + ", x2=" + x2
+ + ", y2=" + y2
+ + ", thickness=" + thickness
+ + ", color=" + color
+ + ", rotation=" + rotation
+ + "}";
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/AFPObjectAreaInfo.java b/src/java/org/apache/fop/afp/AFPObjectAreaInfo.java
new file mode 100644
index 000000000..963424470
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPObjectAreaInfo.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+/**
+ * A common class used to convey locations,
+ * dimensions and resolutions of data objects.
+ */
+public class AFPObjectAreaInfo {
+ private int x;
+ private int y;
+ private int width;
+ private int height;
+ private int widthRes;
+ private int heightRes;
+ private int rotation = 0;
+
+ /**
+ * Sets the x position of the data object
+ *
+ * @param x the x position of the data object
+ */
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ /**
+ * Sets the y position of the data object
+ *
+ * @param y the y position of the data object
+ */
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ /**
+ * Sets the data object width
+ *
+ * @param width the width of the data object
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * Sets the data object height
+ *
+ * @param height the height of the data object
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * Sets the width resolution
+ *
+ * @param widthRes the width resolution
+ */
+ public void setWidthRes(int widthRes) {
+ this.widthRes = widthRes;
+ }
+
+ /**
+ * Sets the height resolution
+ *
+ * @param heightRes the height resolution
+ */
+ public void setHeightRes(int heightRes) {
+ this.heightRes = heightRes;
+ }
+
+ /**
+ * Returns the x coordinate of this data object
+ *
+ * @return the x coordinate of this data object
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * Returns the y coordinate of this data object
+ *
+ * @return the y coordinate of this data object
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * Returns the width of this data object
+ *
+ * @return the width of this data object
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Returns the height of this data object
+ *
+ * @return the height of this data object
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Returns the width resolution of this data object
+ *
+ * @return the width resolution of this data object
+ */
+ public int getWidthRes() {
+ return widthRes;
+ }
+
+ /**
+ * Returns the height resolution of this data object
+ *
+ * @return the height resolution of this data object
+ */
+ public int getHeightRes() {
+ return heightRes;
+ }
+
+ /**
+ * Returns the rotation of this data object
+ *
+ * @return the rotation of this data object
+ */
+ public int getRotation() {
+ return rotation;
+ }
+
+ /**
+ * Sets the data object rotation
+ *
+ * @param rotation the data object rotation
+ */
+ public void setRotation(int rotation) {
+ this.rotation = rotation;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "x=" + x
+ + ", y=" + y
+ + ", width=" + width
+ + ", height=" + height
+ + ", widthRes=" + widthRes
+ + ", heightRes=" + heightRes
+ + ", rotation=" + rotation;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/AFPPaintingState.java b/src/java/org/apache/fop/afp/AFPPaintingState.java
new file mode 100644
index 000000000..95a310bcb
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPPaintingState.java
@@ -0,0 +1,495 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.fonts.AFPPageFonts;
+import org.apache.fop.util.AbstractPaintingState;
+
+/**
+ * This keeps information about the current painting state when writing to an AFP datastream.
+ */
+public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
+implements Cloneable {
+
+ private static final long serialVersionUID = 8206711712452344473L;
+
+ private static Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
+
+ /** the portrait rotation */
+ private int portraitRotation = 0;
+
+ /** the landscape rotation */
+ private int landscapeRotation = 270;
+
+ /** color image support */
+ private boolean colorImages = false;
+
+ /** images are supported in this AFP environment */
+ private boolean nativeImagesSupported = false;
+
+ /** default value for image depth */
+ private int bitsPerPixel = 8;
+
+ /** the output resolution */
+ private int resolution = 240; // 240 dpi
+
+ /** the current page */
+ private AFPPagePaintingState pagePaintingState = new AFPPagePaintingState();
+
+// /** reference orientation */
+// private int orientation = 0;
+
+ /** a unit converter */
+ private final transient AFPUnitConverter unitConv = new AFPUnitConverter(this);
+
+ /**
+ * Sets the rotation to be used for portrait pages, valid values are 0
+ * (default), 90, 180, 270.
+ *
+ * @param rotation
+ * The rotation in degrees.
+ */
+ public void setPortraitRotation(int rotation) {
+ if (rotation == 0 || rotation == 90 || rotation == 180
+ || rotation == 270) {
+ portraitRotation = rotation;
+ } else {
+ throw new IllegalArgumentException(
+ "The portrait rotation must be one"
+ + " of the values 0, 90, 180, 270");
+
+ }
+ }
+
+ /**
+ * Returns the rotation to be used for portrait pages
+ *
+ * @return the rotation to be used for portrait pages
+ */
+ protected int getPortraitRotation() {
+ return this.portraitRotation;
+ }
+
+ /**
+ * Sets the rotation to be used for landscape pages, valid values are 0, 90,
+ * 180, 270 (default).
+ *
+ * @param rotation
+ * The rotation in degrees.
+ */
+ public void setLandscapeRotation(int rotation) {
+ if (rotation == 0 || rotation == 90 || rotation == 180
+ || rotation == 270) {
+ landscapeRotation = rotation;
+ } else {
+ throw new IllegalArgumentException(
+ "The landscape rotation must be one"
+ + " of the values 0, 90, 180, 270");
+ }
+ }
+
+ /**
+ * Returns the landscape rotation
+ *
+ * @return the landscape rotation
+ */
+ protected int getLandscapeRotation() {
+ return this.landscapeRotation;
+ }
+
+ /**
+ * Sets the number of bits used per pixel
+ *
+ * @param bitsPerPixel
+ * number of bits per pixel
+ */
+ public void setBitsPerPixel(int bitsPerPixel) {
+ switch (bitsPerPixel) {
+ case 1:
+ case 4:
+ case 8:
+ this.bitsPerPixel = bitsPerPixel;
+ break;
+ default:
+ log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
+ this.bitsPerPixel = 8;
+ break;
+ }
+ }
+
+ /**
+ * Returns the number of bits per pixel
+ *
+ * @return the number of bits per pixel
+ */
+ public int getBitsPerPixel() {
+ return this.bitsPerPixel;
+ }
+
+ /**
+ * Sets whether images are color or not
+ *
+ * @param colorImages
+ * color image output
+ */
+ public void setColorImages(boolean colorImages) {
+ this.colorImages = colorImages;
+ }
+
+ /**
+ * Returns true if color images are to be used
+ *
+ * @return true if color images are to be used
+ */
+ public boolean isColorImages() {
+ return this.colorImages;
+ }
+
+ /**
+ * Sets whether images are natively supported or not in the AFP environment
+ *
+ * @param nativeImagesSupported true if images are natively supported in this AFP environment
+ */
+ public void setNativeImagesSupported(boolean nativeImagesSupported) {
+ this.nativeImagesSupported = nativeImagesSupported;
+ }
+
+ /**
+ * Returns true if images are supported natively in this AFP environment
+ *
+ * @return true if images are supported natively in this AFP environment
+ */
+ public boolean isNativeImagesSupported() {
+ return this.nativeImagesSupported;
+ }
+
+ /**
+ * Sets the output/device resolution
+ *
+ * @param resolution
+ * the output resolution (dpi)
+ */
+ public void setResolution(int resolution) {
+ if (log.isDebugEnabled()) {
+ log.debug("renderer-resolution set to: " + resolution + "dpi");
+ }
+ this.resolution = resolution;
+ }
+
+ /**
+ * Returns the output/device resolution.
+ *
+ * @return the resolution in dpi
+ */
+ public int getResolution() {
+ return this.resolution;
+ }
+
+ /** {@inheritDoc} */
+ protected AbstractData instantiateData() {
+ return new AFPData();
+ }
+
+ /** {@inheritDoc} */
+ protected AbstractPaintingState instantiate() {
+ return new AFPPaintingState();
+ }
+
+ /**
+ * Returns the painting state of the current page
+ *
+ * @return the painting state of the current page
+ */
+ protected AFPPagePaintingState getPagePaintingState() {
+ return this.pagePaintingState;
+ }
+
+ /**
+ * Gets the current page fonts
+ *
+ * @return the current page fonts
+ */
+ public AFPPageFonts getPageFonts() {
+ return pagePaintingState.getFonts();
+ }
+
+ /**
+ * Sets the page width
+ *
+ * @param pageWidth the page width
+ */
+ public void setPageWidth(int pageWidth) {
+ pagePaintingState.setWidth(pageWidth);
+ }
+
+ /**
+ * Returns the page width
+ *
+ * @return the page width
+ */
+ public int getPageWidth() {
+ return pagePaintingState.getWidth();
+ }
+
+ /**
+ * Sets the page height
+ *
+ * @param pageHeight the page height
+ */
+ public void setPageHeight(int pageHeight) {
+ pagePaintingState.setHeight(pageHeight);
+ }
+
+ /**
+ * Returns the page height
+ *
+ * @return the page height
+ */
+ public int getPageHeight() {
+ return pagePaintingState.getHeight();
+ }
+
+ /**
+ * Returns the page rotation
+ *
+ * @return the page rotation
+ */
+ public int getPageRotation() {
+ return pagePaintingState.getOrientation();
+ }
+
+ /**
+ * Sets the uri of the current image
+ *
+ * @param uri the uri of the current image
+ */
+ public void setImageUri(String uri) {
+ ((AFPData)getData()).imageUri = uri;
+ }
+
+ /**
+ * Gets the uri of the current image
+ *
+ * @return the uri of the current image
+ */
+ public String getImageUri() {
+ return ((AFPData)getData()).imageUri;
+ }
+
+ /**
+ * Returns the currently derived rotation
+ *
+ * @return the currently derived rotation
+ */
+ public int getRotation() {
+ return getData().getDerivedRotation();
+ }
+
+ /**
+ * Returns the unit converter
+ *
+ * @return the unit converter
+ */
+ public AFPUnitConverter getUnitConverter() {
+ return this.unitConv;
+ }
+
+ /** {@inheritDoc} */
+ public Object clone() {
+ AFPPaintingState paintingState = (AFPPaintingState)super.clone();
+ paintingState.pagePaintingState = (AFPPagePaintingState)this.pagePaintingState.clone();
+ paintingState.portraitRotation = this.portraitRotation;
+ paintingState.landscapeRotation = this.landscapeRotation;
+ paintingState.bitsPerPixel = this.bitsPerPixel;
+ paintingState.colorImages = this.colorImages;
+ paintingState.resolution = this.resolution;
+ return paintingState;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPPaintingState{" + "portraitRotation=" + portraitRotation
+ + ", landscapeRotation=" + landscapeRotation
+ + ", colorImages=" + colorImages
+ + ", bitsPerPixel=" + bitsPerPixel
+ + ", resolution=" + resolution
+ + ", pageState=" + pagePaintingState
+ + super.toString()
+ + "}";
+ }
+
+ /**
+ * Page level state data
+ */
+ private class AFPPagePaintingState implements Cloneable {
+ /** page width */
+ private int width = 0;
+
+ /** page height */
+ private int height = 0;
+
+ /** page fonts */
+ private AFPPageFonts fonts = new AFPPageFonts();
+
+ /** page font count */
+ private int fontCount = 0;
+
+ /** page orientation */
+ private int orientation = 0;
+
+ /**
+ * Returns the page width
+ *
+ * @return the page width
+ */
+ protected int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the page width
+ *
+ * @param width the page width
+ */
+ protected void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * Returns the page height
+ *
+ * @return the page height
+ */
+ protected int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the page height
+ *
+ * @param height the page height
+ */
+ protected void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * Returns the page fonts
+ *
+ * @return the page fonts
+ */
+ protected AFPPageFonts getFonts() {
+ return fonts;
+ }
+
+ /**
+ * Sets the current page fonts
+ *
+ * @param fonts the current page fonts
+ */
+ protected void setFonts(AFPPageFonts fonts) {
+ this.fonts = fonts;
+ }
+
+ /**
+ * Increments and returns the current page font count
+ *
+ * @return increment and return the current page font count
+ */
+ protected int incrementFontCount() {
+ return ++fontCount;
+ }
+
+ /**
+ * Returns the current page orientation
+ *
+ * @return the current page orientation
+ */
+ protected int getOrientation() {
+ return orientation;
+ }
+
+ /**
+ * Sets the current page orientation
+ *
+ * @param orientation the current page orientation
+ */
+ protected void setOrientation(int orientation) {
+ this.orientation = orientation;
+ }
+
+ /** {@inheritDoc} */
+ public Object clone() {
+ AFPPagePaintingState state = new AFPPagePaintingState();
+ state.width = this.width;
+ state.height = this.height;
+ state.orientation = this.orientation;
+ state.fonts = new AFPPageFonts(this.fonts);
+ state.fontCount = this.fontCount;
+ return state;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPPagePaintingState{width=" + width
+ + ", height=" + height
+ + ", orientation=" + orientation
+ + ", fonts=" + fonts
+ + ", fontCount=" + fontCount
+ + "}";
+ }
+ }
+
+ /**
+ * Block level state data
+ */
+ private class AFPData extends org.apache.fop.util.AbstractPaintingState.AbstractData {
+ private static final long serialVersionUID = -1789481244175275686L;
+
+ /** The current fill status */
+ private boolean filled = false;
+
+ private String imageUri = null;
+
+ /** {@inheritDoc} */
+ public Object clone() {
+ AFPData obj = (AFPData)super.clone();
+ obj.filled = this.filled;
+ obj.imageUri = this.imageUri;
+ return obj;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPData{" + super.toString()
+ + ", filled=" + filled
+ + ", imageUri=" + imageUri
+ + "}";
+ }
+
+ /** {@inheritDoc} */
+ protected AbstractData instantiate() {
+ return new AFPData();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPRectanglePainter.java b/src/java/org/apache/fop/afp/AFPRectanglePainter.java
new file mode 100644
index 000000000..e2bad6159
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPRectanglePainter.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.geom.AffineTransform;
+
+
+/**
+ * A painter of rectangles in AFP
+ */
+public class AFPRectanglePainter extends AbstractAFPPainter {
+
+ /**
+ * Main constructor
+ *
+ * @param paintingState the AFP painting state
+ * @param dataStream the AFP datastream
+ */
+ public AFPRectanglePainter(AFPPaintingState paintingState, DataStream dataStream) {
+ super(paintingState, dataStream);
+ }
+
+ /** {@inheritDoc} */
+ public void paint(PaintingInfo paintInfo) {
+ RectanglePaintingInfo rectanglePaintInfo = (RectanglePaintingInfo)paintInfo;
+ int pageWidth = dataStream.getCurrentPage().getWidth();
+ int pageHeight = dataStream.getCurrentPage().getHeight();
+
+ AFPUnitConverter unitConv = paintingState.getUnitConverter();
+ float width = unitConv.pt2units(rectanglePaintInfo.getWidth());
+ float height = unitConv.pt2units(rectanglePaintInfo.getHeight());
+ float x = unitConv.pt2units(rectanglePaintInfo.getX());
+ float y = unitConv.pt2units(rectanglePaintInfo.getY());
+
+ AffineTransform at = paintingState.getData().getTransform();
+
+ AFPLineDataInfo lineDataInfo = new AFPLineDataInfo();
+ lineDataInfo.color = paintingState.getColor();
+ lineDataInfo.rotation = paintingState.getRotation();
+ lineDataInfo.thickness = Math.round(height);
+
+ switch (lineDataInfo.rotation) {
+ case 0:
+ lineDataInfo.x1 = Math.round((float)at.getTranslateX() + x);
+ lineDataInfo.y1 = lineDataInfo.y2 = Math.round((float)at.getTranslateY() + y);
+ lineDataInfo.x2 = Math.round((float)at.getTranslateX() + x + width);
+ break;
+ case 90:
+ lineDataInfo.x1 = Math.round((float)at.getTranslateY() + x);
+ lineDataInfo.y1 = lineDataInfo.y2
+ = pageWidth - Math.round((float)at.getTranslateX()) + Math.round(y);
+ lineDataInfo.x2 = Math.round(width + (float)at.getTranslateY() + x);
+ break;
+ case 180:
+ lineDataInfo.x1 = pageWidth - Math.round((float)at.getTranslateX() - x);
+ lineDataInfo.y1 = lineDataInfo.y2 = pageHeight - Math.round((float)at.getTranslateY() - y);
+ lineDataInfo.x2 = pageWidth - Math.round((float)at.getTranslateX() - x - width);
+ break;
+ case 270:
+ lineDataInfo.x1 = pageHeight - Math.round((float)at.getTranslateY() - x);
+ lineDataInfo.y1 = lineDataInfo.y2 = Math.round((float)at.getTranslateX() + y);
+ lineDataInfo.x2 = lineDataInfo.x1 + Math.round(width - x);
+ break;
+ }
+ dataStream.createLine(lineDataInfo);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/AFPResourceInfo.java b/src/java/org/apache/fop/afp/AFPResourceInfo.java
new file mode 100644
index 000000000..729339fa4
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPResourceInfo.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp;
+
+
+/**
+ * The level at which a resource is to reside in the AFP output
+ */
+public class AFPResourceInfo {
+ private static final AFPResourceLevel DEFAULT_LEVEL
+ = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE);
+
+ /** the uri of this resource */
+ private String uri = null;
+
+ /** the reference name of this resource */
+ private String name = null;
+
+ /** the resource level of this resource */
+ private AFPResourceLevel level = DEFAULT_LEVEL;
+
+ /** true when the resource level was changed */
+ private boolean levelChanged = false;
+
+ /**
+ * Sets the data object uri
+ *
+ * @param uri the data object uri
+ */
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Returns the uri of this data object
+ *
+ * @return the uri of this data object
+ */
+ public String getUri() {
+ return uri;
+ }
+
+ /**
+ * Sets the resource reference name
+ *
+ * @param resourceName the resource reference name
+ */
+ public void setName(String resourceName) {
+ this.name = resourceName;
+ }
+
+ /**
+ * Returns the resource reference name
+ *
+ * @return the resource reference name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Returns the resource level
+ *
+ * @return the resource level
+ */
+ public AFPResourceLevel getLevel() {
+ if (level == null) {
+ return DEFAULT_LEVEL;
+ }
+ return this.level;
+ }
+
+ /**
+ * Sets the resource level
+ *
+ * @param resourceLevel the resource level
+ */
+ public void setLevel(AFPResourceLevel resourceLevel) {
+ this.level = resourceLevel;
+ levelChanged = true;
+ }
+
+ /**
+ * Returns true when the resource level was set
+ *
+ * @return true when the resource level was set
+ */
+ public boolean levelChanged() {
+ return levelChanged;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPResourceInfo{uri=" + uri
+ + (name != null ? ", name=" + name : "")
+ + (level != null ? ", level=" + level : "")
+ + "}";
+
+ }
+
+ /** {@inheritDoc} */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || !(obj instanceof AFPResourceInfo)) {
+ return false;
+ }
+
+ AFPResourceInfo ri = (AFPResourceInfo)obj;
+ return (uri == ri.uri || uri != null && uri.equals(ri.uri))
+ && (name == ri.name || name != null && name.equals(ri.name))
+ && (level == ri.level || level != null && level.equals(ri.level));
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + (null == uri ? 0 : uri.hashCode());
+ hash = 31 * hash + (null == name ? 0 : name.hashCode());
+ hash = 31 * hash + (null == level ? 0 : level.hashCode());
+ return hash;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPResourceLevel.java b/src/java/org/apache/fop/afp/AFPResourceLevel.java
new file mode 100644
index 000000000..5e8d54aae
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPResourceLevel.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+/**
+ * A resource level
+ */
+public class AFPResourceLevel {
+
+ /** directly in page **/
+ public static final int INLINE = 0;
+
+ /** page level **/
+ public static final int PAGE = 1;
+
+ /** page group level **/
+ public static final int PAGE_GROUP = 2;
+
+ /** document level **/
+ public static final int DOCUMENT = 3;
+
+ /** print file level **/
+ public static final int PRINT_FILE = 4;
+
+ /** external level **/
+ public static final int EXTERNAL = 5;
+
+ private static final String NAME_INLINE = "inline";
+ private static final String NAME_PAGE = "page";
+ private static final String NAME_PAGE_GROUP = "page-group";
+ private static final String NAME_DOCUMENT = "document";
+ private static final String NAME_PRINT_FILE = "print-file";
+ private static final String NAME_EXTERNAL = "external";
+
+ private static final String[] NAMES = new String[] {
+ NAME_INLINE, NAME_PAGE, NAME_PAGE_GROUP, NAME_DOCUMENT, NAME_PRINT_FILE, NAME_EXTERNAL
+ };
+
+
+ /** where the resource will reside in the AFP output */
+ private int level = PRINT_FILE; // default is print-file level (images)
+
+ /** the external resource group file path */
+ private String extFilePath = null;
+
+ /**
+ * Sets the resource placement level within the AFP output
+ *
+ * @param levelString the resource level (page, page-group, document, print-file or external)
+ * @return true if the resource level was successfully set
+ */
+ public static AFPResourceLevel valueOf(String levelString) {
+ if (levelString != null) {
+ levelString = levelString.toLowerCase();
+ AFPResourceLevel resourceLevel = null;
+ for (int i = 0; i < NAMES.length; i++) {
+ if (NAMES[i].equals(levelString)) {
+ resourceLevel = new AFPResourceLevel(i);
+ break;
+ }
+ }
+ return resourceLevel;
+ }
+ return null;
+ }
+
+ /**
+ * Main constructor
+ *
+ * @param level the resource level
+ */
+ public AFPResourceLevel(int level) {
+ setLevel(level);
+ }
+
+ /**
+ * Sets the resource level
+ *
+ * @param level the resource level
+ */
+ public void setLevel(int level) {
+ this.level = level;
+ }
+
+ /**
+ * Returns true if this is at page level
+ *
+ * @return true if this is at page level
+ */
+ public boolean isPage() {
+ return level == PAGE;
+ }
+
+ /**
+ * Returns true if this is at page group level
+ *
+ * @return true if this is at page group level
+ */
+ public boolean isPageGroup() {
+ return level == PAGE_GROUP;
+ }
+
+ /**
+ * Returns true if this is at document level
+ *
+ * @return true if this is at document level
+ */
+ public boolean isDocument() {
+ return level == DOCUMENT;
+ }
+
+ /**
+ * Returns true if this is at external level
+ *
+ * @return true if this is at external level
+ */
+ public boolean isExternal() {
+ return level == EXTERNAL;
+ }
+
+ /**
+ * Returns true if this is at print-file level
+ *
+ * @return true if this is at print-file level
+ */
+ public boolean isPrintFile() {
+ return level == PRINT_FILE;
+ }
+
+ /**
+ * Returns true if this resource level is inline
+ *
+ * @return true if this resource level is inline
+ */
+ public boolean isInline() {
+ return level == INLINE;
+ }
+
+ /**
+ * Returns the destination file path of the external resource group file
+ *
+ * @return the destination file path of the external resource group file
+ */
+ public String getExternalFilePath() {
+ return this.extFilePath;
+ }
+
+ /**
+ * Sets the external destination of the resource
+ *
+ * @param filePath the external resource group file
+ */
+ public void setExternalFilePath(String filePath) {
+ this.extFilePath = filePath;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return NAMES[level] + (isExternal() ? ", file=" + extFilePath : "");
+ }
+
+ /** {@inheritDoc} */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || !(obj instanceof AFPResourceLevel)) {
+ return false;
+ }
+
+ AFPResourceLevel rl = (AFPResourceLevel)obj;
+ return (level == level)
+ && (extFilePath == rl.extFilePath
+ || extFilePath != null && extFilePath.equals(rl.extFilePath));
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ int hash = 7;
+ hash = 31 * hash + level;
+ hash = 31 * hash + (null == extFilePath ? 0 : extFilePath.hashCode());
+ return hash;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java
new file mode 100644
index 000000000..164ebfd2d
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPResourceManager.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
+import org.apache.fop.afp.modca.AbstractNamedAFPObject;
+import org.apache.fop.afp.modca.IncludeObject;
+import org.apache.fop.afp.modca.Registry;
+import org.apache.fop.afp.modca.ResourceGroup;
+
+/**
+ * Manages the creation and storage of document resources
+ */
+public class AFPResourceManager {
+ /** The AFP datastream (document tree) */
+ private DataStream dataStream;
+
+ /** Resource creation factory */
+ private final Factory factory;
+
+ private final AFPStreamer streamer;
+
+ private final AFPDataObjectFactory dataObjectFactory;
+
+ /** Maintain a reference count of instream objects for referencing purposes */
+ private int instreamObjectCount = 0;
+
+ /** a mapping of resourceInfo --> include name */
+ private final Map/*<AFPResourceInfo,String>*/ includeNameMap
+ = new java.util.HashMap()/*<AFPResourceInfo,String>*/;
+
+ /**
+ * Main constructor
+ */
+ public AFPResourceManager() {
+ this.factory = new Factory();
+ this.streamer = new AFPStreamer(factory);
+ this.dataObjectFactory = new AFPDataObjectFactory(factory);
+ }
+
+ /**
+ * Sets the outputstream
+ *
+ * @param paintingState the AFP painting state
+ * @param outputStream the outputstream
+ * @return a new AFP DataStream
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public DataStream createDataStream(AFPPaintingState paintingState, OutputStream outputStream)
+ throws IOException {
+ this.dataStream = streamer.createDataStream(paintingState);
+ streamer.setOutputStream(outputStream);
+ return this.dataStream;
+ }
+
+ /**
+ * Returns the AFP DataStream
+ *
+ * @return the AFP DataStream
+ */
+ public DataStream getDataStream() {
+ return this.dataStream;
+ }
+
+ /**
+ * Tells the streamer to write
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ public void writeToStream() throws IOException {
+ streamer.close();
+ }
+
+ /**
+ * Sets the default resource group file path
+ *
+ * @param filePath the default resource group file path
+ */
+
+ public void setDefaultResourceGroupFilePath(String filePath) {
+ streamer.setDefaultResourceGroupFilePath(filePath);
+ }
+
+ /**
+ * Creates a new data object in the AFP datastream
+ *
+ * @param dataObjectInfo the data object info
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ public void createObject(AFPDataObjectInfo dataObjectInfo) throws IOException {
+ AbstractNamedAFPObject namedObj = null;
+
+ AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
+ String uri = resourceInfo.getUri();
+ if (uri == null) {
+ uri = "/";
+ }
+ // if this is an instream data object adjust the uri to ensure that its unique
+ if (uri.endsWith("/")) {
+ uri += "#" + (++instreamObjectCount);
+ resourceInfo.setUri(uri);
+ }
+
+ String objectName = (String)includeNameMap.get(resourceInfo);
+ if (objectName == null) {
+ boolean useInclude = true;
+ Registry.ObjectType objectType = null;
+
+ // new resource so create
+ if (dataObjectInfo instanceof AFPImageObjectInfo) {
+ AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo;
+ namedObj = dataObjectFactory.createImage(imageObjectInfo);
+ } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) {
+ AFPGraphicsObjectInfo graphicsObjectInfo = (AFPGraphicsObjectInfo)dataObjectInfo;
+ namedObj = dataObjectFactory.createGraphic(graphicsObjectInfo);
+ } else {
+ // natively embedded data object
+ namedObj = dataObjectFactory.createObjectContainer(dataObjectInfo);
+ objectType = dataObjectInfo.getObjectType();
+ useInclude = objectType != null && objectType.isIncludable();
+ }
+
+ AFPResourceLevel resourceLevel = resourceInfo.getLevel();
+ ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel);
+ useInclude &= resourceGroup != null;
+ if (useInclude) {
+ // if it is to reside within a resource group at print-file or external level
+ if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) {
+ // wrap newly created data object in a resource object
+ namedObj = dataObjectFactory.createResource(namedObj, resourceInfo, objectType);
+ }
+
+ // add data object into its resource group destination
+ resourceGroup.addObject(namedObj);
+
+ // create the include object
+ objectName = namedObj.getName();
+ IncludeObject includeObject
+ = dataObjectFactory.createInclude(objectName, dataObjectInfo);
+
+ // add an include to the current page
+ dataStream.getCurrentPage().addObject(includeObject);
+
+ // record mapping of resource info to data object resource name
+ includeNameMap.put(resourceInfo, objectName);
+ } else {
+ // not to be included so inline data object directly into the current page
+ dataStream.getCurrentPage().addObject(namedObj);
+ }
+ } else {
+ // an existing data resource so reference it by adding an include to the current page
+ IncludeObject includeObject
+ = dataObjectFactory.createInclude(objectName, dataObjectInfo);
+ dataStream.getCurrentPage().addObject(includeObject);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPStreamer.java b/src/java/org/apache/fop/afp/AFPStreamer.java
new file mode 100644
index 000000000..7e208bb6e
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPStreamer.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.modca.ResourceGroup;
+import org.apache.fop.afp.modca.StreamedResourceGroup;
+
+/**
+ * Manages the streaming of the AFP output
+ */
+public class AFPStreamer implements Streamable {
+ /** Static logging instance */
+ private static final Log log = LogFactory.getLog(AFPStreamer.class);
+
+ private static final String AFPDATASTREAM_TEMP_FILE_PREFIX = "AFPDataStream_";
+
+ private static final int BUFFER_SIZE = 4096; // 4k writing buffer
+
+ private static final String DEFAULT_EXTERNAL_RESOURCE_FILENAME = "resources.afp";
+
+
+ private final Factory factory;
+
+ /** A mapping of external resource destinations to resource groups */
+ private final Map/*<String,AFPExternalResourceGroup>*/pathResourceGroupMap
+ = new java.util.HashMap/*<String,AFPExternalResourceGroup>*/();
+
+ private StreamedResourceGroup printFileResourceGroup;
+
+ /** Sets the default resource group file path */
+ private String defaultResourceGroupFilePath = DEFAULT_EXTERNAL_RESOURCE_FILENAME;
+
+ private File tempFile;
+
+ /** temporary document outputstream */
+ private OutputStream documentOutputStream;
+
+ /** the final outputstream */
+ private OutputStream outputStream;
+
+ private RandomAccessFile documentFile;
+
+ private DataStream dataStream;
+
+ /**
+ * Main constructor
+ *
+ * @param factory a factory
+ */
+ public AFPStreamer(Factory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * Creates a new DataStream
+ *
+ * @param paintingState the AFP painting state
+ * @return a new {@link DataStream}
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public DataStream createDataStream(AFPPaintingState paintingState) throws IOException {
+ this.tempFile = File.createTempFile(AFPDATASTREAM_TEMP_FILE_PREFIX, null);
+ this.documentFile = new RandomAccessFile(tempFile, "rw");
+ this.documentOutputStream = new BufferedOutputStream(
+ new FileOutputStream(documentFile.getFD()));
+ this.dataStream = factory.createDataStream(paintingState, documentOutputStream);
+ return dataStream;
+ }
+
+ /**
+ * Sets the default resource group file path
+ *
+ * @param filePath the default resource group file path
+ */
+ public void setDefaultResourceGroupFilePath(String filePath) {
+ this.defaultResourceGroupFilePath = filePath;
+ }
+
+ /**
+ * Returns the resource group for a given resource info
+ *
+ * @param level a resource level
+ * @return a resource group for the given resource info
+ */
+ public ResourceGroup getResourceGroup(AFPResourceLevel level) {
+ ResourceGroup resourceGroup = null;
+ if (level.isInline()) { // no resource group for inline level
+ return null;
+ }
+ if (level.isExternal()) {
+ String filePath = level.getExternalFilePath();
+ if (filePath == null) {
+ log.warn("No file path provided for external resource, using default.");
+ filePath = defaultResourceGroupFilePath;
+ }
+ resourceGroup = (ResourceGroup)pathResourceGroupMap.get(filePath);
+ if (resourceGroup == null) {
+ OutputStream os = null;
+ try {
+ os = new BufferedOutputStream(new FileOutputStream(filePath));
+ } catch (FileNotFoundException fnfe) {
+ log.error("Failed to create/open external resource group file '"
+ + filePath + "'");
+ } finally {
+ if (os != null) {
+ resourceGroup = factory.createStreamedResourceGroup(os);
+ pathResourceGroupMap.put(filePath, resourceGroup);
+ }
+ }
+ }
+ } else if (level.isPrintFile()) {
+ if (printFileResourceGroup == null) {
+ // use final outputstream for print-file resource group
+ printFileResourceGroup = factory.createStreamedResourceGroup(outputStream);
+ }
+ resourceGroup = printFileResourceGroup;
+ } else {
+ // resource group in afp document datastream
+ resourceGroup = dataStream.getResourceGroup(level);
+ }
+ return resourceGroup;
+ }
+
+ /**
+ * Closes off the AFP stream writing the document stream
+ *
+ * @throws IOException if an an I/O exception of some sort has occurred
+ */
+ // write out any external resource groups
+ public void close() throws IOException {
+ Iterator it = pathResourceGroupMap.entrySet().iterator();
+ while (it.hasNext()) {
+ StreamedResourceGroup resourceGroup = (StreamedResourceGroup)it.next();
+ resourceGroup.close();
+ }
+
+ // close any open print-file resource group
+ if (printFileResourceGroup != null) {
+ printFileResourceGroup.close();
+ }
+
+ // write out document
+ writeToStream(outputStream);
+
+ outputStream.close();
+
+ // delete temporary file
+ tempFile.delete();
+ }
+
+ /**
+ * Sets the final outputstream
+ *
+ * @param outputStream an outputstream
+ */
+ public void setOutputStream(OutputStream outputStream) {
+ this.outputStream = outputStream;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+// long start = System.currentTimeMillis();
+ int len = (int)documentFile.length();
+ int numChunks = len / BUFFER_SIZE;
+ int remainingChunkSize = len % BUFFER_SIZE;
+ byte[] buffer;
+
+ documentFile.seek(0);
+ if (numChunks > 0) {
+ buffer = new byte[BUFFER_SIZE];
+ for (int i = 0; i < numChunks; i++) {
+ documentFile.read(buffer, 0, BUFFER_SIZE);
+ os.write(buffer, 0, BUFFER_SIZE);
+ }
+ } else {
+ buffer = new byte[remainingChunkSize];
+ }
+ if (remainingChunkSize > 0) {
+ documentFile.read(buffer, 0, remainingChunkSize);
+ os.write(buffer, 0, remainingChunkSize);
+ }
+ os.flush();
+// long end = System.currentTimeMillis();
+// log.debug("writing time " + (end - start) + "ms");
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPTextDataInfo.java b/src/java/org/apache/fop/afp/AFPTextDataInfo.java
new file mode 100644
index 000000000..8047c927c
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPTextDataInfo.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.Color;
+
+/**
+ * Text data information
+ */
+public class AFPTextDataInfo {
+
+ /** the text font reference */
+ private int fontReference;
+
+ /** the text x coordinate position */
+ private int x;
+
+ /** the text y coordinate position */
+ private int y;
+
+ /** the text color */
+ private Color color;
+
+ /** the text variable space adjustment */
+ private int variableSpaceCharacterIncrement;
+
+ /** the text inter character adjustment */
+ private int interCharacterAdjustment;
+
+ /** the text orientation */
+ private int rotation;
+
+ /** the text encoding */
+ private String textEncoding;
+
+ /** the text string */
+ private String textString;
+
+ /**
+ * Returns the font reference
+ *
+ * @return the font reference
+ */
+ public int getFontReference() {
+ return fontReference;
+ }
+
+ /**
+ * Sets the font reference
+ *
+ * @param fontReference the font reference
+ */
+ public void setFontReference(int fontReference) {
+ this.fontReference = fontReference;
+ }
+
+ /**
+ * Returns the x coordinate
+ *
+ * @return the x coordinate
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * Sets the X coordinate
+ *
+ * @param x the X coordinate
+ */
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ /**
+ * Returns the y coordinate
+ *
+ * @return the y coordinate
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * Sets the Y coordinate
+ *
+ * @param y the Y coordinate
+ */
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ /**
+ * Returns the color
+ *
+ * @return the color
+ */
+ public Color getColor() {
+ return color;
+ }
+
+ /**
+ * Sets the color
+ *
+ * @param color the color
+ */
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ /**
+ * Return the variable space character increment
+ *
+ * @return the variable space character increment
+ */
+ public int getVariableSpaceCharacterIncrement() {
+ return variableSpaceCharacterIncrement;
+ }
+
+ /**
+ * Sets the variable space character increment
+ *
+ * @param variableSpaceCharacterIncrement the variable space character increment
+ */
+ public void setVariableSpaceCharacterIncrement(
+ int variableSpaceCharacterIncrement) {
+ this.variableSpaceCharacterIncrement = variableSpaceCharacterIncrement;
+ }
+
+ /**
+ * Return the inter character adjustment
+ *
+ * @return the inter character adjustment
+ */
+ public int getInterCharacterAdjustment() {
+ return interCharacterAdjustment;
+ }
+
+ /**
+ * Sets the inter character adjustment
+ *
+ * @param interCharacterAdjustment the inter character adjustment
+ */
+ public void setInterCharacterAdjustment(int interCharacterAdjustment) {
+ this.interCharacterAdjustment = interCharacterAdjustment;
+ }
+
+ /**
+ * Sets the text orientation
+ *
+ * @param rotation the text rotation
+ */
+ public void setRotation(int rotation) {
+ this.rotation = rotation;
+ }
+
+ /**
+ * Returns the text rotation
+ *
+ * @return the text rotation
+ */
+ public int getRotation() {
+ return this.rotation;
+ }
+
+ /**
+ * Sets the text encoding
+ *
+ * @param textEncoding the text encoding
+ */
+ public void setEncoding(String textEncoding) {
+ this.textEncoding = textEncoding;
+ }
+
+ /**
+ * Returns the text encoding
+ *
+ * @return the text encoding
+ */
+ public String getEncoding() {
+ return this.textEncoding;
+ }
+
+ /**
+ * Sets the text string
+ *
+ * @param textString the text string
+ */
+ public void setString(String textString) {
+ this.textString = textString;
+ }
+
+ /**
+ * Returns the text string
+ *
+ * @return the text string
+ */
+ public String getString() {
+ return this.textString;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "TextDataInfo{fontReference=" + fontReference
+ + ", x=" + x
+ + ", y=" + y
+ + ", color=" + color
+ + ", vsci=" + variableSpaceCharacterIncrement
+ + ", ica=" + interCharacterAdjustment
+ + ", orientation=" + rotation
+ + ", textString=" + textString
+ + ", textEncoding=" + textEncoding
+ + "}";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPUnitConverter.java b/src/java/org/apache/fop/afp/AFPUnitConverter.java
new file mode 100644
index 000000000..3195ba70f
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AFPUnitConverter.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.geom.AffineTransform;
+
+
+
+/**
+ * AFP Unit converter
+ */
+public class AFPUnitConverter {
+
+ /** the AFP state */
+ private final AFPPaintingState paintingState;
+
+ /**
+ * Unit converter
+ *
+ * @param paintingState the AFP painting state
+ */
+ public AFPUnitConverter(AFPPaintingState paintingState) {
+ this.paintingState = paintingState;
+ }
+
+ /**
+ * Converts millipoints to units
+ *
+ * @param srcPts source points
+ * @param dstPts destination points
+ * @return transformed points
+ */
+ public int[] mpts2units(float[] srcPts, float[] dstPts) {
+ return transformPoints(srcPts, dstPts, true);
+ }
+
+ /**
+ * Converts points to units
+ *
+ * @param srcPts source points
+ * @param dstPts destination points
+ * @return transformed points
+ */
+ public int[] pts2units(float[] srcPts, float[] dstPts) {
+ return transformPoints(srcPts, dstPts, false);
+ }
+
+ /**
+ * Converts millipoints to units
+ *
+ * @param srcPts source points
+ * @return transformed points
+ */
+ public int[] mpts2units(float[] srcPts) {
+ return transformPoints(srcPts, null, true);
+ }
+
+ /**
+ * Converts points to units
+ *
+ * @param srcPts source points
+ * @return transformed points
+ */
+ public int[] pts2units(float[] srcPts) {
+ return transformPoints(srcPts, null, false);
+ }
+
+ /**
+ * Converts point to unit
+ *
+ * @param pt point
+ * @return transformed point
+ */
+ public float pt2units(float pt) {
+ return pt / ((float)AFPConstants.DPI_72 / paintingState.getResolution());
+ }
+
+ /**
+ * Converts millipoint to unit
+ *
+ * @param mpt millipoint
+ * @return transformed point
+ */
+ public float mpt2units(float mpt) {
+ return mpt / ((float)AFPConstants.DPI_72_MPTS / paintingState.getResolution());
+ }
+
+ private int[] transformPoints(float[] srcPts, float[] dstPts, boolean milli) {
+ if (dstPts == null) {
+ dstPts = new float[srcPts.length];
+ }
+ AffineTransform at = paintingState.getData().getTransform();
+ at.transform(srcPts, 0, dstPts, 0, srcPts.length / 2);
+ int[] coords = new int[srcPts.length];
+ for (int i = 0; i < srcPts.length; i++) {
+ if (!milli) {
+ dstPts[i] *= 1000;
+ }
+ coords[i] = Math.round(dstPts[i]);
+ }
+ return coords;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/AbstractAFPPainter.java b/src/java/org/apache/fop/afp/AbstractAFPPainter.java
new file mode 100644
index 000000000..576b8bb11
--- /dev/null
+++ b/src/java/org/apache/fop/afp/AbstractAFPPainter.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A base AFP painter
+ */
+public abstract class AbstractAFPPainter {
+
+ /** Static logging instance */
+ protected static Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
+
+ protected final DataStream dataStream;
+ protected final AFPPaintingState paintingState;
+
+ /**
+ * Main constructor
+ *
+ * @param paintingState the AFP painting state
+ * @param dataStream the AFP Datastream
+ */
+ public AbstractAFPPainter(AFPPaintingState paintingState, DataStream dataStream) {
+ this.paintingState = paintingState;
+ this.dataStream = dataStream;
+ }
+
+ /**
+ * Paints the painting item
+ *
+ * @param paintInfo the painting information
+ */
+ public abstract void paint(PaintingInfo paintInfo);
+}
diff --git a/src/java/org/apache/fop/afp/BorderPaintingInfo.java b/src/java/org/apache/fop/afp/BorderPaintingInfo.java
new file mode 100644
index 000000000..4917c7bc0
--- /dev/null
+++ b/src/java/org/apache/fop/afp/BorderPaintingInfo.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.Color;
+
+/**
+ * Border painting information
+ */
+public class BorderPaintingInfo implements PaintingInfo {
+
+ private final float x1;
+ private final float y1;
+ private final float x2;
+ private final float y2;
+ private final boolean isHorizontal;
+ private final int style;
+ private final Color color;
+
+ /**
+ * Main constructor
+ *
+ * @param x1 the x1 coordinate
+ * @param y1 the y1 coordinate
+ * @param x2 the x2 coordinate
+ * @param y2 the y2 coordinate
+ * @param isHorizontal true when the border line is horizontal
+ * @param style the border style
+ * @param color the border color
+ */
+ public BorderPaintingInfo(float x1, float y1, float x2, float y2,
+ boolean isHorizontal, int style, Color color) {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.isHorizontal = isHorizontal;
+ this.style = style;
+ this.color = color;
+ }
+
+ /**
+ * Returns the x1 coordinate
+ *
+ * @return the x1 coordinate
+ */
+ public float getX1() {
+ return x1;
+ }
+
+ /**
+ * Returns the y1 coordinate
+ *
+ * @return the y1 coordinate
+ */
+ public float getY1() {
+ return y1;
+ }
+
+ /**
+ * Returns the x2 coordinate
+ *
+ * @return the x2 coordinate
+ */
+ public float getX2() {
+ return x2;
+ }
+
+ /**
+ * Returns the y2 coordinate
+ *
+ * @return the y2 coordinate
+ */
+ public float getY2() {
+ return y2;
+ }
+
+ /**
+ * Returns true when this is a horizontal line
+ *
+ * @return true when this is a horizontal line
+ */
+ public boolean isHorizontal() {
+ return isHorizontal;
+ }
+
+ /**
+ * Returns the style
+ *
+ * @return the style
+ */
+ public int getStyle() {
+ return style;
+ }
+
+ /**
+ * Returns the color
+ *
+ * @return the color
+ */
+ public Color getColor() {
+ return color;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/Completable.java b/src/java/org/apache/fop/afp/Completable.java
new file mode 100644
index 000000000..e1fc764dd
--- /dev/null
+++ b/src/java/org/apache/fop/afp/Completable.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+/**
+ * Set and expose the internal completeness of an object.
+ */
+public interface Completable {
+
+ /**
+ * Sets whether or not this object is complete or not
+ *
+ * @param complete true if this object is complete
+ */
+ void setComplete(boolean complete);
+
+ /**
+ * Returns true if this object is complete
+ *
+ * @return true if this object is complete
+ */
+ boolean isComplete();
+}
diff --git a/src/java/org/apache/fop/afp/DataStream.java b/src/java/org/apache/fop/afp/DataStream.java
new file mode 100644
index 000000000..783c698ea
--- /dev/null
+++ b/src/java/org/apache/fop/afp/DataStream.java
@@ -0,0 +1,602 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.awt.Color;
+import java.awt.Point;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.fonts.AFPFont;
+import org.apache.fop.afp.fonts.AFPFontAttributes;
+import org.apache.fop.afp.modca.AbstractPageObject;
+import org.apache.fop.afp.modca.Document;
+import org.apache.fop.afp.modca.InterchangeSet;
+import org.apache.fop.afp.modca.Overlay;
+import org.apache.fop.afp.modca.PageGroup;
+import org.apache.fop.afp.modca.PageObject;
+import org.apache.fop.afp.modca.ResourceGroup;
+import org.apache.fop.afp.modca.TagLogicalElementBean;
+import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet;
+
+/**
+ * A data stream is a continuous ordered stream of data elements and objects
+ * conforming to a given format. Application programs can generate data streams
+ * destined for a presentation service, archive library, presentation device or
+ * another application program. The strategic presentation data stream
+ * architectures used is Mixed Object Document Content Architecture (MO:DCA).
+ *
+ * The MO:DCA architecture defines the data stream used by applications to
+ * describe documents and object envelopes for interchange with other
+ * applications and application services. Documents defined in the MO:DCA format
+ * may be archived in a database, then later retrieved, viewed, annotated and
+ * printed in local or distributed systems environments. Presentation fidelity
+ * is accommodated by including resource objects in the documents that reference
+ * them.
+ */
+public class DataStream {
+
+ /** Static logging instance */
+ protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
+
+ /** Boolean completion indicator */
+ private boolean complete = false;
+
+ /** The AFP document object */
+ private Document document = null;
+
+ /** The current page group object */
+ private PageGroup currentPageGroup = null;
+
+ /** The current page object */
+ private PageObject currentPageObject = null;
+
+ /** The current overlay object */
+ private Overlay currentOverlay = null;
+
+ /** The current page */
+ private AbstractPageObject currentPage = null;
+
+ /** The MO:DCA interchange set in use (default to MO:DCA-P IS/2 set) */
+ private InterchangeSet interchangeSet
+ = InterchangeSet.valueOf(InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2);
+
+ private final Factory factory;
+
+ private OutputStream outputStream;
+
+ /** the afp painting state */
+ private final AFPPaintingState paintingState;
+
+ /**
+ * Default constructor for the AFPDocumentStream.
+ *
+ * @param factory the resource factory
+ * @param paintingState the AFP painting state
+ * @param outputStream the outputstream to write to
+ */
+ public DataStream(Factory factory, AFPPaintingState paintingState, OutputStream outputStream) {
+ this.paintingState = paintingState;
+ this.factory = factory;
+ this.outputStream = outputStream;
+ }
+
+ /**
+ * Returns the outputstream
+ *
+ * @return the outputstream
+ */
+ public OutputStream getOutputStream() {
+ return this.outputStream;
+ }
+
+ /**
+ * Returns the document object
+ *
+ * @return the document object
+ */
+ private Document getDocument() {
+ return this.document;
+ }
+
+ /**
+ * Returns the current page
+ *
+ * @return the current page
+ */
+ public AbstractPageObject getCurrentPage() {
+ return this.currentPage;
+ }
+
+ /**
+ * The document is started by invoking this method which creates an instance
+ * of the AFP Document object.
+ *
+ * @param name
+ * the name of this document.
+ */
+ public void setDocumentName(String name) {
+ if (name != null) {
+ getDocument().setFullyQualifiedName(
+ FullyQualifiedNameTriplet.TYPE_BEGIN_DOCUMENT_REF,
+ FullyQualifiedNameTriplet.FORMAT_CHARSTR, name);
+ }
+ }
+
+ /**
+ * Helper method to mark the end of the current document.
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public void endDocument() throws IOException {
+ if (complete) {
+ String msg = "Invalid state - document already ended.";
+ log.warn("endDocument():: " + msg);
+ throw new IllegalStateException(msg);
+ }
+
+ if (currentPageObject != null) {
+ // End the current page if necessary
+ endPage();
+ }
+
+ if (currentPageGroup != null) {
+ // End the current page group if necessary
+ endPageGroup();
+ }
+
+ // Write out document
+ if (document != null) {
+ document.endDocument();
+ document.writeToStream(this.outputStream);
+ }
+
+ this.outputStream.flush();
+
+ this.complete = true;
+
+ this.document = null;
+
+ this.outputStream = null;
+ }
+
+ /**
+ * Start a new page. When processing has finished on the current page, the
+ * {@link #endPage()}method must be invoked to mark the page ending.
+ *
+ * @param pageWidth
+ * the width of the page
+ * @param pageHeight
+ * the height of the page
+ * @param pageRotation
+ * the rotation of the page
+ * @param pageWidthRes
+ * the width resolution of the page
+ * @param pageHeightRes
+ * the height resolution of the page
+ */
+ public void startPage(int pageWidth, int pageHeight, int pageRotation,
+ int pageWidthRes, int pageHeightRes) {
+ currentPageObject = factory.createPage(pageWidth, pageHeight,
+ pageRotation, pageWidthRes, pageHeightRes);
+ currentPage = currentPageObject;
+ currentOverlay = null;
+ }
+
+ /**
+ * Start a new overlay. When processing has finished on the current overlay,
+ * the {@link #endOverlay()}method must be invoked to mark the overlay
+ * ending.
+ *
+ * @param x
+ * the x position of the overlay on the page
+ * @param y
+ * the y position of the overlay on the page
+ * @param width
+ * the width of the overlay
+ * @param height
+ * the height of the overlay
+ * @param widthRes
+ * the width resolution of the overlay
+ * @param heightRes
+ * the height resolution of the overlay
+ * @param overlayRotation
+ * the rotation of the overlay
+ */
+ public void startOverlay(int x, int y, int width, int height, int widthRes,
+ int heightRes, int overlayRotation) {
+ this.currentOverlay = factory.createOverlay(
+ width, height, widthRes, heightRes, overlayRotation);
+
+ String overlayName = currentOverlay.getName();
+ currentPageObject.createIncludePageOverlay(overlayName, x, y, 0);
+ currentPage = currentOverlay;
+ }
+
+ /**
+ * Helper method to mark the end of the current overlay.
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public void endOverlay() throws IOException {
+ if (currentOverlay != null) {
+ currentOverlay.endPage();
+ currentOverlay = null;
+ currentPage = currentPageObject;
+ }
+ }
+
+ /**
+ * Helper method to save the current page.
+ *
+ * @return current page object that was saved
+ */
+ public PageObject savePage() {
+ PageObject pageObject = currentPageObject;
+ if (currentPageGroup != null) {
+ currentPageGroup.addPage(currentPageObject);
+ } else {
+ document.addPage(currentPageObject);
+ }
+ currentPageObject = null;
+ currentPage = null;
+ return pageObject;
+ }
+
+ /**
+ * Helper method to restore the current page.
+ *
+ * @param pageObject
+ * page object
+ */
+ public void restorePage(PageObject pageObject) {
+ currentPageObject = pageObject;
+ currentPage = pageObject;
+ }
+
+ /**
+ * Helper method to mark the end of the current page.
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public void endPage() throws IOException {
+ if (currentPageObject != null) {
+ currentPageObject.endPage();
+ if (currentPageGroup != null) {
+ currentPageGroup.addPage(currentPageObject);
+ currentPageGroup.writeToStream(this.outputStream);
+ } else {
+ document.addPage(currentPageObject);
+ document.writeToStream(this.outputStream);
+ }
+ currentPageObject = null;
+ currentPage = null;
+ }
+ }
+
+ /**
+ * Creates the given page fonts in the current page
+ *
+ * @param pageFonts
+ * a collection of AFP font attributes
+ */
+ public void addFontsToCurrentPage(Map pageFonts) {
+ Iterator iter = pageFonts.values().iterator();
+ while (iter.hasNext()) {
+ AFPFontAttributes afpFontAttributes = (AFPFontAttributes) iter
+ .next();
+ createFont(afpFontAttributes.getFontReference(), afpFontAttributes
+ .getFont(), afpFontAttributes.getPointSize());
+ }
+ }
+
+ /**
+ * Helper method to create a map coded font object on the current page, this
+ * method delegates the construction of the map coded font object to the
+ * active environment group on the current page.
+ *
+ * @param fontReference
+ * the font number used as the resource identifier
+ * @param font
+ * the font
+ * @param size
+ * the point size of the font
+ */
+ public void createFont(int fontReference, AFPFont font, int size) {
+ currentPage.createFont(fontReference, font, size);
+ }
+
+ /**
+ * Returns a point on the current page
+ *
+ * @param x the X-coordinate
+ * @param y the Y-coordinate
+ * @return a point on the current page
+ */
+ private Point getPoint(int x, int y) {
+ Point p = new Point();
+ int rotation = paintingState.getRotation();
+ switch (rotation) {
+ case 90:
+ p.x = y;
+ p.y = currentPage.getWidth() - x;
+ break;
+ case 180:
+ p.x = currentPage.getWidth() - x;
+ p.y = currentPage.getHeight() - y;
+ break;
+ case 270:
+ p.x = currentPage.getHeight() - y;
+ p.y = x;
+ break;
+ default:
+ p.x = x;
+ p.y = y;
+ break;
+ }
+ return p;
+ }
+
+ /**
+ * Helper method to create text on the current page, this method delegates
+ * to the current presentation text object in order to construct the text.
+ *
+ * @param textDataInfo
+ * the afp text data
+ * @throws UnsupportedEncodingException thrown if character encoding is not supported
+ */
+ public void createText(AFPTextDataInfo textDataInfo) throws UnsupportedEncodingException {
+ int rotation = paintingState.getRotation();
+ if (rotation != 0) {
+ textDataInfo.setRotation(rotation);
+ Point p = getPoint(textDataInfo.getX(), textDataInfo.getY());
+ textDataInfo.setX(p.x);
+ textDataInfo.setY(p.y);
+ }
+ currentPage.createText(textDataInfo);
+ }
+
+ /**
+ * Method to create a line on the current page.
+ *
+ * @param lineDataInfo the line data information.
+ */
+ public void createLine(AFPLineDataInfo lineDataInfo) {
+ currentPage.createLine(lineDataInfo);
+ }
+
+ /**
+ * This method will create shading on the page using the specified
+ * coordinates (the shading contrast is controlled via the red, green, blue
+ * parameters, by converting this to grey scale).
+ *
+ * @param x
+ * the x coordinate of the shading
+ * @param y
+ * the y coordinate of the shading
+ * @param w
+ * the width of the shaded area
+ * @param h
+ * the height of the shaded area
+ * @param col
+ * the shading color
+ */
+ public void createShading(int x, int y, int w, int h, Color col) {
+ currentPageObject.createShading(x, y, w, h, col.getRed(), col.getGreen(), col.getBlue());
+ }
+
+ /**
+ * Helper method which allows creation of the MPO object, via the AEG. And
+ * the IPO via the Page. (See actual object for descriptions.)
+ *
+ * @param name
+ * the name of the static overlay
+ */
+ public void createIncludePageOverlay(String name) {
+ currentPageObject.createIncludePageOverlay(name, 0, 0, paintingState.getRotation());
+ currentPageObject.getActiveEnvironmentGroup().createOverlay(name);
+ }
+
+ /**
+ * Helper method which allows creation of the IMM object.
+ *
+ * @param name
+ * the name of the medium map
+ */
+ public void createInvokeMediumMap(String name) {
+ currentPageGroup.createInvokeMediumMap(name);
+ }
+
+ /**
+ * Creates an IncludePageSegment on the current page.
+ *
+ * @param name
+ * the name of the include page segment
+ * @param x
+ * the x coordinate for the overlay
+ * @param y
+ * the y coordinate for the overlay
+ */
+ public void createIncludePageSegment(String name, int x, int y) {
+ int xOrigin;
+ int yOrigin;
+ int orientation = paintingState.getRotation();
+ switch (orientation) {
+ case 90:
+ xOrigin = currentPage.getWidth() - y;
+ yOrigin = x;
+ break;
+ case 180:
+ xOrigin = currentPage.getWidth() - x;
+ yOrigin = currentPage.getHeight() - y;
+ break;
+ case 270:
+ xOrigin = y;
+ yOrigin = currentPage.getHeight() - x;
+ break;
+ default:
+ xOrigin = x;
+ yOrigin = y;
+ break;
+ }
+ currentPage.createIncludePageSegment(name, xOrigin, yOrigin);
+ }
+
+ /**
+ * Creates a TagLogicalElement on the current page.
+ *
+ * @param attributes
+ * the array of key value pairs.
+ */
+ public void createPageTagLogicalElement(TagLogicalElementBean[] attributes) {
+ for (int i = 0; i < attributes.length; i++) {
+ String name = attributes[i].getKey();
+ String value = attributes[i].getValue();
+ currentPage.createTagLogicalElement(name, value);
+ }
+ }
+
+ /**
+ * Creates a TagLogicalElement on the current page group.
+ *
+ * @param attributes
+ * the array of key value pairs.
+ */
+ public void createPageGroupTagLogicalElement(TagLogicalElementBean[] attributes) {
+ for (int i = 0; i < attributes.length; i++) {
+ String name = attributes[i].getKey();
+ String value = attributes[i].getValue();
+ currentPageGroup.createTagLogicalElement(name, value);
+ }
+ }
+
+ /**
+ * Creates a TagLogicalElement on the current page or page group
+ *
+ * @param name
+ * The tag name
+ * @param value
+ * The tag value
+ */
+ public void createTagLogicalElement(String name, String value) {
+ if (currentPageGroup != null) {
+ currentPageGroup.createTagLogicalElement(name, value);
+ } else {
+ currentPage.createTagLogicalElement(name, value);
+ }
+ }
+
+ /**
+ * Creates a NoOperation item
+ *
+ * @param content
+ * byte data
+ */
+ public void createNoOperation(String content) {
+ currentPage.createNoOperation(content);
+ }
+
+ /**
+ * Returns the current page group
+ *
+ * @return the current page group
+ */
+ public PageGroup getCurrentPageGroup() {
+ return this.currentPageGroup;
+ }
+
+ /**
+ * Start a new document.
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public void startDocument() throws IOException {
+ this.document = factory.createDocument();
+ document.writeToStream(this.outputStream);
+ }
+
+ /**
+ * Start a new page group. When processing has finished on the current page
+ * group the {@link #endPageGroup()}method must be invoked to mark the page
+ * group ending.
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public void startPageGroup() throws IOException {
+ endPageGroup();
+ this.currentPageGroup = factory.createPageGroup();
+ }
+
+ /**
+ * Helper method to mark the end of the page group.
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred
+ */
+ public void endPageGroup() throws IOException {
+ if (currentPageGroup != null) {
+ currentPageGroup.endPageGroup();
+ document.addPageGroup(currentPageGroup);
+ document.writeToStream(outputStream);
+ currentPageGroup = null;
+ }
+ }
+
+ /**
+ * Sets the MO:DCA interchange set to use
+ *
+ * @param interchangeSet the MO:DCA interchange set
+ */
+ public void setInterchangeSet(InterchangeSet interchangeSet) {
+ this.interchangeSet = interchangeSet;
+ }
+
+ /**
+ * Returns the MO:DCA interchange set in use
+ *
+ * @return the MO:DCA interchange set in use
+ */
+ public InterchangeSet getInterchangeSet() {
+ return this.interchangeSet;
+ }
+
+ /**
+ * Returns the resource group for a given resource info
+ *
+ * @param level a resource level
+ * @return a resource group for the given resource info
+ */
+ public ResourceGroup getResourceGroup(AFPResourceLevel level) {
+ ResourceGroup resourceGroup = null;
+ if (level.isDocument()) {
+ resourceGroup = document.getResourceGroup();
+ } else if (level.isPageGroup()) {
+ resourceGroup = currentPageGroup.getResourceGroup();
+ } else if (level.isPage()) {
+ resourceGroup = currentPageObject.getResourceGroup();
+ }
+ return resourceGroup;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/Factory.java b/src/java/org/apache/fop/afp/Factory.java
new file mode 100644
index 000000000..a278a5761
--- /dev/null
+++ b/src/java/org/apache/fop/afp/Factory.java
@@ -0,0 +1,635 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.io.OutputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.goca.GraphicsData;
+import org.apache.fop.afp.ioca.ImageContent;
+import org.apache.fop.afp.ioca.ImageRasterData;
+import org.apache.fop.afp.ioca.ImageSegment;
+import org.apache.fop.afp.ioca.ImageSizeParameter;
+import org.apache.fop.afp.modca.ActiveEnvironmentGroup;
+import org.apache.fop.afp.modca.ContainerDataDescriptor;
+import org.apache.fop.afp.modca.Document;
+import org.apache.fop.afp.modca.GraphicsDataDescriptor;
+import org.apache.fop.afp.modca.GraphicsObject;
+import org.apache.fop.afp.modca.IMImageObject;
+import org.apache.fop.afp.modca.ImageDataDescriptor;
+import org.apache.fop.afp.modca.ImageObject;
+import org.apache.fop.afp.modca.IncludeObject;
+import org.apache.fop.afp.modca.IncludePageSegment;
+import org.apache.fop.afp.modca.InvokeMediumMap;
+import org.apache.fop.afp.modca.MapCodedFont;
+import org.apache.fop.afp.modca.MapContainerData;
+import org.apache.fop.afp.modca.MapDataResource;
+import org.apache.fop.afp.modca.ObjectAreaDescriptor;
+import org.apache.fop.afp.modca.ObjectAreaPosition;
+import org.apache.fop.afp.modca.ObjectContainer;
+import org.apache.fop.afp.modca.ObjectEnvironmentGroup;
+import org.apache.fop.afp.modca.Overlay;
+import org.apache.fop.afp.modca.PageDescriptor;
+import org.apache.fop.afp.modca.PageGroup;
+import org.apache.fop.afp.modca.PageObject;
+import org.apache.fop.afp.modca.PresentationEnvironmentControl;
+import org.apache.fop.afp.modca.PresentationTextDescriptor;
+import org.apache.fop.afp.modca.PresentationTextObject;
+import org.apache.fop.afp.modca.ResourceEnvironmentGroup;
+import org.apache.fop.afp.modca.ResourceGroup;
+import org.apache.fop.afp.modca.ResourceObject;
+import org.apache.fop.afp.modca.StreamedResourceGroup;
+import org.apache.fop.afp.modca.TagLogicalElement;
+import org.apache.fop.afp.util.StringUtils;
+
+/**
+ * Creator of MO:DCA structured field objects
+ */
+public class Factory {
+
+ /** Static logging instance */
+ private static final Log log = LogFactory.getLog(Factory.class);
+
+ private static final String OBJECT_ENVIRONMENT_GROUP_NAME_PREFIX = "OEG";
+
+ private static final String ACTIVE_ENVIRONMENT_GROUP_NAME_PREFIX = "AEG";
+
+ private static final String IMAGE_NAME_PREFIX = "IMG";
+
+ private static final String GRAPHIC_NAME_PREFIX = "GRA";
+
+ private static final String BARCODE_NAME_PREFIX = "BAR";
+
+// private static final String OTHER_NAME_PREFIX = "OTH";
+
+ private static final String OBJECT_CONTAINER_NAME_PREFIX = "OC";
+
+ private static final String RESOURCE_NAME_PREFIX = "RES";
+
+ private static final String RESOURCE_GROUP_NAME_PREFIX = "RG";
+
+ private static final String PAGE_GROUP_NAME_PREFIX = "PGP";
+
+ private static final String PAGE_NAME_PREFIX = "PGN";
+
+ private static final String OVERLAY_NAME_PREFIX = "OVL";
+
+ private static final String PRESENTATION_TEXT_NAME_PREFIX = "PT";
+
+ private static final String DOCUMENT_NAME_PREFIX = "DOC";
+
+ private static final String IM_IMAGE_NAME_PREFIX = "IMIMG";
+
+ private static final String IMAGE_SEGMENT_NAME_PREFIX = "IS";
+
+
+ /** the page group count */
+ private int pageGroupCount = 0;
+
+ /** the page count */
+ private int pageCount = 0;
+
+ /** the image count */
+ private int imageCount = 0;
+
+ /** the im image count */
+ private int imImageCount = 0;
+
+ /** the image segment count */
+ private int imageSegmentCount = 0;
+
+ /** the graphic count */
+ private int graphicCount = 0;
+
+ /** the object container count */
+ private int objectContainerCount = 0;
+
+ /** the resource count */
+ private int resourceCount = 0;
+
+ /** the resource group count */
+ private int resourceGroupCount = 0;
+
+ /** the overlay count */
+ private int overlayCount = 0;
+
+ /** the presentation text object count */
+ private int textObjectCount = 0;
+
+ /** the active environment group count */
+ private int activeEnvironmentGroupCount = 0;
+
+ /** the document count */
+ private int documentCount = 0;
+
+ /** the object environment group count */
+ private int objectEnvironmentGroupCount = 0;
+
+ /**
+ * Main constructor
+ */
+ public Factory() {
+ }
+
+ /**
+ * Creates a new IOCA {@link ImageObject}
+ *
+ * @return a new {@link ImageObject}
+ */
+ public ImageObject createImageObject() {
+ String name = IMAGE_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++imageCount), '0', 5);
+ ImageObject imageObject = new ImageObject(this, name);
+ return imageObject;
+ }
+
+ /**
+ * Creates an IOCA {@link IMImageObject}
+ *
+ * @return a new {@link IMImageObject}
+ */
+ public IMImageObject createIMImageObject() {
+ String name = IM_IMAGE_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++imImageCount), '0', 3);
+ IMImageObject imImageObject = new IMImageObject(name);
+ return imImageObject;
+ }
+
+ /**
+ * Creates a new GOCA {@link GraphicsObject}
+ *
+ * @return a new {@link GraphicsObject}
+ */
+ public GraphicsObject createGraphicsObject() {
+ String name = GRAPHIC_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++graphicCount), '0', 5);
+ GraphicsObject graphicsObj = new GraphicsObject(this, name);
+ return graphicsObj;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link ObjectContainer}
+ *
+ * @return a new {@link ObjectContainer}
+ */
+ public ObjectContainer createObjectContainer() {
+ String name = OBJECT_CONTAINER_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++objectContainerCount), '0', 6);
+ return new ObjectContainer(this, name);
+ }
+
+ /**
+ * Creates a new MO:DCA {@link ResourceObject}
+ *
+ * @param resourceName the resource object name
+ * @return a new {@link ResourceObject}
+ */
+ public ResourceObject createResource(String resourceName) {
+ return new ResourceObject(resourceName);
+ }
+
+ /**
+ * Creates a new MO:DCA {@link ResourceObject}
+ *
+ * @return a new {@link ResourceObject}
+ */
+ public ResourceObject createResource() {
+ String name = RESOURCE_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++resourceCount), '0', 5);
+ return createResource(name);
+ }
+
+ /**
+ * Creates a new MO:DCA {@link PageGroup}
+ *
+ * @return a new {@link PageGroup}
+ */
+ public PageGroup createPageGroup() {
+ String name = PAGE_GROUP_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++pageGroupCount), '0', 5);
+ return new PageGroup(this, name);
+ }
+
+ /**
+ * Creates a new MO:DCA {@link ActiveEnvironmentGroup}
+ *
+ * @param width the page width
+ * @param height the page height
+ * @param widthRes the page width resolution
+ * @param heightRes the page height resolution
+ * @return a new {@link ActiveEnvironmentGroup}
+ */
+ public ActiveEnvironmentGroup createActiveEnvironmentGroup(
+ int width, int height, int widthRes, int heightRes) {
+ String name = ACTIVE_ENVIRONMENT_GROUP_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++activeEnvironmentGroupCount ), '0', 5);
+ return new ActiveEnvironmentGroup(this, name, width, height, widthRes, heightRes);
+ }
+
+ /**
+ * Creates a new MO:DCA {@link ResourceGroup}
+ *
+ * @return a new {@link ResourceGroup}
+ */
+ public ResourceGroup createResourceGroup() {
+ String name = RESOURCE_GROUP_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++resourceGroupCount), '0', 6);
+ return new ResourceGroup(name);
+ }
+
+ /**
+ * Creates a new MO:DCA {@link StreamedResourceGroup}
+ *
+ * @param os the outputstream of the streamed resource group
+ * @return a new {@link StreamedResourceGroup}
+ */
+ public StreamedResourceGroup createStreamedResourceGroup(OutputStream os) {
+ String name = RESOURCE_GROUP_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++resourceGroupCount), '0', 6);
+ return new StreamedResourceGroup(name, os);
+ }
+
+ /**
+ * Creates a new MO:DCA {@link PageObject}.
+ *
+ * @param pageWidth
+ * the width of the page
+ * @param pageHeight
+ * the height of the page
+ * @param pageRotation
+ * the rotation of the page
+ * @param pageWidthRes
+ * the width resolution of the page
+ * @param pageHeightRes
+ * the height resolution of the page
+ *
+ * @return a new {@link PageObject}
+ */
+ public PageObject createPage(int pageWidth, int pageHeight, int pageRotation,
+ int pageWidthRes, int pageHeightRes) {
+ String pageName = PAGE_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++pageCount), '0', 5);
+ return new PageObject(this, pageName, pageWidth, pageHeight,
+ pageRotation, pageWidthRes, pageHeightRes);
+ }
+
+
+ /**
+ * Creates a new MO:DCA {@link PresentationTextObject}.
+ *
+ * @return a new {@link PresentationTextObject}
+ */
+ public PresentationTextObject createPresentationTextObject() {
+ String textObjectName = PRESENTATION_TEXT_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++textObjectCount), '0', 6);
+ return new PresentationTextObject(textObjectName);
+ }
+
+
+ /**
+ * Creates a new MO:DCA {@link Overlay}.
+ *
+ * @param width
+ * the width of the overlay
+ * @param height
+ * the height of the overlay
+ * @param widthRes
+ * the width resolution of the overlay
+ * @param heightRes
+ * the height resolution of the overlay
+ * @param overlayRotation
+ * the rotation of the overlay
+ *
+ * @return a new {@link Overlay}.
+ */
+ public Overlay createOverlay(int width, int height,
+ int widthRes, int heightRes, int overlayRotation) {
+ String overlayName = OVERLAY_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++overlayCount), '0', 5);
+ Overlay overlay = new Overlay(this, overlayName, width, height,
+ overlayRotation, widthRes, heightRes);
+ return overlay;
+ }
+
+ /**
+ * Creates a MO:DCA {@link Document}
+ *
+ * @return a new {@link Document}
+ */
+ public Document createDocument() {
+ String documentName = DOCUMENT_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++documentCount), '0', 5);
+ Document document = new Document(this, documentName);
+ return document;
+ }
+
+ /**
+ * Creates a MO:DCA {@link MapCodedFont}
+ *
+ * @return a new {@link MapCodedFont}
+ */
+ public MapCodedFont createMapCodedFont() {
+ MapCodedFont mapCodedFont = new MapCodedFont();
+ return mapCodedFont;
+ }
+
+ /**
+ * Creates a MO:DCA {@link IncludePageSegment}
+ *
+ * @param name the page segment name
+ * @param x the x coordinate
+ * @param y the y coordinate
+ *
+ * @return a new {@link IncludePageSegment}
+ */
+ public IncludePageSegment createIncludePageSegment(String name, int x, int y) {
+ IncludePageSegment includePageSegment = new IncludePageSegment(name, x, y);
+ return includePageSegment;
+ }
+
+ /**
+ * Creates a MO:DCA {@link IncludeObject}
+ *
+ * @param name the name of this include object
+ * @return a new {@link IncludeObject}
+ */
+ public IncludeObject createInclude(String name) {
+ IncludeObject includeObject = new IncludeObject(name);
+ return includeObject;
+ }
+
+ /**
+ * Creates a MO:DCA {@link TagLogicalElement}
+ *
+ * @param name name of the element
+ * @param value value of the element
+ * @return a new {@link TagLogicalElement}
+ */
+ public TagLogicalElement createTagLogicalElement(String name, String value) {
+ TagLogicalElement tle = new TagLogicalElement(name, value);
+ return tle;
+ }
+
+ /**
+ * Creates a new {@link DataStream}
+ *
+ * @param paintingState the AFP painting state
+ * @param outputStream an outputstream to write to
+ * @return a new {@link DataStream}
+ */
+ public DataStream createDataStream(AFPPaintingState paintingState, OutputStream outputStream) {
+ DataStream dataStream = new DataStream(this, paintingState, outputStream);
+ return dataStream;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link PageDescriptor}
+ *
+ * @param width the page width.
+ * @param height the page height.
+ * @param widthRes the page width resolution.
+ * @param heightRes the page height resolution.
+ * @return a new {@link PageDescriptor}
+ */
+ public PageDescriptor createPageDescriptor(int width, int height, int widthRes, int heightRes) {
+ PageDescriptor pageDescriptor = new PageDescriptor(width, height, widthRes, heightRes);
+ return pageDescriptor;
+ }
+
+ /**
+ * Returns a new MO:DCA {@link ObjectEnvironmentGroup}
+ *
+ * @return a new {@link ObjectEnvironmentGroup}
+ */
+ public ObjectEnvironmentGroup createObjectEnvironmentGroup() {
+ String oegName = OBJECT_ENVIRONMENT_GROUP_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++objectEnvironmentGroupCount), '0', 5);
+ ObjectEnvironmentGroup objectEnvironmentGroup = new ObjectEnvironmentGroup(oegName);
+ return objectEnvironmentGroup;
+ }
+
+ /**
+ * Creates a new GOCA {@link GraphicsData}
+ *
+ * @return a new {@link GraphicsData}
+ */
+ public GraphicsData createGraphicsData() {
+ GraphicsData graphicsData = new GraphicsData();
+ return graphicsData;
+ }
+
+ /**
+ * Creates a new {@link ObjectAreaDescriptor}
+ *
+ * @param width the object width.
+ * @param height the object height.
+ * @param widthRes the object width resolution.
+ * @param heightRes the object height resolution.
+ * @return a new {@link ObjectAreaDescriptor}
+ */
+ public ObjectAreaDescriptor createObjectAreaDescriptor(
+ int width, int height, int widthRes, int heightRes) {
+ ObjectAreaDescriptor objectAreaDescriptor
+ = new ObjectAreaDescriptor(width, height, widthRes, heightRes);
+ return objectAreaDescriptor;
+ }
+
+ /**
+ * Creates a new {@link ObjectAreaPosition}
+ *
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ * @param rotation the coordinate system rotation (must be 0, 90, 180, 270).
+ * @return a new {@link ObjectAreaPosition}
+ */
+ public ObjectAreaPosition createObjectAreaPosition(int x, int y,
+ int rotation) {
+ ObjectAreaPosition objectAreaPosition = new ObjectAreaPosition(
+ x, y, rotation);
+ return objectAreaPosition;
+ }
+
+ /**
+ * Creates a new {@link ImageDataDescriptor}
+ *
+ * @param width the image width
+ * @param height the image height
+ * @param widthRes the x resolution of the image
+ * @param heightRes the y resolution of the image
+ * @return a new {@link ImageDataDescriptor}
+ */
+ public ImageDataDescriptor createImageDataDescriptor(
+ int width, int height, int widthRes, int heightRes) {
+ ImageDataDescriptor imageDataDescriptor = new ImageDataDescriptor(
+ width, height, widthRes, heightRes);
+ return imageDataDescriptor;
+ }
+
+ /**
+ * Creates a new GOCA {@link GraphicsDataDescriptor}
+ *
+ * @param xlwind the left edge of the graphics window
+ * @param xrwind the right edge of the graphics window
+ * @param ybwind the top edge of the graphics window
+ * @param ytwind the bottom edge of the graphics window
+ * @param widthRes the x resolution of the graphics window
+ * @param heightRes the y resolution of the graphics window
+ * @return a new {@link GraphicsDataDescriptor}
+ */
+ public GraphicsDataDescriptor createGraphicsDataDescriptor(
+ int xlwind, int xrwind, int ybwind, int ytwind, int widthRes, int heightRes) {
+ GraphicsDataDescriptor graphicsDataDescriptor = new GraphicsDataDescriptor(
+ xlwind, xrwind, ybwind, ytwind, widthRes, heightRes);
+ return graphicsDataDescriptor;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link ContainerDataDescriptor}
+ *
+ * @param dataWidth the container data width
+ * @param dataHeight the container data height
+ * @param widthRes the container data width resolution
+ * @param heightRes the container data height resolution
+ * @return a new {@link ContainerDataDescriptor}
+ */
+ public ContainerDataDescriptor createContainerDataDescriptor(
+ int dataWidth, int dataHeight, int widthRes, int heightRes) {
+ ContainerDataDescriptor containerDataDescriptor
+ = new ContainerDataDescriptor(dataWidth, dataHeight, widthRes, heightRes);
+ return containerDataDescriptor;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link MapContainerData}
+ *
+ * @param optionValue the option value
+ * @return a new {@link MapContainerData}
+ */
+ public MapContainerData createMapContainerData(byte optionValue) {
+ MapContainerData mapContainerData = new MapContainerData(optionValue);
+ return mapContainerData;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link MapDataResource}
+ *
+ * @return a new {@link MapDataResource}
+ */
+ public MapDataResource createMapDataResource() {
+ MapDataResource mapDataResource = new MapDataResource();
+ return mapDataResource;
+ }
+
+ /**
+ * Creates a new PTOCA {@link PresentationTextDescriptor}
+ *
+ * @return a new {@link PresentationTextDescriptor}
+ */
+ public PresentationTextDescriptor createPresentationTextDataDescriptor(
+ int width, int height, int widthRes, int heightRes) {
+ PresentationTextDescriptor presentationTextDescriptor
+ = new PresentationTextDescriptor(width, height,
+ widthRes, heightRes);
+ return presentationTextDescriptor;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link PresentationEnvironmentControl}
+ *
+ * @return a new {@link PresentationEnvironmentControl}
+ */
+ public PresentationEnvironmentControl createPresentationEnvironmentControl() {
+ PresentationEnvironmentControl presentationEnvironmentControl
+ = new PresentationEnvironmentControl();
+ return presentationEnvironmentControl;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link InvokeMediumMap}
+ *
+ * @param name the object name
+ * @return a new {@link InvokeMediumMap}
+ */
+ public InvokeMediumMap createInvokeMediumMap(String name) {
+ InvokeMediumMap invokeMediumMap = new InvokeMediumMap(name);
+ return invokeMediumMap;
+ }
+
+ /**
+ * Creates a new MO:DCA {@link ResourceEnvironmentGroup}
+ *
+ * @return a new {@link ResourceEnvironmentGroup}
+ */
+ public ResourceEnvironmentGroup createResourceEnvironmentGroup() {
+ ResourceEnvironmentGroup resourceEnvironmentGroup = new ResourceEnvironmentGroup();
+ return resourceEnvironmentGroup;
+ }
+
+ /**
+ * Creates a new IOCA {@link ImageSegment}
+ *
+ * @return a new {@link ImageSegment}
+ */
+ public ImageSegment createImageSegment() {
+ String name = IMAGE_SEGMENT_NAME_PREFIX
+ + StringUtils.lpad(String.valueOf(++imageSegmentCount), '0', 2);
+ ImageSegment imageSegment = new ImageSegment(this, name);
+ return imageSegment;
+ }
+
+ /**
+ * Creates an new IOCA {@link ImageContent}
+ *
+ * @return an {@link ImageContent}
+ */
+ public ImageContent createImageContent() {
+ ImageContent imageContent = new ImageContent();
+ return imageContent;
+ }
+
+ /**
+ * Creates a new IOCA {@link ImageRasterData}
+ *
+ * @param rasterData raster data
+ * @return a new {@link ImageRasterData}
+ */
+ public ImageRasterData createImageRasterData(byte[] rasterData) {
+ ImageRasterData imageRasterData = new ImageRasterData(rasterData);
+ return imageRasterData;
+ }
+
+ /**
+ * Creates an new IOCA {@link ImageSizeParameter}.
+ *
+ * @param hsize The horizontal size of the image.
+ * @param vsize The vertical size of the image.
+ * @param hresol The horizontal resolution of the image.
+ * @param vresol The vertical resolution of the image.
+ * @return a new {@link ImageSizeParameter}
+ */
+ public ImageSizeParameter createImageSizeParameter(int hsize, int vsize,
+ int hresol, int vresol) {
+ ImageSizeParameter imageSizeParameter
+ = new ImageSizeParameter(hsize, vsize, hresol, vresol);
+ return imageSizeParameter;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/PaintingInfo.java b/src/java/org/apache/fop/afp/PaintingInfo.java
new file mode 100644
index 000000000..e53f28306
--- /dev/null
+++ b/src/java/org/apache/fop/afp/PaintingInfo.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+/**
+ * Generic painting information interface
+ */
+public interface PaintingInfo {
+
+}
diff --git a/src/java/org/apache/fop/afp/RectanglePaintingInfo.java b/src/java/org/apache/fop/afp/RectanglePaintingInfo.java
new file mode 100644
index 000000000..64503d0b8
--- /dev/null
+++ b/src/java/org/apache/fop/afp/RectanglePaintingInfo.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+
+/**
+ * Filled rectangle painting information
+ */
+public class RectanglePaintingInfo implements PaintingInfo {
+
+ private final float x;
+ private final float y;
+ private final float width;
+ private final float height;
+
+ /**
+ * Main constructor
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the width
+ * @param height the height
+ */
+ public RectanglePaintingInfo(float x, float y, float width, float height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Returns the x coordinate
+ *
+ * @return the x coordinate
+ */
+ protected float getX() {
+ return x;
+ }
+
+ /**
+ * Returns the y coordinate
+ *
+ * @return the y coordinate
+ */
+ protected float getY() {
+ return y;
+ }
+
+ /**
+ * Returns the width
+ *
+ * @return the width
+ */
+ protected float getWidth() {
+ return width;
+ }
+
+ /**
+ * Returns the height
+ *
+ * @return the height
+ */
+ protected float getHeight() {
+ return height;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/Startable.java b/src/java/org/apache/fop/afp/Startable.java
new file mode 100644
index 000000000..fd05b8455
--- /dev/null
+++ b/src/java/org/apache/fop/afp/Startable.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+/**
+ * Set and expose whether an object has started or not.
+ */
+public interface Startable {
+
+ /**
+ * Sets whether or not this object has started or not
+ *
+ * @param complete true if this object has started
+ */
+ void setStarted(boolean started);
+
+ /**
+ * Returns true if this object has started
+ *
+ * @return true if this object has started
+ */
+ boolean isStarted();
+}
diff --git a/src/java/org/apache/fop/afp/Streamable.java b/src/java/org/apache/fop/afp/Streamable.java
new file mode 100644
index 000000000..cd731ab47
--- /dev/null
+++ b/src/java/org/apache/fop/afp/Streamable.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Implementing object is able to write to an OutputStream
+ */
+public interface Streamable {
+
+ /**
+ * DataStream objects must implement the writeToStream()
+ * method to write its data to the given OutputStream
+ *
+ * @param os the outputsteam stream
+ * @throws java.io.IOException an I/O exception of some sort has occurred.
+ */
+ void writeToStream(OutputStream os) throws IOException;
+}
diff --git a/src/java/org/apache/fop/afp/StructuredData.java b/src/java/org/apache/fop/afp/StructuredData.java
new file mode 100644
index 000000000..99555b39b
--- /dev/null
+++ b/src/java/org/apache/fop/afp/StructuredData.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp;
+
+/**
+ * An AFP object which is able to know its own data length prior to writeToStream()
+ */
+public interface StructuredData {
+
+ /**
+ * Returns the data length of this structured field
+ *
+ * @return the data length of this structured field
+ */
+ int getDataLength();
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java
new file mode 100644
index 000000000..e607bef5f
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.fonts;
+
+import org.apache.fop.fonts.Base14Font;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontCollection;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.base14.Courier;
+import org.apache.fop.fonts.base14.CourierBold;
+import org.apache.fop.fonts.base14.CourierBoldOblique;
+import org.apache.fop.fonts.base14.CourierOblique;
+import org.apache.fop.fonts.base14.Helvetica;
+import org.apache.fop.fonts.base14.HelveticaBold;
+import org.apache.fop.fonts.base14.HelveticaOblique;
+import org.apache.fop.fonts.base14.TimesBold;
+import org.apache.fop.fonts.base14.TimesBoldItalic;
+import org.apache.fop.fonts.base14.TimesItalic;
+import org.apache.fop.fonts.base14.TimesRoman;
+
+/**
+ * Sets up a typical Base 12 font configuration for AFP
+ */
+public class AFPBase12FontCollection implements FontCollection {
+
+ /** standard raster font sizes */
+ private static final int[] RASTER_SIZES = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 30, 36};
+
+ /** standard raster font charset references */
+ private static final String[] CHARSET_REF = {
+ "60", "70", "80", "90", "00", "A0", "B0", "D0", "F0", "H0", "J0", "N0", "T0", "Z0"};
+
+ private void addCharacterSet(RasterFont font, String charsetName, Base14Font base14) {
+ for (int i = 0; i < RASTER_SIZES.length; i++) {
+ int size = RASTER_SIZES[i];
+ FopCharacterSet characterSet = new FopCharacterSet(
+ CharacterSet.DEFAULT_CODEPAGE, CharacterSet.DEFAULT_ENCODING,
+ charsetName + CHARSET_REF[i], base14);
+ font.addCharacterSet(size, characterSet);
+ }
+ }
+
+ private int addFontProperties(FontInfo fontInfo, AFPFont font,
+ String[] names, String style, int weight, int num) {
+ String internalFontKey = "F" + num;
+ fontInfo.addMetrics(internalFontKey, font);
+ fontInfo.addFontProperties(internalFontKey, names, style, weight);
+ num++;
+ return num;
+ }
+
+ /** {@inheritDoc} */
+ public int setup(int start, FontInfo fontInfo) {
+
+ /**
+ * Add the base 12 fonts (Helvetica, Times and Courier)
+ *
+ * Note: this default font configuration may not be available
+ * on your AFP environment.
+ */
+ int num = start;
+ RasterFont font = null;
+
+ /** standard font family reference names for Helvetica font */
+ final String[] helveticaNames = {"Helvetica", "Arial", "sans-serif"};
+ font = new RasterFont("Helvetica");
+ addCharacterSet(font, "C0H200", new Helvetica());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Helvetica Italic");
+ addCharacterSet(font, "C0H300", new HelveticaOblique());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Helvetica (Semi) Bold");
+ addCharacterSet(font, "C0H400", new HelveticaBold());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
+
+ font = new RasterFont("Helvetica Italic (Semi) Bold");
+ addCharacterSet(font, "C0H500", new HelveticaOblique());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
+
+
+ /** standard font family reference names for Times font */
+
+ /** any is treated as serif */
+ final String[] timesNames = {"Times", "TimesRoman", "Times Roman", "Times-Roman",
+ "Times New Roman", "TimesNewRoman", "serif", "any"};
+
+ font = new RasterFont("Times Roman");
+ addCharacterSet(font, "CON200", new TimesRoman());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Times Roman Italic");
+ addCharacterSet(font, "CON300", new TimesItalic());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Times Roman Bold");
+ addCharacterSet(font, "CON400", new TimesBold());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
+
+ font = new RasterFont("Times Roman Italic Bold");
+ addCharacterSet(font, "CON500", new TimesBoldItalic());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
+
+
+ /** standard font family reference names for Courier font */
+ final String[] courierNames = {"Courier", "monospace"};
+
+ font = new RasterFont("Courier");
+ addCharacterSet(font, "C04200", new Courier());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Courier Italic");
+ addCharacterSet(font, "C04300", new CourierOblique());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Courier Bold");
+ addCharacterSet(font, "C04400", new CourierBold());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
+
+ font = new RasterFont("Courier Italic Bold");
+ addCharacterSet(font, "C04500", new CourierBoldOblique());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
+
+ return num;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFont.java b/src/java/org/apache/fop/afp/fonts/AFPFont.java
index 2819cf12c..dc8f9c315 100644
--- a/src/java/org/apache/fop/render/afp/fonts/AFPFont.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPFont.java
@@ -17,7 +17,8 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
+
import java.util.Map;
import java.util.Set;
@@ -41,7 +42,6 @@ public abstract class AFPFont extends Typeface {
*/
public AFPFont(String name) {
this.name = name;
-
}
/** {@inheritDoc} */
@@ -106,4 +106,8 @@ public abstract class AFPFont extends Typeface {
return true;
}
+ /** {@inheritDoc} */
+ public String toString() {
+ return "name=" + name;
+ }
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPFontAttributes.java b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java
index fb6f82463..de7f7f5be 100644
--- a/src/java/org/apache/fop/render/afp/AFPFontAttributes.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java
@@ -17,40 +17,30 @@
/* $Id$ */
-package org.apache.fop.render.afp;
-
-import org.apache.fop.render.afp.fonts.AFPFont;
+package org.apache.fop.afp.fonts;
/**
* This class encapsulates the font attributes that need to be included
* in the AFP data stream. This class does not assist in converting the
* font attributes to AFP code pages and character set values.
- *
*/
public class AFPFontAttributes {
- /**
- * The font reference
- */
+ /** the font reference */
private int fontReference;
- /**
- * The font key
- */
- private String fontKey;
+ /** the font key */
+ private final String fontKey;
- /**
- * The font
- */
- private AFPFont font;
+ /** the font */
+ private final AFPFont font;
- /**
- * The point size
- */
- private int pointSize;
+ /** the point size */
+ private final int pointSize;
/**
* Constructor for the AFPFontAttributes
+ *
* @param fontKey the font key
* @param font the font
* @param pointSize the point size
@@ -62,6 +52,8 @@ public class AFPFontAttributes {
}
/**
+ * Return the font
+ *
* @return the font
*/
public AFPFont getFont() {
@@ -69,6 +61,8 @@ public class AFPFontAttributes {
}
/**
+ * Return the FontKey attribute
+ *
* @return the FontKey attribute
*/
public String getFontKey() {
@@ -76,6 +70,8 @@ public class AFPFontAttributes {
}
/**
+ * Return the point size attribute
+ *
* @return the point size attribute
*/
public int getPointSize() {
@@ -83,6 +79,8 @@ public class AFPFontAttributes {
}
/**
+ * Return the FontReference attribute
+ *
* @return the FontReference attribute
*/
public int getFontReference() {
@@ -91,10 +89,18 @@ public class AFPFontAttributes {
/**
* Sets the FontReference attribute
+ *
* @param fontReference the FontReference to set
*/
public void setFontReference(int fontReference) {
this.fontReference = fontReference;
}
+ /** {@inheritDoc} */
+ public String toString() {
+ return "fontReference=" + fontReference
+ + ", fontKey=" + fontKey
+ + ", font=" + font
+ + ", pointSize=" + pointSize;
+ }
}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java
new file mode 100644
index 000000000..670373fbf
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.fonts;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.afp.AFPEventProducer;
+import org.apache.fop.events.EventBroadcaster;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontCollection;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+
+/**
+ * A base collection of AFP fonts
+ */
+public class AFPFontCollection implements FontCollection {
+
+ private final EventBroadcaster eventBroadcaster;
+
+ private final List/*<AFPFontInfo>*/ fontInfoList;
+
+ /**
+ * Main constructor
+ *
+ * @param eventBroadcaster the event broadcaster
+ * @param fontInfoList the font info list
+ */
+ public AFPFontCollection(EventBroadcaster eventBroadcaster,
+ List/*<AFPFontInfo>*/ fontInfoList) {
+ this.eventBroadcaster = eventBroadcaster;
+ this.fontInfoList = fontInfoList;
+ }
+
+ /** {@inheritDoc} */
+ public int setup(int start, FontInfo fontInfo) {
+ int num = 1;
+ AFPEventProducer eventProducer = AFPEventProducer.Provider.get(eventBroadcaster);
+ if (fontInfoList != null && fontInfoList.size() > 0) {
+ for (Iterator it = fontInfoList.iterator(); it.hasNext();) {
+ AFPFontInfo afpFontInfo = (AFPFontInfo)it.next();
+ AFPFont afpFont = afpFontInfo.getAFPFont();
+ List/*<FontTriplet>*/ tripletList = afpFontInfo.getFontTriplets();
+ for (Iterator it2 = tripletList.iterator(); it2.hasNext();) {
+ FontTriplet triplet = (FontTriplet)it2.next();
+ fontInfo.addFontProperties("F" + num,
+ triplet.getName(), triplet.getStyle(), triplet.getWeight());
+ fontInfo.addMetrics("F" + num, afpFont);
+ num++;
+ }
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
+ }
+ } else {
+ eventProducer.warnDefaultFontSetup(this);
+
+ // Go with a default base 12 configuration for AFP environments
+ FontCollection base12FontCollection = new AFPBase12FontCollection();
+ num = base12FontCollection.setup(num, fontInfo);
+ }
+ return num;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java b/src/java/org/apache/fop/afp/fonts/AFPFontInfo.java
index 42f333a66..0259435c6 100644
--- a/src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontInfo.java
@@ -17,30 +17,33 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
import java.util.List;
+
/**
* FontInfo contains meta information on fonts
*/
public class AFPFontInfo {
private AFPFont font;
- private List fontTriplets;
+ private List/*<FontTriplet>*/ tripletList;
/**
* Main constructor
+ *
* @param afpFont The AFP Font
- * @param fontTriplets List of font triplets to associate with this font
+ * @param tripletList List of font triplets to associate with this font
*/
- public AFPFontInfo(AFPFont afpFont, List fontTriplets) {
+ public AFPFontInfo(AFPFont afpFont, List/*<FontTriplet>*/ tripletList) {
this.font = afpFont;
- this.fontTriplets = fontTriplets;
+ this.tripletList = tripletList;
}
/**
* Returns the afp font
+ *
* @return the afp font
*/
public AFPFont getAFPFont() {
@@ -49,10 +52,11 @@ public class AFPFontInfo {
/**
* Returns the list of font triplets associated with this font.
+ *
* @return List of font triplets
*/
- public List getFontTriplets() {
- return fontTriplets;
+ public List/*<FontTriplet>*/ getFontTriplets() {
+ return tripletList;
}
}
diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java
index 0c190738c..16c341ac4 100644
--- a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
import java.io.File;
import java.io.FileNotFoundException;
@@ -31,8 +31,8 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.render.afp.modca.AFPConstants;
-import org.apache.fop.render.afp.tools.StructuredFieldReader;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.StructuredFieldReader;
/**
* The AFPFontReader is responsible for reading the font attributes from binary
@@ -56,7 +56,7 @@ public final class AFPFontReader {
/**
* Static logging instance
*/
- protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.fonts");
+ protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp.fonts");
/**
* Template used to convert lists to arrays.
diff --git a/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java
new file mode 100644
index 000000000..ee7a3c0eb
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.fonts;
+
+/**
+ * Holds the current page fonts
+ */
+public class AFPPageFonts extends java.util.HashMap {
+ private static final long serialVersionUID = -4991896259427109041L;
+
+ /**
+ * Default constructor
+ */
+ public AFPPageFonts() {
+ super();
+ }
+
+ /**
+ * Parameterized constructor
+ *
+ * @param fonts an existing set of afp page fonts
+ */
+ public AFPPageFonts(AFPPageFonts fonts) {
+ super(fonts);
+ }
+
+ /**
+ * Registers a font on the current page and returns font attributes
+ *
+ * @param fontName the internal font name
+ * @param font the AFPFont
+ * @param fontSize the font point size
+ * @return newly registered AFPFontAttributes
+ */
+ public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
+ String pageFontKey = fontName + "_" + fontSize;
+ AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
+ // Add to page font mapping if not already present
+ if (afpFontAttributes == null) {
+ afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
+ super.put(pageFontKey, afpFontAttributes);
+ int fontRef = super.size();
+ afpFontAttributes.setFontReference(fontRef);
+ }
+ return afpFontAttributes;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java
index f7680b15c..31b53bf08 100644
--- a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java
+++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -25,8 +25,8 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.render.afp.modca.AFPConstants;
-import org.apache.fop.render.afp.tools.StringUtils;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.StringUtils;
/**
* The IBM Font Object Content Architecture (FOCA) supports presentation
@@ -51,10 +51,10 @@ public class CharacterSet {
protected static final Log log = LogFactory.getLog(CharacterSet.class.getName());
/** default codepage */
- protected static final String DEFAULT_CODEPAGE = "T1V10500";
+ public static final String DEFAULT_CODEPAGE = "T1V10500";
/** default encoding */
- protected static final String DEFAULT_ENCODING = "Cp500";
+ public static final String DEFAULT_ENCODING = "Cp500";
private static final int MAX_NAME_LEN = 8;
diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java
index e13029717..88e99eccf 100644
--- a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java
+++ b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
/**
* The IBM Font Object Content Architecture (FOCA) supports presentation
diff --git a/src/java/org/apache/fop/render/afp/exceptions/FontRuntimeException.java b/src/java/org/apache/fop/afp/fonts/FontRuntimeException.java
index a54e4ad67..86e41707f 100644
--- a/src/java/org/apache/fop/render/afp/exceptions/FontRuntimeException.java
+++ b/src/java/org/apache/fop/afp/fonts/FontRuntimeException.java
@@ -17,13 +17,15 @@
/* $Id$ */
-package org.apache.fop.render.afp.exceptions;
+package org.apache.fop.afp.fonts;
/**
* A runtime exception for handling fatal errors in processing fonts.
* <p/>
*/
-public class FontRuntimeException extends NestedRuntimeException {
+public class FontRuntimeException extends RuntimeException {
+
+ private static final long serialVersionUID = -2217420523816384707L;
/**
* Constructs a FontRuntimeException with the specified message.
diff --git a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java
index d5beb5a33..aec220b40 100644
--- a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java
+++ b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
import org.apache.fop.fonts.Typeface;
@@ -28,7 +28,6 @@ public class FopCharacterSet extends CharacterSet {
/** The character set for this font */
private Typeface charSet = null;
- private int size = 0;
/**
* Constructor for the CharacterSetMetric object, the character set is used
@@ -36,19 +35,16 @@ public class FopCharacterSet extends CharacterSet {
* @param codePage the code page identifier
* @param encoding the encoding of the font
* @param name the character set name
- * @param size the font size
* @param charSet the fop character set
*/
public FopCharacterSet(
String codePage,
String encoding,
String name,
- int size,
Typeface charSet) {
super(codePage, encoding, name, null);
this.charSet = charSet;
- this.size = size * 1000;
}
/**
@@ -64,7 +60,7 @@ public class FopCharacterSet extends CharacterSet {
* @return the ascender value in millipoints
*/
public int getAscender() {
- return charSet.getAscender(size);
+ return charSet.getAscender(1);
}
/**
@@ -74,7 +70,7 @@ public class FopCharacterSet extends CharacterSet {
* @return the cap height value in millipoints
*/
public int getCapHeight() {
- return charSet.getCapHeight(size);
+ return charSet.getCapHeight(1);
}
/**
@@ -84,7 +80,7 @@ public class FopCharacterSet extends CharacterSet {
* @return the descender value in millipoints
*/
public int getDescender() {
- return charSet.getDescender(size);
+ return charSet.getDescender(1);
}
/**
@@ -116,7 +112,7 @@ public class FopCharacterSet extends CharacterSet {
* @return the typical height of characters
*/
public int getXHeight() {
- return charSet.getXHeight(size);
+ return charSet.getXHeight(1);
}
/**
@@ -126,7 +122,7 @@ public class FopCharacterSet extends CharacterSet {
* @return the width of the character
*/
public int getWidth(int character) {
- return charSet.getWidth(character, size);
+ return charSet.getWidth(character, 1);
}
/**
diff --git a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/afp/fonts/OutlineFont.java
index 71c5dfb6f..ac45a2467 100644
--- a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
+++ b/src/java/org/apache/fop/afp/fonts/OutlineFont.java
@@ -17,7 +17,8 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
+
/**
* A font defined as a set of lines and curves as opposed to a bitmap font. An
@@ -91,7 +92,7 @@ public class OutlineFont extends AFPFont {
* @return the ascender for the given size
*/
public int getAscender(int size) {
- return charSet.getAscender() / 1000 * size;
+ return charSet.getAscender() * size;
}
/**
@@ -102,7 +103,7 @@ public class OutlineFont extends AFPFont {
* @return the cap height for the given size
*/
public int getCapHeight(int size) {
- return charSet.getCapHeight() / 1000 * size;
+ return charSet.getCapHeight() * size;
}
/**
@@ -115,7 +116,7 @@ public class OutlineFont extends AFPFont {
* @return the descender for the given size
*/
public int getDescender(int size) {
- return charSet.getDescender() / 1000 * size;
+ return charSet.getDescender() * size;
}
/**
@@ -126,7 +127,7 @@ public class OutlineFont extends AFPFont {
* @return the x height for the given size
*/
public int getXHeight(int size) {
- return charSet.getXHeight() / 1000 * size;
+ return charSet.getXHeight() * size;
}
/**
@@ -136,7 +137,7 @@ public class OutlineFont extends AFPFont {
* @return the width of the character for the specified point size
*/
public int getWidth(int character, int size) {
- return charSet.getWidth(character) / 1000 * size;
+ return charSet.getWidth(character) * size;
}
/**
@@ -150,7 +151,7 @@ public class OutlineFont extends AFPFont {
public int[] getWidths(int size) {
int[] widths = charSet.getWidths();
for (int i = 0; i < widths.length; i++) {
- widths[i] = widths[i] / 1000 * size;
+ widths[i] = widths[i] * size;
}
return widths;
}
diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/afp/fonts/RasterFont.java
index 5c1696aa4..ddce2d4d5 100644
--- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
+++ b/src/java/org/apache/fop/afp/fonts/RasterFont.java
@@ -17,18 +17,14 @@
/* $Id$ */
-package org.apache.fop.render.afp.fonts;
+package org.apache.fop.afp.fonts;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.fo.properties.FixedLength;
-import org.apache.fop.render.afp.exceptions.FontRuntimeException;
-
/**
* A font where each character is stored as an array of pixels (a bitmap). Such
* fonts are not easily scalable, in contrast to vectored fonts. With this type
@@ -39,9 +35,10 @@ import org.apache.fop.render.afp.exceptions.FontRuntimeException;
public class RasterFont extends AFPFont {
/** Static logging instance */
- protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.fonts");
+ protected static final Log log = LogFactory.getLog("org.apache.fop.afp.fonts");
- private Map charSets = new HashMap();
+ private final Map/*<String,CharacterSet>*/ charSets
+ = new java.util.HashMap/*<String,CharacterSet>*/();
private CharacterSet charSet = null;
@@ -66,6 +63,9 @@ public class RasterFont extends AFPFont {
this.charSet = characterSet;
}
+ /** Describes the unit millipoint. */
+ public static final String MPT = "mpt";
+
/**
* Get the character set metrics for the specified point size.
*
@@ -77,7 +77,7 @@ public class RasterFont extends AFPFont {
String pointsize = String.valueOf(size / 1000);
CharacterSet csm = (CharacterSet) charSets.get(pointsize);
if (csm == null) {
- csm = (CharacterSet) charSets.get(size + FixedLength.MPT);
+ csm = (CharacterSet) charSets.get(size + MPT);
}
if (csm == null) {
// Get char set with nearest font size
@@ -85,7 +85,7 @@ public class RasterFont extends AFPFont {
for (Iterator it = charSets.entrySet().iterator(); it.hasNext();) {
Map.Entry me = (Map.Entry)it.next();
String key = (String)me.getKey();
- if (!key.endsWith(FixedLength.MPT)) {
+ if (!key.endsWith(MPT)) {
int mpt = Integer.parseInt(key) * 1000;
if (Math.abs(size - mpt) < distance) {
distance = Math.abs(size - mpt);
@@ -95,7 +95,7 @@ public class RasterFont extends AFPFont {
}
}
if (csm != null) {
- charSets.put(size + FixedLength.MPT, csm);
+ charSets.put(size + MPT, csm);
String msg = "No " + (size / 1000) + "pt font " + getFontName()
+ " found, substituted with " + pointsize + "pt font";
log.warn(msg);
@@ -154,7 +154,7 @@ public class RasterFont extends AFPFont {
* @return the ascender for the given point size
*/
public int getAscender(int size) {
- return getCharacterSet(size).getAscender();
+ return getCharacterSet(size).getAscender() * size;
}
/**
@@ -164,7 +164,7 @@ public class RasterFont extends AFPFont {
* @return the cap height for the specified point size
*/
public int getCapHeight(int size) {
- return getCharacterSet(size).getCapHeight();
+ return getCharacterSet(size).getCapHeight() * size;
}
/**
@@ -176,7 +176,7 @@ public class RasterFont extends AFPFont {
* @return the descender for the specified point size
*/
public int getDescender(int size) {
- return getCharacterSet(size).getDescender();
+ return getCharacterSet(size).getDescender() * size;
}
/**
@@ -186,7 +186,7 @@ public class RasterFont extends AFPFont {
* @return the x height for the given point size
*/
public int getXHeight(int size) {
- return getCharacterSet(size).getXHeight();
+ return getCharacterSet(size).getXHeight() * size;
}
/**
@@ -196,7 +196,7 @@ public class RasterFont extends AFPFont {
* @return the width for the given point size
*/
public int getWidth(int character, int size) {
- return getCharacterSet(size).getWidth(character);
+ return getCharacterSet(size).getWidth(character) * size;
}
/**
diff --git a/src/java/org/apache/fop/afp/fonts/package.html b/src/java/org/apache/fop/afp/fonts/package.html
new file mode 100644
index 000000000..74f8bf450
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.goca Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Graphics Object Content Architecture (GOCA) structured objects.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java b/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java
new file mode 100644
index 000000000..3d8495667
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * A base class encapsulating the structure of coordinate based GOCA objects
+ */
+public abstract class AbstractGraphicsCoord extends AbstractGraphicsDrawingOrder {
+
+ /** array of x/y coordinates */
+ protected int[] coords = null;
+
+ protected boolean relative = false;
+
+ /**
+ * Constructor
+ *
+ * @param coords the x/y coordinates for this object
+ */
+ public AbstractGraphicsCoord(int[] coords) {
+ if (coords == null) {
+ relative = true;
+ } else {
+ this.coords = coords;
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param coords the x/y coordinates for this object
+ * @param relative
+ */
+ public AbstractGraphicsCoord(int[] coords, boolean relative) {
+ this(coords);
+ this.relative = relative;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param x the x coordinate for this object
+ * @param y the y coordinate for this object
+ */
+ public AbstractGraphicsCoord(int x, int y) {
+ this(new int[] {x, y});
+ }
+
+ /**
+ * Constructor
+ *
+ * @param x1 the x1 coordinate for this object
+ * @param y1 the y1 coordinate for this object
+ * @param x2 the x2 coordinate for this object
+ * @param y2 the y2 coordinate for this object
+ */
+ public AbstractGraphicsCoord(int x1, int y1, int x2, int y2) {
+ this(new int[] {x1, y1, x2, y2});
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2 + (coords != null ? coords.length * 2 : 0);
+ }
+
+ /**
+ * Returns the coordinate data start index
+ *
+ * @return the coordinate data start index
+ */
+ int getCoordinateDataStartIndex() {
+ return 2;
+ }
+
+ /**
+ * Returns the coordinate data
+ *
+ * @return the coordinate data
+ */
+ byte[] getData() {
+ byte[] data = super.getData();
+ if (coords != null) {
+ addCoords(data, getCoordinateDataStartIndex());
+ }
+ return data;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ os.write(getData());
+ }
+
+ /**
+ * Adds the coordinates to the structured field data
+ *
+ * @param data the structured field data
+ * @param fromIndex the start index
+ */
+ protected void addCoords(byte[] data, int fromIndex) {
+ // X/Y POS
+ for (int i = 0; i < coords.length; i++, fromIndex += 2) {
+ byte[] coord = BinaryUtils.convert(coords[i], 2);
+ data[fromIndex] = coord[0];
+ data[fromIndex + 1] = coord[1];
+ }
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ String coordsStr = "";
+ for (int i = 0; i < coords.length; i++) {
+ coordsStr += (i % 2 == 0) ? "x" : "y";
+ coordsStr += (i / 2) + "=" + coords[i] + ",";
+ }
+ coordsStr = coordsStr.substring(0, coordsStr.length() - 1);
+ return getName() + "{" + coordsStr + "}";
+ }
+
+ /**
+ * Returns true if this is a relative drawing order
+ *
+ * @return true if this is a relative drawing order
+ */
+ protected boolean isRelative() {
+ return this.relative;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrder.java b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrder.java
new file mode 100644
index 000000000..0d8f793c0
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrder.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.goca;
+
+import org.apache.fop.afp.StructuredData;
+import org.apache.fop.afp.modca.AbstractAFPObject;
+
+/**
+ * A base GOCA drawing order
+ */
+public abstract class AbstractGraphicsDrawingOrder extends AbstractAFPObject
+ implements StructuredData {
+
+ /**
+ * Returns the order code of this structured field
+ *
+ * @return the order code of this structured field
+ */
+ abstract byte getOrderCode();
+
+ /**
+ * Returns the coordinate data
+ *
+ * @return the coordinate data
+ */
+ byte[] getData() {
+ int len = getDataLength();
+ byte[] data = new byte[len];
+ data[0] = getOrderCode();
+ data[1] = (byte)(len - 2);
+ return data;
+ }
+
+ /**
+ * Returns the short name of this GOCA object
+ *
+ * @return the short name of this GOCA object
+ */
+ public String getName() {
+ String className = getClass().getName();
+ return className.substring(className.lastIndexOf(".") + 1);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrderContainer.java b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrderContainer.java
new file mode 100644
index 000000000..34398b094
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrderContainer.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.afp.Completable;
+import org.apache.fop.afp.Startable;
+import org.apache.fop.afp.StructuredData;
+import org.apache.fop.afp.modca.AbstractNamedAFPObject;
+
+/**
+ * A base container of prepared structured AFP objects
+ */
+public abstract class AbstractGraphicsDrawingOrderContainer extends AbstractNamedAFPObject
+implements StructuredData, Completable, Startable {
+
+ /** list of objects contained within this container */
+ protected List/*<StructuredDataObject>*/ objects
+ = new java.util.ArrayList/*<StructuredDataObject>*/();
+
+ /** object is complete */
+ private boolean complete = false;
+
+ /** object has started */
+ private boolean started = false;
+
+ /**
+ * Default constructor
+ */
+ protected AbstractGraphicsDrawingOrderContainer() {
+ }
+
+ /**
+ * Named constructor
+ *
+ * @param name the name of the container
+ */
+ protected AbstractGraphicsDrawingOrderContainer(String name) {
+ super(name);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ setStarted(true);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ writeObjects(objects, os);
+ }
+
+ /**
+ * Adds a given graphics object to this container
+ *
+ * @param object the structured data object
+ */
+ public void addObject(StructuredData object) {
+ objects.add(object);
+ }
+
+ /**
+ * Adds all the contents of a given graphics container to this container
+ *
+ * @param graphicsContainer a graphics container
+ */
+ public void addAll(AbstractGraphicsDrawingOrderContainer graphicsContainer) {
+ Collection/*<StructuredDataObject>*/ objects = graphicsContainer.getObjects();
+ objects.addAll(objects);
+ }
+
+ /**
+ * Returns all the objects in this container
+ *
+ * @return all the objects in this container
+ */
+ private Collection getObjects() {
+ return this.objects;
+ }
+
+ /**
+ * Removes the last drawing order from this container and returns it
+ *
+ * @return the last drawing order from this container or null if empty
+ */
+ public StructuredData removeLast() {
+ int lastIndex = objects.size() - 1;
+ StructuredData object = null;
+ if (lastIndex > -1) {
+ object = (StructuredData)objects.get(lastIndex);
+ objects.remove(lastIndex);
+ }
+ return object;
+ }
+
+ /**
+ * Returns the current data length
+ *
+ * @return the current data length of this container including
+ * all enclosed objects (and their containers)
+ */
+ public int getDataLength() {
+ int dataLen = 0;
+ Iterator it = objects.iterator();
+ while (it.hasNext()) {
+ dataLen += ((StructuredData)it.next()).getDataLength();
+ }
+ return dataLen;
+ }
+
+ /** {@inheritDoc} */
+ public void setComplete(boolean complete) {
+ Iterator it = objects.iterator();
+ while (it.hasNext()) {
+ Object object = it.next();
+ if (object instanceof Completable) {
+ ((Completable)object).setComplete(true);
+ }
+ }
+ this.complete = true;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isComplete() {
+ return this.complete;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ /** {@inheritDoc} */
+ public void setStarted(boolean started) {
+ this.started = started;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsAreaBegin.java b/src/java/org/apache/fop/afp/goca/GraphicsAreaBegin.java
new file mode 100644
index 000000000..fc66fa8cd
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsAreaBegin.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The beginning of a filled region (graphics area).
+ */
+public class GraphicsAreaBegin extends AbstractGraphicsDrawingOrder {
+
+ private static final int RES1 = 1;
+ private static final int BOUNDARY = 2;
+ private static final int NO_BOUNDARY = 0;
+
+ /** draw boundary lines around this area */
+ private boolean drawBoundary = false;
+
+ /**
+ * Sets whether boundary lines are drawn
+ *
+ * @param drawBoundaryLines whether boundary lines are drawn
+ */
+ public void setDrawBoundaryLines(boolean drawBoundaryLines) {
+ this.drawBoundary = drawBoundaryLines;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ getOrderCode(), // GBAR order code
+ (byte)(RES1 + (drawBoundary ? BOUNDARY : NO_BOUNDARY))
+ };
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsAreaBegin{drawBoundary=" + drawBoundary + "}";
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x68;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsAreaEnd.java b/src/java/org/apache/fop/afp/goca/GraphicsAreaEnd.java
new file mode 100644
index 000000000..12f14bfa4
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsAreaEnd.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The end of a filled region (graphics area).
+ */
+public class GraphicsAreaEnd extends AbstractGraphicsDrawingOrder {
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ getOrderCode(), // GEAR order code
+ 0x00, // LENGTH
+ };
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsAreaEnd";
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x60;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsBox.java b/src/java/org/apache/fop/afp/goca/GraphicsBox.java
new file mode 100644
index 000000000..945697ec2
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsBox.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A GOCA graphics rectangular box
+ */
+public final class GraphicsBox extends AbstractGraphicsCoord {
+
+ /**
+ * Constructor
+ *
+ * @param coords the x/y coordinates for this object
+ */
+ public GraphicsBox(int[] coords) {
+ super(coords);
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 12;
+ }
+
+ /** {@inheritDoc} */
+ int getCoordinateDataStartIndex() {
+ return 4;
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return (byte)0xC0;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = (byte)0x20; // CONTROL draw control flags
+ data[3] = 0x00; // reserved
+
+ os.write(data);
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsChainedSegment.java b/src/java/org/apache/fop/afp/goca/GraphicsChainedSegment.java
new file mode 100644
index 000000000..8a92db296
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsChainedSegment.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * A GOCA graphics segment
+ */
+public final class GraphicsChainedSegment extends AbstractGraphicsDrawingOrderContainer {
+
+ /** The maximum segment data length */
+ protected static final int MAX_DATA_LEN = 8192;
+
+ private byte[] predecessorNameBytes;
+
+ /**
+ * Main constructor
+ *
+ * @param name
+ * the name of this graphics segment
+ */
+ public GraphicsChainedSegment(String name) {
+ super(name);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name
+ * the name of this graphics segment
+ * @param predecessorNameBytes
+ * the name of the predecessor in this chain
+ */
+ public GraphicsChainedSegment(String name, byte[] predecessorNameBytes) {
+ super(name);
+ this.predecessorNameBytes = predecessorNameBytes;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 14 + super.getDataLength();
+ }
+
+ private static final byte APPEND_NEW_SEGMENT = 0;
+// private static final byte PROLOG = 4;
+// private static final byte APPEND_TO_EXISING = 48;
+
+ private static final int NAME_LENGTH = 4;
+
+ /** {@inheritDoc} */
+ protected int getNameLength() {
+ return NAME_LENGTH;
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x70;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[14];
+ data[0] = getOrderCode(); // BEGIN_SEGMENT
+ data[1] = 0x0C; // Length of following parameters
+
+ // segment name
+ byte[] nameBytes = getNameBytes();
+ System.arraycopy(nameBytes, 0, data, 2, NAME_LENGTH);
+
+ data[6] = 0x00; // FLAG1 (ignored)
+ data[7] = APPEND_NEW_SEGMENT;
+
+ int dataLength = super.getDataLength();
+ byte[] len = BinaryUtils.convert(dataLength, 2);
+ data[8] = len[0]; // SEGL
+ data[9] = len[1];
+
+ // P/S NAME (predecessor name)
+ if (predecessorNameBytes != null) {
+ System.arraycopy(predecessorNameBytes, 0, data, 10, NAME_LENGTH);
+ }
+ os.write(data);
+
+ writeObjects(objects, os);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsChainedSegment(name=" + super.getName() + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java b/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java
new file mode 100644
index 000000000..70039d167
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.fop.afp.AFPConstants;
+
+/**
+ * A GOCA graphics string
+ */
+public class GraphicsCharacterString extends AbstractGraphicsCoord {
+
+ /** Up to 255 bytes of character data */
+ protected static final int MAX_STR_LEN = 255;
+
+ /** the string to draw */
+ protected final String str;
+
+ /**
+ * Constructor (absolute positioning)
+ *
+ * @param str the character string
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public GraphicsCharacterString(String str, int x, int y) {
+ super(x, y);
+ this.str = truncate(str);
+ }
+
+ /**
+ * Constructor (relative positioning)
+ *
+ * @param str the character string
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public GraphicsCharacterString(String str) {
+ super(null);
+ this.str = truncate(str);
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ if (isRelative()) {
+ return (byte)0x83;
+ } else {
+ return (byte)0xC3;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return super.getDataLength() + str.length();
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ byte[] strData = getStringAsBytes();
+ System.arraycopy(strData, 0, data, 6, strData.length);
+ os.write(data);
+ }
+
+ /**
+ * Truncates the string as necessary
+ *
+ * @param str a character string
+ * @return a possibly truncated string
+ */
+ private String truncate(String str) {
+ if (str.length() > MAX_STR_LEN) {
+ str = str.substring(0, MAX_STR_LEN);
+ log.warn("truncated character string, longer than " + MAX_STR_LEN + " chars");
+ }
+ return str;
+ }
+
+ /**
+ * Returns the text string as an encoded byte array
+ *
+ * @return the text string as an encoded byte array
+ */
+ private byte[] getStringAsBytes() throws UnsupportedEncodingException {
+ return str.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsCharacterString{"
+ + (coords != null ? "x=" + coords[0] + ", y=" + coords[1] : "")
+ + "str='" + str + "'" + "}";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsData.java b/src/java/org/apache/fop/afp/goca/GraphicsData.java
new file mode 100644
index 000000000..89be8dd94
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsData.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.StructuredData;
+import org.apache.fop.afp.util.BinaryUtils;
+import org.apache.fop.afp.util.StringUtils;
+
+/**
+ * A GOCA graphics data
+ */
+public final class GraphicsData extends AbstractGraphicsDrawingOrderContainer {
+
+ /** the maximum graphics data length */
+ public static final int MAX_DATA_LEN = 32767;
+
+ /** the graphics segment */
+ private GraphicsChainedSegment currentSegment = null;
+
+ /**
+ * Main constructor
+ */
+ public GraphicsData() {
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 8 + super.getDataLength();
+ }
+
+ /**
+ * Returns a new segment name
+ *
+ * @return a new segment name
+ */
+ public String createSegmentName() {
+ return StringUtils.lpad(String.valueOf(
+ (super.objects != null ? super.objects.size() : 0) + 1),
+ '0', 4);
+ }
+
+ /**
+ * Creates a new graphics segment
+ *
+ * @return a newly created graphics segment
+ */
+ public GraphicsChainedSegment newSegment() {
+ String segmentName = createSegmentName();
+ if (currentSegment == null) {
+ currentSegment = new GraphicsChainedSegment(segmentName);
+ } else {
+ currentSegment.setComplete(true);
+ currentSegment = new GraphicsChainedSegment(segmentName, currentSegment.getNameBytes());
+ }
+ super.addObject(currentSegment);
+ return currentSegment;
+ }
+
+ /** {@inheritDoc} */
+ public void addObject(StructuredData object) {
+ if (currentSegment == null
+ || (currentSegment.getDataLength() + object.getDataLength())
+ >= GraphicsChainedSegment.MAX_DATA_LEN) {
+ newSegment();
+ }
+ currentSegment.addObject(object);
+ }
+
+ /**
+ * Removes the current segment from this graphics data
+ *
+ * @return the current segment from this graphics data
+ */
+ public StructuredData removeCurrentSegment() {
+ this.currentSegment = null;
+ return super.removeLast();
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[9];
+ copySF(data, SF_CLASS, Type.DATA, Category.GRAPHICS);
+ int dataLength = getDataLength();
+ byte[] len = BinaryUtils.convert(dataLength, 2);
+ data[1] = len[0]; // Length byte 1
+ data[2] = len[1]; // Length byte 2
+ os.write(data);
+
+ writeObjects(objects, os);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsData";
+ }
+
+ /**
+ * Adds the given segment to this graphics data
+ *
+ * @param segment a graphics chained segment
+ */
+ public void addSegment(GraphicsChainedSegment segment) {
+ currentSegment = segment;
+ super.addObject(currentSegment);
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsFillet.java b/src/java/org/apache/fop/afp/goca/GraphicsFillet.java
new file mode 100644
index 000000000..294be6d9b
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsFillet.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+/**
+ * A GOCA graphics curved tangential line to a specified set of
+ * straight lines drawn from the given position or current position
+ */
+public final class GraphicsFillet extends AbstractGraphicsCoord {
+
+ /**
+ * Constructor
+ *
+ * @param coords the x/y coordinates for this object
+ */
+ public GraphicsFillet(int[] coords, boolean relative) {
+ super(coords, relative);
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ if (isRelative()) {
+ return (byte)0x85;
+ } else {
+ return (byte)0xC5;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsFullArc.java b/src/java/org/apache/fop/afp/goca/GraphicsFullArc.java
new file mode 100644
index 000000000..a4b6916ae
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsFullArc.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * A GOCA graphics arc (circle/ellipse)
+ */
+public class GraphicsFullArc extends AbstractGraphicsCoord {
+
+ /** the integer portion of the multiplier */
+ private final int mh;
+
+ /** the fractional portion of the multiplier */
+ private final int mhr;
+
+ /**
+ * Constructor
+ *
+ * @param x the x coordinate of the center of the circle/ellipse
+ * @param y the y coordinate of the center of the circle/ellipse
+ * @param mh the integer portion of the multiplier
+ * @param mhr the fractional portion of the multiplier
+ */
+ public GraphicsFullArc(int x, int y, int mh, int mhr) {
+ super(x, y);
+ this.mh = mh;
+ this.mhr = mhr;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 8;
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return (byte)0xC7;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+
+ // integer portion of multiplier
+ data[6] = BinaryUtils.convert(mh, 1)[0];
+
+ // fractional portion of multiplier
+ data[7] = BinaryUtils.convert(mhr, 1)[0];
+
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsFullArc{"
+ + ", centerx=" + coords[0]
+ + ", centery=" + coords[1]
+ + ", mh=" + mh
+ + ", mhr=" + mhr
+ + "}";
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsImage.java b/src/java/org/apache/fop/afp/goca/GraphicsImage.java
new file mode 100644
index 000000000..3b1dafeea
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsImage.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * A GOCA Image
+ */
+public class GraphicsImage extends AbstractGraphicsDrawingOrder {
+
+ /** the maximum image data length */
+ public static final short MAX_DATA_LEN = 255;
+
+ /** x coordinate */
+ private final int x;
+
+ /** y coordinate */
+ private final int y;
+
+ /** width */
+ private final int width;
+
+ /** height */
+ private final int height;
+
+ /** image data */
+ private final byte[] imageData;
+
+ /**
+ * Main constructor
+ *
+ * @param x the x coordinate of the image
+ * @param y the y coordinate of the image
+ * @param width the image width
+ * @param height the image height
+ * @param imageData the image data
+ */
+ public GraphicsImage(int x, int y, int width, int height, byte[] imageData) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.imageData = imageData;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ //TODO:
+ return 0;
+ }
+
+ byte getOrderCode() {
+ return (byte)0xD1;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] xcoord = BinaryUtils.convert(x, 2);
+ byte[] ycoord = BinaryUtils.convert(y, 2);
+ byte[] w = BinaryUtils.convert(width, 2);
+ byte[] h = BinaryUtils.convert(height, 2);
+ byte[] startData = new byte[] {
+ getOrderCode(), // GBIMG order code
+ (byte) 0x0A, // LENGTH
+ xcoord[0],
+ xcoord[1],
+ ycoord[0],
+ ycoord[1],
+ 0x00, // FORMAT
+ 0x00, // RES
+ w[0], // WIDTH
+ w[1], //
+ h[0], // HEIGHT
+ h[1] //
+ };
+ os.write(startData);
+
+ byte[] dataHeader = new byte[] {
+ (byte) 0x92 // GIMD
+ };
+ final int lengthOffset = 1;
+ writeChunksToStream(imageData, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+
+ byte[] endData = new byte[] {
+ (byte) 0x93, // GEIMG order code
+ 0x00 // LENGTH
+ };
+ os.write(endData);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsImage{x=" + x
+ + ", y=" + y
+ + ", width=" + width
+ + ", height=" + height
+ + "}";
+ }
+}
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsLine.java b/src/java/org/apache/fop/afp/goca/GraphicsLine.java
new file mode 100644
index 000000000..17bd43ce0
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsLine.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A GOCA graphics straight line drawn from the
+ * given absolute position
+ */
+public class GraphicsLine extends AbstractGraphicsCoord {
+
+ /**
+ * Constructor
+ *
+ * @param coords the x/y coordinates for this object
+ *
+ * @param relative is this a relative drawing order
+ */
+ public GraphicsLine(int[] coords, boolean relative) {
+ super(coords, relative);
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ if (isRelative()) {
+ return (byte)0x81;
+ } else {
+ return (byte)0xC1;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ os.write(data);
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetArcParameters.java b/src/java/org/apache/fop/afp/goca/GraphicsSetArcParameters.java
new file mode 100644
index 000000000..693cf21a9
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetArcParameters.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+/**
+ * Sets the arc parameters for a GOCA graphics arc (circle/ellipse)
+ */
+public class GraphicsSetArcParameters extends AbstractGraphicsCoord {
+
+ /**
+ * Constructor
+ *
+ * @param xmaj x coordinate of the major axis point
+ * @param ymin y coordinate of the minor axis point
+ * @param xmin x coordinate of the minor axis point
+ * @param ymaj y coordinate of the major axis point
+ */
+ public GraphicsSetArcParameters(int xmaj, int ymin, int xmin, int ymaj) {
+ super(xmaj, ymin, xmin, ymaj);
+ }
+
+ /** {@inheritDoc} */
+ protected byte getOrderCode() {
+ return 0x22;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return getName() + "{xmaj=" + coords[0]
+ + ",ymin=" + coords[1]
+ + ",xmin=" + coords[2]
+ + ",ymaj=" + coords[3] + "}";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetCharacterSet.java b/src/java/org/apache/fop/afp/goca/GraphicsSetCharacterSet.java
new file mode 100644
index 000000000..b3d1158fe
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetCharacterSet.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * Sets the current character set (font) to be used for following graphics strings
+ */
+public class GraphicsSetCharacterSet extends AbstractGraphicsDrawingOrder {
+
+ /** font character set reference */
+ private final int fontReference;
+
+ /**
+ * @param fontReference character set font reference
+ */
+ public GraphicsSetCharacterSet(int fontReference) {
+ this.fontReference = fontReference;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ getOrderCode(), // GSCS order code
+ BinaryUtils.convert(fontReference)[0]
+ };
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsSetCharacterSet(" + fontReference + ")";
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x38;
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetCurrentPosition.java b/src/java/org/apache/fop/afp/goca/GraphicsSetCurrentPosition.java
new file mode 100644
index 000000000..675c2f034
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetCurrentPosition.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+/**
+ * Sets the current painting position of the graphics object
+ */
+public class GraphicsSetCurrentPosition extends AbstractGraphicsCoord {
+
+ /**
+ * Constructor
+ *
+ * @param coords the x/y coordinates for this object
+ */
+ public GraphicsSetCurrentPosition(int[] coords) {
+ super(coords);
+ }
+
+ /** {@inheritDoc} */
+ protected byte getOrderCode() {
+ return (byte)0x21;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetLineType.java b/src/java/org/apache/fop/afp/goca/GraphicsSetLineType.java
new file mode 100644
index 000000000..b6512f57c
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetLineType.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Sets the value of the current line type attribute when stroking GOCA shapes (structured fields)
+ */
+public class GraphicsSetLineType extends AbstractGraphicsDrawingOrder {
+
+ /** the default line type */
+ public static final byte DEFAULT = 0x00; // normally SOLID
+
+ /** the default line type */
+ public static final byte DOTTED = 0x01;
+
+ /** short dashed line type */
+ public static final byte SHORT_DASHED = 0x02;
+
+ /** dashed dotted line type */
+ public static final byte DASH_DOT = 0x03;
+
+ /** double dotted line type */
+ public static final byte DOUBLE_DOTTED = 0x04;
+
+ /** long dashed line type */
+ public static final byte LONG_DASHED = 0x05;
+
+ /** dash double dotted line type */
+ public static final byte DASH_DOUBLE_DOTTED = 0x06;
+
+ /** solid line type */
+ public static final byte SOLID = 0x07;
+
+ /** invisible line type */
+ public static final byte INVISIBLE = 0x08;
+
+ /** line type */
+ private byte type = DEFAULT;
+
+ /**
+ * Main constructor
+ *
+ * @param type line type
+ */
+ public GraphicsSetLineType(byte type) {
+ this.type = type;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ getOrderCode(), // GSLW order code
+ type // line type
+ };
+ os.write(data);
+ }
+
+ private static final String[] TYPES = {
+ "default (solid)", "dotted", "short dashed", "dash dotted", "double dotted",
+ "long dashed", "dash double dotted", "solid", "invisible"
+ };
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsSetLineType{type=" + TYPES[type] + "}";
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x18;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java b/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java
new file mode 100644
index 000000000..96eac0677
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Sets the line width to use when stroking GOCA shapes (structured fields)
+ */
+public class GraphicsSetLineWidth extends AbstractGraphicsDrawingOrder {
+
+ /** line width multiplier */
+ private int multiplier = 1;
+
+ /**
+ * Main constructor
+ *
+ * @param multiplier the line width multiplier
+ */
+ public GraphicsSetLineWidth(int multiplier) {
+ this.multiplier = multiplier;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ getOrderCode(), // GSLW order code
+ (byte)multiplier // MH (line-width)
+ };
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsSetLineWidth{multiplier=" + multiplier + "}";
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x19;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetMix.java b/src/java/org/apache/fop/afp/goca/GraphicsSetMix.java
new file mode 100644
index 000000000..dfb5ae0d2
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetMix.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Sets the foreground mix mode.
+ */
+public class GraphicsSetMix extends AbstractGraphicsDrawingOrder {
+
+ public static final byte MODE_DEFAULT = 0x00;
+ public static final byte MODE_OVERPAINT = 0x02;
+
+ /** the mix mode value */
+ private final byte mode;
+
+ /**
+ * Main constructor
+ *
+ * @param mode the mix mode value
+ */
+ public GraphicsSetMix(byte mode) {
+ this.mode = mode;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ 0x0C, // GSMX order code
+ mode // MODE (mix mode value)
+ };
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsSetMix{mode=" + mode + "}";
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x0C;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetPatternSymbol.java b/src/java/org/apache/fop/afp/goca/GraphicsSetPatternSymbol.java
new file mode 100644
index 000000000..3d6cf7cd6
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetPatternSymbol.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Sets the pattern symbol to use when filling following GOCA structured fields
+ */
+public class GraphicsSetPatternSymbol extends AbstractGraphicsDrawingOrder {
+
+ /** dotted density 1 */
+ public static final byte DOTTED_DENSITY_1 = 0x01;
+
+ /** dotted density 2 */
+ public static final byte DOTTED_DENSITY_2 = 0x02;
+
+ /** dotted density 3 */
+ public static final byte DOTTED_DENSITY_3 = 0x03;
+
+ /** dotted density 4 */
+ public static final byte DOTTED_DENSITY_4 = 0x04;
+
+ /** dotted density 5 */
+ public static final byte DOTTED_DENSITY_5 = 0x05;
+
+ /** dotted density 6 */
+ public static final byte DOTTED_DENSITY_6 = 0x06;
+
+ /** dotted density 7 */
+ public static final byte DOTTED_DENSITY_7 = 0x07;
+
+ /** dotted density 8 */
+ public static final byte DOTTED_DENSITY_8 = 0x08;
+
+ /** dotted density 9 */
+ public static final byte VERTICAL_LINES = 0x09;
+
+ /** horizontal lines */
+ public static final byte HORIZONTAL_LINES = 0x0A;
+
+ /** diagonal lines, bottom left to top right 1 */
+ public static final byte DIAGONAL_LINES_BLTR_1 = 0x0B;
+
+ /** diagonal lines, bottom left to top right 2 */
+ public static final byte DIAGONAL_LINES_BLTR_2 = 0x0C;
+
+ /** diagonal lines, top left to bottom right 1 */
+ public static final byte DIAGONAL_LINES_TLBR_1 = 0x0D;
+
+ /** diagonal lines, top left to bottom right 2 */
+ public static final byte DIAGONAL_LINES_TLBR_2 = 0x0E;
+
+ /** no fill */
+ public static final byte NO_FILL = 0x0F;
+
+ /** solid fill */
+ public static final byte SOLID_FILL = 0x10;
+
+ /** blank (same as no fill) */
+ public static final byte BLANK = 0x40; // processed same as NO_FILL
+
+ /** the graphics pattern symbol to use */
+ private final byte pattern;
+
+ /**
+ * Main constructor
+ *
+ * @param symb the pattern symbol to use
+ */
+ public GraphicsSetPatternSymbol(byte pattern) {
+ this.pattern = pattern;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ getOrderCode(), // GSPT order code
+ pattern
+ };
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsSetPatternSymbol(fill="
+ + (pattern == SOLID_FILL ? true : false) + ")";
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return 0x28;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java b/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java
new file mode 100644
index 000000000..05a6ee5d1
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.goca;
+
+import java.awt.Color;
+import java.awt.color.ColorSpace;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Sets the current processing color for the following GOCA structured fields
+ */
+public class GraphicsSetProcessColor extends AbstractGraphicsDrawingOrder {
+
+ private final Color color;
+
+ private final float[] colorComponents;
+
+ /**
+ * Main constructor
+ *
+ * @param color the color to set
+ */
+ public GraphicsSetProcessColor(Color color) {
+ this.color = color;
+ this.colorComponents = color.getColorComponents(null);
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 12 + colorComponents.length;
+ }
+
+ /** {@inheritDoc} */
+ byte getOrderCode() {
+ return (byte)0xB2;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+
+ // COLSPCE
+ byte colspace;
+ int colSpaceType = color.getColorSpace().getType();
+ if (colSpaceType == ColorSpace.TYPE_CMYK) {
+ colspace = 0x04;
+ } else if (colSpaceType == ColorSpace.TYPE_RGB) {
+ colspace = 0x01;
+ } else {
+ log.error("unsupported colorspace " + colSpaceType);
+ colspace = 0x01;
+ }
+
+ // COLSIZE(S)
+ byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00};
+ for (int i = 0; i < colorComponents.length; i++) {
+ colsizes[i] = (byte)8;
+ }
+
+ int len = getDataLength();
+ byte[] data = new byte[len];
+ data[0] = getOrderCode(); // GSPCOL order code
+ data[1] = (byte)(len - 2); // LEN
+ data[2] = 0x00; // reserved; must be zero
+ data[3] = colspace; // COLSPCE
+ data[4] = 0x00; // reserved; must be zero
+ data[5] = 0x00; // reserved; must be zero
+ data[6] = 0x00; // reserved; must be zero
+ data[7] = 0x00; // reserved; must be zero
+ data[8] = colsizes[0]; // COLSIZE(S)
+ data[9] = colsizes[1];
+ data[10] = colsizes[2];
+ data[11] = colsizes[3];
+
+ // COLVALUE(S)
+ for (int i = 0; i < colorComponents.length; i++) {
+ data[i + 12] = (byte)(colorComponents[i] * 255);
+ }
+
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsSetProcessColor(col=" + color + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/package.html b/src/java/org/apache/fop/afp/goca/package.html
new file mode 100644
index 000000000..539be8d13
--- /dev/null
+++ b/src/java/org/apache/fop/afp/goca/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.fonts Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP font related classes.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java b/src/java/org/apache/fop/afp/ioca/ImageCellPosition.java
index c0b28904d..97489a9b1 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageCellPosition.java
@@ -17,11 +17,13 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.ioca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+
+import org.apache.fop.afp.modca.AbstractAFPObject;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The IM Image Cell Position structured field specifies the placement,
@@ -29,38 +31,27 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class ImageCellPosition extends AbstractAFPObject {
- /**
- * Offset of image cell in X direction
- */
+ /** offset of image cell in X direction */
private int xOffset = 0;
- /**
- * Offset of image cell in Y direction
- */
+ /** offset of image cell in Y direction */
private int yOffset = 0;
- /**
- * Size of image cell in X direction
- */
- private byte[] xSize = new byte[] {(byte)0xFF, (byte)0xFF};
+ /** size of image cell in X direction */
+ private final byte[] xSize = new byte[] {(byte)0xFF, (byte)0xFF};
- /**
- * Size of image cell in Y direction
- */
- private byte[] ySize = new byte[] {(byte)0xFF, (byte)0xFF};
+ /** size of image cell in Y direction */
+ private final byte[] ySize = new byte[] {(byte)0xFF, (byte)0xFF};
- /**
- * Size of fill rectangle in X direction
- */
- private byte[] xFillSize = new byte[] {(byte)0xFF, (byte)0xFF};
+ /** size of fill rectangle in X direction */
+ private final byte[] xFillSize = new byte[] {(byte)0xFF, (byte)0xFF};
- /**
- * Size of fill rectangle in Y direction
- */
- private byte[] yFillSize = new byte[] {(byte)0xFF, (byte)0xFF};
+ /** size of fill rectangle in Y direction */
+ private final byte[] yFillSize = new byte[] {(byte)0xFF, (byte)0xFF};
/**
- * Constructor for the ImageCellPosition
+ * Main Constructor
+ *
* @param x The offset of image cell in X direction
* @param y The offset of image cell in Y direction
*/
@@ -69,26 +60,14 @@ public class ImageCellPosition extends AbstractAFPObject {
yOffset = y;
}
- /**
- * Accessor method to write the AFP datastream for the Image Cell Position
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occurred
- */
- public void writeDataStream(OutputStream os) throws IOException {
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[21];
+ copySF(data, Type.POSITION, Category.IM_IMAGE);
- data[0] = 0x5A;
-
- data[1] = 0x00;
+ data[1] = 0x00; // length
data[2] = 0x14;
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xAC;
- data[5] = (byte) 0x7B;
- data[6] = 0x00;
- data[7] = 0x00;
- data[8] = 0x00;
-
/**
* Specifies the offset along the Xp direction, in image points,
* of this image cell from the IM image object area origin.
@@ -125,6 +104,7 @@ public class ImageCellPosition extends AbstractAFPObject {
* of this image cell. A value of X'FFFF' indicates that the
* default extent specified in bytes 28 and 29 of the Image
* Input Descriptor (IID) is to be used.
+ *
* @param xcSize The size to set.
*/
public void setXSize(int xcSize) {
@@ -141,6 +121,7 @@ public class ImageCellPosition extends AbstractAFPObject {
* be used as the fill rectangle X-extent. The fill rectangle is
* filled in the X direction by repeating the image cell in the
* X direction. The image cell can be truncated to fit the rectangle.
+ *
* @param size The size to set.
*/
public void setXFillSize(int size) {
@@ -154,6 +135,7 @@ public class ImageCellPosition extends AbstractAFPObject {
* of this image cell. A value of X'FFFF' indicates that the
* default extent specified in bytes 30 and 31 of the Image
* Input Descriptor (IID) is to be used.
+ *
* @param size The size to set.
*/
public void setYSize(int size) {
@@ -170,6 +152,7 @@ public class ImageCellPosition extends AbstractAFPObject {
* be used as the fill rectangle Y-extent. The fill rectangle is
* filled in the Y direction by repeating the image cell in the
* Y direction. The image cell can be truncated to fit the rectangle.
+ *
* @param size The size to set.
*/
public void setYFillSize(int size) {
diff --git a/src/java/org/apache/fop/afp/ioca/ImageContent.java b/src/java/org/apache/fop/afp/ioca/ImageContent.java
new file mode 100644
index 000000000..40e51578b
--- /dev/null
+++ b/src/java/org/apache/fop/afp/ioca/ImageContent.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.ioca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.AbstractStructuredObject;
+
+/**
+ * An IOCA Image Content
+ */
+public class ImageContent extends AbstractStructuredObject {
+
+ /**
+ * The CCITT T.4 Group 3 Coding Standard (G3 MH-Modified Huffman) is a
+ * compression method standardized by the International Telegraph and
+ * Telephone Consultative Committee (CCITT) for facsimile. It enables
+ * one-dimensional compression.
+ */
+ public static final byte COMPID_G3_MH = (byte)0x80;
+
+ /**
+ * The CCITT T.4 Group 3 Coding Option (G3 MR-Modified READ) is a
+ * compression method standardized by the International Telegraph and
+ * Telephone Consultative Committee (CCITT) for facsimile. It enables
+ * two-dimensional compression.
+ */
+ public static final byte COMPID_G3_MR = (byte)0x81;
+
+ /**
+ * The CCITT T.6 Group 4 Coding Standard (G4 MMR-Modified Modified READ) is a
+ * compression method standardized by the International Telegraph and
+ * Telephone Consultative Committee (CCITT) for facsimile. It enables
+ * two-dimensional compression.
+ */
+ public static final byte COMPID_G3_MMR = (byte)0x82;
+
+ /** the image size parameter */
+ private ImageSizeParameter imageSizeParameter = null;
+
+ /** the image encoding */
+ private byte encoding = (byte)0x03;
+
+ /** the image ide size */
+ private byte size = 1;
+
+ /** the image compression */
+ private byte compression = (byte)0xC0;
+
+ /** the image color model */
+ private byte colorModel = (byte)0x01;
+
+ /** the image data */
+ private byte[] data;
+
+ /**
+ * Main Constructor
+ */
+ public ImageContent() {
+ }
+
+ /**
+ * Sets the image size parameter
+ *
+ * @param imageSizeParameter the image size parameter.
+ */
+ public void setImageSizeParameter(ImageSizeParameter imageSizeParameter) {
+ this.imageSizeParameter = imageSizeParameter;
+ }
+
+ /**
+ * Sets the image encoding.
+ *
+ * @param enc The image encoding.
+ */
+ public void setImageEncoding(byte enc) {
+ this.encoding = enc;
+ }
+
+ /**
+ * Sets the image compression.
+ *
+ * @param comp The image compression.
+ */
+ public void setImageCompression(byte comp) {
+ this.compression = comp;
+ }
+
+ /**
+ * Sets the image IDE size.
+ *
+ * @param s The IDE size.
+ */
+ public void setImageIDESize(byte s) {
+ this.size = s;
+ }
+
+ /**
+ * Sets the image IDE color model.
+ *
+ * @param color the IDE color model.
+ */
+ public void setImageIDEColorModel(byte color) {
+ this.colorModel = color;
+ }
+
+ /**
+ * Set the image data (can be byte array or inputstream)
+ *
+ * @param imageData the image data
+ */
+ public void setImageData(byte[] imageData) {
+ this.data = imageData;
+ }
+
+ private static final int MAX_DATA_LEN = 65535;
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ if (imageSizeParameter != null) {
+ imageSizeParameter.writeToStream(os);
+ }
+
+ // TODO convert to triplet/parameter class
+ os.write(getImageEncodingParameter());
+
+ os.write(getImageIDESizeParameter());
+
+ os.write(getIDEStructureParameter());
+
+ os.write(getExternalAlgorithmParameter());
+
+ final byte[] dataHeader = new byte[] {
+ (byte)0xFE, // ID
+ (byte)0x92, // ID
+ 0x00, // length
+ 0x00 // length
+ };
+ final int lengthOffset = 2;
+
+ // Image Data
+ if (data != null) {
+ writeChunksToStream(data, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ final byte[] startData = new byte[] {
+ (byte)0x91, // ID
+ 0x01, // Length
+ (byte)0xff, // Object Type = IOCA Image Object
+ };
+ os.write(startData);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ final byte[] endData = new byte[] {
+ (byte)0x93, // ID
+ 0x00, // Length
+ };
+ os.write(endData);
+ }
+
+ /**
+ * Helper method to return the image encoding parameter.
+ *
+ * @return byte[] The data stream.
+ */
+ private byte[] getImageEncodingParameter() {
+ final byte[] encodingData = new byte[] {
+ (byte)0x95, // ID
+ 0x02, // Length
+ encoding,
+ 0x01, // RECID
+ };
+ return encodingData;
+ }
+
+ /**
+ * Helper method to return the external algorithm parameter.
+ *
+ * @return byte[] The data stream.
+ */
+ private byte[] getExternalAlgorithmParameter() {
+ if (encoding == (byte)0x83 && compression != 0) {
+ final byte[] extAlgData = new byte[] {
+ (byte)0x95, // ID
+ 0x00, // Length
+ 0x10, // ALGTYPE = Compression Algorithm
+ 0x00, // Reserved
+ (byte)0x83, // COMPRID = JPEG
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Reserved
+ compression, // MARKER
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Reserved
+ };
+ extAlgData[1] = (byte)(extAlgData.length - 2);
+ return extAlgData;
+ }
+ return new byte[0];
+ }
+
+ /**
+ * Helper method to return the image encoding parameter.
+ *
+ * @return byte[] The data stream.
+ */
+ private byte[] getImageIDESizeParameter() {
+ final byte[] ideSizeData = new byte[] {
+ (byte)0x96, // ID
+ 0x01, // Length
+ size,
+ };
+ return ideSizeData;
+ }
+
+ /**
+ * Helper method to return the external algorithm parameter.
+ *
+ * @return byte[] The data stream.
+ */
+ private byte[] getIDEStructureParameter() {
+ if (colorModel != 0 && size == 24) {
+ final byte bits = (byte)(size / 3);
+ final byte[] ideStructData = new byte[] {
+ (byte)0x9B, // ID
+ 0x00, // Length
+ 0x00, // FLAGS
+ 0x00, // Reserved
+ colorModel, // COLOR MODEL
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Reserved
+ bits,
+ bits,
+ bits,
+ };
+ ideStructData[1] = (byte)(ideStructData.length - 2);
+ return ideStructData;
+ }
+ return new byte[0];
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java b/src/java/org/apache/fop/afp/ioca/ImageInputDescriptor.java
index bba416c88..af237a467 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageInputDescriptor.java
@@ -17,11 +17,13 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.ioca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+
+import org.apache.fop.afp.modca.AbstractAFPObject;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The IM Image Input Descriptor structured field contains the
@@ -30,30 +32,17 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class ImageInputDescriptor extends AbstractAFPObject {
- /**
- * The resolution of the raster image (default 240)
- */
+ /** the resolution of the raster image (default 240) */
private int resolution = 240;
-
- /**
- * Accessor method to write the AFP datastream for the Image Input Descriptor
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occurred
- */
- public void writeDataStream(OutputStream os) throws IOException {
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[45];
+ copySF(data, Type.DESCRIPTOR, Category.IM_IMAGE);
- data[0] = 0x5A;
- data[1] = 0x00;
+ data[1] = 0x00; // length
data[2] = 0x2C;
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xA6;
- data[5] = (byte) 0x7B;
- data[6] = 0x00;
- data[7] = 0x00;
- data[8] = 0x00;
// Constant data.
data[9] = 0x00;
@@ -131,12 +120,12 @@ public class ImageInputDescriptor extends AbstractAFPObject {
data[44] = (byte)0xFF;
os.write(data);
-
}
/**
* Sets the resolution information for the raster image
* the default value is a resolution of 240 dpi.
+ *
* @param resolution The resolution value
*/
public void setResolution(int resolution) {
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java b/src/java/org/apache/fop/afp/ioca/ImageOutputControl.java
index 558a600a5..3d500b3fd 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageOutputControl.java
@@ -17,11 +17,13 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.ioca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+
+import org.apache.fop.afp.modca.AbstractAFPObject;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The IM Image Output Control structured field specifies the position and
@@ -31,9 +33,7 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class ImageOutputControl extends AbstractAFPObject {
- /**
- * The orientation of the image
- */
+ /** the orientation of the image */
private int orientation = 0;
/**
@@ -48,9 +48,7 @@ public class ImageOutputControl extends AbstractAFPObject {
*/
private int yCoord = 0;
- /**
- * Map an image point to a single presentation device
- */
+ /** map an image point to a single presentation device */
private boolean singlePoint = true;
/**
@@ -67,18 +65,12 @@ public class ImageOutputControl extends AbstractAFPObject {
* The Y-axis offset.
*/
public ImageOutputControl(int x, int y) {
-
xCoord = x;
yCoord = y;
-
}
- /**
- * Accessor method to write the AFP datastream for the Image Output Control
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occured
- */
- public void writeDataStream(OutputStream os) throws IOException {
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[33];
@@ -170,7 +162,6 @@ public class ImageOutputControl extends AbstractAFPObject {
data[32] = (byte) 0xFF;
os.write(data);
-
}
/**
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java b/src/java/org/apache/fop/afp/ioca/ImageRasterData.java
index ca440a859..50f44d39d 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageRasterData.java
@@ -17,11 +17,13 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.ioca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+
+import org.apache.fop.afp.modca.AbstractAFPObject;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* Contains the image points that define the IM image raster pattern.
@@ -45,43 +47,28 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class ImageRasterData extends AbstractAFPObject {
- /**
- * The image raster data
- */
- private byte[] rasterData;
+ /** the image raster data */
+ private final byte[] rasterData;
/**
* Constructor for the image raster data object
+ *
* @param data The raster image data
*/
public ImageRasterData(byte[] data) {
this.rasterData = data;
}
- /**
- * Accessor method to write the AFP datastream for the Image Raster Data
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occurred
- */
- public void writeDataStream(OutputStream os) throws IOException {
-
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[9];
-
- data[0] = 0x5A;
-
+ copySF(data, Type.DATA, Category.IM_IMAGE);
// The size of the structured field
- byte[] x = BinaryUtils.convert(rasterData.length + 8, 2);
- data[1] = x[0];
- data[2] = x[1];
-
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xEE;
- data[5] = (byte) 0x7B;
- data[6] = 0x00;
- data[7] = 0x00;
- data[8] = 0x00;
-
+ byte[] len = BinaryUtils.convert(rasterData.length + 8, 2);
+ data[1] = len[0];
+ data[2] = len[1];
os.write(data);
+
os.write(rasterData);
}
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageRasterPattern.java b/src/java/org/apache/fop/afp/ioca/ImageRasterPattern.java
index 373e50631..789eeb950 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageRasterPattern.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageRasterPattern.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.ioca;
/**
* Raster data is a grid of cells covering an area of interest.
diff --git a/src/java/org/apache/fop/afp/ioca/ImageSegment.java b/src/java/org/apache/fop/afp/ioca/ImageSegment.java
new file mode 100644
index 000000000..9fb544719
--- /dev/null
+++ b/src/java/org/apache/fop/afp/ioca/ImageSegment.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.ioca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.modca.AbstractNamedAFPObject;
+
+/**
+ * An Image Segment is represented by a set of self-defining fields, fields
+ * that describe their own contents. It starts with a Begin Segment, and
+ * ends with an End Segment.
+ *
+ * Between the Begin Segment and End Segment is the image information to
+ * be processed, called the Image Content.
+ *
+ * Only one Image Content can exist within a single IOCA Image Segment.
+ */
+public class ImageSegment extends AbstractNamedAFPObject {
+
+ /**
+ * The ImageContent for the image segment
+ */
+ private ImageContent imageContent = null;
+
+ private final Factory factory;
+
+ /**
+ * Constructor for the image segment with the specified name,
+ * the name must be a fixed length of eight characters.
+ * @param factory the object factory
+ *
+ * @param name the name of the image.
+ */
+ public ImageSegment(Factory factory, String name) {
+ super(name);
+ this.factory = factory;
+ }
+
+ private ImageContent getImageContent() {
+ if (imageContent == null) {
+ this.imageContent = factory.createImageContent();
+ }
+ return imageContent;
+ }
+
+ /**
+ * Sets the image size parameters resolution, hsize and vsize.
+ *
+ * @param hsize The horizontal size of the image.
+ * @param vsize The vertical size of the image.
+ * @param hresol The horizontal resolution of the image.
+ * @param vresol The vertical resolution of the image.
+ */
+ public void setImageSize(int hsize, int vsize, int hresol, int vresol) {
+ ImageSizeParameter imageSizeParameter
+ = factory.createImageSizeParameter(hsize, vsize, hresol, vresol);
+ getImageContent().setImageSizeParameter(imageSizeParameter);
+ }
+
+ /**
+ * Sets the image encoding.
+ *
+ * @param encoding The image encoding.
+ */
+ public void setEncoding(byte encoding) {
+ getImageContent().setImageEncoding(encoding);
+ }
+
+ /**
+ * Sets the image compression.
+ *
+ * @param compression The image compression.
+ */
+ public void setCompression(byte compression) {
+ getImageContent().setImageCompression(compression);
+ }
+
+ /**
+ * Sets the image IDE size.
+ *
+ * @param size The IDE size.
+ */
+ public void setIDESize(byte size) {
+ getImageContent().setImageIDESize(size);
+ }
+
+ /**
+ * Sets the image IDE color model.
+ *
+ * @param colorModel the IDE color model.
+ */
+ public void setIDEColorModel(byte colorModel) {
+ getImageContent().setImageIDEColorModel(colorModel);
+ }
+
+ /**
+ * Set the data image data.
+ *
+ * @param data the image data
+ */
+ public void setData(byte[] imageData) {
+ getImageContent().setImageData(imageData);
+ }
+
+ /** {@inheritDoc} */
+ public void writeContent(OutputStream os) throws IOException {
+ if (imageContent != null) {
+ imageContent.writeToStream(os);
+ }
+ }
+
+ private static final int NAME_LENGTH = 4;
+
+ /** {@inheritDoc} */
+ protected int getNameLength() {
+ return NAME_LENGTH;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] nameBytes = getNameBytes();
+ byte[] data = new byte[] {
+ 0x70, // ID
+ 0x04, // Length
+ nameBytes[0], // Name byte 1
+ nameBytes[1], // Name byte 2
+ nameBytes[2], // Name byte 3
+ nameBytes[3], // Name byte 4
+ };
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ 0x71, // ID
+ 0x00, // Length
+ };
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java b/src/java/org/apache/fop/afp/ioca/ImageSizeParameter.java
index 7dd210a1e..38e7d9e56 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageSizeParameter.java
@@ -17,43 +17,42 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.ioca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+
+import org.apache.fop.afp.modca.AbstractAFPObject;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* Describes the measurement characteristics of the image when it is created.
*/
public class ImageSizeParameter extends AbstractAFPObject {
- private int hRes = 0;
- private int vRes = 0;
private int hSize = 0;
private int vSize = 0;
+ private int hRes = 0;
+ private int vRes = 0;
/**
* Constructor for a ImageSizeParameter for the specified
* resolution, hsize and vsize.
- * @param hresol The horizontal resolution of the image.
- * @param vresol The vertical resolution of the image.
+ *
* @param hsize The horizontal size of the image.
* @param vsize The vertical size of the image.
+ * @param hresol The horizontal resolution of the image.
+ * @param vresol The vertical resolution of the image.
*/
- public ImageSizeParameter(int hresol, int vresol, int hsize, int vsize) {
- this.hRes = hresol;
- this.vRes = vresol;
+ public ImageSizeParameter(int hsize, int vsize, int hresol, int vresol) {
this.hSize = hsize;
this.vSize = vsize;
+ this.hRes = hresol;
+ this.vRes = vresol;
}
- /**
- * Accessor method to write the AFP datastream for the Image Size Parameter
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occured
- */
- public void writeDataStream(OutputStream os) throws IOException {
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[] {
(byte)0x94, // ID = Image Size Parameter
0x09, // Length
diff --git a/src/java/org/apache/fop/afp/ioca/package.html b/src/java/org/apache/fop/afp/ioca/package.html
new file mode 100644
index 000000000..34e0bc19d
--- /dev/null
+++ b/src/java/org/apache/fop/afp/ioca/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.ioca Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Image Object Content Architecture (IOCA) structured objects.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java
new file mode 100644
index 000000000..f1b76c447
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.Streamable;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * This is the base class for all data stream objects. Page objects are
+ * responsible for building and generating the binary datastream in an
+ * AFP format.
+ */
+public abstract class AbstractAFPObject implements Streamable {
+
+ /** Static logging instance */
+ protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp.modca");
+
+ /** the structured field class id */
+ protected static final byte SF_CLASS = (byte)0xD3;
+
+ private static final byte[] SF_HEADER = new byte[] {
+ 0x5A, // Structured field identifier
+ 0x00, // Length byte 1
+ 0x10, // Length byte 2
+ SF_CLASS, // Structured field id byte 1
+ (byte) 0x00, // Structured field id byte 2
+ (byte) 0x00, // Structured field id byte 3
+ 0x00, // Flags
+ 0x00, // Reserved
+ 0x00, // Reserved
+ };
+
+ /**
+ * Copies the template structured field data array to the given byte array
+ *
+ * @param data the structured field data byte array
+ * @param type the type code
+ * @param category the category code
+ */
+ protected void copySF(byte[] data, byte type, byte category) {
+ copySF(data, SF_CLASS, type, category);
+ }
+
+ /**
+ * Copies the template structured field data array to the given byte array
+ *
+ * @param data the structured field data byte array
+ * @param clazz the class code
+ * @param type the type code
+ * @param category the category code
+ */
+ protected static void copySF(byte[] data, byte clazz, byte type, byte category) {
+ System.arraycopy(SF_HEADER, 0, data, 0, SF_HEADER.length);
+ data[3] = clazz;
+ data[4] = type;
+ data[5] = category;
+ }
+
+ /**
+ * Writes a collection of Streamable to the AFP Datastream.
+ *
+ * @param objects a list of AFPObjects
+ * @param os The stream to write to
+ * @throws java.io.IOException an I/O exception of some sort has occurred.
+ */
+ protected void writeObjects(Collection/*<Streamable>*/ objects, OutputStream os)
+ throws IOException {
+ if (objects != null && objects.size() > 0) {
+ Iterator it = objects.iterator();
+ while (it.hasNext()) {
+ Object object = it.next();
+ if (object instanceof Streamable) {
+ ((Streamable)object).writeToStream(os);
+ it.remove(); // once written, immediately remove the object
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads data chunks from an InputStream
+ * and then formats them with a structured header to a given OutputStream
+ *
+ * @param dataHeader the header data
+ * @param lengthOffset offset of length field in data chunk
+ * @param maxChunkLength the maximum chunk length
+ * @param inputStream the InputStream to read from
+ * @param outputStream the OutputStream to write to
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ protected static void copyChunks(byte[] dataHeader, int lengthOffset,
+ int maxChunkLength, InputStream inputStream, OutputStream outputStream)
+ throws IOException {
+ int headerLen = dataHeader.length - lengthOffset;
+ // length field is just before data so do not include in data length
+ if (headerLen == 2) {
+ headerLen = 0;
+ }
+ byte[] data = new byte[maxChunkLength];
+ int numBytesRead = 0;
+ while ((numBytesRead = inputStream.read(data, 0, maxChunkLength)) > 0) {
+ byte[] len = BinaryUtils.convert(headerLen + numBytesRead, 2);
+ dataHeader[lengthOffset] = len[0]; // Length byte 1
+ dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
+ outputStream.write(dataHeader);
+ outputStream.write(data, 0, numBytesRead);
+ }
+ }
+
+ /**
+ * Writes data chunks to a given outputstream
+ *
+ * @param data the data byte array
+ * @param dataHeader the header data
+ * @param lengthOffset offset of length field in data chunk
+ * @param maxChunkLength the maximum chunk length
+ * @param os the outputstream to write to
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ protected static void writeChunksToStream(byte[] data, byte[] dataHeader,
+ int lengthOffset, int maxChunkLength, OutputStream os) throws IOException {
+ int dataLength = data.length;
+ int numFullChunks = dataLength / maxChunkLength;
+ int lastChunkLength = dataLength % maxChunkLength;
+
+ int headerLen = dataHeader.length - lengthOffset;
+ // length field is just before data so do not include in data length
+ if (headerLen == 2) {
+ headerLen = 0;
+ }
+
+ byte[] len;
+ int off = 0;
+ if (numFullChunks > 0) {
+ // write out full data chunks
+ len = BinaryUtils.convert(headerLen + maxChunkLength, 2);
+ dataHeader[lengthOffset] = len[0]; // Length byte 1
+ dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
+ for (int i = 0; i < numFullChunks; i++, off += maxChunkLength) {
+ os.write(dataHeader);
+ os.write(data, off, maxChunkLength);
+ }
+ }
+
+ if (lastChunkLength > 0) {
+ // write last data chunk
+ len = BinaryUtils.convert(headerLen + lastChunkLength, 2);
+ dataHeader[lengthOffset] = len[0]; // Length byte 1
+ dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
+ os.write(dataHeader);
+ os.write(data, off, lastChunkLength);
+ }
+ }
+
+ /** structured field type codes */
+ public interface Type {
+
+ /** Attribute */
+ byte ATTRIBUTE = (byte)0x0A;
+
+ /** Copy Count */
+ byte COPY_COUNT = (byte)0xA2;
+
+ /** Descriptor */
+ byte DESCRIPTOR = (byte)0xA6;
+
+ /** Control */
+ byte CONTROL = (byte)0xA7;
+
+ /** Begin */
+ byte BEGIN = (byte)0xA8;
+
+ /** End */
+ byte END = (byte)0xA9;
+
+ /** Map */
+ byte MAP = (byte)0xAB;
+
+ /** Position */
+ byte POSITION = (byte)0xAC;
+
+ /** Process */
+ byte PROCESS = (byte)0xAD;
+
+ /** Include */
+ byte INCLUDE = (byte)0xAF;
+
+ /** Table */
+ byte TABLE = (byte)0xB0;
+
+ /** Migration */
+ byte MIGRATION = (byte)0xB1;
+
+ /** Variable */
+ byte VARIABLE = (byte)0xB2;
+
+ /** Link */
+ byte LINK = (byte)0xB4;
+
+ /** Data */
+ byte DATA = (byte)0xEE;
+ }
+
+ /** structured field category codes */
+ public interface Category {
+
+ /** Page Segment */
+ byte PAGE_SEGMENT = (byte)0x5F;
+
+ /** Object Area */
+ byte OBJECT_AREA = (byte)0x6B;
+
+ /** Color Attribute Table */
+ byte COLOR_ATTRIBUTE_TABLE = (byte)0x77;
+
+ /** IM Image */
+ byte IM_IMAGE = (byte)0x7B;
+
+ /** Medium */
+ byte MEDIUM = (byte)0x88;
+
+ /** Coded Font */
+ byte CODED_FONT = (byte)0x8A;
+
+ /** Process Element */
+ byte PROCESS_ELEMENT = (byte)0x90;
+
+ /** Object Container */
+ byte OBJECT_CONTAINER = (byte)0x92;
+
+ /** Presentation Text */
+ byte PRESENTATION_TEXT = (byte)0x9B;
+
+ /** Index */
+ byte INDEX = (byte)0xA7;
+
+ /** Document */
+ byte DOCUMENT = (byte)0xA8;
+
+ /** Page Group */
+ byte PAGE_GROUP = (byte)0xAD;
+
+ /** Page */
+ byte PAGE = (byte)0xAF;
+
+ /** Graphics */
+ byte GRAPHICS = (byte)0xBB;
+
+ /** Data Resource */
+ byte DATA_RESOURCE = (byte)0xC3;
+
+ /** Document Environment Group (DEG) */
+ byte DOCUMENT_ENVIRONMENT_GROUP = (byte)0xC4;
+
+ /** Resource Group */
+ byte RESOURCE_GROUP = (byte)0xC6;
+
+ /** Object Environment Group (OEG) */
+ byte OBJECT_ENVIRONMENT_GROUP = (byte)0xC7;
+
+ /** Active Environment Group (AEG) */
+ byte ACTIVE_ENVIRONMENT_GROUP = (byte)0xC9;
+
+ /** Medium Map */
+ byte MEDIUM_MAP = (byte)0xCC;
+
+ /** Form Map */
+ byte FORM_MAP = (byte)0xCD;
+
+ /** Name Resource */
+ byte NAME_RESOURCE = (byte)0xCE;
+
+ /** Page Overlay */
+ byte PAGE_OVERLAY = (byte)0xD8;
+
+ /** Resource Environment Group (REG) */
+ byte RESOURCE_ENVIROMENT_GROUP = (byte)0xD9;
+
+ /** Overlay */
+ byte OVERLAY = (byte)0xDF;
+
+ /** Data Suppression */
+ byte DATA_SUPRESSION = (byte)0xEA;
+
+ /** Bar Code */
+ byte BARCODE = (byte)0xEB;
+
+ /** No Operation */
+ byte NO_OPERATION = (byte)0xEE;
+
+ /** Image */
+ byte IMAGE = (byte)0xFB;
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/afp/modca/AbstractDataObject.java b/src/java/org/apache/fop/afp/modca/AbstractDataObject.java
new file mode 100644
index 000000000..4a13b4a55
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractDataObject.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.fop.afp.Completable;
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.Startable;
+
+/**
+ * Abstract base class used by the ImageObject and GraphicsObject which both
+ * have define an ObjectEnvironmentGroup
+ */
+public abstract class AbstractDataObject extends AbstractNamedAFPObject implements Startable, Completable {
+
+ /** the object environment group */
+ protected ObjectEnvironmentGroup objectEnvironmentGroup = null;
+
+ /** the object factory */
+ protected final Factory factory;
+
+ /** the completion status of this object */
+ private boolean complete;
+
+ /** the starting status of this object */
+ private boolean started;
+
+ /**
+ * Named constructor
+ *
+ * @param factory the object factory
+ * @param name data object name
+ */
+ public AbstractDataObject(Factory factory, String name) {
+ super(name);
+ this.factory = factory;
+ }
+
+ /**
+ * Sets the object view port (area position and size).
+ *
+ * @param dataObjectInfo
+ * the object area info
+ */
+ public void setViewport(AFPDataObjectInfo dataObjectInfo) {
+ AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
+
+ // object area descriptor
+ int width = objectAreaInfo.getWidth();
+ int height = objectAreaInfo.getHeight();
+ int widthRes = objectAreaInfo.getWidthRes();
+ int heightRes = objectAreaInfo.getHeightRes();
+ ObjectAreaDescriptor objectAreaDescriptor
+ = factory.createObjectAreaDescriptor(width, height, widthRes, heightRes);
+ getObjectEnvironmentGroup().setObjectAreaDescriptor(objectAreaDescriptor);
+
+ // object area position
+ AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
+ AFPResourceLevel resourceLevel = resourceInfo.getLevel();
+ ObjectAreaPosition objectAreaPosition = null;
+ if (resourceLevel.isInline()) {
+ int x = objectAreaInfo.getX();
+ int y = objectAreaInfo.getY();
+ int rotation = objectAreaInfo.getRotation();
+ objectAreaPosition = factory.createObjectAreaPosition(x, y, rotation);
+ } else {
+ // positional values are specified in the oaOffset of the include object
+ objectAreaPosition = factory.createObjectAreaPosition(0, 0, 0);
+ }
+ getObjectEnvironmentGroup().setObjectAreaPosition(objectAreaPosition);
+ }
+
+ /**
+ * Gets the ObjectEnvironmentGroup
+ *
+ * @return the object environment group
+ */
+ public ObjectEnvironmentGroup getObjectEnvironmentGroup() {
+ if (objectEnvironmentGroup == null) {
+ this.objectEnvironmentGroup = factory.createObjectEnvironmentGroup();
+ }
+ return objectEnvironmentGroup;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ setStarted(true);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ writeTriplets(os);
+ if (objectEnvironmentGroup != null) {
+ objectEnvironmentGroup.writeToStream(os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void setStarted(boolean started) {
+ this.started = started;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ /** {@inheritDoc} */
+ public void setComplete(boolean complete) {
+ this.complete = complete;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isComplete() {
+ return this.complete;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java b/src/java/org/apache/fop/afp/modca/AbstractDescriptor.java
index 83ed9b99a..8344bf0d1 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java
+++ b/src/java/org/apache/fop/afp/modca/AbstractDescriptor.java
@@ -17,33 +17,68 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
/**
* Base class for AFP descriptor objects
*/
-public abstract class AbstractDescriptor extends AbstractAFPObject {
+public abstract class AbstractDescriptor extends AbstractTripletStructuredObject {
+
/** width of this descriptor */
protected int width = 0;
/** height of this descriptor */
protected int height = 0;
/** width resolution of this descriptor */
- protected int widthResolution = 0;
+ protected int widthRes = 0;
/** height resolution of this descriptor */
- protected int heightResolution = 0;
+ protected int heightRes = 0;
+
+ /**
+ * Default constructor
+ */
+ public AbstractDescriptor() {
+ }
/**
* Constructor a PresentationTextDescriptor for the specified
* width and height.
+ *
* @param width The width of the page.
* @param height The height of the page.
- * @param widthResolution The width resolution of the page.
- * @param heightResolution The height resolution of the page.
+ * @param widthRes The width resolution of the page.
+ * @param heightRes The height resolution of the page.
*/
- public AbstractDescriptor(int width, int height, int widthResolution, int heightResolution) {
+ public AbstractDescriptor(int width, int height, int widthRes, int heightRes) {
this.width = width;
this.height = height;
- this.widthResolution = widthResolution;
- this.heightResolution = heightResolution;
+ this.widthRes = widthRes;
+ this.heightRes = heightRes;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "width=" + width
+ + ", height=" + height
+ + ", widthRes=" + widthRes
+ + ", heightRes=" + heightRes;
+ }
+
+ /**
+ * Returns the width
+ *
+ * @return the width
+ */
+ public int getWidth() {
+ return this.width;
+ }
+
+ /**
+ * Returns the height
+ *
+ * @return the height
+ */
+ public int getHeight() {
+ return this.height;
}
+
}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java
new file mode 100644
index 000000000..a58bba1f0
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * A base class that encapsulates common features of
+ * ActiveEnvironmentGroup and ResourceEnvironmentGroup
+ */
+public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject {
+
+ /**
+ * The collection of MapPageOverlay objects
+ */
+ protected List mapPageOverlays = null;
+
+ /**
+ * Main constructor
+ *
+ * @param name the object name
+ */
+ public AbstractEnvironmentGroup(String name) {
+ super(name);
+ }
+
+ private List getMapPageOverlays() {
+ if (mapPageOverlays == null) {
+ mapPageOverlays = new java.util.ArrayList();
+ }
+ return mapPageOverlays;
+ }
+
+ /**
+ * Actually creates the MPO object.
+ * Also creates the supporting object (an IPO)
+ *
+ * @param name the name of the overlay to be used
+ */
+ public void createOverlay(String name) {
+ MapPageOverlay mpo = getCurrentMapPageOverlay();
+ if (mpo == null) {
+ mpo = new MapPageOverlay();
+ getMapPageOverlays().add(mpo);
+ }
+
+ try {
+ mpo.addOverlay(name);
+ } catch (MaximumSizeExceededException msee) {
+ mpo = new MapPageOverlay();
+ getMapPageOverlays().add(mpo);
+ try {
+ mpo.addOverlay(name);
+ } catch (MaximumSizeExceededException ex) {
+ // Should never happen (but log just in case)
+ log.error("createOverlay():: resulted in a MaximumSizeExceededException");
+ }
+ }
+ }
+
+ /**
+ * Getter method for the most recent MapPageOverlay added to the
+ * Active Environment Group (returns null if no MapPageOverlay exist)
+ *
+ * @return the most recent Map Coded Font
+ */
+ private MapPageOverlay getCurrentMapPageOverlay() {
+ if (mapPageOverlays != null && mapPageOverlays.size() > 0) {
+ return (MapPageOverlay) mapPageOverlays.get(mapPageOverlays.size() - 1);
+ } else {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+ if (mapPageOverlays != null) {
+ writeObjects(mapPageOverlays, os);
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/afp/modca/AbstractNamedAFPObject.java
new file mode 100644
index 000000000..4e0dbc349
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractNamedAFPObject.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.UnsupportedEncodingException;
+
+import org.apache.fop.afp.AFPConstants;
+
+/**
+ * This is the base class for all named data stream objects.
+ * A named data stream object has an 8 byte EBCIDIC name.
+ */
+public abstract class AbstractNamedAFPObject extends AbstractTripletStructuredObject {
+
+ private static final int DEFAULT_NAME_LENGTH = 8;
+
+ /**
+ * The actual name of the object
+ */
+ protected String name = null;
+
+ /**
+ * Default constructor
+ */
+ protected AbstractNamedAFPObject() {
+ }
+
+ /**
+ * Constructor for the ActiveEnvironmentGroup, this takes a
+ * name parameter which should be 8 characters long.
+ *
+ * @param name the object name
+ */
+ protected AbstractNamedAFPObject(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the name length
+ *
+ * @return the name length
+ */
+ protected int getNameLength() {
+ return DEFAULT_NAME_LENGTH;
+ }
+
+ /**
+ * Returns the name as a byte array in EBCIDIC encoding
+ *
+ * @return the name as a byte array in EBCIDIC encoding
+ */
+ public byte[] getNameBytes() {
+ int afpNameLen = getNameLength();
+ int nameLen = name.length();
+ if (nameLen < afpNameLen) {
+ name = (name + " ").substring(0, afpNameLen);
+ } else if (name.length() > afpNameLen) {
+ String truncatedName = name.substring(nameLen - afpNameLen, nameLen);
+ log.warn("Constructor:: name '" + name + "'"
+ + " truncated to " + afpNameLen + " chars"
+ + " ('" + truncatedName + "')");
+ name = truncatedName;
+ }
+ byte[] nameBytes = null;
+ try {
+ nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ } catch (UnsupportedEncodingException usee) {
+ nameBytes = name.getBytes();
+ log.warn(
+ "Constructor:: UnsupportedEncodingException translating the name "
+ + name);
+ }
+ return nameBytes;
+ }
+
+ /** {@inheritDoc} */
+ protected void copySF(byte[] data, byte type, byte category) {
+ super.copySF(data, type, category);
+ byte[] nameData = getNameBytes();
+ System.arraycopy(nameData, 0, data, 9, nameData.length);
+ }
+
+ /**
+ * Returns the name of this object
+ *
+ * @return the name of this object
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Sets the name of this object
+ *
+ * @param name the object name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
new file mode 100644
index 000000000..249de1339
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import org.apache.fop.afp.AFPLineDataInfo;
+import org.apache.fop.afp.AFPTextDataInfo;
+import org.apache.fop.afp.Completable;
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.fonts.AFPFont;
+
+/**
+ * Pages contain the data objects that comprise a presentation document. Each
+ * page has a set of data objects associated with it. Each page within a
+ * document is independent from any other page, and each must establish its own
+ * environment parameters.
+ *
+ * The page is the level in the document component hierarchy that is used for
+ * printing or displaying a document's content. The data objects contained in
+ * the page envelope in the data stream are presented when the page is
+ * presented. Each data object has layout information associated with it that
+ * directs the placement and orientation of the data on the page. In addition,
+ * each page contains layout information that specifies the measurement units,
+ * page width, and page depth.
+ *
+ * A page is initiated by a begin page structured field and terminated by an end
+ * page structured field. Structured fields that define objects and active
+ * environment groups or that specify attributes of the page may be encountered
+ * in page state.
+ *
+ */
+public abstract class AbstractPageObject extends AbstractNamedAFPObject implements Completable {
+
+ /** The active environment group for the page */
+ protected ActiveEnvironmentGroup activeEnvironmentGroup = null;
+
+ /** The current presentation text object */
+ private PresentationTextObject currentPresentationTextObject = null;
+
+ /** The list of tag logical elements */
+ protected List/*<TagLogicalElement>*/ tagLogicalElements = null;
+
+ /** The list of the include page segments */
+ protected List/*<IncludePageSegment>*/ includePageSegments = null;
+
+ /** The list of objects within this resource container */
+ protected List/*<AbstractStructuredAFPObject>*/ objects = new java.util.ArrayList();
+
+ /** The page width */
+ private int width;
+
+ /** The page height */
+ private int height;
+
+ /** The page rotation */
+ protected int rotation = 0;
+
+ /** The page state */
+ protected boolean complete = false;
+
+ /** The width resolution */
+ private int widthRes;
+
+ /** The height resolution */
+ private int heightRes;
+
+ /** the object factory */
+ protected final Factory factory;
+
+ /**
+ * Default constructor
+ *
+ * @param factory the object factory
+ */
+ public AbstractPageObject(Factory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * Main constructor
+ *
+ * @param factory the object factory
+ * @param name the name of this page object
+ */
+ public AbstractPageObject(Factory factory, String name) {
+ super(name);
+ this.factory = factory;
+ }
+
+ /**
+ * Construct a new page object for the specified name argument, the page
+ * name should be an 8 character identifier.
+ *
+ * @param factory
+ * the object factory.
+ * @param name
+ * the name of the page.
+ * @param width
+ * the width of the page.
+ * @param height
+ * the height of the page.
+ * @param rotation
+ * the rotation of the page.
+ * @param widthRes
+ * the width resolution of the page.
+ * @param heightRes
+ * the height resolution of the page.
+ */
+ public AbstractPageObject(Factory factory,
+ String name, int width, int height, int rotation,
+ int widthRes, int heightRes) {
+ super(name);
+
+ this.factory = factory;
+ this.width = width;
+ this.height = height;
+ this.rotation = rotation;
+ this.widthRes = widthRes;
+ this.heightRes = heightRes;
+ }
+
+ /**
+ * Helper method to create a map coded font object on the current page, this
+ * method delegates the construction of the map coded font object to the
+ * active environment group on the page.
+ *
+ * @param fontReference
+ * the font number used as the resource identifier
+ * @param font
+ * the font
+ * @param size
+ * the point size of the font
+ */
+ public void createFont(int fontReference, AFPFont font, int size) {
+ getActiveEnvironmentGroup().createFont(fontReference, font, size, 0);
+ }
+
+ /**
+ * Helper method to create a line on the current page, this method delegates
+ * to the presentation text object in order to construct the line.
+ *
+ * @param lineDataInfo the line data information.
+ */
+ public void createLine(AFPLineDataInfo lineDataInfo) {
+ getPresentationTextObject().createLineData(lineDataInfo);
+ }
+
+ /**
+ * Helper method to create text on the current page, this method delegates
+ * to the presentation text object in order to construct the text.
+ *
+ * @param textDataInfo
+ * the afp text data
+ * @throws UnsupportedEncodingException thrown if character encoding is not supported
+ */
+ public void createText(AFPTextDataInfo textDataInfo) throws UnsupportedEncodingException {
+ getPresentationTextObject().createTextData(textDataInfo);
+ }
+
+ /**
+ * Helper method to mark the end of the page. This should end the control
+ * sequence on the current presentation text object.
+ */
+ public void endPage() {
+ if (currentPresentationTextObject != null) {
+ currentPresentationTextObject.endControlSequence();
+ }
+ setComplete(true);
+ }
+
+ /**
+ * Ends the presentation text object
+ */
+ protected void endPresentationObject() {
+ if (currentPresentationTextObject != null) {
+ currentPresentationTextObject.endControlSequence();
+ currentPresentationTextObject = null;
+ }
+ }
+
+ /**
+ * Helper method to create a presentation text object
+ * on the current page and to return the object.
+ *
+ * @return the presentation text object
+ */
+ private PresentationTextObject getPresentationTextObject() {
+ if (currentPresentationTextObject == null) {
+ PresentationTextObject presentationTextObject
+ = factory.createPresentationTextObject();
+ addObject(presentationTextObject);
+ this.currentPresentationTextObject = presentationTextObject;
+ }
+ return currentPresentationTextObject;
+ }
+
+ /**
+ * Creates a TagLogicalElement on the page.
+ *
+ * @param name
+ * the name of the tag
+ * @param value
+ * the value of the tag
+ */
+ public void createTagLogicalElement(String name, String value) {
+ TagLogicalElement tle = new TagLogicalElement(name, value);
+ if (tagLogicalElements == null) {
+ tagLogicalElements = new java.util.ArrayList/*<TagLogicalElement>*/();
+ }
+ tagLogicalElements.add(tle);
+ }
+
+ /**
+ * Creates a NoOperation on the page.
+ *
+ * @param content the byte data
+ */
+ public void createNoOperation(String content) {
+ addObject(new NoOperation(content));
+ }
+
+ /**
+ * Creates an IncludePageSegment on the current page.
+ *
+ * @param name
+ * the name of the page segment
+ * @param x
+ * the x coordinate of the page segment.
+ * @param y
+ * the y coordinate of the page segment.
+ */
+ public void createIncludePageSegment(String name, int x, int y) {
+ IncludePageSegment ips = factory.createIncludePageSegment(name, x, y);
+ getIncludePageSegments().add(ips);
+ }
+
+ /**
+ * Returns the include page segments list
+ *
+ * @return the include page segments list
+ */
+ private List getIncludePageSegments() {
+ if (this.includePageSegments == null) {
+ this.includePageSegments = new java.util.ArrayList/*<IncludePageSegment>*/();
+ }
+ return this.includePageSegments;
+ }
+
+ /**
+ * Returns the ActiveEnvironmentGroup associated with this page.
+ *
+ * @return the ActiveEnvironmentGroup object
+ */
+ public ActiveEnvironmentGroup getActiveEnvironmentGroup() {
+ if (activeEnvironmentGroup == null) {
+ // every page object must have an ActiveEnvironmentGroup
+ this.activeEnvironmentGroup
+ = factory.createActiveEnvironmentGroup(width, height, widthRes, heightRes);
+
+ if (rotation != 0) {
+ switch (rotation) {
+ case 90:
+ activeEnvironmentGroup.setObjectAreaPosition(width, 0, rotation);
+ break;
+ case 180:
+ activeEnvironmentGroup.setObjectAreaPosition(width, height, rotation);
+ break;
+ case 270:
+ activeEnvironmentGroup.setObjectAreaPosition(0, height, rotation);
+ break;
+ default:
+ }
+ }
+ }
+ return activeEnvironmentGroup;
+ }
+
+ /**
+ * Returns the height of the page
+ *
+ * @return the height of the page
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Returns the width of the page
+ *
+ * @return the width of the page
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Returns the rotation of the page
+ *
+ * @return the rotation of the page
+ */
+ public int getRotation() {
+ return rotation;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+ writeObjects(this.objects, os);
+ }
+
+ /**
+ * Adds an AFP object reference to this page
+ *
+ * @param obj an AFP object
+ */
+ public void addObject(Object obj) {
+ objects.add(obj);
+ }
+
+ /** {@inheritDoc} */
+ public void setComplete(boolean complete) {
+ this.complete = complete;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isComplete() {
+ return this.complete;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractResourceEnvironmentGroupContainer.java b/src/java/org/apache/fop/afp/modca/AbstractResourceEnvironmentGroupContainer.java
new file mode 100644
index 000000000..baba170f7
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractResourceEnvironmentGroupContainer.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.Factory;
+
+
+/**
+ * An abstract class which encapsulates the common features of
+ * Document and PageGroup resource containers
+ */
+public abstract class AbstractResourceEnvironmentGroupContainer
+ extends AbstractResourceGroupContainer {
+
+ /**
+ * The resource environment group used to store complex resources
+ */
+ protected ResourceEnvironmentGroup resourceEnvironmentGroup = null;
+
+ /**
+ * Main constructor
+ *
+ * @param factory the object factory
+ * @param name the name of this resource container
+ */
+ public AbstractResourceEnvironmentGroupContainer(
+ Factory factory, String name) {
+ super(factory, name);
+ }
+
+ /**
+ * Adds a page to the resource container.
+ *
+ * @param page - the Page object
+ */
+ public void addPage(PageObject page) {
+ addObject(page);
+ }
+
+ /**
+ * Adds a PageGroup to the resource container.
+ *
+ * @param pageGroup the PageGroup object
+ */
+ public void addPageGroup(PageGroup pageGroup) {
+ addObject(pageGroup);
+ }
+
+ /**
+ * Creates an InvokeMediaMap on the page.
+ *
+ * @param name
+ * the name of the media map
+ */
+ public void createInvokeMediumMap(String name) {
+ InvokeMediumMap invokeMediumMap = factory.createInvokeMediumMap(name);
+ addObject(invokeMediumMap);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+ if (resourceEnvironmentGroup != null) {
+ resourceEnvironmentGroup.writeToStream(os);
+ }
+ }
+
+ /**
+ * Returns the resource environment group
+ *
+ * @return the resource environment group
+ */
+ protected ResourceEnvironmentGroup getResourceEnvironmentGroup() {
+ if (resourceEnvironmentGroup == null) {
+ this.resourceEnvironmentGroup = factory.createResourceEnvironmentGroup();
+ }
+ return this.resourceEnvironmentGroup;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/afp/modca/AbstractResourceGroupContainer.java
new file mode 100644
index 000000000..9dcd56277
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractResourceGroupContainer.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.fop.afp.Completable;
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.Streamable;
+
+
+/**
+ * An abstract container of resource objects
+ */
+public abstract class AbstractResourceGroupContainer extends AbstractPageObject
+implements Streamable {
+
+ /** The container started state */
+ protected boolean started = false;
+
+ /** the resource group object */
+ protected ResourceGroup resourceGroup = null;
+
+ /**
+ * Default constructor
+ *
+ * @param factory the object factory
+ */
+ public AbstractResourceGroupContainer(Factory factory) {
+ super(factory);
+ }
+
+ /**
+ * Named constructor
+ *
+ * @param factory the object factory
+ * @param name the name of this resource container
+ */
+ public AbstractResourceGroupContainer(Factory factory, String name) {
+ super(factory, name);
+ }
+
+ /**
+ * Construct a new page object for the specified name argument, the page
+ * name should be an 8 character identifier.
+ *
+ * @param factory
+ * the object factory
+ * @param name
+ * the name of the page.
+ * @param width
+ * the width of the page.
+ * @param height
+ * the height of the page.
+ * @param rotation
+ * the rotation of the page.
+ * @param widthRes
+ * the width resolution of the page.
+ * @param heightRes
+ * the height resolution of the page.
+ */
+ public AbstractResourceGroupContainer(Factory factory,
+ String name, int width, int height, int rotation, int widthRes, int heightRes) {
+ super(factory, name, width, height, rotation, widthRes, heightRes);
+ }
+
+ /**
+ * Return the number of resources in this container
+ *
+ * @return the number of resources in this container
+ */
+ protected int getResourceCount() {
+ if (resourceGroup != null) {
+ return resourceGroup.getResourceCount();
+ }
+ return 0;
+ }
+
+ /**
+ * Returns true if this resource group container contains resources
+ *
+ * @return true if this resource group container contains resources
+ */
+ protected boolean hasResources() {
+ return resourceGroup != null && resourceGroup.getResourceCount() > 0;
+ }
+
+ /**
+ * Returns the resource group in this resource group container
+ *
+ * @return the resource group in this resource group container
+ */
+ public ResourceGroup getResourceGroup() {
+ if (resourceGroup == null) {
+ resourceGroup = factory.createResourceGroup();
+ }
+ return resourceGroup;
+ }
+
+// /** {@inheritDoc} */
+// protected void writeContent(OutputStream os) throws IOException {
+// if (resourceGroup != null) {
+// resourceGroup.writeToStream(os);
+// }
+// super.writeContent(os);
+// }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ if (!started) {
+ writeStart(os);
+ started = true;
+ }
+
+ writeContent(os);
+
+ if (complete) {
+ writeEnd(os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeObjects(Collection/*<AbstractAFPObject>*/ objects, OutputStream os)
+ throws IOException {
+ if (objects != null && objects.size() > 0) {
+ Iterator it = objects.iterator();
+ while (it.hasNext()) {
+ AbstractAFPObject ao = (AbstractAFPObject)it.next();
+ if (canWrite(ao)) {
+ ao.writeToStream(os);
+ it.remove();
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true if this object can be written
+ *
+ * @param obj an AFP object
+ * @return true if this object can be written
+ */
+ protected boolean canWrite(AbstractAFPObject obj) {
+ return obj instanceof AbstractPageObject && ((Completable)obj).isComplete();
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractStructuredObject.java b/src/java/org/apache/fop/afp/modca/AbstractStructuredObject.java
new file mode 100644
index 000000000..e848583b5
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractStructuredObject.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An abstract class encapsulating an MODCA structured object
+ */
+public abstract class AbstractStructuredObject extends AbstractAFPObject {
+
+ /**
+ * Default constructor
+ */
+ protected AbstractStructuredObject() {
+ }
+
+ /**
+ * Helper method to write the start of the Object.
+ *
+ * @param os The stream to write to
+ * @throws IOException throws an I/O exception if one occurred
+ */
+ protected void writeStart(OutputStream os) throws IOException {
+ }
+
+ /**
+ * Helper method to write the end of the Object.
+ *
+ * @param os The stream to write to
+ * @throws IOException an I/O exception if one occurred
+ */
+ protected void writeEnd(OutputStream os) throws IOException {
+ }
+
+ /**
+ * Helper method to write the contents of the Object.
+ *
+ * @param os The stream to write to
+ * @throws IOException throws an I/O exception if one occurred
+ */
+ protected void writeContent(OutputStream os) throws IOException {
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ writeStart(os);
+ writeContent(os);
+ writeEnd(os);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java b/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java
new file mode 100644
index 000000000..a14af2967
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.afp.modca.Registry.ObjectType;
+import org.apache.fop.afp.modca.triplets.AbstractTriplet;
+import org.apache.fop.afp.modca.triplets.CommentTriplet;
+import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet;
+import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet;
+
+/**
+ * A MODCA structured object base class providing support for Triplets
+ */
+public class AbstractTripletStructuredObject extends AbstractStructuredObject {
+
+ /** list of object triplets */
+ protected List/*<AbstractTriplet>*/ triplets = new java.util.ArrayList/*<AbstractTriplet>*/();
+
+ /**
+ * Returns the triplet data length
+ *
+ * @return the triplet data length
+ */
+ protected int getTripletDataLength() {
+ int dataLength = 0;
+ if (hasTriplets()) {
+ Iterator it = triplets.iterator();
+ while (it.hasNext()) {
+ AbstractTriplet triplet = (AbstractTriplet)it.next();
+ dataLength += triplet.getDataLength();
+ }
+ }
+ return dataLength;
+ }
+
+ /**
+ * Returns true when this structured field contains triplets
+ *
+ * @return true when this structured field contains triplets
+ */
+ public boolean hasTriplets() {
+ return triplets.size() > 0;
+ }
+
+ /**
+ * Writes any triplet data
+ *
+ * @param os The stream to write to
+ * @throws IOException The stream to write to
+ */
+ protected void writeTriplets(OutputStream os) throws IOException {
+ if (hasTriplets()) {
+ writeObjects(triplets, os);
+ triplets = null; // gc
+ }
+ }
+
+ /**
+ * Returns the first matching triplet found in the structured field triplet list
+ *
+ * @param tripletId the triplet identifier
+ */
+ private AbstractTriplet getTriplet(byte tripletId) {
+ Iterator it = getTriplets().iterator();
+ while (it.hasNext()) {
+ AbstractTriplet triplet = (AbstractTriplet)it.next();
+ if (triplet.getId() == tripletId) {
+ return triplet;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true of this structured field has the given triplet
+ *
+ * @param tripletId the triplet identifier
+ * @return true if the structured field has the given triplet
+ */
+ public boolean hasTriplet(byte tripletId) {
+ return getTriplet(tripletId) != null;
+ }
+
+ /**
+ * Adds a triplet to this structured object
+ *
+ * @param triplet the triplet to add
+ */
+ protected void addTriplet(AbstractTriplet triplet) {
+ triplets.add(triplet);
+ }
+
+ /**
+ * Adds a list of triplets to the triplets contained within this structured field
+ *
+ * @param tripletCollection a collection of triplets
+ */
+ public void addTriplets(Collection/*<Triplet>*/ tripletCollection) {
+ if (tripletCollection != null) {
+ triplets.addAll(tripletCollection);
+ }
+ }
+
+ /** @return the triplet list pertaining to this resource */
+ protected List/*<Triplet>*/ getTriplets() {
+ return triplets;
+ }
+
+ /**
+ * Sets the fully qualified name of this resource
+ *
+ * @param fqnType the fully qualified name type of this resource
+ * @param fqnFormat the fully qualified name format of this resource
+ * @param fqName the fully qualified name of this resource
+ */
+ public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName) {
+ addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqName));
+ }
+
+ /** @return the fully qualified name of this triplet or null if it does not exist */
+ public String getFullyQualifiedName() {
+ FullyQualifiedNameTriplet fqNameTriplet
+ = (FullyQualifiedNameTriplet)getTriplet(AbstractTriplet.FULLY_QUALIFIED_NAME);
+ if (fqNameTriplet != null) {
+ return fqNameTriplet.getFullyQualifiedName();
+ }
+ log.warn(this + " has no fully qualified name");
+ return null;
+ }
+
+ /**
+ * Sets the objects classification
+ *
+ * @param objectClass the classification of the object
+ * @param objectType the MOD:CA registry object type entry for the given
+ * object/component type of the object
+ * @param dataInContainer whether the data resides in the container
+ * @param containerHasOEG whether the container has an object environment group
+ * @param dataInOCD whether the data resides in a object container data structured field
+ */
+ public void setObjectClassification(
+ byte objectClass, ObjectType objectType,
+ boolean dataInContainer, boolean containerHasOEG, boolean dataInOCD) {
+ addTriplet(
+ new ObjectClassificationTriplet(
+ objectClass, objectType, dataInContainer, containerHasOEG, dataInOCD));
+ }
+
+ /**
+ * Sets a comment on this resource
+ *
+ * @param commentString a comment string
+ */
+ public void setComment(String commentString) {
+ addTriplet(new CommentTriplet(AbstractTriplet.COMMENT, commentString));
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java
new file mode 100644
index 000000000..ddc986be3
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.fonts.AFPFont;
+
+/**
+ * An Active Environment Group (AEG) is associated with each page,
+ * and is contained in the page's begin-end envelope in the data stream.
+ * The active environment group contains layout and formatting information
+ * that defines the measurement units and size of the page, and may contain
+ * resource information.
+ *
+ * Any objects that are required for page presentation and that are to be
+ * treated as resource objects must be mapped with a map structured field
+ * in the AEG. The scope of an active environment group is the scope of its
+ * containing page or overlay.
+ *
+ */
+public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup {
+
+ /** The collection of MapCodedFont objects */
+ private final List/*<MapCodedFonts>*/ mapCodedFonts
+ = new java.util.ArrayList/*<MapCodedFonts>*/();
+
+ /** the collection of MapDataResource objects */
+ private final List mapDataResources = null;
+
+ /** the Object Area Descriptor for the active environment group */
+ private ObjectAreaDescriptor objectAreaDescriptor = null;
+
+ /** the Object Area Position for the active environment group */
+ private ObjectAreaPosition objectAreaPosition = null;
+
+ /** the PresentationTextDescriptor for the active environment group */
+ private PresentationTextDescriptor presentationTextDataDescriptor = null;
+
+ /** the PageDescriptor for the active environment group */
+ private PageDescriptor pageDescriptor = null;
+
+ /** the resource manager */
+ private final Factory factory;
+
+ /**
+ * Constructor for the ActiveEnvironmentGroup, this takes a
+ * name parameter which must be 8 characters long.
+ *
+ * @param factory the object factory
+ * @param name the active environment group name
+ * @param width the page width
+ * @param height the page height
+ * @param widthRes the page width resolution
+ * @param heightRes the page height resolution
+ */
+ public ActiveEnvironmentGroup(Factory factory,
+ String name, int width, int height, int widthRes, int heightRes) {
+ super(name);
+
+ this.factory = factory;
+
+ // Create PageDescriptor
+ this.pageDescriptor
+ = factory.createPageDescriptor(width, height, widthRes, heightRes);
+
+ // Create ObjectAreaDescriptor
+ this.objectAreaDescriptor
+ = factory.createObjectAreaDescriptor(width, height, widthRes, heightRes);
+
+ // Create PresentationTextDataDescriptor
+ this.presentationTextDataDescriptor
+ = factory.createPresentationTextDataDescriptor(width, height,
+ widthRes, heightRes);
+ }
+
+ /**
+ * Set the position of the object area
+ *
+ * @param x the x offset
+ * @param y the y offset
+ * @param rotation the rotation
+ */
+ public void setObjectAreaPosition(int x, int y, int rotation) {
+ this.objectAreaPosition = factory.createObjectAreaPosition(x, y, rotation);
+ }
+
+ /**
+ * Accessor method to obtain the PageDescriptor object of the
+ * active environment group.
+ *
+ * @return the page descriptor object
+ */
+ public PageDescriptor getPageDescriptor() {
+ return pageDescriptor;
+ }
+
+ /**
+ * Accessor method to obtain the PresentationTextDataDescriptor object of
+ * the active environment group.
+ *
+ * @return the presentation text descriptor
+ */
+ public PresentationTextDescriptor getPresentationTextDataDescriptor() {
+ return presentationTextDataDescriptor;
+ }
+
+ /** {@inheritDoc} */
+ public void writeContent(OutputStream os) throws IOException {
+ super.writeTriplets(os);
+
+ writeObjects(mapCodedFonts, os);
+ writeObjects(mapDataResources, os);
+ writeObjects(mapPageOverlays, os);
+
+ if (pageDescriptor != null) {
+ pageDescriptor.writeToStream(os);
+ }
+ if (objectAreaDescriptor != null && objectAreaPosition != null) {
+ objectAreaDescriptor.writeToStream(os);
+ objectAreaPosition.writeToStream(os);
+ }
+ if (presentationTextDataDescriptor != null) {
+ presentationTextDataDescriptor.writeToStream(os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.ACTIVE_ENVIRONMENT_GROUP);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.ACTIVE_ENVIRONMENT_GROUP);
+ os.write(data);
+ }
+
+ /**
+ * Method to create a map coded font object
+ *
+ * @param fontRef the font number used as the resource identifier
+ * @param font the font
+ * @param size the point size of the font
+ * @param orientation the orientation of the font (e.g. 0, 90, 180, 270)
+ */
+ public void createFont(int fontRef, AFPFont font, int size, int orientation) {
+ MapCodedFont mapCodedFont = getCurrentMapCodedFont();
+ if (mapCodedFont == null) {
+ mapCodedFont = factory.createMapCodedFont();
+ mapCodedFonts.add(mapCodedFont);
+ }
+
+ try {
+ mapCodedFont.addFont(fontRef, font, size, orientation);
+ } catch (MaximumSizeExceededException msee) {
+ mapCodedFont = factory.createMapCodedFont();
+ mapCodedFonts.add(mapCodedFont);
+
+ try {
+ mapCodedFont.addFont(fontRef, font, size, orientation);
+ } catch (MaximumSizeExceededException ex) {
+ // Should never happen (but log just in case)
+ log.error("createFont():: resulted in a MaximumSizeExceededException");
+ }
+ }
+ }
+
+ /**
+ * Getter method for the most recent MapCodedFont added to the
+ * Active Environment Group (returns null if no MapCodedFonts exist)
+ *
+ * @return the most recent Map Coded Font.
+ */
+ private MapCodedFont getCurrentMapCodedFont() {
+ int size = mapCodedFonts.size();
+ if (size > 0) {
+ return (MapCodedFont)mapCodedFonts.get(size - 1);
+ } else {
+ return null;
+ }
+ }
+
+// private List getMapDataResources() {
+// if (mapDataResources == null) {
+// mapDataResources = new java.util.ArrayList();
+// }
+// return mapDataResources;
+//}
+
+// /**
+// * Method to create a map data resource object
+// * @param dataObjectAccessor a data object accessor
+// */
+// protected void createMapDataResource(DataObjectAccessor dataObjectAccessor) {
+// getMapDataResources().add(new MapDataResource(dataObjectAccessor));
+// }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java b/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java
new file mode 100644
index 000000000..0f99d6624
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * Container data descriptor (to maintain compatibility with pre-year 2000 applications)
+ */
+public class ContainerDataDescriptor extends AbstractDescriptor {
+
+ /**
+ * Main constructor
+ *
+ * @param width the container data width
+ * @param height the container data height
+ * @param widthRes the container width resolution
+ * @param heightRes the container height resolution
+ */
+ public ContainerDataDescriptor(int width, int height, int widthRes,
+ int heightRes) {
+ super(width, height, widthRes, heightRes);
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[21];
+ copySF(data, Type.DESCRIPTOR, Category.OBJECT_CONTAINER);
+
+ // SF length
+ byte[] len = BinaryUtils.convert(data.length - 1, 2);
+ data[1] = len[0];
+ data[2] = len[1];
+
+ // XocBase = 10 inches
+ data[9] = 0x00;
+
+ // YocBase = 10 inches
+ data[10] = 0x00;
+
+ // XocUnits
+ byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2);
+ data[11] = xdpi[0];
+ data[12] = xdpi[1];
+
+ // YocUnits
+ byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2);
+ data[13] = ydpi[0];
+ data[14] = ydpi[1];
+
+ // XocSize
+ byte[] xsize = BinaryUtils.convert(width, 3);
+ data[15] = xsize[0];
+ data[16] = xsize[1];
+ data[17] = xsize[2];
+
+ // YocSize
+ byte[] ysize = BinaryUtils.convert(height, 3);
+ data[18] = ysize[0];
+ data[19] = ysize[1];
+ data[20] = ysize[2];
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/Document.java b/src/java/org/apache/fop/afp/modca/Document.java
new file mode 100644
index 000000000..02a7b64e1
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/Document.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.Factory;
+
+/**
+ * The document is the highest level of the MO:DCA data-stream document
+ * component hierarchy. Documents can be made up of pages, and the pages, which
+ * are at the intermediate level, can be made up of objects. Objects are at the
+ * lowest level, and can be bar codes, graphics, images, and presentation text.
+ *
+ * At each level of the hierarchy certain sets of MO:DCA data structures, called
+ * structured fields, are permissible. The document, pages and objects are
+ * bounded by structured fields that define their beginnings and their ends.
+ * These structured fields, called begin-end pairs, provide an envelope for the
+ * data-stream components. This feature enables a processor of the data stream
+ * that is not fully compliant with the architecture to bypass those objects
+ * that are beyond its scope, and to process the data stream to the best of its
+ * abilities.
+ *
+ * A presentation document is one that has been formatted and is intended for
+ * presentation, usually on a printer or display device. A data stream
+ * containing a presentation document should produce the same document content
+ * in the same format on different printers or display devices dependent,
+ * however, on the capabilities of each of the printers or display devices. A
+ * presentation document can reference resources that are to be included as part
+ * of the document to be presented.
+ *
+ */
+public final class Document extends AbstractResourceEnvironmentGroupContainer {
+
+ /**
+ * Constructor for the document object.
+ *
+ * @param factory
+ * the object factory
+ * @param name
+ * the name of the document
+ */
+ public Document(Factory factory, String name) {
+ super(factory, name);
+ }
+
+ /**
+ * Method to mark the end of the page group.
+ */
+ public void endDocument() {
+ complete = true;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isComplete() {
+ return complete;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.DOCUMENT);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.DOCUMENT);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.name;
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java b/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java
new file mode 100644
index 000000000..5495e2e9c
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * GOCA Graphics Data Descriptor
+ */
+public class GraphicsDataDescriptor extends AbstractDescriptor {
+
+ private final int xlwind;
+
+ private final int xrwind;
+
+ private final int ybwind;
+
+ private final int ytwind;
+
+ /**
+ * Main constructor
+ *
+ * @param xlwind
+ * the left edge of the graphics window
+ * @param xrwind
+ * the right edge of the graphics window
+ * @param ybwind
+ * the top edge of the graphics window
+ * @param ytwind
+ * the bottom edge of the graphics window
+ * @param widthRes
+ * the width resolution of the graphics window
+ * @param heightRes
+ * the height resolution of the graphics window
+ */
+ public GraphicsDataDescriptor(int xlwind, int xrwind, int ybwind,
+ int ytwind, int widthRes, int heightRes) {
+ this.xlwind = xlwind;
+ this.xrwind = xrwind;
+ this.ybwind = ybwind;
+ this.ytwind = ytwind;
+ super.widthRes = widthRes;
+ super.heightRes = heightRes;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] headerData = new byte[9];
+ copySF(headerData, Type.DESCRIPTOR, Category.GRAPHICS);
+
+ byte[] drawingOrderSubsetData = getDrawingOrderSubset();
+
+ byte[] windowSpecificationData = getWindowSpecification();
+
+ byte[] len = BinaryUtils.convert(headerData.length
+ + drawingOrderSubsetData.length
+ + windowSpecificationData.length - 1, 2);
+ headerData[1] = len[0];
+ headerData[2] = len[1];
+
+ os.write(headerData);
+ os.write(drawingOrderSubsetData);
+ os.write(windowSpecificationData);
+ }
+
+ /**
+ * Returns the drawing order subset data
+ *
+ * @return the drawing order subset data
+ */
+ private byte[] getDrawingOrderSubset() {
+ final byte[] data = new byte[] {
+ // Drawing order subset
+ (byte) 0xF7,
+ 7, // LENGTH
+ (byte) 0xB0, // drawing order subset
+ 0x00, // reserved (must be zero)
+ 0x00, // reserved (must be zero)
+ 0x02, // SUBLEV
+ 0x00, // VERSION 0
+ 0x01, // LENGTH (of following field)
+ 0x00 // GEOM
+ };
+ return data;
+ }
+
+ private static final int ABS = 2;
+ private static final int IMGRES = 8;
+
+ /**
+ * Returns the window specification data
+ *
+ * @return the window specification data
+ */
+ private byte[] getWindowSpecification() {
+ byte[] xlcoord = BinaryUtils.convert(xlwind, 2);
+ byte[] xrcoord = BinaryUtils.convert(xrwind, 2);
+ byte[] xbcoord = BinaryUtils.convert(ybwind, 2);
+ byte[] ytcoord = BinaryUtils.convert(ytwind, 2);
+ byte[] xResol = BinaryUtils.convert(widthRes * 10, 2);
+ byte[] yResol = BinaryUtils.convert(heightRes * 10, 2);
+ byte[] imxyres = xResol;
+
+ // Window specification
+ final byte[] data = new byte[] {
+ (byte) 0xF6,
+ 18, // LENGTH
+ (ABS + IMGRES), // FLAGS (ABS)
+ 0x00, // reserved (must be zero)
+ 0x00, // CFORMAT (coordinate format - 16bit high byte first signed)
+ 0x00, // UBASE (unit base - ten inches)
+
+ xResol[0], // XRESOL
+ xResol[1],
+ yResol[0], // YRESOL
+ yResol[1],
+
+ imxyres[0], // IMXYRES (Number of image points per ten inches
+ imxyres[1], // in X and Y directions)
+
+ xlcoord[0], // XLWIND
+ xlcoord[1],
+ xrcoord[0], // XRWIND
+ xrcoord[1],
+ xbcoord[0], // YBWIND
+ xbcoord[1],
+ ytcoord[0], // YTWIND
+ ytcoord[1]
+ };
+ return data;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/afp/modca/GraphicsObject.java
new file mode 100644
index 000000000..24b3f949e
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/GraphicsObject.java
@@ -0,0 +1,385 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.Completable;
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.StructuredData;
+import org.apache.fop.afp.goca.GraphicsAreaBegin;
+import org.apache.fop.afp.goca.GraphicsAreaEnd;
+import org.apache.fop.afp.goca.GraphicsBox;
+import org.apache.fop.afp.goca.GraphicsChainedSegment;
+import org.apache.fop.afp.goca.GraphicsCharacterString;
+import org.apache.fop.afp.goca.GraphicsData;
+import org.apache.fop.afp.goca.GraphicsFillet;
+import org.apache.fop.afp.goca.GraphicsFullArc;
+import org.apache.fop.afp.goca.GraphicsImage;
+import org.apache.fop.afp.goca.GraphicsLine;
+import org.apache.fop.afp.goca.GraphicsSetArcParameters;
+import org.apache.fop.afp.goca.GraphicsSetCharacterSet;
+import org.apache.fop.afp.goca.GraphicsSetCurrentPosition;
+import org.apache.fop.afp.goca.GraphicsSetLineType;
+import org.apache.fop.afp.goca.GraphicsSetLineWidth;
+import org.apache.fop.afp.goca.GraphicsSetPatternSymbol;
+import org.apache.fop.afp.goca.GraphicsSetProcessColor;
+
+/**
+ * Top-level GOCA graphics object.
+ *
+ * Acts as container and factory of all other graphic objects
+ */
+public class GraphicsObject extends AbstractDataObject {
+
+ /** the graphics data */
+ private GraphicsData currentData = null;
+
+ /** list of objects contained within this container */
+ protected List/*<GraphicsData>*/ objects
+ = new java.util.ArrayList/*<GraphicsData>*/();
+
+ /** the graphics state */
+ private final GraphicsState graphicsState = new GraphicsState();
+
+ /**
+ * Default constructor
+ *
+ * @param factory the object factory
+ * @param name the name of graphics object
+ */
+ public GraphicsObject(Factory factory, String name) {
+ super(factory, name);
+ }
+
+ /** {@inheritDoc} */
+ public void setViewport(AFPDataObjectInfo dataObjectInfo) {
+ super.setViewport(dataObjectInfo);
+
+ AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
+ int width = objectAreaInfo.getWidth();
+ int height = objectAreaInfo.getHeight();
+ int widthRes = objectAreaInfo.getWidthRes();
+ int heightRes = objectAreaInfo.getHeightRes();
+ final int leftEdge = 0;
+ final int topEdge = 0;
+ GraphicsDataDescriptor graphicsDataDescriptor = factory.createGraphicsDataDescriptor(
+ leftEdge, width, topEdge, height, widthRes, heightRes);
+
+ getObjectEnvironmentGroup().setDataDescriptor(graphicsDataDescriptor);
+ }
+
+ /** {@inheritDoc} */
+ public void addObject(StructuredData object) {
+ if (currentData == null) {
+ newData();
+ } else if (currentData.getDataLength() + object.getDataLength()
+ >= GraphicsData.MAX_DATA_LEN) {
+ // graphics data full so transfer current incomplete segment to new data
+ GraphicsChainedSegment currentSegment
+ = (GraphicsChainedSegment)currentData.removeCurrentSegment();
+ currentSegment.setName(newData().createSegmentName());
+ currentData.addSegment(currentSegment);
+ }
+ currentData.addObject(object);
+ }
+
+ /**
+ * Gets the current graphics data, creating a new one if necessary
+ *
+ * @return the current graphics data
+ */
+ private GraphicsData getData() {
+ if (this.currentData == null) {
+ return newData();
+ }
+ return this.currentData;
+ }
+
+ /**
+ * Creates a new graphics data
+ *
+ * @return a newly created graphics data
+ */
+ private GraphicsData newData() {
+ if (currentData != null) {
+ currentData.setComplete(true);
+ }
+ this.currentData = factory.createGraphicsData();
+ objects.add(currentData);
+ return currentData;
+ }
+
+ /**
+ * Sets the current color
+ *
+ * @param color the active color to use
+ */
+ public void setColor(Color color) {
+ if (!color.equals(graphicsState.color)) {
+ addObject(new GraphicsSetProcessColor(color));
+ graphicsState.color = color;
+ }
+ }
+
+ /**
+ * Sets the current position
+ *
+ * @param coords the x and y coordinates of the current position
+ */
+ public void setCurrentPosition(int[] coords) {
+ addObject(new GraphicsSetCurrentPosition(coords));
+ }
+
+ /**
+ * Sets the line width
+ *
+ * @param lineWidth the line width multiplier
+ */
+ public void setLineWidth(int lineWidth) {
+ if (lineWidth != graphicsState.lineWidth) {
+ addObject(new GraphicsSetLineWidth(lineWidth));
+ graphicsState.lineWidth = lineWidth;
+ }
+ }
+
+ /**
+ * Sets the line type
+ *
+ * @param lineType the line type
+ */
+ public void setLineType(byte lineType) {
+ if (lineType != graphicsState.lineType) {
+ addObject(new GraphicsSetLineType(lineType));
+ graphicsState.lineType = lineType;
+ }
+ }
+
+ /**
+ * Sets whether the following shape is to be filled
+ *
+ * @param fill true if the following shape is to be filled
+ */
+ public void setFill(boolean fill) {
+ setPatternSymbol(fill ?
+ GraphicsSetPatternSymbol.SOLID_FILL :
+ GraphicsSetPatternSymbol.NO_FILL);
+ }
+
+ /**
+ * Sets the fill pattern of the next shape
+ *
+ * @param the fill pattern of the next shape
+ */
+ public void setPatternSymbol(byte patternSymbol) {
+ if (patternSymbol != graphicsState.patternSymbol) {
+ addObject(new GraphicsSetPatternSymbol(patternSymbol));
+ graphicsState.patternSymbol = patternSymbol;
+ }
+ }
+
+ /**
+ * Sets the character set to use
+ *
+ * @param characterSet the character set (font) reference
+ */
+ public void setCharacterSet(int characterSet) {
+ if (characterSet != graphicsState.characterSet) {
+ addObject(new GraphicsSetCharacterSet(characterSet));
+ graphicsState.characterSet = characterSet;
+ }
+ }
+
+ /**
+ * Adds a line at the given x/y coordinates
+ *
+ * @param coords the x/y coordinates (can be a series)
+ */
+ public void addLine(int[] coords) {
+ addLine(coords, false);
+ }
+
+ /**
+ * Adds a line at the given x/y coordinates
+ *
+ * @param coords the x/y coordinates (can be a series)
+ * @param relative relative true for a line at current position (relative to)
+ */
+ public void addLine(int[] coords, boolean relative) {
+ addObject(new GraphicsLine(coords, relative));
+ }
+
+ /**
+ * Adds a box at the given coordinates
+ *
+ * @param coords the x/y coordinates
+ */
+ public void addBox(int[] coords) {
+ addObject(new GraphicsBox(coords));
+ }
+
+ /**
+ * Adds a fillet (curve) at the given coordinates
+ *
+ * @param coords the x/y coordinates
+ */
+ public void addFillet(int[] coords) {
+ addFillet(coords, false);
+ }
+
+ /**
+ * Adds a fillet (curve) at the given coordinates
+ *
+ * @param coords the x/y coordinates
+ * @param relative relative true for a fillet (curve) at current position (relative to)
+ */
+ public void addFillet(int[] coords, boolean relative) {
+ addObject(new GraphicsFillet(coords, relative));
+ }
+
+ /**
+ * Sets the arc parameters
+ *
+ * @param xmaj the maximum value of the x coordinate
+ * @param ymin the minimum value of the y coordinate
+ * @param xmin the minimum value of the x coordinate
+ * @param ymaj the maximum value of the y coordinate
+ */
+ public void setArcParams(int xmaj, int ymin, int xmin, int ymaj) {
+ addObject(new GraphicsSetArcParameters(xmaj, ymin, xmin, ymaj));
+ }
+
+ /**
+ * Adds a full arc
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param mh the integer portion of the multiplier
+ * @param mhr the fractional portion of the multiplier
+ */
+ public void addFullArc(int x, int y, int mh, int mhr) {
+ addObject(new GraphicsFullArc(x, y, mh, mhr));
+ }
+
+ /**
+ * Adds an image
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the image width
+ * @param height the image height
+ * @param imgData the image data
+ */
+ public void addImage(int x, int y, int width, int height, byte[] imgData) {
+ addObject(new GraphicsImage(x, y, width, height, imgData));
+ }
+
+ /**
+ * Adds a string
+ *
+ * @param str the string
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public void addString(String str, int x, int y) {
+ addObject(new GraphicsCharacterString(str, x, y));
+ }
+
+ /**
+ * Begins a graphics area (start of fill)
+ */
+ public void beginArea() {
+ addObject(new GraphicsAreaBegin());
+ }
+
+ /**
+ * Ends a graphics area (end of fill)
+ */
+ public void endArea() {
+ addObject(new GraphicsAreaEnd());
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "GraphicsObject: " + getName();
+ }
+
+ /**
+ * Creates a new graphics segment
+ */
+ public void newSegment() {
+ getData().newSegment();
+ }
+
+ /** {@inheritDoc} */
+ public void setComplete(boolean complete) {
+ Iterator it = objects.iterator();
+ while (it.hasNext()) {
+ Completable completedObject = (Completable)it.next();
+ completedObject.setComplete(true);
+ }
+ super.setComplete(complete);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ super.writeStart(os);
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.GRAPHICS);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+ writeObjects(objects, os);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.GRAPHICS);
+ os.write(data);
+ }
+
+ /** the internal graphics state */
+ private class GraphicsState {
+ /** the current color */
+ private Color color;
+
+ /** the current line type */
+ private byte lineType;
+
+ /** the current line width */
+ private int lineWidth;
+
+ /** the current fill pattern */
+ private byte patternSymbol;
+
+ /** the current character set */
+ private int characterSet;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java b/src/java/org/apache/fop/afp/modca/IMImageObject.java
index bb43950dd..a09042441 100644
--- a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java
+++ b/src/java/org/apache/fop/afp/modca/IMImageObject.java
@@ -17,11 +17,16 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
+import org.apache.fop.afp.ioca.ImageCellPosition;
+import org.apache.fop.afp.ioca.ImageInputDescriptor;
+import org.apache.fop.afp.ioca.ImageOutputControl;
+import org.apache.fop.afp.ioca.ImageRasterData;
+
/**
* An IM image data object specifies the contents of a raster image and
* its placement on a page, overlay, or page segment. An IM image can be
@@ -60,16 +65,16 @@ public class IMImageObject extends AbstractNamedAFPObject {
/**
* Constructor for the image object with the specified name,
* the name must be a fixed length of eight characters.
+ *
* @param name The name of the image.
*/
public IMImageObject(String name) {
-
super(name);
-
}
/**
* Sets the ImageOutputControl.
+ *
* @param imageOutputControl The imageOutputControl to set
*/
public void setImageOutputControl(ImageOutputControl imageOutputControl) {
@@ -78,6 +83,7 @@ public class IMImageObject extends AbstractNamedAFPObject {
/**
* Sets the ImageCellPosition.
+ *
* @param imageCellPosition The imageCellPosition to set
*/
public void setImageCellPosition(ImageCellPosition imageCellPosition) {
@@ -86,6 +92,7 @@ public class IMImageObject extends AbstractNamedAFPObject {
/**
* Sets the ImageInputDescriptor.
+ *
* @param imageInputDescriptor The imageInputDescriptor to set
*/
public void setImageInputDescriptor(ImageInputDescriptor imageInputDescriptor) {
@@ -94,98 +101,41 @@ public class IMImageObject extends AbstractNamedAFPObject {
/**
* Sets the ImageRastorData.
+ *
* @param imageRasterData The imageRasterData to set
*/
public void setImageRasterData(ImageRasterData imageRasterData) {
this.imageRasterData = imageRasterData;
}
- /**
- * Accessor method to write the AFP datastream for the IM Image Objetc
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
if (imageOutputControl != null) {
- imageOutputControl.writeDataStream(os);
+ imageOutputControl.writeToStream(os);
}
-
if (imageInputDescriptor != null) {
- imageInputDescriptor.writeDataStream(os);
+ imageInputDescriptor.writeToStream(os);
}
-
if (imageCellPosition != null) {
- imageCellPosition.writeDataStream(os);
+ imageCellPosition.writeToStream(os);
}
-
if (imageRasterData != null) {
- imageRasterData.writeDataStream(os);
+ imageRasterData.writeToStream(os);
}
-
- writeEnd(os);
-
}
- /**
- * Helper method to write the start of the IM Image Object.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0x7B; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
+ copySF(data, Type.BEGIN, Category.IM_IMAGE);
os.write(data);
-
}
- /**
- * Helper method to write the end of the IM Image Object.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0x7B; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
+ copySF(data, Type.END, Category.IM_IMAGE);
os.write(data);
-
}
-
}
diff --git a/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java
new file mode 100644
index 000000000..07976e18a
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * ImageDataDescriptor
+ */
+public class ImageDataDescriptor extends AbstractDescriptor {
+
+ /**
+ * Constructor for a ImageDataDescriptor for the specified
+ * resolution, width and height.
+ *
+ * @param width The width of the image.
+ * @param height The height of the height.
+ * @param widthRes The horizontal resolution of the image.
+ * @param heightRes The vertical resolution of the image.
+ */
+ public ImageDataDescriptor(int width, int height, int widthRes, int heightRes) {
+ super(width, height, widthRes, heightRes);
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[22];
+ copySF(data, Type.DESCRIPTOR, Category.IMAGE);
+
+ // SF length
+ byte[] len = BinaryUtils.convert(data.length - 1, 2);
+ data[1] = len[0];
+ data[2] = len[1];
+
+ byte[] x = BinaryUtils.convert(widthRes, 2);
+ data[10] = x[0];
+ data[11] = x[1];
+
+ byte[] y = BinaryUtils.convert(heightRes, 2);
+ data[12] = y[0];
+ data[13] = y[1];
+
+ byte[] w = BinaryUtils.convert(width, 2);
+ data[14] = w[0];
+ data[15] = w[1];
+
+ byte[] h = BinaryUtils.convert(height, 2);
+ data[16] = h[0];
+ data[17] = h[1];
+
+ data[18] = (byte)0xF7; // ID = Set IOCA Function Set
+ data[19] = 0x02; // Length
+ data[20] = 0x01; // Category = Function set identifier
+ data[21] = 0x0B; // FCNSET = IOCA FS 11
+
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/ImageObject.java b/src/java/org/apache/fop/afp/modca/ImageObject.java
new file mode 100644
index 000000000..24ac0cb22
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ImageObject.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPImageObjectInfo;
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.ioca.ImageSegment;
+
+/**
+ * An IOCA Image Data Object
+ */
+public class ImageObject extends AbstractDataObject {
+
+ private static final int MAX_DATA_LEN = 32759;
+
+ /** the image segment */
+ private ImageSegment imageSegment = null;
+
+ /**
+ * Constructor for the image object with the specified name,
+ * the name must be a fixed length of eight characters.
+ *
+ * @param name The name of the image.
+ * @param factory the resource manager
+ */
+ public ImageObject(Factory factory, String name) {
+ super(factory, name);
+ }
+
+ private ImageSegment getImageSegment() {
+ if (imageSegment == null) {
+ this.imageSegment = factory.createImageSegment();
+ }
+ return imageSegment;
+ }
+
+ /** {@inheritDoc} */
+ public void setViewport(AFPDataObjectInfo dataObjectInfo) {
+ super.setViewport(dataObjectInfo);
+
+ AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo;
+ int dataWidth = imageObjectInfo.getDataWidth();
+ int dataHeight = imageObjectInfo.getDataHeight();
+
+// AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
+// int widthRes = objectAreaInfo.getWidthRes();
+// int heightRes = objectAreaInfo.getHeightRes();
+
+ int dataWidthRes = imageObjectInfo.getDataWidthRes();
+ int dataHeightRes = imageObjectInfo.getDataWidthRes();
+ ImageDataDescriptor imageDataDescriptor
+ = factory.createImageDataDescriptor(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
+ getObjectEnvironmentGroup().setDataDescriptor(imageDataDescriptor);
+
+ getImageSegment().setImageSize(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
+ }
+
+ /**
+ * Sets the image encoding.
+ *
+ * @param encoding The image encoding.
+ */
+ public void setEncoding(byte encoding) {
+ getImageSegment().setEncoding(encoding);
+ }
+
+ /**
+ * Sets the image compression.
+ *
+ * @param compression The image compression.
+ */
+ public void setCompression(byte compression) {
+ getImageSegment().setCompression(compression);
+ }
+
+ /**
+ * Sets the image IDE size.
+ *
+ * @param size The IDE size.
+ */
+ public void setIDESize(byte size) {
+ getImageSegment().setIDESize(size);
+ }
+
+ /**
+ * Sets the image IDE color model.
+ *
+ * @param colorModel the IDE color model.
+ */
+ public void setIDEColorModel(byte colorModel) {
+ getImageSegment().setIDEColorModel(colorModel);
+ }
+
+ /**
+ * Set the data of the image.
+ *
+ * @param data the image data
+ */
+ public void setData(byte[] imageData) {
+ getImageSegment().setData(imageData);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.IMAGE);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+
+ if (imageSegment != null) {
+ final byte[] dataHeader = new byte[9];
+ copySF(dataHeader, SF_CLASS, Type.DATA, Category.IMAGE);
+ final int lengthOffset = 1;
+
+ // TODO save memory!
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ imageSegment.writeToStream(baos);
+ byte[] data = baos.toByteArray();
+ writeChunksToStream(data, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.IMAGE);
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/IncludeObject.java b/src/java/org/apache/fop/afp/modca/IncludeObject.java
new file mode 100644
index 000000000..2dff6bd87
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/IncludeObject.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
+import org.apache.fop.afp.modca.triplets.MeasurementUnitsTriplet;
+import org.apache.fop.afp.modca.triplets.ObjectAreaSizeTriplet;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * An Include Object structured field references an object on a page or overlay.
+ * It optionally contains parameters that identify the object and that specify
+ * presentation parameters such as object position, size, orientation, mapping,
+ * and default color.
+ * <p>
+ * Where the presentation parameters conflict with parameters specified in the
+ * object's environment group (OEG), the parameters in the Include Object
+ * structured field override. If the referenced object is a page segment, the
+ * IOB parameters override the corresponding environment group parameters on all
+ * data objects in the page segment.
+ * </p>
+ */
+public class IncludeObject extends AbstractNamedAFPObject {
+
+ /** the object referenced is of type page segment */
+ public static final byte TYPE_PAGE_SEGMENT = (byte)0x5F;
+
+ /** the object referenced is of type other */
+ public static final byte TYPE_OTHER = (byte)0x92;
+
+ /** the object referenced is of type graphic */
+ public static final byte TYPE_GRAPHIC = (byte)0xBB;
+
+ /** the object referenced is of type barcode */
+ public static final byte TYPE_BARCODE = (byte)0xEB;
+
+ /** the object referenced is of type image */
+ public static final byte TYPE_IMAGE = (byte)0xFB;
+
+
+ /** the object type referenced (default is other) */
+ private byte objectType = TYPE_OTHER;
+
+ /** the X-axis origin of the object area */
+ private int xoaOset = 0;
+
+ /** the Y-axis origin of the object area */
+ private int yoaOset = 0;
+
+ /** the orientation of the referenced object */
+ private int oaOrent = 0;
+
+ /** the X-axis origin defined in the object */
+ private int xocaOset = -1;
+
+ /** the Y-axis origin defined in the object */
+ private int yocaOset = -1;
+
+ /**
+ * Constructor for the include object with the specified name, the name must
+ * be a fixed length of eight characters and is the name of the referenced
+ * object.
+ *
+ * @param name the name of this include object
+ */
+ public IncludeObject(String name) {
+ super(name);
+ }
+
+ /**
+ * Sets the orientation to use for the Include Object.
+ *
+ * @param orientation
+ * The orientation (0,90, 180, 270)
+ */
+ public void setObjectAreaOrientation(int orientation) {
+ if (orientation == 0 || orientation == 90 || orientation == 180
+ || orientation == 270) {
+ this.oaOrent = orientation;
+ } else {
+ throw new IllegalArgumentException(
+ "The orientation must be one of the values 0, 90, 180, 270");
+ }
+ }
+
+ /**
+ * Sets the x and y offset to the origin in the object area
+ *
+ * @param x the X-axis origin of the object area
+ * @param y the Y-axis origin of the object area
+ */
+ public void setObjectAreaOffset(int x, int y) {
+ this.xoaOset = x;
+ this.yoaOset = y;
+ }
+
+ /**
+ * Sets the x and y offset of the content area to the object area
+ * used in conjunction with the {@link MappingOptionTriplet.POSITION} and
+ * {@link MappingOptionTriplet.POSITION_AND_TRIM}.
+ *
+ * @param x the X-axis origin defined in the object
+ * @param y the Y-axis origin defined in the object
+ */
+ public void setContentAreaOffset(int x, int y) {
+ this.xocaOset = x;
+ this.yocaOset = y;
+ }
+
+ /**
+ * Sets the data object type
+ *
+ * @param type the data object type
+ */
+ public void setObjectType(byte type) {
+ this.objectType = type;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[36];
+ super.copySF(data, Type.INCLUDE, Category.DATA_RESOURCE);
+
+ // Set the total record length
+ int tripletDataLength = getTripletDataLength();
+ byte[] len = BinaryUtils.convert(35 + tripletDataLength, 2); //Ignore first byte
+ data[1] = len[0];
+ data[2] = len[1];
+
+ data[17] = 0x00; // reserved
+ data[18] = objectType;
+
+ //XoaOset (object area)
+ if (xoaOset > -1) {
+ byte[] x = BinaryUtils.convert(xoaOset, 3);
+ data[19] = x[0];
+ data[20] = x[1];
+ data[21] = x[2];
+ } else {
+ data[19] = (byte)0xFF;
+ data[20] = (byte)0xFF;
+ data[21] = (byte)0xFF;
+ }
+
+ // YoaOset (object area)
+ if (yoaOset > -1) {
+ byte[] y = BinaryUtils.convert(yoaOset, 3);
+ data[22] = y[0];
+ data[23] = y[1];
+ data[24] = y[2];
+ } else {
+ data[22] = (byte)0xFF;
+ data[23] = (byte)0xFF;
+ data[24] = (byte)0xFF;
+ }
+
+ // XoaOrent/YoaOrent
+ switch (oaOrent) {
+ case -1: // use x/y axis orientation defined in object
+ data[25] = (byte)0xFF; // x axis rotation
+ data[26] = (byte)0xFF; //
+ data[27] = (byte)0xFF; // y axis rotation
+ data[28] = (byte)0xFF;
+ break;
+ case 90:
+ data[25] = 0x2D;
+ data[26] = 0x00;
+ data[27] = 0x5A;
+ data[28] = 0x00;
+ break;
+ case 180:
+ data[25] = 0x5A;
+ data[25] = 0x00;
+ data[27] = (byte)0x87;
+ data[28] = 0x00;
+ break;
+ case 270:
+ data[25] = (byte)0x87;
+ data[26] = 0x00;
+ data[27] = 0x00;
+ data[28] = 0x00;
+ break;
+ default: // 0 degrees
+ data[25] = 0x00;
+ data[26] = 0x00;
+ data[27] = 0x2D;
+ data[28] = 0x00;
+ break;
+ }
+
+ // XocaOset (object content)
+ if (xocaOset > -1) {
+ byte[] x = BinaryUtils.convert(xocaOset, 3);
+ data[29] = x[0];
+ data[30] = x[1];
+ data[31] = x[2];
+ } else {
+ data[29] = (byte)0xFF;
+ data[30] = (byte)0xFF;
+ data[31] = (byte)0xFF;
+ }
+
+ // YocaOset (object content)
+ if (yocaOset > -1) {
+ byte[] y = BinaryUtils.convert(yocaOset, 3);
+ data[32] = y[0];
+ data[33] = y[1];
+ data[34] = y[2];
+ } else {
+ data[32] = (byte)0xFF;
+ data[33] = (byte)0xFF;
+ data[34] = (byte)0xFF;
+ }
+ // RefCSys (Reference coordinate system)
+ data[35] = 0x01; // Page or overlay coordinate system
+
+ // Write structured field data
+ os.write(data);
+
+ // Write triplet for FQN internal/external object reference
+ writeTriplets(os);
+ }
+
+ private String getObjectTypeName() {
+ String objectTypeName = null;
+ if (objectType == TYPE_PAGE_SEGMENT) {
+ objectTypeName = "page segment";
+ } else if (objectType == TYPE_OTHER) {
+ objectTypeName = "other";
+ } else if (objectType == TYPE_GRAPHIC) {
+ objectTypeName = "graphic";
+ } else if (objectType == TYPE_BARCODE) {
+ objectTypeName = "barcode";
+ } else if (objectType == TYPE_IMAGE) {
+ objectTypeName = "image";
+ }
+ return objectTypeName;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "IncludeObject{name=" + this.getName()
+ + ", objectType=" + getObjectTypeName()
+ + ", xoaOset=" + xoaOset
+ + ", yoaOset=" + yoaOset
+ + ", oaOrent" + oaOrent
+ + ", xocaOset=" + xocaOset
+ + ", yocaOset=" + yocaOset
+ + "}";
+ }
+
+ /**
+ * Sets the mapping option
+ *
+ * @param optionValue the mapping option value
+ */
+ public void setMappingOption(byte optionValue) {
+ addTriplet(new MappingOptionTriplet(optionValue));
+ }
+
+ /**
+ * Sets the extent of an object area in the X and Y directions
+ *
+ * @param x the x direction extent
+ * @param y the y direction extent
+ */
+ public void setObjectAreaSize(int x, int y) {
+ addTriplet(new ObjectAreaSizeTriplet(x, y));
+ }
+
+ /**
+ * Sets the measurement units used to specify the units of measure
+ *
+ * @param xRes units per base on the x-axis
+ * @param yRes units per base on the y-axis
+ */
+ public void setMeasurementUnits(int xRes, int yRes) {
+ addTriplet(new MeasurementUnitsTriplet(xRes, xRes));
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java b/src/java/org/apache/fop/afp/modca/IncludePageOverlay.java
index 7c52fe0a2..44f0edc5b 100644
--- a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java
+++ b/src/java/org/apache/fop/afp/modca/IncludePageOverlay.java
@@ -17,12 +17,12 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.afp.util.BinaryUtils;
/**
*
@@ -56,6 +56,7 @@ public class IncludePageOverlay extends AbstractNamedAFPObject {
/**
* Constructor for the Include Page Overlay
+ *
* @param overlayName Name of the page segment
* @param x The x position
* @param y The y position
@@ -63,13 +64,14 @@ public class IncludePageOverlay extends AbstractNamedAFPObject {
*/
public IncludePageOverlay(String overlayName, int x, int y, int orientation) {
super(overlayName);
+
this.x = x;
this.y = y;
setOrientation(orientation);
}
/**
- * Sets the orienation to use for the overlay.
+ * Sets the orientation to use for the overlay.
*
* @param orientation
* The orientation (0,90, 180, 270)
@@ -84,45 +86,25 @@ public class IncludePageOverlay extends AbstractNamedAFPObject {
}
}
- /**
- * Accessor method to write the AFP datastream for the Include Page Overlay
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[25]; //(9 +16)
-
- data[0] = 0x5A;
+ copySF(data, Type.INCLUDE, Category.PAGE_OVERLAY);
// Set the total record length
byte[] len = BinaryUtils.convert(24, 2); //Ignore first byte
data[1] = len[0];
data[2] = len[1];
- // Structured field ID for a IPO
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xAF;
- data[5] = (byte) 0xD8;
-
- data[6] = 0x00; // Reserved
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
- data[9 + i] = nameBytes[i];
- }
-
- byte[] xcoord = BinaryUtils.convert(x, 3);
- data[17] = xcoord[0]; // x coordinate
- data[18] = xcoord[1];
- data[19] = xcoord[2];
+ byte[] xPos = BinaryUtils.convert(x, 3);
+ data[17] = xPos[0]; // x coordinate
+ data[18] = xPos[1];
+ data[19] = xPos[2];
- byte[] ycoord = BinaryUtils.convert(y, 3);
- data[20] = ycoord[0]; // y coordinate
- data[21] = ycoord[1];
- data[22] = ycoord[2];
+ byte[] yPos = BinaryUtils.convert(y, 3);
+ data[20] = yPos[0]; // y coordinate
+ data[21] = yPos[1];
+ data[22] = yPos[2];
switch (orientation) {
case 90:
diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java b/src/java/org/apache/fop/afp/modca/IncludePageSegment.java
index 7792a7162..7355e3b1a 100644
--- a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java
+++ b/src/java/org/apache/fop/afp/modca/IncludePageSegment.java
@@ -17,12 +17,12 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The Include Page Segment structured field references a page segment resource
@@ -45,64 +45,46 @@ public class IncludePageSegment extends AbstractNamedAFPObject {
/**
* The x position where we need to put this object on the page
*/
- private byte[] x;
-
+ private int x;
+
/**
* The y position where we need to put this object on the page
*/
- private byte[] y;
-
+ private int y;
+
/**
* Constructor for the Include Page Segment
+ *
* @param name Name of the page segment
* @param x The x position
* @param y The y position
*/
public IncludePageSegment(String name, int x, int y) {
-
super(name);
- this.x = BinaryUtils.convert(x, 3);
- this.y = BinaryUtils.convert(y, 3);
-
+
+ this.x = x;
+ this.y = y;
}
- /**
- * Accessor method to write the AFP datastream for the Include Page Segment
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[23]; //(9 +14)
-
- data[0] = 0x5A;
+ copySF(data, Type.INCLUDE, Category.PAGE_SEGMENT);
// Set the total record length
- byte[] rl1 = BinaryUtils.convert(22, 2); //Ignore first byte
- data[1] = rl1[0];
- data[2] = rl1[1];
-
- // Structured field ID for a IPS
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xAF;
- data[5] = (byte) 0x5F;
-
- data[6] = 0x00; // Reserved
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
- data[9 + i] = nameBytes[i];
- }
-
- data[17] = x[0]; // x coordinate
- data[18] = x[1];
- data[19] = x[2];
-
- data[20] = y[0]; // y coordinate
- data[21] = y[1];
- data[22] = y[2];
+ byte[] len = BinaryUtils.convert(22, 2); //Ignore first byte
+ data[1] = len[0];
+ data[2] = len[1];
+
+ byte[] xPos = BinaryUtils.convert(x, 3);
+ data[17] = xPos[0]; // x coordinate
+ data[18] = xPos[1];
+ data[19] = xPos[2];
+
+ byte[] yPos = BinaryUtils.convert(y, 3);
+ data[20] = yPos[0]; // y coordinate
+ data[21] = yPos[1];
+ data[22] = yPos[2];
os.write(data);
}
diff --git a/src/java/org/apache/fop/afp/modca/InterchangeSet.java b/src/java/org/apache/fop/afp/modca/InterchangeSet.java
new file mode 100644
index 000000000..28a4da42b
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/InterchangeSet.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+/**
+ * MO:DCA Interchange Set
+ */
+public class InterchangeSet {
+ /** interchange set 1 string value */
+ public static final String MODCA_PRESENTATION_INTERCHANGE_SET_1 = "MO:DCA-P IS/1";
+
+ /** interchange set 2 string value */
+ public static final String MODCA_PRESENTATION_INTERCHANGE_SET_2 = "MO:DCA-P IS/2";
+
+ /** resource interchange set string value */
+ public static final String MODCA_RESOURCE_INTERCHANGE_SET = "MO:DCA-L";
+
+ private static final String[] NAMES = {
+ MODCA_PRESENTATION_INTERCHANGE_SET_1,
+ MODCA_PRESENTATION_INTERCHANGE_SET_2,
+ MODCA_RESOURCE_INTERCHANGE_SET
+ };
+
+ private static final int SET_1 = 0;
+ private static final int SET_2 = 1;
+ private static final int RESOURCE_SET = 2;
+
+ /** the actual interchange set in use */
+ private int value;
+
+ /**
+ * Returns the interchange set value of a given string
+ *
+ * @param str an interchange set value
+ * @return an interchange set
+ */
+ public static InterchangeSet valueOf(String str) {
+ if (MODCA_PRESENTATION_INTERCHANGE_SET_1.equals(str)) {
+ return new InterchangeSet(SET_1);
+ } else if (MODCA_PRESENTATION_INTERCHANGE_SET_2.equals(str)) {
+ return new InterchangeSet(SET_2);
+ } else if (MODCA_RESOURCE_INTERCHANGE_SET.equals(str)) {
+ return new InterchangeSet(RESOURCE_SET);
+ } else {
+ throw new IllegalArgumentException("Invalid MO:DCA interchange set :" + str);
+ }
+ }
+
+ /**
+ * Main constructor
+ *
+ * @param value the interchange set value
+ */
+ public InterchangeSet(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns true if complies with MOD:CA interchange set 1
+ *
+ * @return true if complies with MOD:CA interchange set 1
+ */
+ protected boolean is1() {
+ return value == SET_1;
+ }
+
+ /**
+ * Returns true if complies with MOD:CA interchange set 2
+ *
+ * @return true if complies with MOD:CA interchange set 2
+ */
+ public boolean is2() {
+ return value == SET_2;
+ }
+
+ /**
+ * Returns true if complies with MOD:CA resource set
+ *
+ * @return true if complies with MOD:CA resource set
+ */
+ public boolean isResource() {
+ return value == RESOURCE_SET;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return NAMES[value];
+ }
+
+ /**
+ * Returns true if MOD:CA interchange set 2 (resource groups) is supported
+ *
+ * @return true if MOD:CA interchange set 2 (resource groups) is supported
+ */
+ public boolean supportsLevel2() {
+ return is2() || isResource();
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java b/src/java/org/apache/fop/afp/modca/InvokeMediumMap.java
index f38096ade..f910a0b9c 100644
--- a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java
+++ b/src/java/org/apache/fop/afp/modca/InvokeMediumMap.java
@@ -17,12 +17,12 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The Invoke Medium Map structured field identifies the Medium Map that is to
@@ -34,48 +34,24 @@ public class InvokeMediumMap extends AbstractNamedAFPObject {
/**
* Constructor for the Invoke Medium Map
- * @param mediumMapName Name of the medium map
+ *
+ * @param name the name of the medium map
*/
- public InvokeMediumMap(String mediumMapName) {
-
- super(mediumMapName);
-
+ public InvokeMediumMap(String name) {
+ super(name);
}
- /**
- * Accessor method to write the AFP datastream for the Invoke Medium Map
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[17];
-
- data[0] = 0x5A;
+ copySF(data, Type.MAP, Category.MEDIUM_MAP);
// Set the total record length
- byte[] rl1 = BinaryUtils.convert(16, 2); //Ignore first byte
- data[1] = rl1[0];
- data[2] = rl1[1];
-
- // Structured field ID for a IPO
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xAB;
- data[5] = (byte) 0xCC;
-
- data[6] = 0x00; // Reserved
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
+ byte[] len = BinaryUtils.convert(16, 2); //Ignore first byte
+ data[1] = len[0];
+ data[2] = len[1];
os.write(data);
-
}
-
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java b/src/java/org/apache/fop/afp/modca/MapCodedFont.java
index f0f372fcb..54b4d1796 100644
--- a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java
+++ b/src/java/org/apache/fop/afp/modca/MapCodedFont.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -26,12 +26,13 @@ import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;
-import org.apache.fop.render.afp.exceptions.FontRuntimeException;
-import org.apache.fop.render.afp.fonts.AFPFont;
-import org.apache.fop.render.afp.fonts.CharacterSet;
-import org.apache.fop.render.afp.fonts.OutlineFont;
-import org.apache.fop.render.afp.fonts.RasterFont;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.fonts.AFPFont;
+import org.apache.fop.afp.fonts.CharacterSet;
+import org.apache.fop.afp.fonts.FontRuntimeException;
+import org.apache.fop.afp.fonts.OutlineFont;
+import org.apache.fop.afp.fonts.RasterFont;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The Map Coded Font structured field maps a unique coded font resource local
@@ -39,46 +40,29 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
* descriptor, to the identifier of a coded font resource object. Additionally,
* the Map Coded Font structured field specifies a set of resource attributes
* for the coded font.
- *
- * @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a>
*/
-public class MapCodedFont extends AbstractAFPObject {
+public class MapCodedFont extends AbstractStructuredObject {
- /**
- * The collection of map coded fonts (maximum of 254)
- */
- private List fontList = null;
+ /** the collection of map coded fonts (maximum of 254) */
+ private final List/*<FontDefinition>*/ fontList
+ = new java.util.ArrayList/*<FontDefinition>*/();
/**
- * Constructor for the MapCodedFont
+ * Main constructor
*/
public MapCodedFont() {
-
- fontList = new java.util.ArrayList();
-
}
- /**
- * Accessor method to write the AFP datastream for the Map Coded Font
- * @param os The stream to write to
- * @throws java.io.IOException an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os) throws IOException {
-
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- baos.write(0x5A);
- baos.write(new byte[] {0x00, 0x00});
-
- // Field identifier for a MapCodedFont
- baos.write(new byte[] {(byte) 0xD3, (byte) 0xAB, (byte) 0x8A});
-
- // Reserved
- baos.write(new byte[] {0x00, 0x00, 0x00});
+ byte[] startData = new byte[9];
+ copySF(startData, Type.MAP, Category.CODED_FONT);
+ baos.write(startData);
Iterator iter = fontList.iterator();
while (iter.hasNext()) {
-
FontDefinition fd = (FontDefinition) iter.next();
// Start of repeating groups (occurs 1 to 254)
@@ -138,7 +122,6 @@ public class MapCodedFont extends AbstractAFPObject {
baos.write(0x5D);
baos.write(BinaryUtils.convert(fd.scale, 2));
}
-
}
byte[] data = baos.toByteArray();
@@ -149,7 +132,6 @@ public class MapCodedFont extends AbstractAFPObject {
data[2] = rl1[1];
os.write(data);
-
}
/**
@@ -168,29 +150,27 @@ public class MapCodedFont extends AbstractAFPObject {
public void addFont(int fontReference, AFPFont font, int size, int orientation)
throws MaximumSizeExceededException {
- FontDefinition fd = new FontDefinition();
+ FontDefinition fontDefinition = new FontDefinition();
- fd.fontReferenceKey = BinaryUtils.convert(fontReference)[0];
+ fontDefinition.fontReferenceKey = BinaryUtils.convert(fontReference)[0];
switch (orientation) {
case 90:
- fd.orientation = 0x2D;
+ fontDefinition.orientation = 0x2D;
break;
case 180:
- fd.orientation = 0x5A;
+ fontDefinition.orientation = 0x5A;
break;
case 270:
- fd.orientation = (byte) 0x87;
+ fontDefinition.orientation = (byte) 0x87;
break;
default:
- fd.orientation = 0x00;
+ fontDefinition.orientation = 0x00;
break;
}
try {
-
if (font instanceof RasterFont) {
-
RasterFont raster = (RasterFont) font;
CharacterSet cs = raster.getCharacterSet(size);
if (cs == null) {
@@ -200,45 +180,43 @@ public class MapCodedFont extends AbstractAFPObject {
throw new FontRuntimeException(msg);
}
- fd.characterSet = cs.getNameBytes();
+ fontDefinition.characterSet = cs.getNameBytes();
- if (fd.characterSet.length != 8) {
+ if (fontDefinition.characterSet.length != 8) {
throw new IllegalArgumentException("The character set "
- + new String(fd.characterSet,
+ + new String(fontDefinition.characterSet,
AFPConstants.EBCIDIC_ENCODING)
+ " must have a fixed length of 8 characters.");
}
- fd.codePage = cs.getCodePage().getBytes(
+ fontDefinition.codePage = cs.getCodePage().getBytes(
AFPConstants.EBCIDIC_ENCODING);
- if (fd.codePage.length != 8) {
+ if (fontDefinition.codePage.length != 8) {
throw new IllegalArgumentException("The code page "
- + new String(fd.codePage,
+ + new String(fontDefinition.codePage,
AFPConstants.EBCIDIC_ENCODING)
+ " must have a fixed length of 8 characters.");
}
} else if (font instanceof OutlineFont) {
-
OutlineFont outline = (OutlineFont) font;
CharacterSet cs = outline.getCharacterSet();
- fd.characterSet = cs.getNameBytes();
+ fontDefinition.characterSet = cs.getNameBytes();
// There are approximately 72 points to 1 inch or 20 1440ths per point.
- fd.scale = ((size / 1000) * 20);
+ fontDefinition.scale = ((size / 1000) * 20);
- fd.codePage = cs.getCodePage().getBytes(
+ fontDefinition.codePage = cs.getCodePage().getBytes(
AFPConstants.EBCIDIC_ENCODING);
- if (fd.codePage.length != 8) {
+ if (fontDefinition.codePage.length != 8) {
throw new IllegalArgumentException("The code page "
- + new String(fd.codePage,
+ + new String(fontDefinition.codePage,
AFPConstants.EBCIDIC_ENCODING)
+ " must have a fixed length of 8 characters.");
}
-
} else {
String msg = "Font of type " + font.getClass().getName()
+ " not recognized.";
@@ -247,22 +225,19 @@ public class MapCodedFont extends AbstractAFPObject {
}
if (fontList.size() > 253) {
-
// Throw an exception if the size is exceeded
throw new MaximumSizeExceededException();
-
} else {
- fontList.add(fd);
+ fontList.add(fontDefinition);
}
} catch (UnsupportedEncodingException ex) {
-
throw new FontRuntimeException("Failed to create font "
+ " due to a UnsupportedEncodingException", ex);
-
}
}
+
/**
* Private utility class used as a container for font attributes
*/
@@ -292,7 +267,6 @@ public class MapCodedFont extends AbstractAFPObject {
* The scale (only specified for outline fonts)
*/
private int scale = 0;
-
}
-} \ No newline at end of file
+}
diff --git a/src/java/org/apache/fop/afp/modca/MapContainerData.java b/src/java/org/apache/fop/afp/modca/MapContainerData.java
new file mode 100644
index 000000000..8411592aa
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/MapContainerData.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Map Container Data structured field specifies how a presentation data object
+ * that is carried in an Object Container is mapped into its object area.
+ */
+public class MapContainerData extends AbstractTripletStructuredObject {
+
+ /**
+ * Main constructor
+ *
+ * @param optionValue the mapping option value
+ */
+ public MapContainerData(byte optionValue) {
+ super.addTriplet(new MappingOptionTriplet(optionValue));
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[11];
+ copySF(data, Type.MAP, Category.OBJECT_CONTAINER);
+ int tripletLen = getTripletDataLength();
+
+ byte[] len = BinaryUtils.convert(10 + tripletLen, 2);
+ data[1] = len[0];
+ data[2] = len[1];
+
+ len = BinaryUtils.convert(2 + tripletLen, 2);
+ data[9] = len[0];
+ data[10] = len[1];
+ os.write(data);
+ writeTriplets(os);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/MapDataResource.java b/src/java/org/apache/fop/afp/modca/MapDataResource.java
new file mode 100644
index 000000000..566f60ce5
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/MapDataResource.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Map Data Resource structured field specifies resources that are
+ * required for presentation.
+ */
+public class MapDataResource extends AbstractTripletStructuredObject {
+
+ /**
+ * Main constructor
+ */
+ public MapDataResource() {
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ super.writeStart(os);
+ byte[] data = new byte[11];
+ copySF(data, Type.MAP, Category.DATA_RESOURCE);
+
+ int tripletDataLen = getTripletDataLength();
+
+ byte[] len = BinaryUtils.convert(10 + tripletDataLen, 2);
+ data[1] = len[0];
+ data[2] = len[1];
+
+ len = BinaryUtils.convert(2 + tripletDataLen, 2);
+ data[9] = len[0];
+ data[10] = len[1];
+
+ os.write(data);
+ writeTriplets(os);
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java b/src/java/org/apache/fop/afp/modca/MapPageOverlay.java
index 129a3f5a1..9fd3c7059 100644
--- a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java
+++ b/src/java/org/apache/fop/afp/modca/MapPageOverlay.java
@@ -17,14 +17,15 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The Map Page Overlay structured field maps a Resource Local ID to the name of
@@ -33,18 +34,26 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class MapPageOverlay extends AbstractAFPObject {
+ private static final int MAX_SIZE = 253;
+
/**
* The collection of overlays (maximum of 254 stored as byte[])
*/
- private List overLays = new java.util.ArrayList();
+ private List overLays = null;
/**
* Constructor for the Map Page Overlay
*/
public MapPageOverlay() {
-
}
+ private List getOverlays() {
+ if (overLays == null) {
+ this.overLays = new java.util.ArrayList();
+ }
+ return this.overLays;
+ }
+
/**
* Add an overlay to to the map page overlay object.
*
@@ -53,36 +62,28 @@ public class MapPageOverlay extends AbstractAFPObject {
* @throws MaximumSizeExceededException if the maximum size is reached
*/
public void addOverlay(String name) throws MaximumSizeExceededException {
-
- if (overLays.size() > 253) {
+ if (getOverlays().size() > MAX_SIZE) {
throw new MaximumSizeExceededException();
}
-
if (name.length() != 8) {
throw new IllegalArgumentException("The name of overlay " + name
+ " must be 8 characters");
}
-
if (log.isDebugEnabled()) {
log.debug("addOverlay():: adding overlay " + name);
}
-
try {
byte[] data = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
- overLays.add(data);
+ getOverlays().add(data);
} catch (UnsupportedEncodingException usee) {
log.error("addOverlay():: UnsupportedEncodingException translating the name "
+ name);
}
}
- /**
- * Accessor method to write the AFP datastream for the Map Page Overlay
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occurred
- */
- public void writeDataStream(OutputStream os) throws IOException {
- int oLayCount = overLays.size();
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ int oLayCount = getOverlays().size();
int recordlength = oLayCount * 18;
byte[] data = new byte[recordlength + 9];
@@ -98,8 +99,8 @@ public class MapPageOverlay extends AbstractAFPObject {
// Structured field ID for a MPO
data[3] = (byte) 0xD3;
- data[4] = (byte) 0xAB;
- data[5] = (byte) 0xD8;
+ data[4] = (byte) Type.MAP;
+ data[5] = (byte) Category.PAGE_OVERLAY;
data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
diff --git a/src/java/org/apache/fop/render/afp/modca/MaximumSizeExceededException.java b/src/java/org/apache/fop/afp/modca/MaximumSizeExceededException.java
index a66fa9b30..6d1c74156 100644
--- a/src/java/org/apache/fop/render/afp/modca/MaximumSizeExceededException.java
+++ b/src/java/org/apache/fop/afp/modca/MaximumSizeExceededException.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
/**
* An exception to handle maximum sizes being exceeded.
diff --git a/src/java/org/apache/fop/render/afp/modca/NoOperation.java b/src/java/org/apache/fop/afp/modca/NoOperation.java
index 54515a070..cb5841346 100644
--- a/src/java/org/apache/fop/render/afp/modca/NoOperation.java
+++ b/src/java/org/apache/fop/afp/modca/NoOperation.java
@@ -17,12 +17,13 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The No Operation structured field may be used to carry comments
@@ -60,7 +61,7 @@ public class NoOperation extends AbstractAFPObject {
* @param os The outputsteam stream
* @throws java.io.IOException if an I/O exception occurs during processing
*/
- public void writeDataStream(OutputStream os) throws IOException {
+ public void writeToStream(OutputStream os) throws IOException {
byte[] contentData = content.getBytes(AFPConstants.EBCIDIC_ENCODING);
int contentLen = contentData.length;
diff --git a/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java
new file mode 100644
index 000000000..25323b864
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.triplets.DescriptorPositionTriplet;
+import org.apache.fop.afp.modca.triplets.MeasurementUnitsTriplet;
+import org.apache.fop.afp.modca.triplets.ObjectAreaSizeTriplet;
+import org.apache.fop.afp.modca.triplets.PresentationSpaceResetMixingTriplet;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Object Area Descriptor structured field specifies the size and attributes
+ * of an object area presentation space.
+ */
+public class ObjectAreaDescriptor extends AbstractDescriptor {
+
+ /**
+ * Construct an object area descriptor for the specified object width
+ * and object height.
+ *
+ * @param width the object width.
+ * @param height the object height.
+ * @param widthRes the object width resolution.
+ * @param heightRes the object height resolution.
+ */
+ public ObjectAreaDescriptor(int width, int height, int widthRes, int heightRes) {
+ super(width, height, widthRes, heightRes);
+ }
+
+ private static final byte OBJECT_AREA_POSITION_ID = 0x01;
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[9];
+ copySF(data, Type.DESCRIPTOR, Category.OBJECT_AREA);
+
+ addTriplet(new DescriptorPositionTriplet(OBJECT_AREA_POSITION_ID));
+ addTriplet(new MeasurementUnitsTriplet(widthRes, heightRes));
+ addTriplet(new ObjectAreaSizeTriplet(width, height));
+ addTriplet(new PresentationSpaceResetMixingTriplet(
+ PresentationSpaceResetMixingTriplet.NOT_RESET));
+
+ int tripletDataLength = getTripletDataLength();
+ byte[] len = BinaryUtils.convert(data.length + tripletDataLength - 1, 2);
+ data[1] = len[0]; // Length
+ data[2] = len[1];
+ os.write(data);
+
+ writeTriplets(os);
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java
new file mode 100644
index 000000000..3929c1196
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Object Area Position structured field specifies the origin and
+ * orientation of the object area, and the origin and orientation of the
+ * object content within the object area.
+ */
+public class ObjectAreaPosition extends AbstractAFPObject {
+
+ private final int x;
+ private final int y;
+ private final int rotation;
+ private int xOffset;
+ private int yOffset;
+
+ /**
+ * Construct an object area position for the specified object y, y position.
+ *
+ * @param x The x coordinate.
+ * @param y The y coordinate.
+ * @param rotation The coordinate system rotation (must be 0, 90, 180, 270).
+ */
+ public ObjectAreaPosition(int x, int y, int rotation) {
+ this.x = x;
+ this.y = y;
+ this.rotation = rotation;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[33];
+ copySF(data, Type.POSITION, Category.OBJECT_AREA);
+
+ byte[] len = BinaryUtils.convert(32, 2);
+ data[1] = len[0]; // Length
+ data[2] = len[1];
+
+ data[9] = 0x01; // OAPosID = 1
+ data[10] = 0x17; // RGLength = 23
+
+ byte[] xcoord = BinaryUtils.convert(x, 3);
+ data[11] = xcoord[0]; // XoaOSet
+ data[12] = xcoord[1];
+ data[13] = xcoord[2];
+
+ byte[] ycoord = BinaryUtils.convert(y, 3);
+ data[14] = ycoord[0]; // YoaOSet
+ data[15] = ycoord[1];
+ data[16] = ycoord[2];
+
+ byte xorient = (byte)(rotation / 2);
+ data[17] = xorient; // XoaOrent
+
+ byte yorient = (byte)(rotation / 2 + 45);
+ data[19] = yorient; // YoaOrent
+
+ byte[] xoffset = BinaryUtils.convert(xOffset, 3);
+ data[22] = xoffset[0]; // XocaOSet
+ data[23] = xoffset[1];
+ data[24] = xoffset[2];
+
+ byte[] yoffset = BinaryUtils.convert(yOffset, 3);
+ data[25] = yoffset[0]; // YocaOSet
+ data[26] = yoffset[1];
+ data[27] = yoffset[2];
+
+ data[28] = 0x00; // XocaOrent
+ data[29] = 0x00;
+
+ data[30] = 0x2D; // YocaOrent
+ data[31] = 0x00;
+
+ data[32] = 0x01; // RefCSys
+
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "ObjectAreaPosition{"
+ + "x=" + x
+ + ", y=" + y
+ + ", rotation=" + rotation
+ + ", rotation=" + rotation
+ + ", xOffset=" + xOffset
+ + ", yOffset=" + yOffset;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/afp/modca/ObjectContainer.java
new file mode 100644
index 000000000..39b935d01
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ObjectContainer.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * Object containers are MO:DCA objects that envelop and carry object data.
+ */
+public class ObjectContainer extends AbstractDataObject {
+
+ /** the object container data maximum length */
+ private static final int MAX_DATA_LEN = 32759;
+
+ private byte[] data;
+
+ /**
+ * Main constructor
+ *
+ * @param factory the object factory
+ * @param name the name of this object container
+ */
+ public ObjectContainer(Factory factory, String name) {
+ super(factory, name);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] headerData = new byte[17];
+ copySF(headerData, Type.BEGIN, Category.OBJECT_CONTAINER);
+
+ // Set the total record length
+ int containerLen = headerData.length + getTripletDataLength() - 1;
+ byte[] len = BinaryUtils.convert(containerLen, 2);
+ headerData[1] = len[0]; // Length byte 1
+ headerData[2] = len[1]; // Length byte 2
+
+ os.write(headerData);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os); // write triplets and OEG
+
+ // write OCDs
+ byte[] dataHeader = new byte[9];
+ copySF(dataHeader, SF_CLASS, Type.DATA, Category.OBJECT_CONTAINER);
+ final int lengthOffset = 1;
+
+ if (data != null) {
+ writeChunksToStream(data, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.OBJECT_CONTAINER);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public void setViewport(AFPDataObjectInfo dataObjectInfo) {
+ AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
+ AFPResourceLevel resourceLevel = resourceInfo.getLevel();
+
+ // only need to set MCD and CDD when OC when is inlined (pre-2000 apps)
+ if (resourceLevel.isInline()) {
+ super.setViewport(dataObjectInfo);
+
+ MapContainerData mapContainerData
+ = factory.createMapContainerData(MappingOptionTriplet.SCALE_TO_FIT);
+ getObjectEnvironmentGroup().setMapContainerData(mapContainerData);
+
+ int dataWidth = dataObjectInfo.getDataWidth();
+ int dataHeight = dataObjectInfo.getDataHeight();
+
+ AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
+ int widthRes = objectAreaInfo.getWidthRes();
+ int heightRes = objectAreaInfo.getHeightRes();
+
+ ContainerDataDescriptor containerDataDescriptor
+ = factory.createContainerDataDescriptor(
+ dataWidth, dataHeight, widthRes, heightRes);
+ getObjectEnvironmentGroup().setDataDescriptor(containerDataDescriptor);
+ }
+ }
+
+ /**
+ * Sets the inputstream for the the object container data
+ *
+ * @param inputStream the inputstream for the object container data
+ */
+ public void setData(byte[] data) {
+ this.data = data;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java
new file mode 100644
index 000000000..bc0cc5a63
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * An Object Environment Group (OEG) may be associated with an object and is contained
+ * within the object's begin-end envelope.
+ * The object environment group defines the object's origin and orientation on the page,
+ * and can contain font and color attribute table information. The scope of an object
+ * environment group is the scope of its containing object.
+ *
+ * An application that creates a data-stream document may omit some of the parameters
+ * normally contained in the object environment group, or it may specify that one or
+ * more default values are to be used.
+ */
+public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
+
+ /** the PresentationEnvironmentControl for the object environment group */
+ private PresentationEnvironmentControl presentationEnvironmentControl;
+
+ /** the ObjectAreaDescriptor for the object environment group */
+ private ObjectAreaDescriptor objectAreaDescriptor;
+
+ /** the ObjectAreaPosition for the object environment group */
+ private ObjectAreaPosition objectAreaPosition;
+
+ /** the DataDescriptor for the object environment group */
+ private AbstractDescriptor dataDescriptor;
+
+ /** the MapDataResource for the object environment group */
+ private MapDataResource mapDataResource;
+
+ /** the MapContainerData for the object environment group */
+ private MapContainerData mapContainerData;
+
+ /**
+ * Constructor for the ObjectEnvironmentGroup, this takes a
+ * name parameter which must be 8 characters long.
+ *
+ * @param name the object environment group name
+ */
+ public ObjectEnvironmentGroup(String name) {
+ super(name);
+ }
+
+ /**
+ * Sets the Object Area Descriptor
+ *
+ * @param objectAreaDescriptor the object area descriptor
+ */
+ public void setObjectAreaDescriptor(ObjectAreaDescriptor objectAreaDescriptor) {
+ this.objectAreaDescriptor = objectAreaDescriptor;
+ }
+
+ /**
+ * Sets the Object Area Position
+ *
+ * @param objectAreaPosition the object area position
+ */
+ public void setObjectAreaPosition(ObjectAreaPosition objectAreaPosition) {
+ this.objectAreaPosition = objectAreaPosition;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.OBJECT_ENVIRONMENT_GROUP);
+
+ int tripletDataLength = getTripletDataLength();
+ int sfLen = data.length + tripletDataLength - 1;
+ byte[] len = BinaryUtils.convert(sfLen, 2);
+ data[1] = len[0];
+ data[2] = len[1];
+
+ os.write(data);
+
+ writeTriplets(os);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+
+ if (presentationEnvironmentControl != null) {
+ presentationEnvironmentControl.writeToStream(os);
+ }
+
+ if (objectAreaDescriptor != null) {
+ objectAreaDescriptor.writeToStream(os);
+ }
+
+ if (objectAreaPosition != null) {
+ objectAreaPosition.writeToStream(os);
+ }
+
+ if (mapContainerData != null) {
+ mapContainerData.writeToStream(os);
+ }
+
+ if (mapDataResource != null) {
+ mapDataResource.writeToStream(os);
+ }
+
+ if (dataDescriptor != null) {
+ dataDescriptor.writeToStream(os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.OBJECT_ENVIRONMENT_GROUP);
+ os.write(data);
+ }
+
+ /**
+ * Sets the presentation environment control
+ *
+ * @param presentationEnvironmentControl the presentation environment control
+ */
+ public void setPresentationEnvironmentControl(
+ PresentationEnvironmentControl presentationEnvironmentControl) {
+ this.presentationEnvironmentControl = presentationEnvironmentControl;
+ }
+
+ /**
+ * Sets the data descriptor
+ *
+ * @param dataDescriptor the data descriptor
+ */
+ public void setDataDescriptor(AbstractDescriptor dataDescriptor) {
+ this.dataDescriptor = dataDescriptor;
+ }
+
+ /**
+ * Sets the map data resource
+ *
+ * @param mapDataResource the map data resource
+ */
+ public void setMapDataResource(MapDataResource mapDataResource) {
+ this.mapDataResource = mapDataResource;
+ }
+
+ /**
+ * Sets the map container data
+ *
+ * @param mapContainerData the map container data
+ */
+ public void setMapContainerData(MapContainerData mapContainerData) {
+ this.mapContainerData = mapContainerData;
+ }
+
+ /**
+ * Returns the object area descriptor
+ *
+ * @return the object area descriptor
+ */
+ public ObjectAreaDescriptor getObjectAreaDescriptor() {
+ return this.objectAreaDescriptor;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/Overlay.java b/src/java/org/apache/fop/afp/modca/Overlay.java
new file mode 100644
index 000000000..ea9619b20
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/Overlay.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.Factory;
+
+
+/**
+ * An overlay is a MO:DCA-P resource object.
+ *
+ * It may be stored in an external resource library or it may be
+ * carried in a resource group. An overlay is similar to a page in
+ * that it defines its own environment and carries the same data objects.
+ */
+public class Overlay extends PageObject {
+
+ /**
+ * Construct a new overlay object for the specified name argument, the overlay
+ * name should be an 8 character identifier.
+ *
+ * @param factory
+ * the resource manager of the page.
+ * @param name
+ * the name of the page.
+ * @param width
+ * the width of the page.
+ * @param height
+ * the height of the page.
+ * @param rotation
+ * the rotation of the page.
+ * @param widthResolution
+ * the width resolution of the page.
+ * @param heightResolution
+ * the height resolution of the page.
+ */
+ public Overlay(Factory factory,
+ String name, int width, int height, int rotation,
+ int widthResolution, int heightResolution) {
+ super(factory, name, width, height, rotation, widthResolution, heightResolution);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.OVERLAY);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+
+ getActiveEnvironmentGroup().writeToStream(os);
+
+ writeObjects(includePageSegments, os);
+ writeObjects(tagLogicalElements, os);
+ writeObjects(objects, os);
+ }
+
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.OVERLAY);
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java b/src/java/org/apache/fop/afp/modca/PageDescriptor.java
index 541df823e..502123def 100644
--- a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java
+++ b/src/java/org/apache/fop/afp/modca/PageDescriptor.java
@@ -17,11 +17,12 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The Page Descriptor structured field specifies the size and attributes of
@@ -33,47 +34,35 @@ public class PageDescriptor extends AbstractDescriptor {
/**
* Construct a page descriptor for the specified page width
* and page height.
+ *
* @param width The page width.
* @param height The page height.
- * @param widthResolution The page width resolution
- * @param heightResolution The page height resolution
+ * @param widthRes The page width resolution
+ * @param heightRes The page height resolution
*/
- public PageDescriptor(int width, int height, int widthResolution, int heightResolution) {
- super(width, height, widthResolution, heightResolution);
+ public PageDescriptor(int width, int height, int widthRes, int heightRes) {
+ super(width, height, widthRes, heightRes);
}
- /**
- * Accessor method to write the AFP datastream for the Page Descriptor
- * @param os The stream to write to
- * @throws java.io.IOException in the event that an I/O Exception occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- log.debug("width=" + width);
- log.debug("height=" + height);
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[24];
- data[0] = 0x5A;
- data[1] = 0x00;
+ copySF(data, Type.DESCRIPTOR, Category.PAGE);
data[2] = 0x17;
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xA6;
- data[5] = (byte) 0xAF;
-
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
+ // XpgBase
data[9] = 0x00; // XpgBase = 10 inches
+
+ // YpgBase
data[10] = 0x00; // YpgBase = 10 inches
// XpgUnits
- byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2);
data[11] = xdpi[0];
data[12] = xdpi[1];
// YpgUnits
- byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2);
data[13] = ydpi[0];
data[14] = ydpi[1];
diff --git a/src/java/org/apache/fop/afp/modca/PageGroup.java b/src/java/org/apache/fop/afp/modca/PageGroup.java
new file mode 100644
index 000000000..13be9745e
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/PageGroup.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.fop.afp.Factory;
+
+/**
+ * A page group is used in the data stream to define a named, logical grouping
+ * of sequential pages. Page groups are delimited by begin-end structured fields
+ * that carry the name of the page group. Page groups are defined so that the
+ * pages that comprise the group can be referenced or processed as a single
+ * entity. Page groups are often processed in stand-alone fashion; that is, they
+ * are indexed, retrieved, and presented outside the context of the containing
+ * document.
+ */
+public class PageGroup extends AbstractResourceEnvironmentGroupContainer {
+
+ /** The tag logical elements contained within this group */
+ private List tagLogicalElements = null;
+
+ /**
+ * Constructor for the PageGroup.
+ *
+ * @param factory the resource manager
+ * @param name the name of the page group
+ */
+ public PageGroup(Factory factory, String name) {
+ super(factory, name);
+ }
+
+ private List getTagLogicalElements() {
+ if (tagLogicalElements == null) {
+ this.tagLogicalElements = new java.util.ArrayList();
+ }
+ return this.tagLogicalElements;
+ }
+
+ /**
+ * Creates a TagLogicalElement on the page.
+ *
+ * @param name
+ * the name of the tag
+ * @param value
+ * the value of the tag
+ */
+ public void createTagLogicalElement(String name, String value) {
+ TagLogicalElement tle = factory.createTagLogicalElement(name, value);
+ if (!getTagLogicalElements().contains(tle)) {
+ getTagLogicalElements().add(tle);
+ }
+ }
+
+ /**
+ * Method to mark the end of the page group.
+ */
+ public void endPageGroup() {
+ complete = true;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ writeObjects(tagLogicalElements, os);
+ super.writeContent(os);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.PAGE_GROUP);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.PAGE_GROUP);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.getName();
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/PageObject.java b/src/java/org/apache/fop/afp/modca/PageObject.java
new file mode 100644
index 000000000..33852d90b
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/PageObject.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.ioca.ImageCellPosition;
+import org.apache.fop.afp.ioca.ImageInputDescriptor;
+import org.apache.fop.afp.ioca.ImageOutputControl;
+import org.apache.fop.afp.ioca.ImageRasterData;
+import org.apache.fop.afp.ioca.ImageRasterPattern;
+
+/**
+ * Pages contain the data objects that comprise a presentation document. Each
+ * page has a set of data objects associated with it. Each page within a
+ * document is independent from any other page, and each must establish its own
+ * environment parameters.
+ *
+ * The page is the level in the document component hierarchy that is used for
+ * printing or displaying a document's content. The data objects contained in
+ * the page envelope in the data stream are presented when the page is
+ * presented. Each data object has layout information associated with it that
+ * directs the placement and orientation of the data on the page. In addition,
+ * each page contains layout information that specifies the measurement units,
+ * page width, and page depth.
+ *
+ * A page is initiated by a begin page structured field and terminated by an end
+ * page structured field. Structured fields that define objects and active
+ * environment groups or that specify attributes of the page may be encountered
+ * in page state.
+ *
+ */
+public class PageObject extends AbstractResourceGroupContainer {
+
+ /**
+ * Construct a new page object for the specified name argument, the page
+ * name should be an 8 character identifier.
+ *
+ * @param factory the resource manager
+ *
+ * @param name
+ * the name of the page.
+ * @param width
+ * the width of the page.
+ * @param height
+ * the height of the page.
+ * @param rotation
+ * the rotation of the page.
+ * @param widthRes
+ * the width resolution of the page.
+ * @param heightRes
+ * the height resolution of the page.
+ */
+ public PageObject(Factory factory,
+ String name, int width, int height, int rotation,
+ int widthRes, int heightRes) {
+ super(factory, name, width, height, rotation, widthRes, heightRes);
+ }
+
+ /**
+ * Creates an IncludePageOverlay on the page.
+ *
+ * @param name
+ * the name of the overlay
+ * @param x
+ * the x position of the overlay
+ * @param y
+ * the y position of the overlay
+ * @param orientation
+ * the orientation required for the overlay
+ */
+ public void createIncludePageOverlay(String name, int x, int y, int orientation) {
+ getActiveEnvironmentGroup().createOverlay(name);
+ IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation);
+ addObject(ipo);
+ }
+
+ /**
+ * This method will create shading on the page using the specified
+ * coordinates (the shading contrast is controlled via the red, green blue
+ * parameters, by converting this to grayscale).
+ *
+ * @param x
+ * the x coordinate of the shading
+ * @param y
+ * the y coordinate of the shading
+ * @param w
+ * the width of the shaded area
+ * @param h
+ * the height of the shaded area
+ * @param red
+ * the red value
+ * @param green
+ * the green value
+ * @param blue
+ * the blue value
+ */
+ public void createShading(int x, int y, int w, int h, int red, int green, int blue) {
+ int xCoord = 0;
+ int yCoord = 0;
+ int areaWidth = 0;
+ int areaHeight = 0;
+ switch (rotation) {
+ case 90:
+ xCoord = areaWidth - y - h;
+ yCoord = x;
+ areaWidth = h;
+ areaHeight = w;
+ break;
+ case 180:
+ xCoord = areaWidth - x - w;
+ yCoord = areaHeight - y - h;
+ areaWidth = w;
+ areaHeight = h;
+ break;
+ case 270:
+ xCoord = y;
+ yCoord = areaHeight - x - w;
+ areaWidth = h;
+ areaHeight = w;
+ break;
+ default:
+ xCoord = x;
+ yCoord = y;
+ areaWidth = w;
+ areaHeight = h;
+ break;
+ }
+
+ // Convert the color to grey scale
+ float shade = (float) ((red * 0.3) + (green * 0.59) + (blue * 0.11));
+
+ int grayscale = Math.round((shade / 255) * 16);
+
+ IMImageObject imImageObject = factory.createIMImageObject();
+
+ ImageOutputControl imageOutputControl = new ImageOutputControl(0, 0);
+ ImageInputDescriptor imageInputDescriptor = new ImageInputDescriptor();
+ ImageCellPosition imageCellPosition = new ImageCellPosition(xCoord, yCoord);
+ imageCellPosition.setXFillSize(areaWidth);
+ imageCellPosition.setYFillSize(areaHeight);
+ imageCellPosition.setXSize(64);
+ imageCellPosition.setYSize(8);
+
+ //defining this as a resource
+ byte[] rasterData = ImageRasterPattern.getRasterData(grayscale);
+ ImageRasterData imageRasterData = factory.createImageRasterData(rasterData);
+
+ imImageObject.setImageOutputControl(imageOutputControl);
+ imImageObject.setImageInputDescriptor(imageInputDescriptor);
+ imImageObject.setImageCellPosition(imageCellPosition);
+ imImageObject.setImageRasterData(imageRasterData);
+ addObject(imImageObject);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.PAGE);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ writeTriplets(os);
+
+ getActiveEnvironmentGroup().writeToStream(os);
+
+ writeObjects(includePageSegments, os);
+ writeObjects(tagLogicalElements, os);
+ writeObjects(objects, os);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.PAGE);
+ os.write(data);
+ }
+
+ /**
+ * Adds an AFP object reference to this page
+ *
+ * @param obj an AFP object
+ */
+ public void addObject(Object obj) {
+ endPresentationObject();
+ super.addObject(obj);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.getName();
+ }
+
+ /** {@inheritDoc} */
+ protected boolean canWrite(AbstractAFPObject ao) {
+ return true;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/PageSegment.java b/src/java/org/apache/fop/afp/modca/PageSegment.java
new file mode 100644
index 000000000..ab1388efb
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/PageSegment.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * A page segment is a MO:DCA-P resource object. It may be stored in an
+ * external resource library or it may be carried in a resource group.
+ * Page segments contain any combination of IOCA image objects and
+ * GOCA graphics objects.
+ */
+public class PageSegment extends AbstractNamedAFPObject {
+
+ private List/*<AbstractAFPObject>*/ objects = null;
+
+ /**
+ * Main constructor
+ *
+ * @param name the name of this object
+ */
+ public PageSegment(String name) {
+ super(name);
+ }
+
+ /**
+ * Returns a list of objects contained withing this page segment
+ *
+ * @return a list of objects contained within this page segment
+ */
+ public List/*<AbstractAFPObject>*/ getObjects() {
+ if (objects == null) {
+ objects = new java.util.ArrayList();
+ }
+ return objects;
+ }
+
+ /**
+ * Adds a resource object (image/graphic) to this page segment
+ *
+ * @param object the resource objec to add to this page segment
+ */
+ public void addObject(AbstractAFPObject object) {
+ getObjects().add(object);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.PAGE_SEGMENT);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
+ writeObjects(objects, os);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.PAGE_SEGMENT);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.name;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java b/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java
new file mode 100644
index 000000000..72e261662
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Preprocess Presentation Object structured field specifies presentation
+ * parameters for a data object that has been mapped as a resource.
+ */
+public class PreprocessPresentationObject extends AbstractTripletStructuredObject {
+ private static final byte TYPE_OTHER = (byte)0x92;
+ private static final byte TYPE_OVERLAY = (byte)0xDF;
+ private static final byte TYPE_IMAGE = (byte)0xFB;
+
+ private byte objType = TYPE_OTHER;
+ private byte objOrent = 0; // object always processed at 0 degree orientation
+ private int objXOffset = -1;
+ private int objYOffset = -1;
+
+ /**
+ * Main constructor
+ *
+ * @param prePresObj the presentation object to be preprocessed
+ */
+ public PreprocessPresentationObject(AbstractTripletStructuredObject prePresObj) {
+ if (prePresObj instanceof ImageObject || prePresObj instanceof Overlay) {
+ if (prePresObj instanceof ImageObject) {
+ this.objType = TYPE_IMAGE;
+ } else {
+ this.objType = TYPE_OVERLAY;
+ }
+ setFullyQualifiedName(
+ FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF,
+ FullyQualifiedNameTriplet.FORMAT_CHARSTR,
+ prePresObj.getFullyQualifiedName());
+ } else {
+ this.objType = TYPE_OTHER;
+ }
+ }
+
+ public static final byte ORIENTATION_ZERO_DEGREES = 1;
+ public static final byte ORIENTATION_90_DEGREES = 2;
+ public static final byte ORIENTATION_180_DEGREES = 4;
+ public static final byte ORIENTATION_270_DEGREES = 8;
+
+ /**
+ * Sets the object orientations relative to media leading edge
+ *
+ * @param orientation the object orientations relative to media leading edge
+ */
+ public void setOrientation(byte orientation) {
+ objOrent = orientation;
+ }
+
+ /**
+ * Sets the X axis origin for object content
+ *
+ * @param xOffset the X axis origin for object content
+ */
+ public void setXOffset(int xOffset) {
+ this.objXOffset = xOffset;
+ }
+
+ /**
+ * Sets the Y axis origin for object content
+ *
+ * @param yOffset the Y axis origin for object content
+ */
+ public void setYOffset(int yOffset) {
+ this.objYOffset = yOffset;
+ }
+
+ /** {@inheritDoc} */
+ public void writeStart(OutputStream os) throws IOException {
+ super.writeStart(os);
+
+ byte[] data = new byte[9];
+ copySF(data, Type.PROCESS, Category.DATA_RESOURCE);
+
+ byte[] l = BinaryUtils.convert(19 + getTripletDataLength(), 2);
+ data[1] = l[0]; // Length byte 1
+ data[2] = l[1]; // Length byte 1
+
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public void writeContent(OutputStream os) throws IOException {
+ byte[] data = new byte[12];
+ byte[] l = BinaryUtils.convert(12 + getTripletDataLength(), 2);
+ data[0] = l[0]; // RGLength
+ data[1] = l[1]; // RGLength
+ data[2] = objType; // ObjType
+ data[3] = 0x00; // Reserved
+ data[4] = 0x00; // Reserved
+ data[5] = objOrent; // ObjOrent
+ if (objXOffset > 0) {
+ byte[] xOff = BinaryUtils.convert(objYOffset, 3);
+ data[6] = xOff[0]; // XocaOset (not specified)
+ data[7] = xOff[1]; // XocaOset
+ data[8] = xOff[2]; // XocaOset
+ } else {
+ data[6] = (byte)0xFF; // XocaOset (not specified)
+ data[7] = (byte)0xFF; // XocaOset
+ data[8] = (byte)0xFF; // XocaOset
+ }
+ if (objYOffset > 0) {
+ byte[] yOff = BinaryUtils.convert(objYOffset, 3);
+ data[9] = yOff[0]; // YocaOset (not specified)
+ data[10] = yOff[1]; // YocaOset
+ data[11] = yOff[2]; // YocaOset
+ } else {
+ data[9] = (byte)0xFF; // YocaOset (not specified)
+ data[10] = (byte)0xFF; // YocaOset
+ data[11] = (byte)0xFF; // YocaOset
+ }
+ os.write(data);
+
+ writeTriplets(os);
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/PresentationEnvironmentControl.java b/src/java/org/apache/fop/afp/modca/PresentationEnvironmentControl.java
new file mode 100644
index 000000000..a2ebe22f6
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/PresentationEnvironmentControl.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Presentation Environment Control structured field specifies parameters that
+ * affect the rendering of presentation data and the appearance that is to be assumed
+ * by the presentation device.
+ */
+public class PresentationEnvironmentControl extends AbstractTripletStructuredObject {
+
+ /**
+ * Main constructor
+ */
+ public PresentationEnvironmentControl() {
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[11];
+ copySF(data, Type.CONTROL, Category.DOCUMENT);
+ int tripletDataLen = getTripletDataLength();
+ byte[] len = BinaryUtils.convert(10 + tripletDataLen);
+ data[1] = len[0];
+ data[2] = len[1];
+ data[9] = 0x00; // Reserved; must be zero
+ data[10] = 0x00; // Reserved; must be zero
+
+ os.write(data);
+
+ writeTriplets(os);
+ }
+
+// /**
+// * Sets the object offset
+// */
+// public void setObjectOffset() {
+// addTriplet(new ObjectOffsetTriplet());
+// }
+//
+// /**
+// * Sets the rendering intent
+// */
+// public void setRenderingIntent() {
+// addTriplet(new RenderingIntentTriplet());
+// }
+//
+// /**
+// * Sets the device appearance
+// */
+// public void setDeviceAppearance() {
+// addTriplet(new DeviceAppearanceTriplet());
+// }
+
+
+ // TODO
+// private class DeviceAppearanceTriplet extends AbstractTriplet {
+// public DeviceAppearanceTriplet() {
+// super(AbstractTriplet.DEVICE_APPEARANCE);
+// }
+// }
+
+ // TODO
+// private class RenderingIntentTriplet extends AbstractTriplet {
+// public RenderingIntentTriplet() {
+// super(AbstractTriplet.RENDERING_INTENT);
+// }
+// }
+
+ // TODO
+// private class ObjectOffsetTriplet extends AbstractTriplet {
+// public ObjectOffsetTriplet() {
+// super(AbstractTriplet.OBJECT_OFFSET);
+// }
+// }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/afp/modca/PresentationTextData.java
index 98beb96f7..645a461d8 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
+++ b/src/java/org/apache/fop/afp/modca/PresentationTextData.java
@@ -17,14 +17,17 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.awt.Color;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.fop.afp.AFPLineDataInfo;
+import org.apache.fop.afp.AFPTextDataInfo;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* Presentation text data contains the graphic characters and the control
@@ -48,58 +51,38 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class PresentationTextData extends AbstractAFPObject {
- /**
- * The maximum size of the presentation text data.
- */
+ /** the maximum size of the presentation text data.*/
private static final int MAX_SIZE = 8192;
- /**
- * The afp data relating to this presentaion text data.
- */
- private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024);
+ /** the AFP data relating to this presentation text data. */
+ private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
- /**
- * The current x coordinate.
- */
- private int _currentXCoordinate = -1;
+ /** the current x coordinate. */
+ private int currentX = -1;
- /**
- * The current y cooridnate
- */
- private int _currentYCoordinate = -1;
+ /** the current y cooridnate */
+ private int currentY = -1;
- /**
- * The current font
- */
- private String _currentFont = "";
+ /** the current font */
+ private String currentFont = "";
- /**
- * The current orientation
- */
- private int _currentOrientation = 0;
+ /** the current orientation */
+ private int currentOrientation = 0;
- /**
- * The current color
- */
- private Color _currentColor = new Color(0, 0, 0);
+ /** the current color */
+ private Color currentColor = new Color(0, 0, 0);
- /**
- * The current variable space increment
- */
- private int _currentVariableSpaceCharacterIncrement = 0;
+ /** the current variable space increment */
+ private int currentVariableSpaceCharacterIncrement = 0;
- /**
- * The current inter character adjustment
- */
- private int _currentInterCharacterAdjustment = 0;
+ /** the current inter character adjustment */
+ private int currentInterCharacterAdjustment = 0;
/**
* Default constructor for the PresentationTextData.
*/
public PresentationTextData() {
-
this(false);
-
}
/**
@@ -111,22 +94,22 @@ public class PresentationTextData extends AbstractAFPObject {
* The control sequence indicator.
*/
public PresentationTextData(boolean controlInd) {
-
- _baos.write(new byte[] { 0x5A, // Structured field identifier
- 0x00, // Record length byte 1
- 0x00, // Record length byte 2
- (byte) 0xD3, // PresentationTextData identifier byte 1
- (byte) 0xEE, // PresentationTextData identifier byte 2
- (byte) 0x9B, // PresentationTextData identifier byte 3
- 0x00, // Flag
- 0x00, // Reserved
- 0x00, // Reserved
- }, 0, 9);
+ final byte[] data = {
+ 0x5A, // Structured field identifier
+ 0x00, // Record length byte 1
+ 0x00, // Record length byte 2
+ SF_CLASS, // PresentationTextData identifier byte 1
+ Type.DATA, // PresentationTextData identifier byte 2
+ Category.PRESENTATION_TEXT, // PresentationTextData identifier byte 3
+ 0x00, // Flag
+ 0x00, // Reserved
+ 0x00, // Reserved
+ };
+ baos.write(data, 0, 9);
if (controlInd) {
- _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2);
+ baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2);
}
-
}
/**
@@ -140,16 +123,14 @@ public class PresentationTextData extends AbstractAFPObject {
* The output stream to which data should be written.
*/
private void setCodedFont(byte font, ByteArrayOutputStream afpdata) {
-
// Avoid unnecessary specification of the font
- if (String.valueOf(font).equals(_currentFont)) {
+ if (String.valueOf(font).equals(currentFont)) {
return;
} else {
- _currentFont = String.valueOf(font);
+ currentFont = String.valueOf(font);
}
- afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3);
-
+ afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3);
}
/**
@@ -163,14 +144,10 @@ public class PresentationTextData extends AbstractAFPObject {
* The output stream to which data should be written.
*/
private void absoluteMoveInline(int coordinate,
- ByteArrayOutputStream afpdata) {
-
+ ByteArrayOutputStream afpdata) {
byte[] b = BinaryUtils.convert(coordinate, 2);
-
- afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4);
-
- _currentXCoordinate = coordinate;
-
+ afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4);
+ currentX = coordinate;
}
/**
@@ -184,16 +161,14 @@ public class PresentationTextData extends AbstractAFPObject {
* The output stream to which data should be written.
*/
private void absoluteMoveBaseline(int coordinate,
- ByteArrayOutputStream afpdata) {
-
+ ByteArrayOutputStream afpdata) {
byte[] b = BinaryUtils.convert(coordinate, 2);
-
- afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4);
-
- _currentYCoordinate = coordinate;
-
+ afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4);
+ currentY = coordinate;
}
+ private static final int TRANSPARENT_MAX_SIZE = 253;
+
/**
* The Transparent Data control sequence contains a sequence of code points
* that are presented without a scan for embedded control sequences.
@@ -204,21 +179,16 @@ public class PresentationTextData extends AbstractAFPObject {
* The output stream to which data should be written.
*/
private void addTransparentData(byte[] data, ByteArrayOutputStream afpdata) {
-
// Calculate the length
int l = data.length + 2;
-
if (l > 255) {
// Check that we are not exceeding the maximum length
throw new IllegalArgumentException(
- "Transparent data is longer than 253 bytes: " + data);
+ "Transparent data is longer than " + TRANSPARENT_MAX_SIZE + " bytes: " + data);
}
-
- afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, },
- 0, 2);
-
+ afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB},
+ 0, 2);
afpdata.write(data, 0, data.length);
-
}
/**
@@ -234,12 +204,11 @@ public class PresentationTextData extends AbstractAFPObject {
* The output stream to which data should be written.
*/
private void drawBaxisRule(int length, int width,
- ByteArrayOutputStream afpdata) {
-
- afpdata.write(new byte[] { 0x07, // Length
- (byte) 0xE7, // Type
+ ByteArrayOutputStream afpdata) {
+ afpdata.write(new byte[] {
+ 0x07, // Length
+ (byte) 0xE7, // Type
}, 0, 2);
-
// Rule length
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
afpdata.write(data1, 0, data1.length);
@@ -248,7 +217,6 @@ public class PresentationTextData extends AbstractAFPObject {
afpdata.write(data2, 0, data2.length);
// Rule width fraction
afpdata.write(0x00);
-
}
/**
@@ -264,12 +232,11 @@ public class PresentationTextData extends AbstractAFPObject {
* The output stream to which data should be written.
*/
private void drawIaxisRule(int length, int width,
- ByteArrayOutputStream afpdata) {
-
- afpdata.write(new byte[] { 0x07, // Length
- (byte) 0xE5, // Type
+ ByteArrayOutputStream afpdata) {
+ afpdata.write(new byte[] {
+ 0x07, // Length
+ (byte) 0xE5, // Type
}, 0, 2);
-
// Rule length
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
afpdata.write(data1, 0, data1.length);
@@ -278,152 +245,170 @@ public class PresentationTextData extends AbstractAFPObject {
afpdata.write(data2, 0, data2.length);
// Rule width fraction
afpdata.write(0x00);
-
}
/**
* Create the presentation text data for the byte array of data.
*
- * @param fontNumber
- * The font resource identifier.
- * @param x
- * The x coordinate for the text data.
- * @param y
- * The y coordinate for the text data.
- * @param orientation
- * The orientation of the text data.
- * @param col
- * The text color.
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * The text data to be created.
+ * @param textDataInfo
+ * the afp text data
* @throws MaximumSizeExceededException
+ * thrown if the maximum number of text data is exceeded
+ * @throws UnsupportedEncodingException
+ * thrown if character encoding is not supported
*/
- public void createTextData(int fontNumber, int x, int y, int orientation,
- Color col, int vsci, int ica, byte[] data)
- throws MaximumSizeExceededException {
+ public void createTextData(AFPTextDataInfo textDataInfo)
+ throws MaximumSizeExceededException, UnsupportedEncodingException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
- if (_currentOrientation != orientation) {
- setTextOrientation(orientation, afpdata);
- _currentOrientation = orientation;
- _currentXCoordinate = -1;
- _currentYCoordinate = -1;
+ int rotation = textDataInfo.getRotation();
+ if (currentOrientation != rotation) {
+ setTextOrientation(rotation, afpdata);
+ currentOrientation = rotation;
+ currentX = -1;
+ currentY = -1;
}
- // Avoid unnecessary specification of the Y co-ordinate
- if (y != _currentYCoordinate) {
+ // Avoid unnecessary specification of the Y coordinate
+ int y = textDataInfo.getY();
+ if (currentY != y) {
absoluteMoveBaseline(y, afpdata);
- _currentXCoordinate = -1;
+ currentX = -1;
}
- // Avoid unnecessary specification of the X co-ordinate
- if (x != _currentXCoordinate) {
+ // Avoid unnecessary specification of the X coordinate
+ int x = textDataInfo.getX();
+ if (currentX != x) {
absoluteMoveInline(x, afpdata);
}
// Avoid unnecessary specification of the variable space increment
- if (vsci != _currentVariableSpaceCharacterIncrement) {
- setVariableSpaceCharacterIncrement(vsci, afpdata);
- _currentVariableSpaceCharacterIncrement = vsci;
+ if (textDataInfo.getVariableSpaceCharacterIncrement()
+ != currentVariableSpaceCharacterIncrement) {
+ setVariableSpaceCharacterIncrement(textDataInfo
+ .getVariableSpaceCharacterIncrement(), afpdata);
+ currentVariableSpaceCharacterIncrement = textDataInfo
+ .getVariableSpaceCharacterIncrement();
}
// Avoid unnecessary specification of the inter character adjustment
- if (ica != _currentInterCharacterAdjustment) {
- setInterCharacterAdjustment(ica, afpdata);
- _currentInterCharacterAdjustment = ica;
+ if (textDataInfo.getInterCharacterAdjustment() != currentInterCharacterAdjustment) {
+ setInterCharacterAdjustment(textDataInfo.getInterCharacterAdjustment(),
+ afpdata);
+ currentInterCharacterAdjustment = textDataInfo
+ .getInterCharacterAdjustment();
}
// Avoid unnecessary specification of the text color
- if (!col.equals(_currentColor)) {
- setExtendedTextColor(col, afpdata);
- _currentColor = col;
+ if (!textDataInfo.getColor().equals(currentColor)) {
+ setExtendedTextColor(textDataInfo.getColor(), afpdata);
+ currentColor = textDataInfo.getColor();
}
- setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata);
- addTransparentData(data, afpdata);
- _currentXCoordinate = -1;
+ setCodedFont(BinaryUtils.convert(textDataInfo.getFontReference())[0],
+ afpdata);
+
+ // Add transparent data
+ String textString = textDataInfo.getString();
+ String encoding = textDataInfo.getEncoding();
+ byte[] data = textString.getBytes(encoding);
+ if (data.length <= TRANSPARENT_MAX_SIZE) {
+ addTransparentData(data, afpdata);
+ } else {
+ // data size greater than TRANSPARENT_MAX_SIZE so slice
+ int numTransData = data.length / TRANSPARENT_MAX_SIZE;
+ byte[] buff = new byte[TRANSPARENT_MAX_SIZE];
+ int currIndex = 0;
+ for (int transDataCnt = 0; transDataCnt < numTransData; transDataCnt++) {
+ currIndex = transDataCnt * TRANSPARENT_MAX_SIZE;
+ System.arraycopy(data, currIndex, buff, 0, TRANSPARENT_MAX_SIZE);
+ addTransparentData(buff, afpdata);
+ }
+ int remainingTransData = data.length / TRANSPARENT_MAX_SIZE;
+ buff = new byte[remainingTransData];
+ System.arraycopy(data, currIndex, buff, 0, remainingTransData);
+ addTransparentData(buff, afpdata);
+ }
+ currentX = -1;
- int s = afpdata.size();
+ int dataSize = afpdata.size();
- if (_baos.size() + s > MAX_SIZE) {
- _currentXCoordinate = -1;
- _currentYCoordinate = -1;
+ if (baos.size() + dataSize > MAX_SIZE) {
+ currentX = -1;
+ currentY = -1;
throw new MaximumSizeExceededException();
}
byte[] outputdata = afpdata.toByteArray();
- _baos.write(outputdata, 0, outputdata.length);
+ baos.write(outputdata, 0, outputdata.length);
+ }
+ private int ensurePositive(int value) {
+ if (value < 0) {
+ return 0;
+ }
+ return value;
}
/**
* Drawing of lines using the starting and ending coordinates, thickness and
* colour arguments.
*
- * @param x1
- * The starting X coordinate.
- * @param y1
- * The starting Y coordinate.
- * @param x2
- * The ending X coordinate.
- * @param y2
- * The ending Y coordinate.
- * @param thickness
- * The line thickness.
- * @param orientation
- * The orientation of the text data.
- * @param col
- * The text color.
+ * @param lineDataInfo the line data information.
+ * @throws MaximumSizeExceededException
+ * thrown if the maximum number of line data has been exceeded
*/
- public void createLineData(int x1, int y1, int x2, int y2, int thickness,
- int orientation, Color col) throws MaximumSizeExceededException {
+ public void createLineData(AFPLineDataInfo lineDataInfo) throws MaximumSizeExceededException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
- if (_currentOrientation != orientation) {
+ int orientation = lineDataInfo.getRotation();
+ if (currentOrientation != orientation) {
setTextOrientation(orientation, afpdata);
- _currentOrientation = orientation;
+ currentOrientation = orientation;
}
// Avoid unnecessary specification of the Y coordinate
- if (y1 != _currentYCoordinate) {
+ int y1 = ensurePositive(lineDataInfo.getY1());
+ if (y1 != currentY) {
absoluteMoveBaseline(y1, afpdata);
}
// Avoid unnecessary specification of the X coordinate
- if (x1 != _currentXCoordinate) {
+ int x1 = ensurePositive(lineDataInfo.getX1());
+ if (x1 != currentX) {
absoluteMoveInline(x1, afpdata);
}
- if (!col.equals(_currentColor)) {
- setExtendedTextColor(col, afpdata);
- _currentColor = col;
+ Color color = lineDataInfo.getColor();
+ if (!color.equals(currentColor)) {
+ setExtendedTextColor(color, afpdata);
+ currentColor = color;
}
+ int x2 = ensurePositive(lineDataInfo.getX2());
+ int y2 = ensurePositive(lineDataInfo.getY2());
+ int thickness = lineDataInfo.getThickness();
if (y1 == y2) {
drawIaxisRule(x2 - x1, thickness, afpdata);
} else if (x1 == x2) {
drawBaxisRule(y2 - y1, thickness, afpdata);
} else {
+ log.error("Invalid axis rule unable to draw line");
return;
}
- int s = afpdata.size();
+ int dataSize = afpdata.size();
- if (_baos.size() + s > MAX_SIZE) {
- _currentXCoordinate = -1;
- _currentYCoordinate = -1;
+ if (baos.size() + dataSize > MAX_SIZE) {
+ currentX = -1;
+ currentY = -1;
throw new MaximumSizeExceededException();
}
byte[] outputdata = afpdata.toByteArray();
- _baos.write(outputdata, 0, outputdata.length);
-
+ baos.write(outputdata, 0, outputdata.length);
}
/**
@@ -436,141 +421,117 @@ public class PresentationTextData extends AbstractAFPObject {
* and minutes.
*
* @param orientation
- * The text orientation (0,90, 180, 270).
- * @param afpdata
+ * The text orientation (0, 90, 180, 270).
+ * @param os
* The output stream to which data should be written.
*/
private void setTextOrientation(int orientation,
- ByteArrayOutputStream afpdata) {
-
- afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2);
-
+ ByteArrayOutputStream os) {
+ os.write(new byte[] {0x06, (byte) 0xF7, }, 0, 2);
switch (orientation) {
- case 90:
- afpdata.write(0x2D);
- afpdata.write(0x00);
- afpdata.write(0x5A);
- afpdata.write(0x00);
- break;
- case 180:
- afpdata.write(0x5A);
- afpdata.write(0x00);
- afpdata.write(0x87);
- afpdata.write(0x00);
- break;
- case 270:
- afpdata.write(0x87);
- afpdata.write(0x00);
- afpdata.write(0x00);
- afpdata.write(0x00);
- break;
- default:
- afpdata.write(0x00);
- afpdata.write(0x00);
- afpdata.write(0x2D);
- afpdata.write(0x00);
- break;
+ case 90:
+ os.write(0x2D);
+ os.write(0x00);
+ os.write(0x5A);
+ os.write(0x00);
+ break;
+ case 180:
+ os.write(0x5A);
+ os.write(0x00);
+ os.write(0x87);
+ os.write(0x00);
+ break;
+ case 270:
+ os.write(0x87);
+ os.write(0x00);
+ os.write(0x00);
+ os.write(0x00);
+ break;
+ default:
+ os.write(0x00);
+ os.write(0x00);
+ os.write(0x2D);
+ os.write(0x00);
+ break;
}
-
}
/**
* The Set Extended Text Color control sequence specifies a color value and
- * defines the color space and encoding for that value. The specified color
- * value is applied to foreground areas of the text presentation space.
- * This is a modal control sequence.
+ * defines the color space and encoding for that value. The specified color
+ * value is applied to foreground areas of the text presentation space. This
+ * is a modal control sequence.
*
* @param col
* The color to be set.
- * @param afpdata
+ * @param os
* The output stream to which data should be written.
*/
- private void setExtendedTextColor(Color col,
- ByteArrayOutputStream afpdata) {
-
- afpdata.write(new byte[] {
- 15 // Control sequence length
- , (byte)0x81 // Control sequence function type
- , 0x00 // Reserved; must be zero
- , 0x01 // Color space - 0x01 = RGB
- , 0x00 // Reserved; must be zero
- , 0x00 // Reserved; must be zero
- , 0x00 // Reserved; must be zero
- , 0x00 // Reserved; must be zero
- , 8 // Number of bits in component 1
- , 8 // Number of bits in component 2
- , 8 // Number of bits in component 3
- , 0 // Number of bits in component 4
- , (byte)(col.getRed()) // Red intensity
- , (byte)(col.getGreen()) // Green intensity
- , (byte)(col.getBlue()) // Blue intensity
- }, 0, 15);
-
+ private void setExtendedTextColor(Color col, ByteArrayOutputStream os) {
+ byte[] colorData = new byte[] {
+ 15, // Control sequence length
+ (byte) 0x81, // Control sequence function type
+ 0x00, // Reserved; must be zero
+ 0x01, // Color space - 0x01 = RGB
+ 0x00, // Reserved; must be zero
+ 0x00, // Reserved; must be zero
+ 0x00, // Reserved; must be zero
+ 0x00, // Reserved; must be zero
+ 8, // Number of bits in component 1
+ 8, // Number of bits in component 2
+ 8, // Number of bits in component 3
+ 0, // Number of bits in component 4
+ (byte) (col.getRed()), // Red intensity
+ (byte) (col.getGreen()), // Green intensity
+ (byte) (col.getBlue()), // Blue intensity
+ };
+
+ os.write(colorData, 0, colorData.length);
}
/**
- * //TODO
- * This is a modal control sequence.
+ * //TODO This is a modal control sequence.
*
* @param incr
* The increment to be set.
- * @param afpdata
+ * @param os
* The output stream to which data should be written.
*/
private void setVariableSpaceCharacterIncrement(int incr,
- ByteArrayOutputStream afpdata) {
-
+ ByteArrayOutputStream os) {
byte[] b = BinaryUtils.convert(incr, 2);
- afpdata.write(new byte[] {
- 4 // Control sequence length
- , (byte)0xC5 // Control sequence function type
- , b[0]
- , b[1]
- }, 0, 4);
-
+ os.write(new byte[] {
+ 4, // Control sequence length
+ (byte) 0xC5, // Control sequence function type
+ b[0], b[1] },
+ 0, 4);
}
/**
- * //TODO
- * This is a modal control sequence.
+ * //TODO This is a modal control sequence.
*
* @param incr
* The increment to be set.
- * @param afpdata
+ * @param os
* The output stream to which data should be written.
*/
- private void setInterCharacterAdjustment(int incr,
- ByteArrayOutputStream afpdata) {
-
+ private void setInterCharacterAdjustment(int incr, ByteArrayOutputStream os) {
byte[] b = BinaryUtils.convert(Math.abs(incr), 2);
-
- afpdata.write(new byte[] {
- 5 // Control sequence length
- , (byte)0xC3 // Control sequence function type
- , b[0]
- , b[1]
- , (byte)(incr >= 0 ? 0 : 1) // Direction
- }, 0, 5);
-
+ os.write(new byte[] {
+ 5, // Control sequence length
+ (byte) 0xC3, // Control sequence function type
+ b[0], b[1], (byte) (incr >= 0 ? 0 : 1) // Direction
+ }, 0, 5);
}
- /**
- * Accessor method to write the AFP datastream for
- * the text data.
- * @param os The stream to write to
- * @throws java.io.IOException
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- byte[] data = _baos.toByteArray();
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = baos.toByteArray();
byte[] size = BinaryUtils.convert(data.length - 1, 2);
data[1] = size[0];
data[2] = size[1];
-
os.write(data);
-
}
/**
@@ -581,19 +542,15 @@ public class PresentationTextData extends AbstractAFPObject {
* method terminates the control sequence.
*
* @throws MaximumSizeExceededException
+ * thrown in the event that maximum size has been exceeded
*/
public void endControlSequence() throws MaximumSizeExceededException {
-
byte[] data = new byte[2];
data[0] = 0x02;
data[1] = (byte) 0xF8;
-
- if (data.length + _baos.size() > MAX_SIZE) {
+ if (data.length + baos.size() > MAX_SIZE) {
throw new MaximumSizeExceededException();
}
-
- _baos.write(data, 0, data.length);
-
+ baos.write(data, 0, data.length);
}
-
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java b/src/java/org/apache/fop/afp/modca/PresentationTextDescriptor.java
index 3858f4169..ef2696da8 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
+++ b/src/java/org/apache/fop/afp/modca/PresentationTextDescriptor.java
@@ -17,11 +17,12 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+
+import org.apache.fop.afp.util.BinaryUtils;
/**
* The Presentation Text Descriptor specifies the units of measure for the
@@ -50,42 +51,34 @@ public class PresentationTextDescriptor extends AbstractDescriptor {
/**
* Constructor a PresentationTextDescriptor for the specified
* width and height.
+ *
* @param width The width of the page.
* @param height The height of the page.
- * @param widthResolution The width resolution of the page.
- * @param heightResolution The height resolution of the page.
+ * @param widthRes The width resolution of the page.
+ * @param heightRes The height resolution of the page.
*/
public PresentationTextDescriptor(int width, int height,
- int widthResolution, int heightResolution) {
- super(width, height, widthResolution, heightResolution);
+ int widthRes, int heightRes) {
+ super(width, height, widthRes, heightRes);
}
- /**
- * Accessor method to write the AFP datastream for the Presentation Text Descriptor
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[23];
- data[0] = 0x5A;
- data[1] = 0x00;
+
+ copySF(data, Type.MIGRATION, Category.PRESENTATION_TEXT);
+
+ data[1] = 0x00; // length
data[2] = 0x16;
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xB1;
- data[5] = (byte) 0x9B;
- data[6] = 0x00;
- data[7] = 0x00;
- data[8] = 0x00;
+
data[9] = 0x00;
data[10] = 0x00;
- byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2);
data[11] = xdpi[0]; // xdpi
data[12] = xdpi[1];
- byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2);
data[13] = ydpi[0]; // ydpi
data[14] = ydpi[1];
@@ -103,7 +96,6 @@ public class PresentationTextDescriptor extends AbstractDescriptor {
data[22] = 0x00;
os.write(data);
-
}
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/afp/modca/PresentationTextObject.java
new file mode 100644
index 000000000..4a8bbbb18
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/PresentationTextObject.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import org.apache.fop.afp.AFPLineDataInfo;
+import org.apache.fop.afp.AFPTextDataInfo;
+
+/**
+ * The Presentation Text object is the data object used in document processing
+ * environments for representing text which has been prepared for presentation.
+ * Text, as used here, means an ordered string of characters, such as graphic
+ * symbols, numbers, and letters, that are suitable for the specific purpose of
+ * representing coherent information. Text which has been prepared for
+ * presentation has been reduced to a primitive form through explicit
+ * specification of the characters and their placement in the presentation
+ * space. Control sequences which designate specific control functions may be
+ * embedded within the text. These functions extend the primitive form by
+ * applying specific characteristics to the text when it is presented. The
+ * collection of the graphic characters and control codes is called Presentation
+ * Text, and the object that contains the Presentation Text is called the
+ * PresentationText object.
+ */
+public class PresentationTextObject extends AbstractNamedAFPObject {
+
+ /**
+ * The current presentation text data
+ */
+ private PresentationTextData currentPresentationTextData = null;
+
+ /**
+ * The presentation text data list
+ */
+ private List/*<PresentationTextData>*/ presentationTextDataList = null;
+
+ /**
+ * Construct a new PresentationTextObject for the specified name argument,
+ * the name should be an 8 character identifier.
+ *
+ * @param name the name of this presentation object
+ */
+ public PresentationTextObject(String name) {
+ super(name);
+ }
+
+ /**
+ * Create the presentation text data for the byte array of data.
+ *
+ * @param textDataInfo
+ * The afp text data
+ * @throws UnsupportedEncodingException thrown if character encoding is not supported
+ */
+ public void createTextData(AFPTextDataInfo textDataInfo) throws UnsupportedEncodingException {
+ if (currentPresentationTextData == null) {
+ startPresentationTextData();
+ }
+ try {
+ currentPresentationTextData.createTextData(textDataInfo);
+ } catch (MaximumSizeExceededException msee) {
+ endPresentationTextData();
+ createTextData(textDataInfo);
+ } catch (UnsupportedEncodingException e) {
+ endPresentationTextData();
+ throw e;
+ }
+ }
+
+ /**
+ * Drawing of lines using the starting and ending coordinates, thickness and
+ * orientation arguments.
+ *
+ * @param lineDataInfo the line data information.
+ */
+ public void createLineData(AFPLineDataInfo lineDataInfo) {
+ if (currentPresentationTextData == null) {
+ startPresentationTextData();
+ }
+ try {
+ currentPresentationTextData.createLineData(lineDataInfo);
+ } catch (MaximumSizeExceededException msee) {
+ endPresentationTextData();
+ createLineData(lineDataInfo);
+ }
+ }
+
+ /**
+ * Helper method to mark the start of the presentation text data
+ */
+ private void startPresentationTextData() {
+ if (presentationTextDataList == null) {
+ presentationTextDataList = new java.util.ArrayList/*<PresentationTextData>*/();
+ }
+ if (presentationTextDataList.size() == 0) {
+ currentPresentationTextData = new PresentationTextData(true);
+ } else {
+ currentPresentationTextData = new PresentationTextData();
+ }
+ presentationTextDataList.add(currentPresentationTextData);
+ }
+
+ /**
+ * Helper method to mark the end of the presentation text data
+ */
+ private void endPresentationTextData() {
+ this.currentPresentationTextData = null;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.PRESENTATION_TEXT);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ writeObjects(this.presentationTextDataList, os);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.PRESENTATION_TEXT);
+ os.write(data);
+ }
+
+ /**
+ * A control sequence is a sequence of bytes that specifies a control
+ * function. A control sequence consists of a control sequence introducer
+ * and zero or more parameters. The control sequence can extend multiple
+ * presentation text data objects, but must eventually be terminated. This
+ * method terminates the control sequence.
+ */
+ public void endControlSequence() {
+ if (currentPresentationTextData == null) {
+ startPresentationTextData();
+ }
+ try {
+ currentPresentationTextData.endControlSequence();
+ } catch (MaximumSizeExceededException msee) {
+ endPresentationTextData();
+ endControlSequence();
+ }
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ if (presentationTextDataList != null) {
+ return presentationTextDataList.toString();
+ }
+ return null;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/Registry.java b/src/java/org/apache/fop/afp/modca/Registry.java
new file mode 100644
index 000000000..481a72afd
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/Registry.java
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.util.Collections;
+
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * MOD:CA Registry of object types
+ */
+public final class Registry {
+ /** IOB supported object types */
+ private static final byte COMPID_IOCA_FS10 = 5;
+ private static final byte COMPID_IOCA_FS11 = 11;
+ private static final byte COMPID_IOCA_FS40 = 55;
+ private static final byte COMPID_IOCA_FS45 = 12;
+ private static final byte COMPID_EPS = 13;
+ private static final byte COMPID_TIFF = 14;
+ private static final byte COMPID_GIF = 22;
+ private static final byte COMPID_JFIF = 23; // jpeg file interchange format
+ private static final byte COMPID_PDF_SINGLE_PAGE = 25;
+ private static final byte COMPID_PCL_PAGE_OBJECT = 34;
+
+ private static final byte COMPID_TRUETYPE_OPENTYPE_FONT_RESOURCE_OBJECT = 51;
+ private static final byte COMPID_TRUETYPE_OPENTYPE_FONT_COLLECTION_RESOURCE_OBJECT = 53;
+
+ /** mime type entry mapping */
+ private final java.util.Map/*<String, ObjectType>*/ mimeObjectTypeMap
+ = Collections.synchronizedMap(
+ new java.util.HashMap/*<String, ObjectType>*/());
+
+ /** singleton instance */
+ private static Registry instance = null;
+
+ /**
+ * Returns a single instance of a MO:DCA Registry
+ *
+ * @return a single instance of an MO:DCA Registry
+ */
+ public static Registry getInstance() {
+ synchronized (Registry.class) {
+ if (instance == null) {
+ instance = new Registry();
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * private constructor
+ */
+ private Registry() {
+ init();
+ }
+
+ /**
+ * Initializes the mimetype map
+ */
+ private void init() {
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_AFP_IOCA_FS10,
+ new ObjectType(
+ COMPID_IOCA_FS10,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x05},
+ "IOCA FS10",
+ true,
+ MimeConstants.MIME_AFP_IOCA_FS10
+ )
+ );
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_AFP_IOCA_FS11,
+ new ObjectType(
+ COMPID_IOCA_FS11,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x11},
+ "IOCA FS11",
+ true,
+ MimeConstants.MIME_AFP_IOCA_FS11
+ )
+ );
+// mimeObjectTypeMap.put(
+// MimeConstants.MIME_AFP_IOCA_FS40,
+// new ObjectType(
+// COMPID_IOCA_FS40,
+// new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x37},
+// "IOCA FS40",
+// true,
+// MimeConstants.MIME_AFP_IOCA_FS40
+// )
+//);
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_AFP_IOCA_FS45,
+ new ObjectType(
+ COMPID_IOCA_FS45,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x12},
+ "IOCA FS45",
+ true,
+ MimeConstants.MIME_AFP_IOCA_FS45
+ )
+ );
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_EPS,
+ new ObjectType(
+ COMPID_EPS,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D},
+ "Encapsulated Postscript",
+ true,
+ MimeConstants.MIME_EPS
+ )
+ );
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_TIFF,
+ new ObjectType(
+ COMPID_TIFF,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E},
+ "TIFF",
+ true,
+ MimeConstants.MIME_TIFF
+ )
+ );
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_GIF,
+ new ObjectType(
+ COMPID_GIF,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16},
+ "GIF",
+ true,
+ MimeConstants.MIME_GIF
+ )
+ );
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_JPEG,
+ new ObjectType(
+ COMPID_JFIF,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17},
+ "JFIF",
+ true,
+ MimeConstants.MIME_JPEG
+ )
+ );
+ mimeObjectTypeMap.put(MimeConstants.MIME_PDF,
+ new ObjectType(
+ COMPID_PDF_SINGLE_PAGE,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19},
+ "PDF Single-page Object",
+ true,
+ MimeConstants.MIME_PDF
+ )
+ );
+ mimeObjectTypeMap.put(
+ MimeConstants.MIME_PCL,
+ new ObjectType(
+ COMPID_PCL_PAGE_OBJECT,
+ new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22},
+ "PCL Page Object",
+ true,
+ MimeConstants.MIME_PCL
+ )
+ );
+// mimeObjectTypeMap.put(
+// null,
+// new ObjectType(
+// COMPID_TRUETYPE_OPENTYPE_FONT_RESOURCE_OBJECT,
+// new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x33},
+// "TrueType/OpenType Font Resource Object",
+// true,
+// null
+// )
+// );
+// mimeObjectTypeMap.put(
+// null,
+// new ObjectType(
+// COMPID_TRUETYPE_OPENTYPE_FONT_COLLECTION_RESOURCE_OBJECT,
+// new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x35},
+// "TrueType/OpenType Font Collection Resource Object",
+// true,
+// null
+// )
+// );
+ }
+
+ /**
+ * Returns the MOD:CA object type given a mimetype
+ *
+ * @param mimeType the object mimetype
+ * @return the MOD:CA object type
+ */
+ public ObjectType getObjectType(String mimeType) {
+ return (ObjectType)mimeObjectTypeMap.get(mimeType);
+ }
+
+ /**
+ * Encapsulates a MOD:CA Registry Object Type entry
+ */
+ public class ObjectType {
+ private final byte componentId;
+ private final byte[] oid;
+ private final String name;
+ private final boolean includable;
+ private final String mimeType;
+
+ /**
+ * Main constructor
+ *
+ * @param componentId the component id of this object type
+ * @param oid the object id of this object type
+ * @param name the object type name
+ * @param includable true if this object can be included with an IOB structured field
+ * @param mimeType the mime type associated with this object type
+ */
+ public ObjectType(byte componentId, byte[] oid, String name,
+ boolean includable, String mimeType) {
+ this.componentId = componentId;
+ this.oid = oid;
+ this.name = name;
+ this.includable = includable;
+ this.mimeType = mimeType;
+ }
+
+ /**
+ * Returns a MOD:CA object type OID from a given a componentId
+ *
+ * @return the corresponding object type id for a given component id
+ * or null if the component id is unknown and the object type OID was not found.
+ */
+ public byte[] getOID() {
+ return this.oid;
+ }
+
+ /**
+ * Returns the object type name for the given componentId
+ *
+ * @return the object type name for the given componentId
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Returns the compontentId for this entry
+ *
+ * @return the compontentId for this entry
+ */
+ public byte getComponentId() {
+ return this.componentId;
+ }
+
+ /**
+ * Returns true if this component can be included with an IOB structured field
+ *
+ * @return true if this component can be included with an IOB structured field
+ */
+ public boolean isIncludable() {
+ return this.includable;
+ }
+
+ /**
+ * Returns the mime type associated with this object type
+ *
+ * @return the mime type associated with this object type
+ */
+ public String getMimeType() {
+ return this.mimeType;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.getName();
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java
new file mode 100644
index 000000000..2e4f57314
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.fop.afp.Completable;
+
+/**
+ * A Resource Environment Group contains a set of resources for a document
+ * or for a group of pages in a document.
+ */
+public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup implements Completable {
+
+ /** default name for the resource group */
+ private static final String DEFAULT_NAME = "REG00001";
+
+ /** the maps data resources contained in this resource environment group */
+ private List/*<MapDataResource>*/ mapDataResources = null;
+
+ /** the maps page overlays contained in this resource environment group */
+ private List mapPageOverlays = null;
+
+ /** the pre-process presentation objects contained in this resource environment group */
+ private List/*<PreprocessPresentationObject>*/ preProcessPresentationObjects = null;
+
+ /** the resource environment group state */
+ private boolean complete = false;
+
+ /**
+ * Default constructor
+ */
+ public ResourceEnvironmentGroup() {
+ this(DEFAULT_NAME);
+ }
+
+ private List/*<MapDataResource>*/ getMapDataResources() {
+ if (mapDataResources == null) {
+ this.mapDataResources = new java.util.ArrayList/*<MapDataResource>*/();
+ }
+ return this.mapDataResources;
+ }
+
+ private List getMapPageOverlays() {
+ if (mapPageOverlays == null) {
+ this.mapPageOverlays = new java.util.ArrayList();
+ }
+ return this.mapPageOverlays;
+ }
+
+ private List/*<PreprocessPresentationObject>*/ getPreprocessPresentationObjects() {
+ if (preProcessPresentationObjects == null) {
+ this.preProcessPresentationObjects
+ = new java.util.ArrayList/*<PreprocessPresentationObject>*/();
+ }
+ return this.preProcessPresentationObjects;
+ }
+
+ /**
+ * Constructor for the ResourceEnvironmentGroup, this takes a
+ * name parameter which must be 8 characters long.
+ * @param name the resource environment group name
+ */
+ public ResourceEnvironmentGroup(String name) {
+ super(name);
+ }
+
+// /**
+// * Adds an AFP object mapping reference to this resource environment group
+// * @param obj the object to add
+// */
+// public void addObject(AbstractStructuredAFPObject obj) {
+// getMapDataResources().add(new MapDataResource(obj));
+// createOverlay(obj.get);
+// getPreprocessPresentationObjects().add(new PreprocessPresentationObject(obj));
+// }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.RESOURCE_ENVIROMENT_GROUP);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.RESOURCE_ENVIROMENT_GROUP);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ writeObjects(mapDataResources, os);
+ writeObjects(mapPageOverlays, os);
+ writeObjects(preProcessPresentationObjects, os);
+ }
+
+ /** {@inheritDoc} */
+ public void setComplete(boolean complete) {
+ this.complete = complete;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isComplete() {
+ return complete;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/afp/modca/ResourceGroup.java
new file mode 100644
index 000000000..2218998a0
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ResourceGroup.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.fop.afp.Streamable;
+
+/**
+ * A Resource Group contains a set of overlays.
+ */
+public class ResourceGroup extends AbstractNamedAFPObject {
+
+ /** Set of resource uri */
+ private final Set/*<String>*/ resourceSet = new java.util.HashSet/*<String>*/();
+
+ /**
+ * Constructor for the ResourceGroup, this takes a
+ * name parameter which must be 8 characters long.
+ *
+ * @param name the resource group name
+ */
+ public ResourceGroup(String name) {
+ super(name);
+ }
+
+ /**
+ * Add this named object to this resource group
+ *
+ * @param namedObject a named object
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ public void addObject(AbstractNamedAFPObject namedObject) throws IOException {
+ resourceSet.add(namedObject);
+ }
+
+ /**
+ * Returns the number of resources contained in this resource group
+ *
+ * @return the number of resources contained in this resource group
+ */
+ public int getResourceCount() {
+ return resourceSet.size();
+ }
+
+ /**
+ * Returns true if the resource exists within this resource group,
+ * false otherwise.
+ *
+ * @param uri the uri of the resource
+ * @return true if the resource exists within this resource group
+ */
+ public boolean resourceExists(String uri) {
+ return resourceSet.contains(uri);
+ }
+
+ /** {@inheritDoc} */
+ public void writeStart(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.BEGIN, Category.RESOURCE_GROUP);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public void writeContent(OutputStream os) throws IOException {
+ Iterator it = resourceSet.iterator();
+ while (it.hasNext()) {
+ Object object = it.next();
+ if (object instanceof Streamable) {
+ Streamable streamableObject = (Streamable)object;
+ streamableObject.writeToStream(os);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.RESOURCE_GROUP);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.name + " " + resourceSet/*getResourceMap()*/;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/ResourceObject.java b/src/java/org/apache/fop/afp/modca/ResourceObject.java
new file mode 100644
index 000000000..0f555a42e
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/ResourceObject.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.triplets.ResourceObjectTypeTriplet;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * This resource structured field begins an envelope that is used to carry
+ * resource objects in print-file-level (external) resource groups.
+ */
+public class ResourceObject extends AbstractNamedAFPObject {
+
+ /** graphics object type */
+ public static final byte TYPE_GRAPHIC = 0x03;
+
+ /** barcode object type */
+ public static final byte TYPE_BARCODE = 0x05;
+
+ /** image object type */
+ public static final byte TYPE_IMAGE = 0x06;
+
+ /** font character set type */
+ public static final byte TYPE_FONT_CHARACTER_SET = 0x40;
+
+ /** code page type */
+ public static final byte TYPE_CODE_PAGE = 0x41;
+
+ /** coded font type */
+ public static final byte TYPE_CODED_FONT = 0x42;
+
+ /** object container type */
+ public static final byte TYPE_OBJECT_CONTAINER = (byte) 0x92;
+
+ /** document object type */
+ public static final byte TYPE_DOCUMENT = (byte) 0xA8;
+
+ /** page segment object type */
+ public static final byte TYPE_PAGE_SEGMENT = (byte) 0xFB;
+
+ /** overlay object type */
+ public static final byte TYPE_OVERLAY_OBJECT = (byte) 0xFC;
+
+ /** page def type */
+ public static final byte TYPE_PAGEDEF = (byte) 0xFD;
+
+ /** form def type */
+ public static final byte TYPE_FORMDEF = (byte) 0xFE;
+
+ private AbstractNamedAFPObject namedObject;
+
+ /**
+ * Default constructor
+ *
+ * @param name the name of this resource (reference id)
+ */
+ public ResourceObject(String name) {
+ super(name);
+ }
+
+ /**
+ * Sets the data object referenced by this resource object
+ *
+ * @param namedObject the named data object
+ */
+ public void setDataObject(AbstractNamedAFPObject namedObject) {
+ this.namedObject = namedObject;
+ }
+
+ /**
+ * Returns the data object referenced by this resource object
+ *
+ * @return the data object referenced by this resource object
+ */
+ public AbstractNamedAFPObject getDataObject() {
+ return namedObject;
+ }
+
+ /** {@inheritDoc} */
+ protected void writeStart(OutputStream os) throws IOException {
+ super.writeStart(os);
+
+ byte[] data = new byte[19];
+ copySF(data, Type.BEGIN, Category.NAME_RESOURCE);
+
+ // Set the total record length
+ int tripletDataLength = getTripletDataLength();
+ byte[] len = BinaryUtils.convert(18 + tripletDataLength, 2);
+ data[1] = len[0]; // Length byte 1
+ data[2] = len[1]; // Length byte 2
+
+ // Set reserved bits
+ data[17] = 0x00; // Reserved
+ data[18] = 0x00; // Reserved
+
+ os.write(data);
+
+ // Write triplets
+ writeTriplets(os);
+ }
+
+ /** {@inheritDoc} */
+ protected void writeContent(OutputStream os) throws IOException {
+ if (namedObject != null) {
+ namedObject.writeToStream(os);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[17];
+ copySF(data, Type.END, Category.NAME_RESOURCE);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.getName();
+ }
+
+ /**
+ * Sets Resource Object Type triplet
+ *
+ * @param type the resource object type
+ */
+ public void setType(byte type) {
+ getTriplets().add(new ResourceObjectTypeTriplet(type));
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/StreamedResourceGroup.java b/src/java/org/apache/fop/afp/modca/StreamedResourceGroup.java
new file mode 100644
index 000000000..65df33ae4
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/StreamedResourceGroup.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.Completable;
+
+/**
+ * A print-file resource group
+ */
+public class StreamedResourceGroup extends ResourceGroup implements Completable {
+ /** the outputstream to write to */
+ private final OutputStream os;
+
+ private boolean started = false;
+
+ private boolean complete = false;
+
+ /**
+ * Main constructor
+ *
+ * @param name the resource group name
+ * @param os the outputstream
+ */
+ public StreamedResourceGroup(String name, OutputStream os) {
+ super(name);
+ this.os = os;
+ }
+
+ /**
+ * Adds a resource to the external resource group
+ *
+ * @param namedObject a named object
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ public void addObject(AbstractNamedAFPObject namedObject) throws IOException {
+ if (!started) {
+ writeStart(os);
+ started = true;
+ }
+ try {
+ namedObject.writeToStream(os);
+ } finally {
+ os.flush();
+ }
+ }
+
+ /**
+ * Closes this external resource group file
+ *
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ public void close() throws IOException {
+ writeEnd(os);
+ complete = true;
+ }
+
+ /**
+ * Returns the outputstream
+ *
+ * @return the outputstream
+ */
+ public OutputStream getOutputStream() {
+ return this.os;
+ }
+
+ /** {@inheritDoc} */
+ public void setComplete(boolean complete) {
+ this.complete = complete;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isComplete() {
+ return this.complete;
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java b/src/java/org/apache/fop/afp/modca/TagLogicalElement.java
index 937f2019a..2e1fa5e07 100644
--- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java
+++ b/src/java/org/apache/fop/afp/modca/TagLogicalElement.java
@@ -17,13 +17,14 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
-import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.BinaryUtils;
/**
* A Tag Logical Element structured field assigns an attribute name and an
@@ -49,72 +50,41 @@ public class TagLogicalElement extends AbstractAFPObject {
/**
* Name of the key, used within the TLE
*/
- private String tleName = null;
+ private String name = null;
/**
* Value returned by the key
*/
- private String tleValue = null;
-
- /**
- * Byte representaion of the name
- */
- private byte[] tleByteName = null;
-
- /**
- * Byte representaion of the value
- */
- private byte[] tleByteValue = null;
+ private String value = null;
/**
* Construct a tag logical element with the name and value specified.
+ *
* @param name the name of the tag logical element
* @param value the value of the tag logical element
*/
public TagLogicalElement(String name, String value) {
-
- this.tleName = name;
- this.tleValue = value;
-
- try {
-
- this.tleByteName = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
- this.tleByteValue = value.getBytes(AFPConstants.EBCIDIC_ENCODING);
-
- } catch (UnsupportedEncodingException usee) {
-
- this.tleByteName = name.getBytes();
- this.tleByteValue = value.getBytes();
- log.warn(
- "Constructor:: UnsupportedEncodingException translating the name "
- + name);
-
- }
-
+ this.name = name;
+ this.value = value;
}
- /**
- * Accessor method to obtain the byte array AFP datastream for the
- * TagLogicalElement.
- * @param os The outputsteam stream
- * @throws java.io.IOException if an I/O exception occurred
- */
- public void writeDataStream(OutputStream os) throws IOException {
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
- byte[] data = new byte[17 + tleName.length() + tleValue.length()];
+ byte[] data = new byte[17 + name.length() + value.length()];
data[0] = 0x5A;
// Set the total record length
byte[] rl1
- = BinaryUtils.convert(16 + tleName.length() + tleValue.length(), 2);
+ = BinaryUtils.convert(16 + name.length() + value.length(), 2);
//Ignore first byte
data[1] = rl1[0];
data[2] = rl1[1];
// Structured field ID for a TLE
data[3] = (byte) 0xD3;
- data[4] = (byte) 0xA0;
- data[5] = (byte) 0x90;
+ data[4] = (byte) Type.ATTRIBUTE;
+ data[5] = (byte) Category.PROCESS_ELEMENT;
data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
@@ -122,12 +92,25 @@ public class TagLogicalElement extends AbstractAFPObject {
//Use 2 triplets, attrubute name and value (the key for indexing)
- byte[] rl2 = BinaryUtils.convert(tleName.length() + 4, 1);
+ byte[] rl2 = BinaryUtils.convert(name.length() + 4, 1);
data[9] = rl2[0]; // length of the triplet, including this field
data[10] = 0x02; //Identifies it as a FQN triplet
data[11] = 0x0B; // GID format
data[12] = 0x00;
+ byte[] tleByteName = null;
+ byte[] tleByteValue = null;
+ try {
+ tleByteName = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ tleByteValue = value.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ } catch (UnsupportedEncodingException usee) {
+ tleByteName = name.getBytes();
+ tleByteValue = value.getBytes();
+ log.warn(
+ "Constructor:: UnsupportedEncodingException translating the name "
+ + name);
+ }
+
int pos = 13;
for (int i = 0; i < tleByteName.length; i++) {
data[pos++] = tleByteName[i];
diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java b/src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java
index 29ac9eb5d..5d4523777 100644
--- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
+++ b/src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.modca;
+package org.apache.fop.afp.modca;
/**
* The TagLogicalElementBean provides a bean for holding the attributes of
@@ -34,6 +34,7 @@ public class TagLogicalElementBean {
/**
* Constructor for the TagLogicalElementBean.
+ *
* @param key the key attribute
* @param value the value attribute
*/
@@ -44,6 +45,7 @@ public class TagLogicalElementBean {
/**
* Getter for the key attribute.
+ *
* @return the key
*/
public String getKey() {
@@ -52,6 +54,7 @@ public class TagLogicalElementBean {
/**
* Getter for the value attribute.
+ *
* @return the value
*/
public String getValue() {
diff --git a/src/java/org/apache/fop/afp/modca/package.html b/src/java/org/apache/fop/afp/modca/package.html
new file mode 100644
index 000000000..572743558
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.modca Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) structured objects.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java
new file mode 100644
index 000000000..4e75d4204
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import org.apache.fop.afp.Streamable;
+import org.apache.fop.afp.StructuredData;
+
+/**
+ * A simple implementation of a MOD:CA triplet
+ */
+public abstract class AbstractTriplet implements Streamable, StructuredData {
+ public static final byte CODED_GRAPHIC_CHARACTER_SET_GLOBAL_IDENTIFIER = 0x01;
+
+ /** Triplet identifiers */
+ public static final byte FULLY_QUALIFIED_NAME = 0x02;
+ public static final byte MAPPING_OPTION = 0x04;
+ public static final byte OBJECT_CLASSIFICATION = 0x10;
+ public static final byte MODCA_INTERCHANGE_SET = 0x18;
+ public static final byte FONT_DESCRIPTOR_SPECIFICATION = 0x1F;
+ public static final byte OBJECT_FUNCTION_SET_SPECIFICATION = 0x21;
+ public static final byte EXTENDED_RESOURCE_LOCAL_IDENTIFIER = 0x22;
+ public static final byte RESOURCE_LOCAL_IDENTIFIER = 0x24;
+ public static final byte RESOURCE_SECTION_NUMBER = 0x25;
+ public static final byte CHARACTER_ROTATION = 0x26;
+ public static final byte OBJECT_BYTE_OFFSET = 0x2D;
+ public static final byte ATTRIBUTE_VALUE = 0x36;
+ public static final byte DESCRIPTOR_POSITION = 0x43;
+ public static final byte MEDIA_EJECT_CONTROL = 0x45;
+ public static final byte PAGE_OVERLAY_CONDITIONAL_PROCESSING = 0x46;
+ public static final byte RESOURCE_USAGE_ATTRIBUTE = 0x47;
+ public static final byte MEASUREMENT_UNITS = 0x4B;
+ public static final byte OBJECT_AREA_SIZE = 0x4C;
+ public static final byte AREA_DEFINITION = 0x4D;
+ public static final byte COLOR_SPECIFICATION = 0x4E;
+ public static final byte ENCODING_SCHEME_ID = 0x50;
+ public static final byte MEDIUM_MAP_PAGE_NUMBER = 0x56;
+ public static final byte OBJECT_BYTE_EXTENT = 0x57;
+ public static final byte OBJECT_STRUCTURED_FIELD_OFFSET = 0x58;
+ public static final byte OBJECT_STRUCTURED_FIELD_EXTENT = 0x59;
+ public static final byte OBJECT_OFFSET = 0x5A;
+ public static final byte FONT_HORIZONTAL_SCALE_FACTOR = 0x5D;
+ public static final byte OBJECT_COUNT = 0x5E;
+ public static final byte OBJECT_DATE_AND_TIMESTAMP = 0x62;
+ public static final byte COMMENT = 0x65;
+ public static final byte MEDIUM_ORIENTATION = 0x68;
+ public static final byte RESOURCE_OBJECT_INCLUDE = 0x6C;
+ public static final byte PRESENTATION_SPACE_RESET_MIXING = 0x70;
+ public static final byte PRESENTATION_SPACE_MIXING_RULE = 0x71;
+ public static final byte UNIVERSAL_DATE_AND_TIMESTAMP = 0x72;
+ public static final byte TONER_SAVER = 0x74;
+ public static final byte COLOR_FIDELITY = 0x75;
+ public static final byte FONT_FIDELITY = 0x78;
+ public static final byte ATTRIBUTE_QUALIFIER = (byte)0x80;
+ public static final byte PAGE_POSITION_INFORMATION = (byte)0x81;
+ public static final byte PARAMETER_VALUE = (byte)0x82;
+ public static final byte PRESENTATION_CONTROL = (byte)0x83;
+ public static final byte FONT_RESOLUTION_AND_METRIC_TECHNOLOGY = (byte)0x84;
+ public static final byte FINISHING_OPERATION = (byte)0x85;
+ public static final byte TEXT_FIDELITY = (byte)0x86;
+ public static final byte MEDIA_FIDELITY = (byte)0x87;
+ public static final byte FINISHING_FIDELITY = (byte)0x88;
+ public static final byte DATA_OBJECT_FONT_DESCRIPTOR = (byte)0x8B;
+ public static final byte LOCALE_SELECTOR = (byte)0x8C;
+ public static final byte UP3I_FINISHING_OPERATION = (byte)0x8E;
+ public static final byte COLOR_MANAGEMENT_RESOURCE_DESCRIPTOR = (byte)0x91;
+ public static final byte RENDERING_INTENT = (byte)0x95;
+ public static final byte CMR_TAG_FIDELITY = (byte)0x96;
+ public static final byte DEVICE_APPEARANCE = (byte)0x97;
+
+ /** the triplet identifier */
+ protected final byte id;
+
+ /**
+ * Constructor
+ *
+ * @param id the triplet identifier (see static definitions above)
+ */
+ public AbstractTriplet(byte id) {
+ this.id = id;
+ }
+
+ /**
+ * Returns the triplet identifier
+ *
+ * @return the triplet identifier
+ */
+ public byte getId() {
+ return this.id;
+ }
+
+ /**
+ * Returns the structured triplet data array
+ *
+ * @return the structured triplet data array
+ */
+ public byte[] getData() {
+ int dataLen = getDataLength();
+ byte[] data = new byte[dataLen];
+ data[0] = (byte)dataLen;
+ data[1] = id;
+ return data;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/CommentTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/CommentTriplet.java
new file mode 100644
index 000000000..9b15de8c1
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/CommentTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.AFPConstants;
+
+/**
+ * An inline comment triplet.
+ */
+public class CommentTriplet extends AbstractTriplet {
+
+ private final String commentString;
+
+ public CommentTriplet(byte id, String commentString) {
+ super(id);
+ this.commentString = commentString;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2 + commentString.length();
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ byte[] strData = commentString.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ System.arraycopy(strData, 0, data, 2, strData.length);
+ os.write(data);
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/DescriptorPositionTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/DescriptorPositionTriplet.java
new file mode 100644
index 000000000..cff6400af
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/DescriptorPositionTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Associates an ObjectAreaPosition with and ObjectAreaDescriptor structured field
+ */
+public class DescriptorPositionTriplet extends AbstractTriplet {
+
+ private final byte oapId;
+
+ /**
+ * Main constructor
+ *
+ * @param oapId the object area position id
+ */
+ public DescriptorPositionTriplet(byte oapId) {
+ super(DESCRIPTOR_POSITION);
+ this.oapId = oapId;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = oapId;
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/ExtendedResourceLocalIdentifierTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ExtendedResourceLocalIdentifierTriplet.java
new file mode 100644
index 000000000..af9452fcb
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/ExtendedResourceLocalIdentifierTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Extended Resource Local Identifier triplet specifies a resource type and a
+ * four byte local identifier or LID. The LID usually is associated with a specific
+ * resource name by a map structured field, such as a Map Data Resource structured
+ * field, or a Map Media Type structured field.
+ */
+public class ExtendedResourceLocalIdentifierTriplet extends AbstractTriplet {
+
+ /** the image resource type */
+ public static final byte TYPE_IMAGE_RESOURCE = 0x10;
+
+ /** the retired value type */
+ public static final byte TYPE_RETIRED_VALUE = 0x30;
+
+ /** the retired value type */
+ public static final byte TYPE_MEDIA_RESOURCE = 0x40;
+
+ /** the resource type */
+ private final byte type;
+
+ /** the resource local id */
+ private final int localId;
+
+ /**
+ * Main constructor
+ *
+ * @param type the resource type
+ * @param localId the resource local id
+ */
+ public ExtendedResourceLocalIdentifierTriplet(byte type, int localId) {
+ super(AbstractTriplet.EXTENDED_RESOURCE_LOCAL_IDENTIFIER);
+ this.type = type;
+ this.localId = localId;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = type;
+ byte[] resLID = BinaryUtils.convert(localId, 4); // 4 bytes
+ System.arraycopy(resLID, 0, data, 3, resLID.length);
+ os.write(data);
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 7;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java
new file mode 100644
index 000000000..55653457c
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.fop.afp.AFPConstants;
+
+/**
+ * A Fully Qualified Name triplet enable the identification and referencing of
+ * objects using Gloabl Identifiers (GIDs).
+ */
+public class FullyQualifiedNameTriplet extends AbstractTriplet {
+
+ // Specifies how the GID will be used
+
+ /** This GID replaces the first parameter in the structured field that contains a GID name. */
+ public static final byte TYPE_REPLACE_FIRST_GID_NAME = 0x01;
+
+ /** This triplet contains the name of a font family. */
+ public static final byte TYPE_FONT_FAMILY_NAME = 0x07;
+
+ /** This triplet contains the name of a font typeface. */
+ public static final byte TYPE_FONT_TYPEFACE_NAME = 0x08;
+
+ /** This triplet specifies a reference to the MO:DCA resource hierarchy. */
+ public static final byte TYPE_MODCA_RESOURCE_HIERARCHY_REF = 0x09;
+
+ /** The triplet contains a GID reference to a begin resource group structured field. */
+ public static final byte TYPE_BEGIN_RESOURCE_GROUP_REF = 0x0A;
+
+ /** The triplet contains a GID reference to a document attribute. */
+ public static final byte TYPE_ATTRIBUTE_GID = 0x0B;
+
+ /** The triplet contains the GID of a process element. */
+ public static final byte TYPE_PROCESS_ELEMENT_GID = 0x0C;
+
+ /** The triplet contains a reference to a begin page group structured field. */
+ public static final byte TYPE_BEGIN_PAGE_GROUP_REF = 0x0D;
+
+ /** The triplet contains a reference to a media type. */
+ public static final byte TYPE_MEDIA_TYPE_REF = 0x11;
+
+ /** The triplet contains a reference to a color management resource. */
+ public static final byte TYPE_COLOR_MANAGEMENT_RESOURCE_REF = 0x41;
+
+ /** The triplet contains a reference to a data-object font file that defines a base font. */
+ public static final byte TYPE_DATA_OBJECT_FONT_BASE_FONT_ID = 0x6E;
+
+ /** The triplet contains a reference to a data-object font file that defines a linked font. */
+ public static final byte TYPE_DATA_OBJECT_FONT_LINKED_FONT_ID = 0x7E;
+
+ /** The triplet contains a reference to a begin document structured field. */
+ public static final byte TYPE_BEGIN_DOCUMENT_REF = (byte)0x83;
+
+ /**
+ * The triplet contains a reference to a begin structured field associated with a resource;
+ * or contains a GID reference to a coded font.
+ */
+ public static final byte TYPE_BEGIN_RESOURCE_OBJECT_REF = (byte)0x84;
+
+ /**
+ * The triplet contains a GID reference to a code page that specifies the code points and
+ * graphic character names for a coded font.
+ */
+ public static final byte TYPE_CODE_PAGE_NAME_REF = (byte)0x85;
+
+ /**
+ * The triplet contains a GID name reference to a font character set that specifies
+ * a set of graphics characters.
+ */
+ public static final byte TYPE_FONT_CHARSET_NAME_REF = (byte)0x86;
+
+ /** The triplet contains a GID reference to a begin page structured field. */
+ public static final byte TYPE_BEGIN_PAGE_REF = (byte)0x87;
+
+ /** The triplet contains a GID reference to a begin medium map structured field. */
+ public static final byte TYPE_BEGIN_MEDIUM_MAP_REF = (byte)0x8D;
+
+ /**
+ * The triplet contains a GID reference to a coded font, which identifies a specific
+ * code page and a specific font character set.
+ */
+ public static final byte TYPE_CODED_FONT_NAME_REF = (byte)0x8E;
+
+ /** The triplet contains a GID reference to a begin document index structured field. */
+ public static final byte TYPE_BEGIN_DOCUMENT_INDEX_REF = (byte)0x98;
+
+ /** The triplet contains a GID reference to a begin overlay structured field. */
+ public static final byte TYPE_BEGIN_OVERLAY_REF = (byte)0xB0;
+
+ /** The triplet contains a GID reference to a resource used by a data object. */
+ public static final byte TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF = (byte)0xBE;
+
+ /** The triplet contains a GID reference to an index element structured field. */
+ public static final byte TYPE_INDEX_ELEMENT_GID = (byte)0xCA;
+
+ /**
+ * The triplet contains a reference to other object data which may or may
+ * not be defined by an IBM presentation architecture.
+ */
+ public static final byte TYPE_OTHER_OBJECT_DATA_REF = (byte)0xCE;
+
+ /**
+ * The triplet contains a reference to a resource used by a data object.
+ * The GID may be a filename or any other identifier associated with the
+ * resource and is used to located the resource object in the resource hierarchy.
+ * The data object that uses the resource may or may not be defined by an
+ * IBM presentation architecture.
+ */
+ public static final byte TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF = (byte)0xDE;
+
+
+ // GID Format
+
+ /** The GID is a character encoded name. */
+ public static final byte FORMAT_CHARSTR = (byte)0x00;
+
+ /** the GID is a ASN.1 object identifier (OID). */
+ public static final byte FORMAT_OID = (byte)0x10;
+
+ /** the GID is a uniform resource locator (URL). */
+ public static final byte FORMAT_URL = (byte)0x20;
+
+ /** the fully qualified name type */
+ private final byte type;
+
+ /** the fully qualified name format */
+ private final byte format;
+
+ /** the actual fully qualified name */
+ private final String fqName;
+
+ /**
+ * Main constructor
+ *
+ * @param type the fully qualified name type
+ * @param format the fully qualified name format
+ * @param fqName the fully qualified name
+ */
+ public FullyQualifiedNameTriplet(byte type, byte format, String fqName) {
+ super(FULLY_QUALIFIED_NAME);
+ this.type = type;
+ this.format = format;
+ this.fqName = fqName;
+ }
+
+ /**
+ * Returns the actual fully qualified name
+ *
+ * @return the actual fully qualified name
+ */
+ public String getFullyQualifiedName() {
+ return fqName;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return this.fqName;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 4 + fqName.length();
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = type;
+ data[3] = format;
+
+ // FQName
+ byte[] fqNameBytes;
+ String encoding = AFPConstants.EBCIDIC_ENCODING;
+ if (format == FORMAT_URL) {
+ encoding = AFPConstants.US_ASCII_ENCODING;
+ }
+ try {
+ fqNameBytes = fqName.getBytes(encoding);
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException(
+ encoding + " encoding failed");
+ }
+ System.arraycopy(fqNameBytes, 0, data, 4, fqNameBytes.length);
+
+ os.write(data);
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/triplets/MappingOptionTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/MappingOptionTriplet.java
new file mode 100644
index 000000000..0d20d0227
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/MappingOptionTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Specifies the mapping of data object presentation space to object area
+ */
+public class MappingOptionTriplet extends AbstractTriplet {
+ /**
+ * the data object is placed in the upper left corner, all data must be presented
+ * within the object area extents
+ */
+ public static final byte POSITION = 0x00;
+
+ /**
+ * the data object is placed in the upper left corner, all data that falls within
+ * the object area extents will be presented but data that falls outside will not be presented
+ */
+ public static final byte POSITION_AND_TRIM = 0x10;
+
+ /**
+ * the data object is centred and symmetrically scaled up or down
+ * while preserving aspect ratio
+ */
+ public static final byte SCALE_TO_FIT = 0x20;
+
+ /**
+ * the data object is centred, all data that falls within the object area extents
+ * will be presented but data that falls outside will not be presented
+ */
+ public static final byte CENTER_AND_TRIM = 0x30;
+
+// public static final byte MIGRATION_MAPPING_1 = 0x41;
+// public static final byte MIGRATION_MAPPING_2 = 0x42;
+// public static final byte MIGRATION_MAPPING_3 = 0x50;
+
+ /** the data object is centred, aspect ratio is not always preserved */
+ public static final byte SCALE_TO_FILL = 0x60;
+
+ /** used to map ip3i print data objects */
+ public static final byte UP3I_PRINT_DATA = 0x70;
+
+ private final byte mapValue;
+
+ /**
+ * Main constructor
+ *
+ * @param mapValue the mapping option to use
+ */
+ public MappingOptionTriplet(byte mapValue) {
+ super(AbstractTriplet.MAPPING_OPTION);
+ this.mapValue = mapValue;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = mapValue;
+
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/MeasurementUnitsTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/MeasurementUnitsTriplet.java
new file mode 100644
index 000000000..68d3fc40c
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/MeasurementUnitsTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Measurement Units triplet is used to specify the units of measure
+ * for a presentation space
+ */
+public class MeasurementUnitsTriplet extends AbstractTriplet {
+
+ private static final byte TEN_INCHES = 0x00;
+ private static final byte TEN_CM = 0x01;
+ private final int xRes;
+ private final int yRes;
+
+ /**
+ * Main constructor
+ *
+ * @param xRes units per base on the x-axis
+ * @param yRes units per base on the y-axis
+ */
+ public MeasurementUnitsTriplet(int xRes, int yRes) {
+ super(MEASUREMENT_UNITS);
+ this.xRes = xRes;
+ this.yRes = yRes;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 8;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+
+ data[2] = TEN_INCHES; // XoaBase
+ data[3] = TEN_INCHES; // YoaBase
+
+ byte[] xUnits = BinaryUtils.convert(xRes * 10, 2);
+ data[4] = xUnits[0]; // XoaUnits (x units per unit base)
+ data[5] = xUnits[1];
+
+ byte[] yUnits = BinaryUtils.convert(yRes * 10, 2);
+ data[6] = yUnits[0]; // YoaUnits (y units per unit base)
+ data[7] = yUnits[1];
+
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/ObjectAreaSizeTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ObjectAreaSizeTriplet.java
new file mode 100644
index 000000000..3d408639e
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/ObjectAreaSizeTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Object Area Size triplet is used to specify the extent of an object area
+ * in the X and Y directions
+ */
+public class ObjectAreaSizeTriplet extends AbstractTriplet {
+
+ private final int x;
+ private final int y;
+ private final byte type;
+
+ /**
+ * Main constructor
+ *
+ * @param x the object area extent for the X axis
+ * @param y the object area extent for the Y axis
+ * @param type the object area size type
+ */
+ public ObjectAreaSizeTriplet(int x, int y, byte type) {
+ super(AbstractTriplet.OBJECT_AREA_SIZE);
+ this.x = x;
+ this.y = y;
+ this.type = type;
+ }
+
+ /**
+ * Main constructor
+ *
+ * @param x the object area extent for the X axis
+ * @param y the object area extent for the Y axis
+ */
+ public ObjectAreaSizeTriplet(int x, int y) {
+ this(x, y, (byte)0x02);
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 9;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+
+ data[2] = type; // SizeType
+
+ byte[] xOASize = BinaryUtils.convert(x, 3);
+ data[3] = xOASize[0]; // XoaSize - Object area extent for X axis
+ data[4] = xOASize[1];
+ data[5] = xOASize[2];
+
+ byte[] yOASize = BinaryUtils.convert(y, 3);
+ data[6] = yOASize[0]; // YoaSize - Object area extent for Y axis
+ data[7] = yOASize[1];
+ data[8] = yOASize[2];
+
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/ObjectByteExtentTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ObjectByteExtentTriplet.java
new file mode 100644
index 000000000..3aaa6969a
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/ObjectByteExtentTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Object Byte Extent triplet is used to specify the number of bytes contained in an object
+ */
+public class ObjectByteExtentTriplet extends AbstractTriplet {
+
+ private final int byteExt;
+
+ /**
+ * Main constructor
+ *
+ * @param byteExt the number of bytes contained in the object
+ */
+ public ObjectByteExtentTriplet(int byteExt) {
+ super(OBJECT_BYTE_EXTENT);
+ this.byteExt = byteExt;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 6;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ byte[] extData = BinaryUtils.convert(byteExt, 4);
+ System.arraycopy(extData, 0, data, 2, extData.length);
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/ObjectClassificationTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ObjectClassificationTriplet.java
new file mode 100644
index 000000000..9c2ab7bc4
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/ObjectClassificationTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.modca.Registry.ObjectType;
+import org.apache.fop.afp.util.StringUtils;
+
+/**
+ * The Object Classification is used to classify and identify object data.
+ * The object data may or may not be defined by an IBM presentation architecture
+ */
+public class ObjectClassificationTriplet extends AbstractTriplet {
+
+ /**
+ * The scope of this object is the including page or overlay
+ */
+ public static final byte CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT = 0x01;
+
+ /**
+ * The scope of this object is not defined
+ */
+ public static final byte CLASS_TIME_VARIANT_PRESENTATION_OBJECT = 0x10;
+
+ /**
+ * This is not a presentation object, the scope of this object is not defined
+ */
+ public static final byte CLASS_EXECUTABLE_PROGRAM = 0x20;
+
+ /**
+ * Setup information file, document level. This is not a presentation object,
+ */
+ public static final byte CLASS_SETUP_FILE = 0x30;
+
+ /**
+ * This is a resource used by a presentation object that may itself be a resource.
+ * The scope of the resource is the object that uses the resource.
+ */
+ public static final byte CLASS_SECONDARY_RESOURCE = 0x40;
+
+ /**
+ * Data object font. This is a non-FOCA font resource used to present
+ * text in a data object. The scope of the resource is the object that
+ * uses the resource.
+ */
+ public static final byte CLASS_DATA_OBJECT_FONT = 0x41;
+
+ /** the object class */
+ private final byte objectClass;
+
+ /** the object type */
+ private final ObjectType objectType;
+
+ /** whether the container has an object environment group */
+ private final boolean containerHasOEG;
+
+ /** whether the data resides within the container */
+ private final boolean dataInContainer;
+
+ /** whether the data resides within the object container data */
+ private final boolean dataInOCD;
+
+ /** the object level (version) */
+ private final String objectLevel;
+
+ /** the company/organization name */
+ private final String companyName;
+
+
+ /**
+ * Main constructor
+ *
+ * @param objectClass the object class type
+ * @param objectType the object type registry entry
+ * @param dataInContainer whether the data resides in the container
+ * @param containerHasOEG whether the container has an object environment group
+ * @param dataInOCD whether the data resides in a object container data structured field
+ */
+ public ObjectClassificationTriplet(byte objectClass, ObjectType objectType,
+ boolean dataInContainer, boolean containerHasOEG, boolean dataInOCD) {
+ // no object level or company name specified
+ this(objectClass, objectType, dataInContainer, containerHasOEG, dataInOCD, null, null);
+ }
+
+ /**
+ * Fully parameterized constructor
+ *
+ * @param objectClass the object class type
+ * @param objectType the object type registry entry
+ * @param dataInContainer whether the data resides in the container
+ * @param containerHasOEG whether the container has an object environment group
+ * @param dataInOCD whether the data resides in a object container data structured field
+ * @param objLev the release level or version number of the object type
+ * @param compName the name of the company or organization that owns the object definition
+ */
+ public ObjectClassificationTriplet(byte objectClass, ObjectType objectType,
+ boolean dataInContainer, boolean containerHasOEG, boolean dataInOCD,
+ String objLev, String compName) {
+ super(OBJECT_CLASSIFICATION);
+
+ this.objectClass = objectClass;
+ if (objectType == null) {
+ throw new IllegalArgumentException("MO:DCA Registry object type is null");
+ }
+ this.objectType = objectType;
+ this.dataInContainer = dataInContainer;
+ this.containerHasOEG = containerHasOEG;
+ this.dataInOCD = dataInOCD;
+ this.objectLevel = objLev;
+ this.companyName = compName;
+ }
+
+ /**
+ * Returns the structured field flags
+ *
+ * @param dataInContainer true if the object data in carried in the object container
+ * @param containerHasOEG true if the object container has an object environment group
+ * @param dataInOCD true if the object container data carries the object data
+ *
+ * @return the byte value of this structure
+ */
+ public byte[] getStructureFlagsAsBytes(boolean dataInContainer, boolean containerHasOEG,
+ boolean dataInOCD) {
+ byte[] strucFlgs = new byte[2];
+ // Object Container (BOC/EOC)
+ if (dataInContainer) {
+ strucFlgs[0] |= 3 << 6;
+ } else {
+ strucFlgs[0] |= 1 << 6;
+ }
+ // Object Environment Group (OEG)
+ if (containerHasOEG) {
+ strucFlgs[0] |= 3 << 4;
+ } else {
+ strucFlgs[0] |= 1 << 4;
+ }
+ // Object Container Data (OCD) structured fields
+ if (dataInOCD) {
+ strucFlgs[0] |= 3 << 2;
+ } else {
+ strucFlgs[0] |= 1 << 2;
+ }
+ strucFlgs[1] = 0x00;
+ return strucFlgs;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 96;
+ }
+
+ private static final int OBJECT_LEVEL_LEN = 8;
+ private static final int OBJECT_TYPE_NAME_LEN = 32;
+ private static final int COMPANY_NAME_LEN = 32;
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = 0x00; // reserved (must be zero)
+ data[3] = objectClass; // ObjClass
+ data[4] = 0x00; // reserved (must be zero)
+ data[5] = 0x00; // reserved (must be zero)
+
+ // StrucFlgs - Information on the structure of the object container
+ byte[] structureFlagsBytes = getStructureFlagsAsBytes(dataInContainer, containerHasOEG, dataInOCD);
+ data[6] = structureFlagsBytes[0];
+ data[7] = structureFlagsBytes[1];
+
+ byte[] objectIdBytes = objectType.getOID();
+ // RegObjId - MOD:CA-registered ASN.1 OID for object type (8-23)
+ System.arraycopy(objectIdBytes, 0, data, 8, objectIdBytes.length);
+
+ // ObjTpName - name of object type (24-55)
+ byte[] objectTypeNameBytes;
+ objectTypeNameBytes
+ = StringUtils.rpad(objectType.getName(), ' ', OBJECT_TYPE_NAME_LEN).getBytes(
+ AFPConstants.EBCIDIC_ENCODING);
+ System.arraycopy(objectTypeNameBytes, 0, data, 24, objectTypeNameBytes.length);
+
+ // ObjLev - release level or version number of object type (56-63)
+ byte[] objectLevelBytes;
+ objectLevelBytes = StringUtils.rpad(objectLevel, ' ', OBJECT_LEVEL_LEN).getBytes(
+ AFPConstants.EBCIDIC_ENCODING);
+ System.arraycopy(objectLevelBytes, 0, data, 56, objectLevelBytes.length);
+
+ // CompName - name of company or organization that owns object definition (64-95)
+ byte[] companyNameBytes;
+ companyNameBytes = StringUtils.rpad(companyName, ' ', COMPANY_NAME_LEN).getBytes(
+ AFPConstants.EBCIDIC_ENCODING);
+ System.arraycopy(companyNameBytes, 0, data, 64, companyNameBytes.length);
+
+ os.write(data);
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceMixingRulesTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceMixingRulesTriplet.java
new file mode 100644
index 000000000..b93ec5477
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceMixingRulesTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This triplet is used to specify the resulting appearance when data in a new
+ * presentation space is merged with data in an existing presentation space.
+ */
+public class PresentationSpaceMixingRulesTriplet extends AbstractTriplet {
+
+ /** background on background mixing rule */
+ public static final byte RULE_BACK_ON_BACK = 0x70;
+
+ /** background on foreground mixing rule */
+ public static final byte RULE_BACK_ON_FORE = 0x71;
+
+ /** foreground on background mixing rule */
+ public static final byte RULE_FORE_ON_BACK = 0x72;
+
+ /** foreground on foreground mixing rule */
+ public static final byte RULE_FORE_ON_FORE = 0x73;
+
+
+ /** overpaint */
+ public static final byte OVERPAINT = (byte)0x01;
+
+ /** underpaint */
+ public static final byte UNDERPAINT = (byte)0x02;
+
+ /** blend */
+ public static final byte BLEND = (byte)0x03;
+
+ /** MO:DCA default mixing */
+ public static final byte DEFAULT = (byte)0xFF;
+
+ /** the mixing rules */
+ private final byte[] rules;
+
+ /**
+ * Main constructor
+ *
+ * @param rules the mixing rules
+ */
+ public PresentationSpaceMixingRulesTriplet(byte[] rules) {
+ super(PRESENTATION_SPACE_MIXING_RULE);
+ this.rules = rules;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 2 + rules.length;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ System.arraycopy(rules, 0, data, 2, rules.length);
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceResetMixingTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceResetMixingTriplet.java
new file mode 100644
index 000000000..cecd40910
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceResetMixingTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This triplet is used to specify the resulting appearance when data in a new
+ * presentation space is merged with data in an existing presentation space.
+ */
+public class PresentationSpaceResetMixingTriplet extends AbstractTriplet {
+
+ /**
+ * Do not reset to the color of the medium prior to
+ * placing data into this MO:DCA presentation space.
+ */
+ public static final byte NOT_RESET = 0x00;
+
+ /**
+ * Reset to the color of the medium prior to placing
+ * data into this MO:DCA presentation space.
+ */
+ public static final byte RESET = 0x01;
+
+ private final byte backgroundMixFlag;
+
+ /**
+ * Main constructor
+ *
+ * @param backgroundMixFlag the background mixing flag
+ */
+ public PresentationSpaceResetMixingTriplet(byte backgroundMixFlag) {
+ super(PRESENTATION_SPACE_RESET_MIXING);
+ this.backgroundMixFlag = backgroundMixFlag;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = backgroundMixFlag;
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/ResourceObjectTypeTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ResourceObjectTypeTriplet.java
new file mode 100644
index 000000000..e4b13177d
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/ResourceObjectTypeTriplet.java
@@ -0,0 +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.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/** A Resource Object Type Triplet */
+public class ResourceObjectTypeTriplet extends AbstractTriplet {
+
+ private static final byte RESOURCE_OBJECT = 0x21;
+
+ /** the resource object type */
+ private final byte objectType;
+
+ /**
+ * Main constructor
+ *
+ * @param objectType the resource object type
+ */
+ public ResourceObjectTypeTriplet(byte objectType) {
+ super(RESOURCE_OBJECT);
+ this.objectType = objectType;
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ return 10;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = getData();
+ data[2] = objectType;
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/package.html b/src/java/org/apache/fop/afp/modca/triplets/package.html
new file mode 100644
index 000000000..99ae55a45
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.modca.triplets Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) triplet classes.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/package.html b/src/java/org/apache/fop/afp/package.html
new file mode 100644
index 000000000..d67498159
--- /dev/null
+++ b/src/java/org/apache/fop/afp/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp Package</TITLE>
+<BODY>
+<P>Contains an AFP library.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java
new file mode 100644
index 000000000..48c1001ef
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.svg;
+
+import java.awt.geom.AffineTransform;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.DocumentLoader;
+import org.apache.batik.bridge.UserAgent;
+import org.apache.batik.gvt.TextPainter;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.svg.AbstractFOPBridgeContext;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+
+/**
+ * An AFP specific implementation of a Batik BridgeContext
+ */
+public class AFPBridgeContext extends AbstractFOPBridgeContext {
+
+ private final AFPGraphics2D g2d;
+
+ /**
+ * Constructs a new bridge context.
+ *
+ * @param userAgent the user agent
+ * @param fontInfo the font list for the text painter, may be null
+ * in which case text is painted as shapes
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
+ * @param g2d an AFPGraphics 2D implementation
+ */
+ public AFPBridgeContext(UserAgent userAgent, FontInfo fontInfo,
+ ImageManager imageManager, ImageSessionContext imageSessionContext,
+ AffineTransform linkTransform, AFPGraphics2D g2d) {
+ super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform);
+ this.g2d = g2d;
+ }
+
+ /**
+ * Constructs a new bridge context.
+ * @param userAgent the user agent
+ * @param loader the Document Loader to use for referenced documents.
+ * @param fontInfo the font list for the text painter, may be null
+ * in which case text is painted as shapes
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
+ * @param an AFPGraphics 2D implementation
+ */
+ public AFPBridgeContext(UserAgent userAgent, DocumentLoader documentLoader,
+ FontInfo fontInfo, ImageManager imageManager,
+ ImageSessionContext imageSessionContext,
+ AffineTransform linkTransform, AFPGraphics2D g2d) {
+ super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform);
+ this.g2d = g2d;
+ }
+
+ /** {@inheritDoc} */
+ public void registerSVGBridges() {
+ super.registerSVGBridges();
+
+ if (fontInfo != null) {
+ AFPTextHandler textHandler = new AFPTextHandler(fontInfo);
+ g2d.setCustomTextHandler(textHandler);
+
+ TextPainter textPainter = new AFPTextPainter(textHandler);
+ setTextPainter(textPainter);
+
+ putBridge(new AFPTextElementBridge(textPainter));
+ }
+
+ putBridge(new AFPImageElementBridge());
+ }
+
+ /** {@inheritDoc} */
+ public BridgeContext createBridgeContext() {
+ return new AFPBridgeContext(getUserAgent(), getDocumentLoader(),
+ fontInfo,
+ getImageManager(),
+ getImageSessionContext(),
+ linkTransform, g2d);
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java b/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java
new file mode 100644
index 000000000..76d6396e3
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.svg;
+
+import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.svg.GraphicsConfiguration;
+
+/**
+ * Our implementation of the class that returns information about
+ * roughly what we can handle and want to see (alpha for example).
+ */
+public class AFPGraphicsConfiguration extends GraphicsConfiguration {
+ // We use this to get a good colormodel..
+ private static final BufferedImage BI_WITH_ALPHA
+ = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ // We use this to get a good colormodel..
+ private static final BufferedImage BI_WITHOUT_ALPHA
+ = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+
+ /**
+ * Construct a buffered image with an alpha channel, unless
+ * transparencty is OPAQUE (no alpha at all).
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param transparency the alpha value of the image
+ * @return the new buffered image
+ */
+ public BufferedImage createCompatibleImage(int width, int height,
+ int transparency) {
+ if (transparency == Transparency.OPAQUE) {
+ return new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ } else {
+ return new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+ }
+ }
+
+ /**
+ * Construct a buffered image with an alpha channel.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the new buffered image
+ */
+ public BufferedImage createCompatibleImage(int width, int height) {
+ return new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+ }
+
+ /**
+ * TODO: This should return the page bounds in Pts,
+ * I couldn't figure out how to get this for the current
+ * page (this still works for now,
+ * but it should be fixed...).
+ *
+ * @return the bounds of the page
+ */
+ public Rectangle getBounds() {
+ return null;
+ }
+
+ /**
+ * Return a good default color model for this 'device'.
+ * @return the colour model for the configuration
+ */
+ public ColorModel getColorModel() {
+ return BI_WITH_ALPHA.getColorModel();
+ }
+
+ /**
+ * Return a good color model given <tt>transparency</tt>
+ *
+ * @param transparency the alpha value for the colour model
+ * @return the colour model for the configuration
+ */
+ public ColorModel getColorModel(int transparency) {
+ if (transparency == Transparency.OPAQUE) {
+ return BI_WITHOUT_ALPHA.getColorModel();
+ } else {
+ return BI_WITH_ALPHA.getColorModel();
+ }
+ }
+
+ private static final Log log = LogFactory.getLog(AFPGraphicsConfiguration.class);
+
+ private AffineTransform defaultTransform = null;
+ private AffineTransform normalizingTransform = null;
+ private final GraphicsDevice graphicsDevice = new AFPGraphicsDevice(this);;
+
+ /**
+ * The default transform (1:1).
+ *
+ * @return the default transform for the configuration
+ */
+ public AffineTransform getDefaultTransform() {
+ log.debug("getDefaultTransform()");
+ if (defaultTransform == null) {
+ defaultTransform = new AffineTransform();
+ }
+ return defaultTransform;
+ }
+
+ /**
+ * The normalizing transform (1:1) (since we currently
+ * render images at 72dpi, which we might want to change
+ * in the future).
+ *
+ * @return the normalizing transform for the configuration
+ */
+ public AffineTransform getNormalizingTransform() {
+ log.debug("getNormalizingTransform()");
+ if (normalizingTransform == null) {
+ normalizingTransform = new AffineTransform(2, 0, 0, 2, 0, 0);
+ }
+ return normalizingTransform;
+ }
+
+ /** {@inheritDoc} */
+ public GraphicsDevice getDevice() {
+ log.debug("getDevice()");
+ return graphicsDevice;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java b/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java
new file mode 100644
index 000000000..daa25aaa0
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.svg;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+
+/**
+ * This implements the GraphicsDevice interface as appropriate for
+ * an AFPGraphics2D.
+ */
+public class AFPGraphicsDevice extends GraphicsDevice {
+
+ /**
+ * The Graphics Config that created us...
+ */
+ protected GraphicsConfiguration gc;
+
+ /**
+ * Create a new AF{ graphics device.
+ *
+ * @param gc The graphics configuration we should reference
+ */
+ public AFPGraphicsDevice(AFPGraphicsConfiguration gc) {
+ this.gc = gc;
+ }
+
+ /**
+ * Return an array of our one GraphicsConfig
+ *
+ * @return an array containing the one graphics configuration
+ */
+ public GraphicsConfiguration[] getConfigurations() {
+ return new GraphicsConfiguration[] {gc};
+ }
+
+ /**
+ * Return out sole GraphicsConfig.
+ *
+ * @return the graphics configuration that created this object
+ */
+ public GraphicsConfiguration getDefaultConfiguration() {
+ return this.gc;
+ }
+
+ /**
+ * Generate an IdString..
+ *
+ * @return the ID string for this device, uses toString
+ */
+ public String getIDstring() {
+ return toString();
+ }
+
+ /**
+ * Let the caller know that we are "a printer"
+ *
+ * @return the type which is always printer
+ */
+ public int getType() {
+ return GraphicsDevice.TYPE_PRINTER;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java b/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java
new file mode 100644
index 000000000..63661940d
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.svg;
+
+import org.apache.fop.svg.AbstractFOPImageElementBridge;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+
+/**
+ * An AFP specific implementation of a Batik SVGImageElementBridge
+ */
+public class AFPImageElementBridge extends AbstractFOPImageElementBridge {
+
+ private final ImageFlavor[] supportedFlavors = new ImageFlavor[]
+ {ImageFlavor.RAW_JPEG,
+ ImageFlavor.RAW_CCITTFAX,
+ ImageFlavor.GRAPHICS2D,
+ ImageFlavor.XML_DOM};
+
+ /** {@inheritDoc} */
+ protected ImageFlavor[] getSupportedFlavours() {
+ return supportedFlavors;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java
new file mode 100644
index 000000000..31aa3fe60
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.svg;
+
+import org.apache.batik.gvt.TextPainter;
+import org.apache.fop.svg.AbstractFOPTextElementBridge;
+
+/**
+ * Bridge class for the &lt;text> element.
+ * This bridge will use the direct text painter if the text
+ * for the element is simple.
+ */
+public class AFPTextElementBridge extends AbstractFOPTextElementBridge {
+
+ /**
+ * Constructs a new bridge for the &lt;text> element.
+ *
+ * @param textPainter the text painter to use
+ */
+ public AFPTextElementBridge(TextPainter textPainter) {
+ super(textPainter);
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/afp/svg/AFPTextHandler.java b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java
new file mode 100644
index 000000000..f44fde269
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.svg;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.fonts.AFPFont;
+import org.apache.fop.afp.fonts.AFPFontAttributes;
+import org.apache.fop.afp.fonts.AFPPageFonts;
+import org.apache.fop.afp.modca.GraphicsObject;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.svg.FOPTextHandler;
+
+/**
+ * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text
+ * using AFP GOCA text operations.
+ */
+public class AFPTextHandler implements FOPTextHandler {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(AFPTextHandler.class);
+
+ /** Overriding FontState */
+ protected Font overrideFont = null;
+
+ /** Font information */
+ private final FontInfo fontInfo;
+
+ /**
+ * Main constructor.
+ *
+ * @param fontInfo the AFPGraphics2D instance
+ */
+ public AFPTextHandler(FontInfo fontInfo) {
+ this.fontInfo = fontInfo;
+ }
+
+ /**
+ * Return the font information associated with this object
+ *
+ * @return the FontInfo object
+ */
+ public FontInfo getFontInfo() {
+ return fontInfo;
+ }
+
+ /**
+ * Registers a page font
+ *
+ * @param internalFontName the internal font name
+ * @param internalFontName the internal font name
+ * @param fontSize the font size
+ * @return a font reference
+ */
+ private int registerPageFont(AFPPageFonts pageFonts, String internalFontName, int fontSize) {
+ FontInfo fontInfo = getFontInfo();
+ AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName);
+ // register if necessary
+ AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
+ internalFontName,
+ afpFont,
+ fontSize
+ );
+ return afpFontAttributes.getFontReference();
+ }
+
+ /** {@inheritDoc} */
+ public void drawString(String text, float x, float y) throws IOException {
+ // TODO Remove me after removing the deprecated method in TextHandler.
+ throw new UnsupportedOperationException("Deprecated method!");
+ }
+
+ /**
+ * Add a text string to the current data object of the AFP datastream.
+ * The text is painted using text operations.
+ *
+ * {@inheritDoc}
+ */
+ public void drawString(Graphics2D g, String str, float x, float y) throws IOException {
+ log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
+ AFPGraphics2D g2d = (AFPGraphics2D)g;
+ GraphicsObject graphicsObj = g2d.getGraphicsObject();
+ Color color = g2d.getColor();
+
+ // set the color
+ AFPPaintingState paintingState = g2d.getPaintingState();
+ if (paintingState.setColor(color)) {
+ graphicsObj.setColor(color);
+ }
+
+ // set the character set
+ int fontReference = 0;
+ AFPPageFonts pageFonts = paintingState.getPageFonts();
+ if (overrideFont != null) {
+ String internalFontName = overrideFont.getFontName();
+ int fontSize = overrideFont.getFontSize();
+ fontReference = registerPageFont(pageFonts, internalFontName, fontSize);
+ } else {
+ java.awt.Font awtFont = g2d.getFont();
+// AffineTransform fontTransform = awtFont.getTransform();
+ FontInfo fontInfo = getFontInfo();
+ Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
+ String internalFontName = fopFont.getFontName();
+ int fontSize = fopFont.getFontSize();
+ fontReference = registerPageFont(pageFonts, internalFontName, fontSize);
+ }
+ graphicsObj.setCharacterSet(fontReference);
+
+ // add the character string
+ graphicsObj.addString(str, Math.round(x), Math.round(y));
+ }
+
+ /**
+ * Sets the overriding font.
+ *
+ * @param overrideFont Overriding Font to set
+ */
+ public void setOverrideFont(Font overrideFont) {
+ this.overrideFont = overrideFont;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPTextPainter.java b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java
new file mode 100644
index 000000000..c6a38b1b5
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.svg;
+
+import org.apache.fop.svg.AbstractFOPTextPainter;
+import org.apache.fop.svg.FOPTextHandler;
+
+
+/**
+ * Renders the attributed character iterator of a <tt>TextNode</tt>.
+ * This class draws the text directly into the AFPGraphics2D so that
+ * the text is not drawn using shapes.
+ * If the text is simple enough to draw then it sets the font and calls
+ * drawString. If the text is complex or the cannot be translated
+ * into a simple drawString the StrokingTextPainter is used instead.
+ */
+public class AFPTextPainter extends AbstractFOPTextPainter {
+
+ /**
+ * Create a new text painter with the given font information.
+ * @param nativeTextHandler the NativeTextHandler instance used for text painting
+ */
+ public AFPTextPainter(FOPTextHandler nativeTextHandler) {
+ super(nativeTextHandler);
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/svg/package.html b/src/java/org/apache/fop/afp/svg/package.html
new file mode 100644
index 000000000..bd24b246f
--- /dev/null
+++ b/src/java/org/apache/fop/afp/svg/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.modca.svg Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP specific Batik bridges.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/tools/BinaryUtils.java b/src/java/org/apache/fop/afp/util/BinaryUtils.java
index 31ba45bcf..2b2649415 100644
--- a/src/java/org/apache/fop/render/afp/tools/BinaryUtils.java
+++ b/src/java/org/apache/fop/afp/util/BinaryUtils.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.tools;
+package org.apache.fop.afp.util;
import java.io.ByteArrayOutputStream;
diff --git a/src/java/org/apache/fop/render/afp/tools/DTDEntityResolver.java b/src/java/org/apache/fop/afp/util/DTDEntityResolver.java
index e9554ecea..dcf5ad7d9 100644
--- a/src/java/org/apache/fop/render/afp/tools/DTDEntityResolver.java
+++ b/src/java/org/apache/fop/afp/util/DTDEntityResolver.java
@@ -17,12 +17,12 @@
/* $Id$ */
-package org.apache.fop.render.afp.tools;
+package org.apache.fop.afp.util;
import java.io.IOException;
import java.net.URL;
-import org.apache.fop.render.afp.exceptions.FontRuntimeException;
+import org.apache.fop.afp.fonts.FontRuntimeException;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
diff --git a/src/java/org/apache/fop/render/afp/tools/StringUtils.java b/src/java/org/apache/fop/afp/util/StringUtils.java
index c49509aa0..ce68d27be 100644
--- a/src/java/org/apache/fop/render/afp/tools/StringUtils.java
+++ b/src/java/org/apache/fop/afp/util/StringUtils.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.tools;
+package org.apache.fop.afp.util;
/**
* Library of utility methods useful in dealing with strings.
diff --git a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java b/src/java/org/apache/fop/afp/util/StructuredFieldReader.java
index 48beff023..34add3bbe 100644
--- a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java
+++ b/src/java/org/apache/fop/afp/util/StructuredFieldReader.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.afp.tools;
+package org.apache.fop.afp.util;
import java.io.IOException;
import java.io.InputStream;
diff --git a/src/java/org/apache/fop/afp/util/package.html b/src/java/org/apache/fop/afp/util/package.html
new file mode 100644
index 000000000..525bdbe2a
--- /dev/null
+++ b/src/java/org/apache/fop/afp/util/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.modca.triplets Package</TITLE>
+<BODY>
+<P>Contains a collection of useful AFP utility classes.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/apps/MimeConstants.java b/src/java/org/apache/fop/apps/MimeConstants.java
index b8a9637a8..851690db1 100644
--- a/src/java/org/apache/fop/apps/MimeConstants.java
+++ b/src/java/org/apache/fop/apps/MimeConstants.java
@@ -22,50 +22,7 @@ package org.apache.fop.apps;
/**
* Frequently used MIME types for various file formats used when working with Apache FOP.
*/
-public interface MimeConstants {
-
- /** Portable Document Format */
- String MIME_PDF = "application/pdf";
-
- /** PostScript */
- String MIME_POSTSCRIPT = "application/postscript";
- /** Encapsulated PostScript (same MIME type as PostScript) */
- String MIME_EPS = MIME_POSTSCRIPT;
-
- /** HP's PCL */
- String MIME_PCL = "application/x-pcl";
- /** HP's PCL (alternative MIME type) */
- String MIME_PCL_ALT = "application/vnd.hp-PCL";
-
- /** IBM's AFP */
- String MIME_AFP = "application/x-afp";
- /** IBM's AFP (alternative MIME type) */
- String MIME_AFP_ALT = "application/vnd.ibm.modcap";
-
- /** Plain text */
- String MIME_PLAIN_TEXT = "text/plain";
-
- /** Rich text format */
- String MIME_RTF = "application/rtf";
- /** Rich text format (alternative 1) */
- String MIME_RTF_ALT1 = "text/richtext";
- /** Rich text format (alternative 2) */
- String MIME_RTF_ALT2 = "text/rtf";
-
- /** FrameMaker's MIF */
- String MIME_MIF = "application/mif";
-
- /** Scalable Vector Graphics */
- String MIME_SVG = "image/svg+xml";
-
- /** GIF images */
- String MIME_GIF = "image/gif";
- /** PNG images */
- String MIME_PNG = "image/png";
- /** JPEG images */
- String MIME_JPEG = "image/jpeg";
- /** TIFF images */
- String MIME_TIFF = "image/tiff";
+public interface MimeConstants extends org.apache.xmlgraphics.util.MimeConstants {
/** Apache FOP's AWT preview (non-standard MIME type) */
String MIME_FOP_AWT_PREVIEW = "application/X-fop-awt-preview";
@@ -75,7 +32,4 @@ public interface MimeConstants {
String MIME_FOP_AREA_TREE = "application/X-fop-areatree";
/** Apache FOP's intermediate format XML */
String MIME_FOP_IF = "application/X-fop-intermediate-format";
- /** Proposed but non-registered MIME type for XSL-FO */
- String MIME_XSL_FO = "text/xsl";
-
}
diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java
index 1379e566d..87ba2146a 100644
--- a/src/java/org/apache/fop/area/Area.java
+++ b/src/java/org/apache/fop/area/Area.java
@@ -119,8 +119,10 @@ public class Area extends AreaTreeObject implements Serializable {
public static final int CLASS_MAX = CLASS_SIDE_FLOAT + 1;
private int areaClass = CLASS_NORMAL;
+
/** the area's inline-progression-dimension */
protected int ipd;
+
/** the area's block-progression-dimension */
protected int bpd;
@@ -141,7 +143,7 @@ public class Area extends AreaTreeObject implements Serializable {
* @return the area class
*/
public int getAreaClass() {
- return areaClass;
+ return this.areaClass;
}
/**
@@ -157,11 +159,11 @@ public class Area extends AreaTreeObject implements Serializable {
* Set the inline progression dimension of content rectangle
* for this area.
*
- * @param i the new inline progression dimension
- * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">ipd</a>
+ * @param ipd the new inline progression dimension
+ * @see <a href="http://www.w3.org/TR/xsl/#inline-progression-dimension">ipd</a>
*/
- public void setIPD(int i) {
- ipd = i;
+ public void setIPD(int ipd) {
+ this.ipd = ipd;
}
/**
@@ -169,10 +171,10 @@ public class Area extends AreaTreeObject implements Serializable {
* for this area.
*
* @return the inline progression dimension
- * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">ipd</a>
+ * @see <a href="http://www.w3.org/TR/xsl/#inline-progression-dimension">ipd</a>
*/
public int getIPD() {
- return ipd;
+ return this.ipd;
}
/**
@@ -180,7 +182,7 @@ public class Area extends AreaTreeObject implements Serializable {
* for this area.
*
* @param b the new block progression dimension
- * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">bpd</a>
+ * @see <a href="http://www.w3.org/TR/xsl/#block-progression-dimension">bpd</a>
*/
public void setBPD(int b) {
bpd = b;
@@ -191,7 +193,7 @@ public class Area extends AreaTreeObject implements Serializable {
* for this area.
*
* @return the block progression dimension
- * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">bpd</a>
+ * @see <a href="http://www.w3.org/TR/xsl/#block-progression-dimension">bpd</a>
*/
public int getBPD() {
return bpd;
diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java
index 59995741b..128fc8ce9 100644
--- a/src/java/org/apache/fop/area/AreaTreeHandler.java
+++ b/src/java/org/apache/fop/area/AreaTreeHandler.java
@@ -101,12 +101,12 @@ public class AreaTreeHandler extends FOEventHandler {
setupModel(userAgent, outputFormat, stream);
- lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride();
+ this.lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride();
if (lmMaker == null) {
lmMaker = new LayoutManagerMapping();
}
- idTracker = new IDTracker();
+ this.idTracker = new IDTracker();
if (log.isDebugEnabled()) {
statistics = new Statistics();
@@ -124,7 +124,7 @@ public class AreaTreeHandler extends FOEventHandler {
*/
protected void setupModel(FOUserAgent userAgent, String outputFormat,
OutputStream stream) throws FOPException {
- model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream);
+ this.model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream);
}
/**
@@ -133,7 +133,7 @@ public class AreaTreeHandler extends FOEventHandler {
* @return AreaTreeModel the model being used for this area tree
*/
public AreaTreeModel getAreaTreeModel() {
- return model;
+ return this.model;
}
/**
@@ -143,7 +143,7 @@ public class AreaTreeHandler extends FOEventHandler {
* area tree
*/
public LayoutManagerMaker getLayoutManagerMaker() {
- return lmMaker;
+ return this.lmMaker;
}
/**
@@ -152,7 +152,7 @@ public class AreaTreeHandler extends FOEventHandler {
* @return IDTracker used to track reference ids for items in this area tree
*/
public IDTracker getIDTracker() {
- return idTracker;
+ return this.idTracker;
}
/**
@@ -207,9 +207,9 @@ public class AreaTreeHandler extends FOEventHandler {
}
private void wrapAndAddExtensionAttachments(List list) {
- Iterator i = list.iterator();
- while (i.hasNext()) {
- ExtensionAttachment attachment = (ExtensionAttachment) i.next();
+ Iterator it = list.iterator();
+ while (it.hasNext()) {
+ ExtensionAttachment attachment = (ExtensionAttachment) it.next();
addOffDocumentItem(new OffDocumentExtensionAttachment(attachment));
}
}
@@ -357,7 +357,7 @@ public class AreaTreeHandler extends FOEventHandler {
*
* @param id the property ID of the area
* @param pv a page viewport that contains the area with this ID
- * @deprecated use getIdTracker().associateIDWithPageViewport(id, pv) instead
+ * @deprecated use getIDTracker().associateIDWithPageViewport(id, pv) instead
*/
public void associateIDWithPageViewport(String id, PageViewport pv) {
idTracker.associateIDWithPageViewport(id, pv);
@@ -369,7 +369,7 @@ public class AreaTreeHandler extends FOEventHandler {
* know when an id can be resolved.
*
* @param id the id of the object being processed
- * @deprecated use getIdTracker().signalPendingID(id) instead
+ * @deprecated use getIDTracker().signalPendingID(id) instead
*/
public void signalPendingID(String id) {
idTracker.signalPendingID(id);
@@ -381,7 +381,7 @@ public class AreaTreeHandler extends FOEventHandler {
* ref-ids can be resolved.
*
* @param id the id of the formatting object which was just finished
- * @deprecated use getIdTracker().signalIDProcessed(id) instead
+ * @deprecated use getIDTracker().signalIDProcessed(id) instead
*/
public void signalIDProcessed(String id) {
idTracker.signalIDProcessed(id);
@@ -392,7 +392,7 @@ public class AreaTreeHandler extends FOEventHandler {
*
* @param id the id to check
* @return true if the ID has been resolved
- * @deprecated use getIdTracker().alreadyResolvedID(id) instead
+ * @deprecated use getIDTracker().alreadyResolvedID(id) instead
*/
public boolean alreadyResolvedID(String id) {
return idTracker.alreadyResolvedID(id);
@@ -402,7 +402,7 @@ public class AreaTreeHandler extends FOEventHandler {
* Tries to resolve all unresolved ID references on the given page.
*
* @param pv page viewport whose ID refs to resolve
- * @deprecated use getIdTracker().tryIDResolution(pv) instead
+ * @deprecated use getIDTracker().tryIDResolution(pv) instead
*/
public void tryIDResolution(PageViewport pv) {
idTracker.tryIDResolution(pv);
@@ -413,7 +413,7 @@ public class AreaTreeHandler extends FOEventHandler {
*
* @param id the id to lookup
* @return the list of PageViewports
- * @deprecated use getIdTracker().getPageViewportsContainingID(id) instead
+ * @deprecated use getIDTracker().getPageViewportsContainingID(id) instead
*/
public List getPageViewportsContainingID(String id) {
return idTracker.getPageViewportsContainingID(id);
@@ -424,7 +424,7 @@ public class AreaTreeHandler extends FOEventHandler {
*
* @param idref the idref whose target id has not yet been located
* @param res the Resolvable object needing the idref to be resolved
- * @deprecated use getIdTracker().addUnresolvedIDRef(idref, res) instead
+ * @deprecated use getIDTracker().addUnresolvedIDRef(idref, res) instead
*/
public void addUnresolvedIDRef(String idref, Resolvable res) {
idTracker.addUnresolvedIDRef(idref, res);
diff --git a/src/java/org/apache/fop/area/AreaTreeModel.java b/src/java/org/apache/fop/area/AreaTreeModel.java
index acf51b913..e5f6db17b 100644
--- a/src/java/org/apache/fop/area/AreaTreeModel.java
+++ b/src/java/org/apache/fop/area/AreaTreeModel.java
@@ -36,11 +36,11 @@ import org.apache.commons.logging.LogFactory;
* the life of the area tree model.
*/
public class AreaTreeModel {
- private List pageSequenceList = null;
+ private List/*<PageSequence>*/ pageSequenceList = null;
private int currentPageSequenceIndex = -1;
/** the current page sequence */
protected PageSequence currentPageSequence;
- private List offDocumentItems = new java.util.ArrayList();
+// private List offDocumentItems = new java.util.ArrayList();
/** logger instance */
protected static Log log = LogFactory.getLog(AreaTreeModel.class);
@@ -48,7 +48,7 @@ public class AreaTreeModel {
* Create a new store pages model
*/
public AreaTreeModel() {
- pageSequenceList = new java.util.ArrayList();
+ pageSequenceList = new java.util.ArrayList/*<PageSequence>*/();
}
/**
@@ -83,13 +83,13 @@ public class AreaTreeModel {
* Handle an OffDocumentItem
* @param ext the extension to handle
*/
- public void handleOffDocumentItem(OffDocumentItem ext) {};
+ public void handleOffDocumentItem(OffDocumentItem ext) { };
/**
* Signal the end of the document for any processing.
* @throws SAXException if a problem was encountered.
*/
- public void endDocument() throws SAXException {};
+ public void endDocument() throws SAXException { };
/**
* Returns the currently active page-sequence.
diff --git a/src/java/org/apache/fop/area/AreaTreeObject.java b/src/java/org/apache/fop/area/AreaTreeObject.java
index 83e7727db..5929e7c4e 100644
--- a/src/java/org/apache/fop/area/AreaTreeObject.java
+++ b/src/java/org/apache/fop/area/AreaTreeObject.java
@@ -21,6 +21,7 @@ package org.apache.fop.area;
import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import org.apache.xmlgraphics.util.QName;
@@ -33,6 +34,9 @@ public abstract class AreaTreeObject {
/** Foreign attributes */
protected Map foreignAttributes = null;
+ /** Extension attachments */
+ protected List/*<ExtensionAttachment>*/ extensionAttachments = null;
+
/**
* Sets a foreign attribute.
* @param name the qualified name of the attribute
@@ -83,6 +87,21 @@ public abstract class AreaTreeObject {
return Collections.EMPTY_MAP;
}
}
+
+ /**
+ * Set extension attachments from a List
+ * @param extensionAttachments a List with extension attachments
+ */
+ public void setExtensionAttachments(List extensionAttachments) {
+ this.extensionAttachments = extensionAttachments;
+ }
-
+ /** @return the extension attachments associated with this area */
+ public List getExtensionAttachments() {
+ if (this.foreignAttributes != null) {
+ return Collections.unmodifiableList(this.extensionAttachments);
+ } else {
+ return Collections.EMPTY_LIST;
+ }
+ }
}
diff --git a/src/java/org/apache/fop/area/IDTracker.java b/src/java/org/apache/fop/area/IDTracker.java
index 9f9023717..b55ed7983 100644
--- a/src/java/org/apache/fop/area/IDTracker.java
+++ b/src/java/org/apache/fop/area/IDTracker.java
@@ -20,8 +20,6 @@
package org.apache.fop.area;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -36,20 +34,20 @@ import org.apache.commons.logging.LogFactory;
*/
public class IDTracker {
- private static Log log = LogFactory.getLog(IDTracker.class);
+ private static final Log log = LogFactory.getLog(IDTracker.class);
// HashMap of ID's whose area is located on one or more consecutive
// PageViewports. Each ID has an arraylist of PageViewports that
// form the defined area of this ID
- private Map idLocations = new HashMap();
+ private Map idLocations = new java.util.HashMap();
// idref's whose target PageViewports have yet to be identified
// Each idref has a HashSet of Resolvable objects containing that idref
- private Map unresolvedIDRefs = new HashMap();
+ private Map unresolvedIDRefs = new java.util.HashMap();
- private Set unfinishedIDs = new HashSet();
+ private Set unfinishedIDs = new java.util.HashSet();
- private Set alreadyResolvedIDs = new HashSet();
+ private Set alreadyResolvedIDs = new java.util.HashSet();
/**
* Tie a PageViewport with an ID found on a child area of the PV. Note that
@@ -198,7 +196,7 @@ public class IDTracker {
public void addUnresolvedIDRef(String idref, Resolvable res) {
Set todo = (Set) unresolvedIDRefs.get(idref);
if (todo == null) {
- todo = new HashSet();
+ todo = new java.util.HashSet();
unresolvedIDRefs.put(idref, todo);
}
// add Resolvable object to this HashSet
diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java
index 23d066099..a7523530b 100644
--- a/src/java/org/apache/fop/area/PageViewport.java
+++ b/src/java/org/apache/fop/area/PageViewport.java
@@ -89,7 +89,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl
//Arbitrary attachments to the page from extensions that need to pass information
//down to the renderers.
- private List extensionAttachments = null;
+ private List/*<ExtensionAttachment>*/ extensionAttachments = null;
/**
* logging instance
@@ -122,7 +122,8 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl
*/
public PageViewport(PageViewport original) {
if (original.extensionAttachments != null) {
- this.extensionAttachments = new java.util.ArrayList(original.extensionAttachments);
+ this.extensionAttachments
+ = new java.util.ArrayList/*<ExtensionAttachment>*/(original.extensionAttachments);
}
this.pageIndex = original.pageIndex;
this.pageNumber = original.pageNumber;
@@ -588,7 +589,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl
*/
public void addExtensionAttachment(ExtensionAttachment attachment) {
if (this.extensionAttachments == null) {
- this.extensionAttachments = new java.util.ArrayList();
+ this.extensionAttachments = new java.util.ArrayList/*<ExtensionAttachment>*/();
}
extensionAttachments.add(attachment);
}
diff --git a/src/java/org/apache/fop/area/RegionReference.java b/src/java/org/apache/fop/area/RegionReference.java
index eac90ce41..bee597673 100644
--- a/src/java/org/apache/fop/area/RegionReference.java
+++ b/src/java/org/apache/fop/area/RegionReference.java
@@ -160,4 +160,13 @@ public class RegionReference extends Area implements Cloneable {
return rr;
}
+ /** {@inheritDoc} */
+ public String toString() {
+ StringBuffer sb = new StringBuffer(super.toString());
+ sb.append(" {regionName=").append(regionName);
+ sb.append(", regionClass=").append(regionClass);
+ sb.append(", ctm=").append(ctm);
+ sb.append("}");
+ return sb.toString();
+ }
}
diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java
index e75fd4e79..13995b099 100644
--- a/src/java/org/apache/fop/area/RenderPagesModel.java
+++ b/src/java/org/apache/fop/area/RenderPagesModel.java
@@ -50,9 +50,9 @@ public class RenderPagesModel extends AreaTreeModel {
/**
* Pages that have been prepared but not rendered yet.
*/
- protected List prepared = new java.util.ArrayList();
- private List pendingODI = new java.util.ArrayList();
- private List endDocODI = new java.util.ArrayList();
+ protected List/*<PageViewport>*/ prepared = new java.util.ArrayList/*<PageViewport>*/();
+ private List/*<OffDocumentItem>*/ pendingODI = new java.util.ArrayList/*<OffDocumentItem>*/();
+ private List/*<OffDocumentItem>*/ endDocODI = new java.util.ArrayList/*<OffDocumentItem>*/();
/**
* Create a new render pages model with the given renderer.
@@ -66,7 +66,7 @@ public class RenderPagesModel extends AreaTreeModel {
FontInfo fontInfo, OutputStream stream) throws FOPException {
super();
- renderer = userAgent.getRendererFactory().createRenderer(
+ this.renderer = userAgent.getRendererFactory().createRenderer(
userAgent, outputFormat);
try {
diff --git a/src/java/org/apache/fop/area/inline/FilledArea.java b/src/java/org/apache/fop/area/inline/FilledArea.java
index 3e108db19..7df62e79b 100644
--- a/src/java/org/apache/fop/area/inline/FilledArea.java
+++ b/src/java/org/apache/fop/area/inline/FilledArea.java
@@ -70,10 +70,10 @@ public class FilledArea extends InlineParent {
/**
* Set the unit width for the areas to fill the full width.
*
- * @param w the unit width
+ * @param width the unit width
*/
- public void setUnitWidth(int w) {
- unitWidth = w;
+ public void setUnitWidth(int width) {
+ this.unitWidth = width;
}
/**
@@ -82,7 +82,7 @@ public class FilledArea extends InlineParent {
* @return the unit width
*/
public int getUnitWidth() {
- return unitWidth;
+ return this.unitWidth;
}
/**
@@ -117,7 +117,7 @@ public class FilledArea extends InlineParent {
}
/**
- * recursively apply the variation factor to all descendant areas
+ * Recursively apply the variation factor to all descendant areas
* @param variationFactor the variation factor that must be applied to adjustments
* @param lineStretch the total stretch of the line
* @param lineShrink the total shrink of the line
diff --git a/src/java/org/apache/fop/area/inline/Image.java b/src/java/org/apache/fop/area/inline/Image.java
index 1fc3375e5..7d802db49 100644
--- a/src/java/org/apache/fop/area/inline/Image.java
+++ b/src/java/org/apache/fop/area/inline/Image.java
@@ -28,14 +28,14 @@ import org.apache.fop.area.Area;
*/
public class Image extends Area {
private String url;
-
+
/**
* Create a new image with the given url.
*
- * @param u the url of the image
+ * @param url the url of the image
*/
- public Image(String u) {
- url = u;
+ public Image(String url) {
+ this.url = url;
}
/**
@@ -45,7 +45,7 @@ public class Image extends Area {
* @return the url of this image
*/
public String getURL() {
- return url;
+ return this.url;
}
}
diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java
index d8936dd42..6d5d9ca98 100644
--- a/src/java/org/apache/fop/area/inline/InlineArea.java
+++ b/src/java/org/apache/fop/area/inline/InlineArea.java
@@ -221,7 +221,7 @@ public class InlineArea extends Area {
notifyIPDVariation(ipdVariation);
}
- /**
+ /**
* notify the parent area about the ipd variation of this area
* or of a descendant area
* @param ipdVariation the difference between new and old ipd
diff --git a/src/java/org/apache/fop/area/inline/TextArea.java b/src/java/org/apache/fop/area/inline/TextArea.java
index 102b0a330..f736b894c 100644
--- a/src/java/org/apache/fop/area/inline/TextArea.java
+++ b/src/java/org/apache/fop/area/inline/TextArea.java
@@ -63,6 +63,7 @@ public class TextArea extends AbstractTextArea {
*
* @param word the word string
* @param offset the offset for the next area
+ * @param letterAdjust the letter adjustment array (may be null)
*/
public void addWord(String word, int offset, int[] letterAdjust) {
WordArea wordArea = new WordArea(word, offset, letterAdjust);
@@ -98,7 +99,7 @@ public class TextArea extends AbstractTextArea {
StringBuffer text = new StringBuffer();
InlineArea child;
// assemble the text
- for (int i = 0; i < inlines.size(); i ++) {
+ for (int i = 0; i < inlines.size(); i++) {
child = (InlineArea) inlines.get(i);
if (child instanceof WordArea) {
text.append(((WordArea) child).getWord());
@@ -109,5 +110,9 @@ public class TextArea extends AbstractTextArea {
return text.toString();
}
+ /** {@inheritDoc} */
+ public String toString() {
+ return "TextArea{text=" + getText() + "}";
+ }
}
diff --git a/src/java/org/apache/fop/area/inline/Viewport.java b/src/java/org/apache/fop/area/inline/Viewport.java
index fadc1ec2a..489f5afda 100644
--- a/src/java/org/apache/fop/area/inline/Viewport.java
+++ b/src/java/org/apache/fop/area/inline/Viewport.java
@@ -45,7 +45,7 @@ public class Viewport extends InlineArea {
* @param child the child content area of this viewport
*/
public Viewport(Area child) {
- content = child;
+ this.content = child;
}
/**
@@ -54,7 +54,7 @@ public class Viewport extends InlineArea {
* @param c true if this viewport should clip
*/
public void setClip(boolean c) {
- clip = c;
+ this.clip = c;
}
/**
@@ -63,7 +63,7 @@ public class Viewport extends InlineArea {
* @return true if this viewport should clip
*/
public boolean getClip() {
- return clip;
+ return this.clip;
}
/**
@@ -72,7 +72,7 @@ public class Viewport extends InlineArea {
* @param cp the position and size to place the content
*/
public void setContentPosition(Rectangle2D cp) {
- contentPosition = cp;
+ this.contentPosition = cp;
}
/**
@@ -81,7 +81,7 @@ public class Viewport extends InlineArea {
* @return the position and size to place the content
*/
public Rectangle2D getContentPosition() {
- return contentPosition;
+ return this.contentPosition;
}
/**
@@ -98,7 +98,7 @@ public class Viewport extends InlineArea {
* @return the content area
*/
public Area getContent() {
- return content;
+ return this.content;
}
private void writeObject(java.io.ObjectOutputStream out)
@@ -123,9 +123,9 @@ public class Viewport extends InlineArea {
in.readFloat(),
in.readFloat());
}
- clip = in.readBoolean();
- props = (HashMap) in.readObject();
- content = (Area) in.readObject();
+ this.clip = in.readBoolean();
+ this.props = (HashMap) in.readObject();
+ this.content = (Area) in.readObject();
}
}
diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java
index 5e38b803a..4f49ea269 100644
--- a/src/java/org/apache/fop/cli/InputHandler.java
+++ b/src/java/org/apache/fop/cli/InputHandler.java
@@ -51,6 +51,9 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.render.awt.viewer.Renderable;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
/**
* Class for handling files input from command line
diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml
index cd956ed6a..3b3b34e36 100644
--- a/src/java/org/apache/fop/events/EventFormatter.xml
+++ b/src/java/org/apache/fop/events/EventFormatter.xml
@@ -23,6 +23,7 @@
<message key="rule.childOfSPM">The element must be a child of fo:simple-page-master.</message>
<message key="rule.childOfDeclarations">The element must be a child of fo:declarations.</message>
<message key="rule.childOfSPMorDeclarations">The element must be a child of fo:declarations or fo:simple-page-master.</message>
+ <message key="rule.childOfInstreamForeignObjectorExternalGraphic">The element must be a child of fo:instream-foreign-object or fo:external-graphic.</message>
<message key="rule.wrapperInvalidChildForParent">An fo:wrapper is only permitted to have children that would be permitted for its parent.</message>
<message key="org.apache.fop.fo.FOValidationEventProducer.tooManyNodes">For "{elementName}", only one "{offendingNode}" may be declared.{{locator}}</message>
<message key="org.apache.fop.fo.FOValidationEventProducer.nodeOutOfOrder">For "{elementName}", "{tooLateNode}" must be declared before "{tooEarlyNode}"!{{locator}}</message>
@@ -99,4 +100,7 @@ Any reference to it will be considered a reference to the first occurrence in th
<message key="org.apache.fop.fonts.FontEventAdapter.fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message>
<message key="org.apache.fop.fonts.FontEventAdapter.fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message>
<message key="org.apache.fop.fonts.FontEventAdapter.glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message>
+<message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup"/>
+<message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont"/>
+<message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError"/>
</catalogue>
diff --git a/src/java/org/apache/fop/fo/ElementMapping.java b/src/java/org/apache/fop/fo/ElementMapping.java
index d51c21993..1651f23a6 100644
--- a/src/java/org/apache/fop/fo/ElementMapping.java
+++ b/src/java/org/apache/fop/fo/ElementMapping.java
@@ -39,6 +39,7 @@ public abstract class ElementMapping {
/** The HashMap table of formatting objects defined by the ElementMapping */
protected HashMap foObjs = null;
+ //Please don't change that to java.util.Map as that can break extensions.
/** The namespace for the ElementMapping */
protected String namespaceURI = null;
diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java
index 3e369b934..e0624df69 100644
--- a/src/java/org/apache/fop/fo/FObj.java
+++ b/src/java/org/apache/fop/fo/FObj.java
@@ -573,6 +573,11 @@ public abstract class FObj extends FONode implements Constants {
}
}
+ /** @return true if this FObj has extension attachments */
+ public boolean hasExtensionAttachments() {
+ return extensionAttachments != null;
+ }
+
/**
* Adds a foreign attribute to this FObj.
* @param attributeName the attribute name as a QName instance
diff --git a/src/java/org/apache/fop/fo/flow/Marker.java b/src/java/org/apache/fop/fo/flow/Marker.java
index 1e8b352bb..01863c0c7 100644
--- a/src/java/org/apache/fop/fo/flow/Marker.java
+++ b/src/java/org/apache/fop/fo/flow/Marker.java
@@ -34,6 +34,7 @@ import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.PropertyListMaker;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.Property;
+import org.apache.fop.fo.properties.PropertyCache;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_marker">
@@ -334,10 +335,10 @@ public class Marker extends FObjMixed {
}
/** Convenience inner class */
- private static final class MarkerAttribute {
+ public static final class MarkerAttribute {
- private static Map attributeCache =
- Collections.synchronizedMap(new java.util.WeakHashMap());
+ private static PropertyCache attributeCache =
+ new PropertyCache(MarkerAttribute.class);
protected String namespace;
protected String qname;
@@ -373,18 +374,26 @@ public class Marker extends FObjMixed {
private static MarkerAttribute getInstance(
String namespace, String qname,
String name, String value) {
- MarkerAttribute newInstance =
- new MarkerAttribute(namespace, qname, name, value);
- if (attributeCache.containsKey(newInstance)) {
- return (MarkerAttribute) attributeCache.get(newInstance);
- } else {
- attributeCache.put(newInstance, newInstance);
- return newInstance;
- }
+ return attributeCache.fetch(
+ new MarkerAttribute(namespace, qname, name, value));
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ int hash = 17;
+ hash = (37 * hash) + (this.namespace == null ? 0 : this.namespace.hashCode());
+ hash = (37 * hash) + (this.qname == null ? 0 : this.qname.hashCode());
+ hash = (37 * hash) + (this.name == null ? 0 : this.name.hashCode());
+ hash = (37 * hash) + (this.value == null ? 0 : this.value.hashCode());
+ return hash;
}
/** {@inheritDoc} */
public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
if (o instanceof MarkerAttribute) {
MarkerAttribute attr = (MarkerAttribute) o;
return ((attr.namespace == this.namespace)
diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java
index d472b574c..dc9abb023 100644
--- a/src/java/org/apache/fop/fo/properties/PropertyCache.java
+++ b/src/java/org/apache/fop/fo/properties/PropertyCache.java
@@ -19,6 +19,8 @@
package org.apache.fop.fo.properties;
+import org.apache.fop.fo.flow.Marker;
+
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
@@ -53,7 +55,7 @@ public final class PropertyCache {
private Class runtimeType;
- private boolean[] votesForRehash = new boolean[SEGMENT_COUNT];
+ private final boolean[] votesForRehash = new boolean[SEGMENT_COUNT];
/* same hash function as used by java.util.HashMap */
private static int hash(Object x) {
@@ -381,6 +383,19 @@ public final class PropertyCache {
return (CommonBorderPaddingBackground.BorderInfo) fetch((Object) bi);
}
+ /**
+ * Checks if the given {@link Marker.MarkerAttribute} is present
+ * in the cache - if so, returns a reference to the cached instance.
+ * Otherwise the given object is added to the cache and returned.
+ *
+ * @param ma the MarkerAttribute instance to check for
+ * @return the cached instance
+ */
+ public Marker.MarkerAttribute fetch(
+ Marker.MarkerAttribute ma) {
+ return (Marker.MarkerAttribute) fetch((Object) ma);
+ }
+
/** {@inheritDoc} */
public String toString() {
return super.toString() + "[runtimeType=" + this.runtimeType + "]";
diff --git a/src/java/org/apache/fop/fonts/Base14Font.java b/src/java/org/apache/fop/fonts/Base14Font.java
index 04349a148..9b2e95bc7 100644
--- a/src/java/org/apache/fop/fonts/Base14Font.java
+++ b/src/java/org/apache/fop/fonts/Base14Font.java
@@ -19,6 +19,7 @@
package org.apache.fop.fonts;
+
/**
* Base class for all Base 14 fonts.
*/
diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java
index eac794514..8f468f7a4 100644
--- a/src/java/org/apache/fop/fonts/CIDFont.java
+++ b/src/java/org/apache/fop/fonts/CIDFont.java
@@ -76,4 +76,4 @@ public abstract class CIDFont extends CustomFont {
return true;
}
-} \ No newline at end of file
+}
diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java
index 0b40dfecc..4cf24ae16 100644
--- a/src/java/org/apache/fop/fonts/CustomFont.java
+++ b/src/java/org/apache/fop/fonts/CustomFont.java
@@ -26,6 +26,7 @@ import java.util.Set;
import javax.xml.transform.Source;
+
/**
* Abstract base class for custom fonts loaded from files, for example.
*/
diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java
index ebd45457d..e9740c00c 100644
--- a/src/java/org/apache/fop/fonts/Font.java
+++ b/src/java/org/apache/fop/fonts/Font.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fonts.CodePointMapping;
/**
* This class holds font state information and provides access to the font
diff --git a/src/java/org/apache/fop/fonts/FontCollection.java b/src/java/org/apache/fop/fonts/FontCollection.java
index 3c9bba7f4..d481ae2f9 100644
--- a/src/java/org/apache/fop/fonts/FontCollection.java
+++ b/src/java/org/apache/fop/fonts/FontCollection.java
@@ -24,6 +24,7 @@ package org.apache.fop.fonts;
* Sets up a set of fonts
*/
public interface FontCollection {
+
/**
* Sets up fonts in a font info object.
*
diff --git a/src/java/org/apache/fop/fonts/FontDescriptor.java b/src/java/org/apache/fop/fonts/FontDescriptor.java
index fadc73834..e7c81c9f3 100644
--- a/src/java/org/apache/fop/fonts/FontDescriptor.java
+++ b/src/java/org/apache/fop/fonts/FontDescriptor.java
@@ -19,6 +19,7 @@
package org.apache.fop.fonts;
+
/**
* This interface enhances the font metrics interface with access methods to
* value needed to register fonts in various target formats like PDF or
diff --git a/src/java/org/apache/fop/fonts/FontEventListener.java b/src/java/org/apache/fop/fonts/FontEventListener.java
index b508d7053..740a05fdc 100644
--- a/src/java/org/apache/fop/fonts/FontEventListener.java
+++ b/src/java/org/apache/fop/fonts/FontEventListener.java
@@ -19,7 +19,6 @@
package org.apache.fop.fonts;
-
/**
* Event listener interface for font-related events.
*/
diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java
index 2bcc6d7e1..8f8032767 100644
--- a/src/java/org/apache/fop/fonts/FontInfo.java
+++ b/src/java/org/apache/fop/fonts/FontInfo.java
@@ -110,6 +110,19 @@ public class FontInfo {
}
/**
+ * Adds a series of new font triplets given an array of font family names.
+ * @param name internal key
+ * @param families an array of font family names
+ * @param style font style (normal, italic, oblique...)
+ * @param weight font weight
+ */
+ public void addFontProperties(String name, String[] families, String style, int weight) {
+ for (int i = 0; i < families.length; i++) {
+ addFontProperties(name, families[i], style, weight);
+ }
+ }
+
+ /**
* Adds a new font triplet.
* @param internalFontKey internal font key
* @param triplet the font triplet to associate with the internal key
@@ -193,7 +206,8 @@ public class FontInfo {
private FontTriplet fontLookup(String family, String style,
int weight, boolean substitutable) {
if (log.isTraceEnabled()) {
- log.trace("Font lookup: " + family + " " + style + " " + weight);
+ log.trace("Font lookup: " + family + " " + style + " " + weight
+ + (substitutable ? " substitutable" : ""));
}
FontTriplet startKey = createFontKey(family, style, weight);
@@ -215,7 +229,7 @@ public class FontInfo {
}
private FontTriplet fuzzyFontLookup(String family, String style,
- int weight, FontTriplet startKey, boolean substFont) {
+ int weight, FontTriplet startKey, boolean substitutable) {
FontTriplet key;
String internalFontKey = null;
if (!family.equals(startKey.getName())) {
@@ -232,7 +246,8 @@ public class FontInfo {
internalFontKey = getInternalFontKey(key);
}
- if (!substFont && internalFontKey == null) {
+ // return null if not found and not substitutable
+ if (!substitutable && internalFontKey == null) {
return null;
}
@@ -263,18 +278,18 @@ public class FontInfo {
// fallback 2: try the same font-family with default style and weight
/* obsolete: replaced by the loop above
- if (f == null) {
+ if (internalFontKey == null) {
key = createFontKey(family, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
- f = getInternalFontKey(key);
+ internalFontKey = getInternalFontKey(key);
}*/
- // fallback 3: try any family with orig style/weight
+ // fallback 3: try any family with original style/weight
if (internalFontKey == null) {
return fuzzyFontLookup("any", style, weight, startKey, false);
}
// last resort: use default
- if (internalFontKey == null) {
+ if (key == null && internalFontKey == null) {
key = Font.DEFAULT_FONT;
internalFontKey = getInternalFontKey(key);
}
@@ -303,6 +318,7 @@ public class FontInfo {
/**
* Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size.
+ *
* @param triplet the font triplet designating the requested font
* @param fontSize the font size
* @return the requested Font instance
@@ -326,6 +342,57 @@ public class FontInfo {
return font;
}
+ private List/*<FontTriplet>*/ getTripletsForName(String fontName) {
+ List/*<FontTriplet>*/ matchedTriplets = new java.util.ArrayList/*<FontTriplet>*/();
+ Iterator it = triplets.keySet().iterator();
+ while (it.hasNext()) {
+ FontTriplet triplet = (FontTriplet)it.next();
+ String tripletName = triplet.getName();
+ if (tripletName.toLowerCase().equals(fontName.toLowerCase())) {
+ matchedTriplets.add(triplet);
+ }
+ }
+ return matchedTriplets;
+ }
+
+ /**
+ * Returns a suitable internal font given an AWT Font instance.
+ *
+ * @param awtFont the AWT font
+ * @return a best matching internal Font
+ */
+ public Font getFontInstanceForAWTFont(java.awt.Font awtFont) {
+ String awtFontName = awtFont.getName();
+ String awtFontFamily = awtFont.getFamily();
+ String awtFontStyle = awtFont.isItalic() ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
+ int awtFontWeight = awtFont.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL;
+
+ FontTriplet matchedTriplet = null;
+ List/*<FontTriplet>*/ triplets = getTripletsForName(awtFontName);
+ if (!triplets.isEmpty()) {
+ Iterator it = triplets.iterator();
+ while (it.hasNext()) {
+ FontTriplet triplet = (FontTriplet)it.next();
+ boolean styleMatched = triplet.getStyle().equals(awtFontStyle);
+ boolean weightMatched = triplet.getWeight() == awtFontWeight;
+ if (styleMatched && weightMatched) {
+ matchedTriplet = triplet;
+ break;
+ }
+ }
+ }
+
+ // not matched on font name so do a lookup using family
+ if (matchedTriplet == null) {
+ if (awtFontFamily.equals("sanserif")) {
+ awtFontFamily = "sans-serif";
+ }
+ matchedTriplet = fontLookup(awtFontFamily, awtFontStyle, awtFontWeight);
+ }
+ int fontSize = Math.round(awtFont.getSize2D() * 1000);
+ return getFontInstance(matchedTriplet, fontSize);
+ }
+
/**
* Lookup a font.
* <br>
@@ -345,7 +412,7 @@ public class FontInfo {
private List/*<FontTriplet>*/ fontLookup(String[] families, String style,
int weight, boolean substitutable) {
- List matchingTriplets = new java.util.ArrayList();
+ List/*<FontTriplet>*/ matchingTriplets = new java.util.ArrayList/*<FontTriplet>*/();
FontTriplet triplet = null;
for (int i = 0; i < families.length; i++) {
triplet = fontLookup(families[i], style, weight, substitutable);
@@ -555,7 +622,7 @@ public class FontInfo {
List/*<FontTriplet>*/ foundTriplets = new java.util.ArrayList();
for (Iterator iter = triplets.entrySet().iterator(); iter.hasNext();) {
Map.Entry tripletEntry = (Map.Entry) iter.next();
- if (fontName.equals(((String)tripletEntry.getValue()))) {
+ if (fontName.equals((tripletEntry.getValue()))) {
foundTriplets.add(tripletEntry.getKey());
}
}
diff --git a/src/java/org/apache/fop/fonts/FontMetrics.java b/src/java/org/apache/fop/fonts/FontMetrics.java
index 7d5588690..29ade1ef3 100644
--- a/src/java/org/apache/fop/fonts/FontMetrics.java
+++ b/src/java/org/apache/fop/fonts/FontMetrics.java
@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.Set;
+
/**
* Main interface for access to font metrics.
*/
diff --git a/src/java/org/apache/fop/fonts/FontTriplet.java b/src/java/org/apache/fop/fonts/FontTriplet.java
index 8e0acd8f2..f5cfe442a 100644
--- a/src/java/org/apache/fop/fonts/FontTriplet.java
+++ b/src/java/org/apache/fop/fonts/FontTriplet.java
@@ -21,6 +21,7 @@ package org.apache.fop.fonts;
import java.io.Serializable;
+
/**
* FontTriplet contains information on name, style and weight of one font
*/
diff --git a/src/java/org/apache/fop/fonts/FontType.java b/src/java/org/apache/fop/fonts/FontType.java
index 0abe06a10..95b594ca4 100644
--- a/src/java/org/apache/fop/fonts/FontType.java
+++ b/src/java/org/apache/fop/fonts/FontType.java
@@ -19,12 +19,10 @@
package org.apache.fop.fonts;
-import org.apache.avalon.framework.ValuedEnum;
-
/**
* This class enumerates all supported font types.
*/
-public class FontType extends ValuedEnum {
+public class FontType {
/**
* Collective identifier for "other" font types
@@ -51,12 +49,16 @@ public class FontType extends ValuedEnum {
*/
public static final FontType TRUETYPE = new FontType("TrueType", 5);
+ private final String name;
+ private final int value;
+
/**
* @see org.apache.avalon.framework.Enum#Enum(String)
*/
protected FontType(String name, int value) {
- super(name, value);
+ this.name = name;
+ this.value = value;
}
@@ -107,4 +109,22 @@ public class FontType extends ValuedEnum {
}
}
+ /**
+ * Returns the name
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value
+ *
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
}
diff --git a/src/java/org/apache/fop/fonts/FontUtil.java b/src/java/org/apache/fop/fonts/FontUtil.java
index 6ec89631f..49f23c12f 100644
--- a/src/java/org/apache/fop/fonts/FontUtil.java
+++ b/src/java/org/apache/fop/fonts/FontUtil.java
@@ -19,6 +19,7 @@
package org.apache.fop.fonts;
+
/**
* Font utilities.
*/
diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java
index f25ca4e7e..b22b92e2f 100644
--- a/src/java/org/apache/fop/fonts/MultiByteFont.java
+++ b/src/java/org/apache/fop/fonts/MultiByteFont.java
@@ -23,6 +23,7 @@ package org.apache.fop.fonts;
import java.text.DecimalFormat;
import java.util.Map;
+
/**
* Generic MultiByte (CID) font
*/
diff --git a/src/java/org/apache/fop/fonts/MutableFont.java b/src/java/org/apache/fop/fonts/MutableFont.java
index 5939bfed4..a5acf51b3 100644
--- a/src/java/org/apache/fop/fonts/MutableFont.java
+++ b/src/java/org/apache/fop/fonts/MutableFont.java
@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.Set;
+
/**
* This interface is used to set the values of a font during configuration time.
*/
diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java
index 2fa8f1888..f4e317de3 100644
--- a/src/java/org/apache/fop/fonts/Typeface.java
+++ b/src/java/org/apache/fop/fonts/Typeface.java
@@ -139,4 +139,9 @@ public abstract class Typeface implements FontMetrics {
}
}
}
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return getFullName();
+ }
}
diff --git a/src/java/org/apache/fop/fonts/package.html b/src/java/org/apache/fop/fonts/package.html
index 33e1e2cb3..fee0bf827 100644
--- a/src/java/org/apache/fop/fonts/package.html
+++ b/src/java/org/apache/fop/fonts/package.html
@@ -1,3 +1,20 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.fonts Package</TITLE>
<BODY>
diff --git a/src/java/org/apache/fop/image/loader/batik/BatikUtil.java b/src/java/org/apache/fop/image/loader/batik/BatikUtil.java
index 558c3b043..20a7bf767 100644
--- a/src/java/org/apache/fop/image/loader/batik/BatikUtil.java
+++ b/src/java/org/apache/fop/image/loader/batik/BatikUtil.java
@@ -19,6 +19,11 @@
package org.apache.fop.image.loader.batik;
+import org.w3c.dom.Document;
+
+import org.apache.batik.dom.AbstractDocument;
+import org.apache.batik.dom.util.DOMUtilities;
+
/**
* Helper utilities for Apache Batik.
*/
@@ -38,4 +43,18 @@ public class BatikUtil {
return false;
}
+ /**
+ * Clones an SVG DOM document. This is used for making SVG production thread-safe when the
+ * SVG document is cached and re-used.
+ * @param doc the SVG DOM to be cloned
+ * @return the cloned SVG DOM
+ */
+ public static Document cloneSVGDocument(Document doc) {
+ Document clonedDoc = DOMUtilities.deepCloneDocument(doc, doc.getImplementation());
+ if (clonedDoc instanceof AbstractDocument) {
+ ((AbstractDocument)clonedDoc).setDocumentURI(((AbstractDocument)doc).getDocumentURI());
+ }
+ return clonedDoc;
+ }
+
}
diff --git a/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java b/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java
new file mode 100644
index 000000000..ea92f748b
--- /dev/null
+++ b/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java
@@ -0,0 +1,67 @@
+package org.apache.fop.image.loader.batik;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.gvt.GraphicsNode;
+
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+
+/**
+ * A generic graphics 2D image painter implementation
+ */
+public class Graphics2DImagePainterImpl implements Graphics2DImagePainter {
+
+ private final GraphicsNode root;
+ /** the Batik bridge context */
+ protected final BridgeContext ctx;
+ /** the intrinsic size of the image */
+ protected final Dimension imageSize;
+
+ /**
+ * Main constructor
+ *
+ * @param root the graphics node root
+ * @param ctx the bridge context
+ * @param imageSize the image size
+ */
+ public Graphics2DImagePainterImpl(GraphicsNode root, BridgeContext ctx, Dimension imageSize) {
+ this.root = root;
+ this.imageSize = imageSize;
+ this.ctx = ctx;
+ }
+
+ /** {@inheritDoc} */
+ public Dimension getImageSize() {
+ return imageSize;
+ }
+
+ private void prepare(Graphics2D g2d, Rectangle2D area) {
+ // If no viewbox is defined in the svg file, a viewbox of 100x100 is
+ // assumed, as defined in SVGUserAgent.getViewportSize()
+ double tx = area.getX();
+ double ty = area.getY();
+ if (tx != 0 || ty != 0) {
+ g2d.translate(tx, ty);
+ }
+
+ float iw = (float) ctx.getDocumentSize().getWidth();
+ float ih = (float) ctx.getDocumentSize().getHeight();
+ float w = (float) area.getWidth();
+ float h = (float) area.getHeight();
+ float sx = w / iw;
+ float sy = h / ih;
+ if (sx != 1.0 || sy != 1.0) {
+ g2d.scale(sx, sy);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void paint(Graphics2D g2d, Rectangle2D area) {
+ prepare(g2d, area);
+ root.paint(g2d);
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java
index 9ea333af0..2bb521dc9 100644
--- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java
+++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java
@@ -20,11 +20,11 @@
package org.apache.fop.image.loader.batik;
import java.awt.Dimension;
-import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
import java.util.Map;
+import org.w3c.dom.Document;
+
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgent;
@@ -32,10 +32,11 @@ import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.svg.SimpleSVGUserAgent;
+
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageProcessingHints;
import org.apache.xmlgraphics.image.loader.XMLNamespaceEnabledImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter;
@@ -44,6 +45,8 @@ import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.apache.xmlgraphics.util.UnitConv;
+import org.apache.fop.svg.SimpleSVGUserAgent;
+
/**
* This ImageConverter converts SVG images to Java2D.
* <p>
@@ -58,7 +61,7 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter {
private static Log log = LogFactory.getLog(ImageConverterSVG2G2D.class);
/** {@inheritDoc} */
- public Image convert(Image src, Map hints) throws ImageException {
+ public Image convert(final Image src, Map hints) throws ImageException {
checkSourceFlavor(src);
final ImageXMLDOM svg = (ImageXMLDOM)src;
if (!SVGDOMImplementation.SVG_NAMESPACE_URI.equals(svg.getRootNamespace())) {
@@ -76,37 +79,28 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter {
GVTBuilder builder = new GVTBuilder();
final BridgeContext ctx = new BridgeContext(ua);
+ Document doc = svg.getDocument();
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+ //to it.
+ Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
+
//Build the GVT tree
final GraphicsNode root;
try {
- root = builder.build(ctx, svg.getDocument());
+ root = builder.build(ctx, clonedDoc);
} catch (Exception e) {
throw new ImageException("GVT tree could not be built for SVG graphic", e);
}
//Create the painter
- Graphics2DImagePainter painter = new Graphics2DImagePainter() {
-
- public void paint(Graphics2D g2d, Rectangle2D area) {
- // If no viewbox is defined in the svg file, a viewbox of 100x100 is
- // assumed, as defined in SVGUserAgent.getViewportSize()
- float iw = (float) ctx.getDocumentSize().getWidth();
- float ih = (float) ctx.getDocumentSize().getHeight();
- float w = (float) area.getWidth();
- float h = (float) area.getHeight();
- g2d.translate(area.getX(), area.getY());
- g2d.scale(w / iw, h / ih);
-
- root.paint(g2d);
- }
-
- public Dimension getImageSize() {
- return new Dimension(svg.getSize().getWidthMpt(), svg.getSize().getHeightMpt());
- }
-
- };
-
- ImageGraphics2D g2dImage = new ImageGraphics2D(src.getInfo(), painter);
+ int width = svg.getSize().getWidthMpt();
+ int height = svg.getSize().getHeightMpt();
+ Dimension imageSize = new Dimension(width, height);
+ Graphics2DImagePainter painter = createPainter(ctx, root, imageSize);
+
+ //Create g2d image
+ ImageInfo imageInfo = src.getInfo();
+ ImageGraphics2D g2dImage = new ImageGraphics2D(imageInfo, painter);
return g2dImage;
}
@@ -129,6 +123,19 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter {
};
}
+ /**
+ * Creates a Graphics 2D image painter
+ *
+ * @param ctx the bridge context
+ * @param root the graphics node root
+ * @param imageSize the image size
+ * @return the newly created graphics 2d image painter
+ */
+ protected Graphics2DImagePainter createPainter(
+ BridgeContext ctx, GraphicsNode root, Dimension imageSize) {
+ return new Graphics2DImagePainterImpl(root, ctx, imageSize);
+ }
+
/** {@inheritDoc} */
public ImageFlavor getSourceFlavor() {
return XMLNamespaceEnabledImageFlavor.SVG_DOM;
diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java
index 154d32e96..9cab6322b 100644
--- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java
+++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java
@@ -29,6 +29,7 @@ import org.apache.fop.datatypes.SimplePercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
+import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
import org.apache.fop.fonts.Font;
diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
index 6b0e88cbb..dc8a020ae 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
@@ -20,12 +20,12 @@
package org.apache.fop.layoutmgr.inline;
import org.apache.fop.fo.flow.PageNumber;
-import org.apache.fop.area.inline.InlineArea;
-import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.Trait;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.area.inline.InlineArea;
+import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.Trait;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java
index 598fd433e..9bc4c0d2e 100644
--- a/src/java/org/apache/fop/pdf/PDFDocument.java
+++ b/src/java/org/apache/fop/pdf/PDFDocument.java
@@ -29,9 +29,12 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -42,7 +45,7 @@ import org.apache.commons.logging.LogFactory;
/* font support based on work by Takayuki Takeuchi */
/**
- * class representing a PDF document.
+ * Class representing a PDF document.
*
* The document is built up by calling various methods and then finally
* output to given filehandle using output method.
@@ -72,53 +75,38 @@ public class PDFDocument {
/** Integer constant to represent PDF 1.4 */
public static final int PDF_VERSION_1_4 = 4;
- /**
- * the encoding to use when converting strings to PDF commandos.
- */
+ /** the encoding to use when converting strings to PDF commands */
public static final String ENCODING = "ISO-8859-1";
+ /** the counter for object numbering */
+ protected int objectcount = 0;
+
+ /** the logger instance */
private Log log = LogFactory.getLog("org.apache.fop.pdf");
- /**
- * the current character position
- */
- protected int position = 0;
+ /** the current character position */
+ private int position = 0;
- /**
- * the character position of each object
- */
- protected List location = new java.util.ArrayList();
+ /** character position of xref table */
+ private int xref;
- /** List of objects to write in the trailer */
- private List trailerObjects = new java.util.ArrayList();
+ /** the character position of each object */
+ private List location = new ArrayList();
- /**
- * the counter for object numbering
- */
- protected int objectcount = 0;
-
- /**
- * the objects themselves
- */
- protected List objects = new java.util.LinkedList();
+ /** List of objects to write in the trailer */
+ private List trailerObjects = new ArrayList();
- /**
- * character position of xref table
- */
- protected int xref;
+ /** the objects themselves */
+ private List objects = new LinkedList();
/** Indicates what PDF version is active */
- protected int pdfVersion = PDF_VERSION_1_4;
+ private int pdfVersion = PDF_VERSION_1_4;
- /**
- * Indicates which PDF profiles are active (PDF/A, PDF/X etc.)
- */
- protected PDFProfile pdfProfile = new PDFProfile(this);
+ /** Indicates which PDF profiles are active (PDF/A, PDF/X etc.) */
+ private PDFProfile pdfProfile = new PDFProfile(this);
- /**
- * the /Root object
- */
- protected PDFRoot root;
+ /** the /Root object */
+ private PDFRoot root;
/** The root outline object */
private PDFOutline outlineRoot = null;
@@ -126,107 +114,67 @@ public class PDFDocument {
/** The /Pages object (mark-fop@inomial.com) */
private PDFPages pages;
- /**
- * the /Info object
- */
- protected PDFInfo info;
+ /** the /Info object */
+ private PDFInfo info;
- /**
- * the /Resources object
- */
- protected PDFResources resources;
+ /** the /Resources object */
+ private PDFResources resources;
- /**
- * the documents encryption, if exists
- */
- protected PDFEncryption encryption;
+ /** the document's encryption, if it exists */
+ private PDFEncryption encryption;
- /**
- * the colorspace (0=RGB, 1=CMYK)
- */
- protected PDFDeviceColorSpace colorspace =
+ /** the colorspace (0=RGB, 1=CMYK) */
+ private PDFDeviceColorSpace colorspace =
new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
- /**
- * the counter for Pattern name numbering (e.g. 'Pattern1')
- */
- protected int patternCount = 0;
+ /** the counter for Pattern name numbering (e.g. 'Pattern1') */
+ private int patternCount = 0;
- /**
- * the counter for Shading name numbering
- */
- protected int shadingCount = 0;
+ /** the counter for Shading name numbering */
+ private int shadingCount = 0;
- /**
- * the counter for XObject numbering
- */
- protected int xObjectCount = 0;
+ /** the counter for XObject numbering */
+ private int xObjectCount = 0;
- /**
- * the XObjects Map.
- * Should be modified (works only for image subtype)
- */
- protected Map xObjectsMap = new java.util.HashMap();
+ /** the {@link PDFXObject}s map */
+ /* TODO: Should be modified (works only for image subtype) */
+ private Map xObjectsMap = new HashMap();
- /**
- * the Font Map.
- */
- protected Map fontMap = new java.util.HashMap();
+ /** The {@link PDFFont} map */
+ private Map fontMap = new HashMap();
- /**
- * The filter map.
- */
- protected Map filterMap = new java.util.HashMap();
+ /** The {@link PDFFilter} map */
+ private Map filterMap = new HashMap();
- /**
- * List of PDFGState objects.
- */
- protected List gstates = new java.util.ArrayList();
+ /** List of {@link PDFGState}s. */
+ private List gstates = new ArrayList();
- /**
- * List of functions.
- */
- protected List functions = new java.util.ArrayList();
+ /** List of {@link PDFFunction}s. */
+ private List functions = new ArrayList();
- /**
- * List of shadings.
- */
- protected List shadings = new java.util.ArrayList();
+ /** List of {@link PDFShading}s. */
+ private List shadings = new ArrayList();
- /**
- * List of patterns.
- */
- protected List patterns = new java.util.ArrayList();
+ /** List of {@link PDFPattern}s. */
+ private List patterns = new ArrayList();
- /**
- * List of Links.
- */
- protected List links = new java.util.ArrayList();
+ /** List of {@link PDFLink}s. */
+ private List links = new ArrayList();
- /**
- * List of Destinations.
- */
- protected List destinations;
+ /** List of {@link PDFDestination}s. */
+ private List destinations;
- /**
- * List of FileSpecs.
- */
- protected List filespecs = new java.util.ArrayList();
+ /** List of {@link PDFFileSpec}s. */
+ private List filespecs = new ArrayList();
- /**
- * List of GoToRemotes.
- */
- protected List gotoremotes = new java.util.ArrayList();
+ /** List of {@link PDFGoToRemote}s. */
+ private List gotoremotes = new ArrayList();
- /**
- * List of GoTos.
- */
- protected List gotos = new java.util.ArrayList();
+ /** List of {@link PDFGoTo}s. */
+ private List gotos = new ArrayList();
- /**
- * List of PDFLaunch objects.
- */
- protected List launches = new java.util.ArrayList();
+ /** List of {@link PDFLaunch}es. */
+ private List launches = new ArrayList();
/**
* The PDFDests object for the name dictionary.
@@ -258,7 +206,7 @@ public class PDFDocument {
this.pages = getFactory().makePages();
// Create the Root object
- this.root = getFactory().makeRoot(pages);
+ this.root = getFactory().makeRoot(this.pages);
// Create the Resources object
this.resources = getFactory().makeResources();
@@ -268,7 +216,8 @@ public class PDFDocument {
}
/**
- * @return the integer representing the active PDF version (one of PDFDocument.PDF_VERSION_*)
+ * @return the integer representing the active PDF version
+ * (one of PDFDocument.PDF_VERSION_*)
*/
public int getPDFVersion() {
return this.pdfVersion;
@@ -293,7 +242,8 @@ public class PDFDocument {
/**
* Returns the factory for PDF objects.
- * @return PDFFactory the factory
+ *
+ * @return the {@link PDFFactory} object
*/
public PDFFactory getFactory() {
return this.factory;
@@ -303,7 +253,8 @@ public class PDFDocument {
* Indicates whether stream encoding on-the-fly is enabled. If enabled
* stream can be serialized without the need for a buffer to merely
* calculate the stream length.
- * @return boolean true if on-the-fly encoding is enabled
+ *
+ * @return <code>true</code> if on-the-fly encoding is enabled
*/
public boolean isEncodingOnTheFly() {
return this.encodingOnTheFly;
@@ -311,8 +262,9 @@ public class PDFDocument {
/**
* Converts text to a byte array for writing to a PDF file.
+ *
* @param text text to convert/encode
- * @return byte[] the resulting byte array
+ * @return the resulting <code>byte</code> array
*/
public static byte[] encode(String text) {
try {
@@ -327,6 +279,7 @@ public class PDFDocument {
* buffered to reduce the number of calls to the encoding converter so don't forget
* to <code>flush()</code> the Writer after use or before writing directly to the
* underlying OutputStream.
+ *
* @param out the OutputStream to write to
* @return the requested Writer
*/
@@ -339,7 +292,7 @@ public class PDFDocument {
}
/**
- * set the producer of the document
+ * Sets the producer of the document.
*
* @param producer string indicating application producing the PDF
*/
@@ -348,16 +301,16 @@ public class PDFDocument {
}
/**
- * Set the creation date of the document.
+ * Sets the creation date of the document.
*
* @param date Date to be stored as creation date in the PDF.
*/
public void setCreationDate(Date date) {
- info.setCreationDate(date);
+ this.info.setCreationDate(date);
}
/**
- * Set the creator of the document.
+ * Sets the creator of the document.
*
* @param creator string indicating application creating the document
*/
@@ -366,7 +319,7 @@ public class PDFDocument {
}
/**
- * Set the filter map to use for filters in this document.
+ * Sets the filter map to use for filters in this document.
*
* @param map the map of filter lists for each stream type
*/
@@ -375,7 +328,7 @@ public class PDFDocument {
}
/**
- * Get the filter map used for filters in this document.
+ * Returns the {@link PDFFilter}s map used for filters in this document.
*
* @return the map of filters being used
*/
@@ -384,36 +337,38 @@ public class PDFDocument {
}
/**
- * Returns the PDFPages object associated with the root object.
- * @return the PDFPages object
+ * Returns the {@link PDFPages} object associated with the root object.
+ *
+ * @return the {@link PDFPages} object
*/
public PDFPages getPages() {
return this.pages;
}
/**
- * Get the PDF root object.
+ * Get the {@link PDFRoot} object for this document.
*
- * @return the PDFRoot object
+ * @return the {@link PDFRoot} object
*/
public PDFRoot getRoot() {
return this.root;
}
/**
- * Get the pdf info object for this document.
+ * Get the {@link PDFInfo} object for this document.
*
- * @return the PDF Info object for this document
+ * @return the {@link PDFInfo} object
*/
public PDFInfo getInfo() {
- return info;
+ return this.info;
}
/**
- * Registers a PDFObject in this PDF document. The PDF is assigned a new
- * object number.
- * @param obj PDFObject to add
- * @return PDFObject the PDFObject added (its object number set)
+ * Registers a {@link PDFObject} in this PDF document.
+ * The object is assigned a new object number.
+ *
+ * @param obj {@link PDFObject} to add
+ * @return the added {@link PDFObject} added (with its object number set)
*/
public PDFObject registerObject(PDFObject obj) {
assignObjectNumber(obj);
@@ -422,9 +377,10 @@ public class PDFDocument {
}
/**
- * Assigns the PDFObject a object number and sets the parent of the
- * PDFObject to this PDFDocument.
- * @param obj PDFObject to assign a number to
+ * Assigns the {@link PDFObject} an object number,
+ * and sets the parent of the {@link PDFObject} to this document.
+ *
+ * @param obj {@link PDFObject} to assign a number to
*/
public void assignObjectNumber(PDFObject obj) {
if (obj == null) {
@@ -450,9 +406,10 @@ public class PDFDocument {
}
/**
- * Adds an PDFObject to this document. The object must have a object number
- * assigned.
- * @param obj PDFObject to add
+ * Adds a {@link PDFObject} to this document.
+ * The object <em>MUST</em> have an object number assigned.
+ *
+ * @param obj {@link PDFObject} to add
*/
public void addObject(PDFObject obj) {
if (obj == null) {
@@ -521,6 +478,7 @@ public class PDFDocument {
/**
* Apply the encryption filter to a PDFStream if encryption is enabled.
+ *
* @param stream PDFStream to encrypt
*/
public void applyEncryption(AbstractPDFStream stream) {
@@ -531,13 +489,14 @@ public class PDFDocument {
/**
* Enables PDF encryption.
+ *
* @param params The encryption parameters for the pdf file
*/
public void setEncryption(PDFEncryptionParams params) {
getProfile().verifyEncryptionAllowed();
this.encryption = PDFEncryptionManager.newInstance(++this.objectcount, params);
- if (encryption != null) {
- PDFObject pdfObject = (PDFObject)encryption;
+ if (this.encryption != null) {
+ PDFObject pdfObject = (PDFObject)this.encryption;
pdfObject.setDocument(this);
addTrailerObject(pdfObject);
} else {
@@ -549,6 +508,7 @@ public class PDFDocument {
/**
* Indicates whether encryption is active for this PDF or not.
+ *
* @return boolean True if encryption is active
*/
public boolean isEncryptionActive() {
@@ -557,10 +517,11 @@ public class PDFDocument {
/**
* Returns the active Encryption object.
+ *
* @return the Encryption object
*/
public PDFEncryption getEncryption() {
- return encryption;
+ return this.encryption;
}
private Object findPDFObject(List list, PDFObject compare) {
@@ -576,21 +537,23 @@ public class PDFDocument {
/**
* Looks through the registered functions to see if one that is equal to
* a reference object exists
+ *
* @param compare reference object
* @return the function if it was found, null otherwise
*/
protected PDFFunction findFunction(PDFFunction compare) {
- return (PDFFunction)findPDFObject(functions, compare);
+ return (PDFFunction)findPDFObject(this.functions, compare);
}
/**
* Looks through the registered shadings to see if one that is equal to
* a reference object exists
+ *
* @param compare reference object
* @return the shading if it was found, null otherwise
*/
protected PDFShading findShading(PDFShading compare) {
- return (PDFShading)findPDFObject(shadings, compare);
+ return (PDFShading)findPDFObject(this.shadings, compare);
}
/**
@@ -598,24 +561,27 @@ public class PDFDocument {
* The problem with this is for tiling patterns the pattern
* data stream is stored and may use up memory, usually this
* would only be a small amount of data.
+ *
* @param compare reference object
* @return the shading if it was found, null otherwise
*/
protected PDFPattern findPattern(PDFPattern compare) {
- return (PDFPattern)findPDFObject(patterns, compare);
+ return (PDFPattern)findPDFObject(this.patterns, compare);
}
/**
* Finds a font.
+ *
* @param fontname name of the font
* @return PDFFont the requested font, null if it wasn't found
*/
protected PDFFont findFont(String fontname) {
- return (PDFFont)fontMap.get(fontname);
+ return (PDFFont)this.fontMap.get(fontname);
}
/**
* Finds a named destination.
+ *
* @param compare reference object to use as search template
* @return the link if found, null otherwise
*/
@@ -630,58 +596,64 @@ public class PDFDocument {
/**
* Finds a link.
+ *
* @param compare reference object to use as search template
* @return the link if found, null otherwise
*/
protected PDFLink findLink(PDFLink compare) {
- return (PDFLink)findPDFObject(links, compare);
+ return (PDFLink)findPDFObject(this.links, compare);
}
/**
* Finds a file spec.
+ *
* @param compare reference object to use as search template
* @return the file spec if found, null otherwise
*/
protected PDFFileSpec findFileSpec(PDFFileSpec compare) {
- return (PDFFileSpec)findPDFObject(filespecs, compare);
+ return (PDFFileSpec)findPDFObject(this.filespecs, compare);
}
/**
* Finds a goto remote.
+ *
* @param compare reference object to use as search template
* @return the goto remote if found, null otherwise
*/
protected PDFGoToRemote findGoToRemote(PDFGoToRemote compare) {
- return (PDFGoToRemote)findPDFObject(gotoremotes, compare);
+ return (PDFGoToRemote)findPDFObject(this.gotoremotes, compare);
}
/**
* Finds a goto.
+ *
* @param compare reference object to use as search template
* @return the goto if found, null otherwise
*/
protected PDFGoTo findGoTo(PDFGoTo compare) {
- return (PDFGoTo)findPDFObject(gotos, compare);
+ return (PDFGoTo)findPDFObject(this.gotos, compare);
}
/**
* Finds a launch.
+ *
* @param compare reference object to use as search template
* @return the launch if found, null otherwise
*/
protected PDFLaunch findLaunch(PDFLaunch compare) {
- return (PDFLaunch) findPDFObject(launches, compare);
+ return (PDFLaunch) findPDFObject(this.launches, compare);
}
/**
* Looks for an existing GState to use
+ *
* @param wanted requested features
* @param current currently active features
- * @return PDFGState the GState if found, null otherwise
+ * @return the GState if found, null otherwise
*/
protected PDFGState findGState(PDFGState wanted, PDFGState current) {
PDFGState poss;
- Iterator iter = gstates.iterator();
+ Iterator iter = this.gstates.iterator();
while (iter.hasNext()) {
PDFGState avail = (PDFGState)iter.next();
poss = new PDFGState();
@@ -695,7 +667,7 @@ public class PDFDocument {
}
/**
- * Get the PDF color space object.
+ * Returns the PDF color space object.
*
* @return the color space
*/
@@ -704,7 +676,7 @@ public class PDFDocument {
}
/**
- * Get the color space.
+ * Returns the color space.
*
* @return the color space
*/
@@ -723,12 +695,12 @@ public class PDFDocument {
}
/**
- * Get the font map for this document.
+ * Returns the font map for this document.
*
* @return the map of fonts used in this document
*/
public Map getFontMap() {
- return fontMap;
+ return this.fontMap;
}
/**
@@ -741,7 +713,7 @@ public class PDFDocument {
protected InputStream resolveURI(String uri)
throws java.io.FileNotFoundException {
try {
- /**@todo Temporary hack to compile, improve later */
+ /* TODO: Temporary hack to compile, improve later */
return new java.net.URL(uri).openStream();
} catch (Exception e) {
throw new java.io.FileNotFoundException(
@@ -757,8 +729,7 @@ public class PDFDocument {
* @deprecated Use getXObject instead (so forms are treated in the same way)
*/
public PDFImageXObject getImage(String key) {
- PDFImageXObject xObject = (PDFImageXObject)xObjectsMap.get(key);
- return xObject;
+ return (PDFImageXObject)this.xObjectsMap.get(key);
}
/**
@@ -768,8 +739,7 @@ public class PDFDocument {
* @return the PDFXObject for the key if found
*/
public PDFXObject getXObject(String key) {
- PDFXObject xObject = (PDFXObject)xObjectsMap.get(key);
- return xObject;
+ return (PDFXObject)this.xObjectsMap.get(key);
}
/**
@@ -778,7 +748,7 @@ public class PDFDocument {
* @return the PDFDests object (which represents the /Dests entry).
*/
public PDFDests getDests() {
- return dests;
+ return this.dests;
}
/**
@@ -787,7 +757,7 @@ public class PDFDocument {
*/
public void addDestination(PDFDestination destination) {
if (this.destinations == null) {
- this.destinations = new java.util.ArrayList();
+ this.destinations = new ArrayList();
}
this.destinations.add(destination);
}
@@ -799,7 +769,7 @@ public class PDFDocument {
*/
public List getDestinationList() {
if (hasDestinations()) {
- return destinations;
+ return this.destinations;
} else {
return Collections.EMPTY_LIST;
}
@@ -818,7 +788,7 @@ public class PDFDocument {
* Add an image to the PDF document.
* This adds an image to the PDF objects.
* If an image with the same key already exists it will return the
- * old PDFXObject.
+ * old {@link PDFXObject}.
*
* @param res the PDF resource context to add to, may be null
* @param img the PDF image to add
@@ -827,7 +797,7 @@ public class PDFDocument {
public PDFImageXObject addImage(PDFResourceContext res, PDFImage img) {
// check if already created
String key = img.getKey();
- PDFImageXObject xObject = (PDFImageXObject)xObjectsMap.get(key);
+ PDFImageXObject xObject = (PDFImageXObject)this.xObjectsMap.get(key);
if (xObject != null) {
if (res != null) {
res.getPDFResources().addXObject(xObject);
@@ -852,7 +822,7 @@ public class PDFDocument {
* Add a form XObject to the PDF document.
* This adds a Form XObject to the PDF objects.
* If a Form XObject with the same key already exists it will return the
- * old PDFFormXObject.
+ * old {@link PDFFormXObject}.
*
* @param res the PDF resource context to add to, may be null
* @param cont the PDF Stream contents of the Form XObject
@@ -896,19 +866,19 @@ public class PDFDocument {
* @return the PDF Outline root object
*/
public PDFOutline getOutlineRoot() {
- if (outlineRoot != null) {
- return outlineRoot;
+ if (this.outlineRoot != null) {
+ return this.outlineRoot;
}
- outlineRoot = new PDFOutline(null, null, true);
- assignObjectNumber(outlineRoot);
- addTrailerObject(outlineRoot);
- root.setRootOutline(outlineRoot);
- return outlineRoot;
+ this.outlineRoot = new PDFOutline(null, null, true);
+ assignObjectNumber(this.outlineRoot);
+ addTrailerObject(this.outlineRoot);
+ this.root.setRootOutline(this.outlineRoot);
+ return this.outlineRoot;
}
/**
- * get the /Resources object for the document
+ * Get the /Resources object for the document
*
* @return the /Resources object
*/
@@ -919,16 +889,18 @@ public class PDFDocument {
/**
* Ensure there is room in the locations xref for the number of
* objects that have been created.
+ * @param objidx the object's index
+ * @param position the position
*/
private void setLocation(int objidx, int position) {
- while (location.size() <= objidx) {
- location.add(LOCATION_PLACEHOLDER);
+ while (this.location.size() <= objidx) {
+ this.location.add(LOCATION_PLACEHOLDER);
}
- location.set(objidx, new Integer(position));
+ this.location.set(objidx, new Integer(position));
}
/**
- * write the entire document out
+ * Writes out the entire document
*
* @param stream the OutputStream to output the document to
* @throws IOException if there is an exception writing to the output stream
@@ -1009,23 +981,23 @@ public class PDFDocument {
}
/**
- * write the trailer
+ * Write the trailer
*
* @param stream the OutputStream to write the trailer to
* @throws IOException if there is an exception writing to the output stream
*/
public void outputTrailer(OutputStream stream) throws IOException {
if (hasDestinations()) {
- Collections.sort(destinations, new DestinationComparator());
- dests = getFactory().makeDests(destinations);
+ Collections.sort(this.destinations, new DestinationComparator());
+ this.dests = getFactory().makeDests(this.destinations);
if (this.root.getNames() == null) {
this.root.setNames(getFactory().makeNames());
}
this.root.getNames().setDests(dests);
}
output(stream);
- for (int count = 0; count < trailerObjects.size(); count++) {
- PDFObject o = (PDFObject)trailerObjects.get(count);
+ for (int count = 0; count < this.trailerObjects.size(); count++) {
+ PDFObject o = (PDFObject)this.trailerObjects.get(count);
this.location.set(
o.getObjectNumber() - 1,
new Integer(this.position));
@@ -1036,39 +1008,36 @@ public class PDFDocument {
this.position += outputXref(stream);
/* construct the trailer */
- String pdf =
- "trailer\n"
- + "<<\n"
- + "/Size "
- + (this.objectcount + 1)
- + "\n"
- + "/Root "
- + this.root.referencePDF()
- + "\n"
- + "/Info "
- + this.info.referencePDF()
- + "\n";
- if (this.encryption != null) {
- pdf += this.encryption.getTrailerEntry();
+ StringBuffer pdf = new StringBuffer(128);
+ pdf.append("trailer\n<<\n/Size ")
+ .append(this.objectcount + 1)
+ .append("\n/Root ")
+ .append(this.root.referencePDF())
+ .append("\n/Info ")
+ .append(this.info.referencePDF())
+ .append('\n');
+
+ if (this.isEncryptionActive()) {
+ pdf.append(this.encryption.getTrailerEntry());
} else {
- pdf += getIDEntry();
+ pdf.append(this.getIDEntry());
}
- pdf += "\n"
- + ">>\n"
- + "startxref\n"
- + this.xref
- + "\n"
- + "%%EOF\n";
+
+ pdf.append("\n>>\nstartxref\n")
+ .append(this.xref)
+ .append("\n%%EOF\n");
/* write the trailer */
- stream.write(encode(pdf));
+ stream.write(encode(pdf.toString()));
}
/**
- * write the xref table
+ * Write the xref table
*
* @param stream the OutputStream to write the xref table to
* @return the number of characters written
+ * @throws IOException in case of an error writing the result to
+ * the parameter stream
*/
private int outputXref(OutputStream stream) throws IOException {
@@ -1077,18 +1046,20 @@ public class PDFDocument {
/* construct initial part of xref */
StringBuffer pdf = new StringBuffer(128);
- pdf.append(
- "xref\n0 " + (this.objectcount + 1) + "\n0000000000 65535 f \n");
+ pdf.append("xref\n0 ");
+ pdf.append(this.objectcount + 1);
+ pdf.append("\n0000000000 65535 f \n");
+ String s, loc;
for (int count = 0; count < this.location.size(); count++) {
- String x = this.location.get(count).toString();
+ final String padding = "0000000000";
+ s = this.location.get(count).toString();
/* contruct xref entry for object */
- String padding = "0000000000";
- String loc = padding.substring(x.length()) + x;
+ loc = padding.substring(s.length()) + s;
/* append to xref table */
- pdf = pdf.append(loc + " 00000 n \n");
+ pdf = pdf.append(loc).append(" 00000 n \n");
}
/* write the xref table and return the character length */
diff --git a/src/java/org/apache/fop/pdf/PDFPaintingState.java b/src/java/org/apache/fop/pdf/PDFPaintingState.java
new file mode 100644
index 000000000..11dfc635a
--- /dev/null
+++ b/src/java/org/apache/fop/pdf/PDFPaintingState.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.util.Iterator;
+
+import org.apache.fop.util.AbstractPaintingState;
+
+/**
+ * This keeps information about the current painting state when writing to pdf.
+ * It allows for creating new graphics states with the q operator.
+ * This class is only used to store the information about the state
+ * the caller needs to handle the actual pdf operators.
+ *
+ * When setting the state for pdf there are three possible ways of
+ * handling the situation.
+ * The values can be set to override previous or default values.
+ * A new state can be added and then the values set.
+ * The current state can be popped and values will return to a
+ * previous state then the necessary values can be overridden.
+ * The current transform behaves differently to other values as the
+ * matrix is combined with the current resolved value.
+ * It is impossible to optimise the result without analysing the all
+ * the possible combinations after completing.
+ */
+public class PDFPaintingState extends org.apache.fop.util.AbstractPaintingState {
+
+ private static final long serialVersionUID = 5384726143906371279L;
+
+ /**
+ * PDF State for storing graphics state.
+ */
+ public PDFPaintingState() {
+ }
+
+ /**
+ * Set the current paint.
+ * This checks if the paint will change and then sets the current paint.
+ *
+ * @param p the new paint
+ * @return true if the new paint changes the current paint
+ */
+ public boolean setPaint(Paint p) {
+ Paint paint = ((PDFData)getData()).paint;
+ if (paint == null) {
+ if (p != null) {
+ ((PDFData)getData()).paint = p;
+ return true;
+ }
+ } else if (!paint.equals(p)) {
+ ((PDFData)getData()).paint = p;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if the clip will change the current state.
+ * A clip is assumed to be used in a situation where it will add
+ * to any clip in the current or parent states.
+ * A clip cannot be cleared, this can only be achieved by going to
+ * a parent level with the correct clip.
+ * If the clip is different then it may start a new state so that
+ * it can return to the previous clip.
+ *
+ * @param cl the clip shape to check
+ * @return true if the clip will change the current clip.
+ */
+ public boolean checkClip(Shape cl) {
+ Shape clip = ((PDFData)getData()).clip;
+ if (clip == null) {
+ if (cl != null) {
+ return true;
+ }
+ } else if (!new Area(clip).equals(new Area(cl))) {
+ return true;
+ }
+ //TODO check for clips that are larger than the current
+ return false;
+ }
+
+ /**
+ * Set the current clip.
+ * This either sets a new clip or sets the clip to the intersect of
+ * the old clip and the new clip.
+ *
+ * @param cl the new clip in the current state
+ */
+ public void setClip(Shape cl) {
+ Shape clip = ((PDFData)getData()).clip;
+ if (clip != null) {
+ Area newClip = new Area(clip);
+ newClip.intersect(new Area(cl));
+ ((PDFData)getData()).clip = new GeneralPath(newClip);
+ } else {
+ ((PDFData)getData()).clip = cl;
+ }
+ }
+
+ /**
+ * Get the current stack level.
+ *
+ * @return the current stack level
+ */
+ public int getStackLevel() {
+ return getStateStack().size();
+ }
+
+ /**
+ * Get the graphics state.
+ * This gets the combination of all graphic states for
+ * the current context.
+ * This is the graphic state set with the gs operator not
+ * the other graphic state changes.
+ *
+ * @return the calculated ExtGState in the current context
+ */
+ public PDFGState getGState() {
+ PDFGState defaultState = PDFGState.DEFAULT;
+
+ PDFGState state;
+ PDFGState newState = new PDFGState();
+ newState.addValues(defaultState);
+ for (Iterator it = getStateStack().iterator(); it.hasNext();) {
+ PDFData data = (PDFData)it.next();
+ state = data.gstate;
+ if (state != null) {
+ newState.addValues(state);
+ }
+ }
+ if (((PDFData)getData()).gstate != null) {
+ newState.addValues(((PDFData)getData()).gstate);
+ }
+ return newState;
+ }
+
+ /** {@inheritDoc} */
+ protected AbstractData instantiateData() {
+ return new PDFData();
+ }
+
+ /** {@inheritDoc} */
+ protected AbstractPaintingState instantiate() {
+ return new PDFPaintingState();
+ }
+
+ /**
+ * Push the current state onto the stack.
+ * This call should be used when the q operator is used
+ * so that the state is known when popped.
+ */
+ public void save() {
+ AbstractData data = getData();
+ AbstractData copy = (AbstractData)data.clone();
+ data.clearTransform();
+ getStateStack().add(copy);
+ }
+
+ private class PDFData extends org.apache.fop.util.AbstractPaintingState.AbstractData {
+
+ private static final long serialVersionUID = 3527950647293177764L;
+
+ private Paint paint = null;
+ private Paint backPaint = null;
+ private int lineCap = 0;
+ private int lineJoin = 0;
+ private float miterLimit = 0;
+ private boolean text = false;
+ private int dashOffset = 0;
+ private Shape clip = null;
+ private PDFGState gstate = null;
+
+ /** {@inheritDoc} */
+ public Object clone() {
+ PDFData obj = (PDFData)super.clone();
+ obj.paint = this.paint;
+ obj.backPaint = this.paint;
+ obj.lineCap = this.lineCap;
+ obj.lineJoin = this.lineJoin;
+ obj.miterLimit = this.miterLimit;
+ obj.text = this.text;
+ obj.dashOffset = this.dashOffset;
+ obj.clip = this.clip;
+ obj.gstate = this.gstate;
+ return obj;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return super.toString()
+ + ", paint=" + paint
+ + ", backPaint=" + backPaint
+ + ", lineCap=" + lineCap
+ + ", miterLimit=" + miterLimit
+ + ", text=" + text
+ + ", dashOffset=" + dashOffset
+ + ", clip=" + clip
+ + ", gstate=" + gstate;
+ }
+
+ /** {@inheritDoc} */
+ protected AbstractData instantiate() {
+ return new PDFData();
+ }
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/pdf/PDFState.java b/src/java/org/apache/fop/pdf/PDFState.java
deleted file mode 100644
index 2e9bd6074..000000000
--- a/src/java/org/apache/fop/pdf/PDFState.java
+++ /dev/null
@@ -1,417 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.pdf;
-
-import java.io.Serializable;
-import java.util.List;
-import java.util.Iterator;
-
-import java.awt.Color;
-import java.awt.Paint;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.GeneralPath;
-
-/**
- * This keeps information about the current state when writing to pdf.
- * It allows for creating new graphics states with the q operator.
- * This class is only used to store the information about the state
- * the caller needs to handle the actual pdf operators.
- *
- * When setting the state for pdf there are three possible ways of
- * handling the situation.
- * The values can be set to override previous or default values.
- * A new state can be added and then the values set.
- * The current state can be popped and values will return to a
- * previous state then the necessary values can be overridden.
- * The current transform behaves differently to other values as the
- * matrix is combined with the current resolved value.
- * It is impossible to optimise the result without analysing the all
- * the possible combinations after completing.
- */
-public class PDFState {
-
- private Data data = new Data();
-
- private List stateStack = new java.util.ArrayList();
-
- /**
- * PDF State for storing graphics state.
- */
- public PDFState() {
-
- }
-
- /**
- * Push the current state onto the stack.
- * This call should be used when the q operator is used
- * so that the state is known when popped.
- */
- public void push() {
- Data copy;
- try {
- copy = (Data)getData().clone();
- getData().resetTransform();
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e.getMessage());
- }
- stateStack.add(copy);
- }
-
- /**
- * @return the currently valid state
- */
- public Data getData() {
- return data;
- }
-
- /**
- * Pop the state from the stack and set current values to popped state.
- * This should be called when a Q operator is used so
- * the state is restored to the correct values.
- * @return the restored state, null if the stack is empty
- */
- public Data pop() {
- if (getStackLevel() > 0) {
- Data popped = (Data)stateStack.remove(stateStack.size() - 1);
-
- data = popped;
- return popped;
- } else {
- return null;
- }
- }
-
- /**
- * Get the current stack level.
- *
- * @return the current stack level
- */
- public int getStackLevel() {
- return stateStack.size();
- }
-
- /**
- * Restore the state to a particular level.
- * this can be used to restore to a known level without making
- * multiple pop calls.
- *
- * @param stack the level to restore to
- */
- /*
- public void restoreLevel(int stack) {
- int pos = stack;
- while (stateStack.size() > pos + 1) {
- stateStack.remove(stateStack.size() - 1);
- }
- if (stateStack.size() > pos) {
- pop();
- }
- }*/
-
- /**
- * Set the current line dash.
- * Check if setting the line dash to the given values
- * will make a change and then set the state to the new values.
- *
- * @param array the line dash array
- * @param offset the line dash start offset
- * @return true if the line dash has changed
- */
- /*
- public boolean setLineDash(int[] array, int offset) {
- return false;
- }*/
-
- /**
- * Set the current line width.
- * @param width the line width in points
- * @return true if the line width has changed
- */
- public boolean setLineWidth(float width) {
- if (getData().lineWidth != width) {
- getData().lineWidth = width;
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Set the current color.
- * Check if the new color is a change and then set the current color.
- *
- * @param col the color to set
- * @return true if the color has changed
- */
- public boolean setColor(Color col) {
- if (!col.equals(getData().color)) {
- getData().color = col;
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Set the current background color.
- * Check if the background color will change and then set the new color.
- *
- * @param col the new background color
- * @return true if the background color has changed
- */
- public boolean setBackColor(Color col) {
- if (!col.equals(getData().backcolor)) {
- getData().backcolor = col;
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Set the current paint.
- * This checks if the paint will change and then sets the current paint.
- *
- * @param p the new paint
- * @return true if the new paint changes the current paint
- */
- public boolean setPaint(Paint p) {
- if (getData().paint == null) {
- if (p != null) {
- getData().paint = p;
- return true;
- }
- } else if (!data.paint.equals(p)) {
- getData().paint = p;
- return true;
- }
- return false;
- }
-
- /**
- * Check if the clip will change the current state.
- * A clip is assumed to be used in a situation where it will add
- * to any clip in the current or parent states.
- * A clip cannot be cleared, this can only be achieved by going to
- * a parent level with the correct clip.
- * If the clip is different then it may start a new state so that
- * it can return to the previous clip.
- *
- * @param cl the clip shape to check
- * @return true if the clip will change the current clip.
- */
- public boolean checkClip(Shape cl) {
- if (getData().clip == null) {
- if (cl != null) {
- return true;
- }
- } else if (!new Area(getData().clip).equals(new Area(cl))) {
- return true;
- }
- //TODO check for clips that are larger than the current
- return false;
- }
-
- /**
- * Set the current clip.
- * This either sets a new clip or sets the clip to the intersect of
- * the old clip and the new clip.
- *
- * @param cl the new clip in the current state
- */
- public void setClip(Shape cl) {
- if (getData().clip != null) {
- Area newClip = new Area(getData().clip);
- newClip.intersect(new Area(cl));
- getData().clip = new GeneralPath(newClip);
- } else {
- getData().clip = cl;
- }
- }
-
- /**
- * Check the current transform.
- * The transform for the current state is the combination of all
- * transforms in the current state. The parameter is compared
- * against this current transform.
- *
- * @param tf the transform the check against
- * @return true if the new transform is different then the current transform
- */
- public boolean checkTransform(AffineTransform tf) {
- return !tf.equals(getData().transform);
- }
-
- /**
- * Set a new transform.
- * This transform is appended to the transform of
- * the current graphic state.
- *
- * @param tf the transform to concatonate to the current level transform
- * @deprecated This method name is misleading. Use concatenate(AffineTransform) instead!
- */
- public void setTransform(AffineTransform tf) {
- concatenate(tf);
- }
-
- /**
- * Concatenates the given AffineTransform to the current one.
- * @param tf the transform to concatenate to the current level transform
- */
- public void concatenate(AffineTransform tf) {
- getData().concatenate(tf);
- }
-
- /**
- * Get the current transform.
- * This gets the combination of all transforms in the
- * current state.
- *
- * @return the calculate combined transform for the current state
- */
- public AffineTransform getTransform() {
- AffineTransform tf;
- AffineTransform at = new AffineTransform();
- for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
- Data d = (Data)iter.next();
- tf = d.transform;
- at.concatenate(tf);
- }
- at.concatenate(getData().transform);
- return at;
- }
-
- /**
- * Get a copy of the base transform for the page. Used to translate
- * IPP/BPP values into X,Y positions when positioning is "fixed".
- *
- * @return the base transform, or null if the state stack is empty
- */
- public AffineTransform getBaseTransform() {
- if (stateStack.size() == 0) {
- return null;
- } else {
- Data baseData = (Data) stateStack.get(0);
- return (AffineTransform) baseData.transform.clone();
- }
- }
-
- /**
- * Get the graphics state.
- * This gets the combination of all graphic states for
- * the current context.
- * This is the graphic state set with the gs operator not
- * the other graphic state changes.
- *
- * @return the calculated ExtGState in the current context
- */
- public PDFGState getGState() {
- PDFGState defaultState = PDFGState.DEFAULT;
-
- PDFGState state;
- PDFGState newstate = new PDFGState();
- newstate.addValues(defaultState);
- for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
- Data d = (Data)iter.next();
- state = d.gstate;
- if (state != null) {
- newstate.addValues(state);
- }
- }
- if (getData().gstate != null) {
- newstate.addValues(getData().gstate);
- }
-
- return newstate;
- }
-
- public class Data implements Cloneable, Serializable {
-
- public Color color = Color.black;
- public Color backcolor = Color.black;
- public Paint paint = null;
- public Paint backPaint = null;
- public int lineCap = 0;
- public int lineJoin = 0;
- public float lineWidth = 1;
- public float miterLimit = 0;
- public boolean text = false;
- public int dashOffset = 0;
- public int[] dashArray = new int[0];
- public AffineTransform transform = new AffineTransform();
- public float fontSize = 0;
- public String fontName = "";
- public Shape clip = null;
- public PDFGState gstate = null;
-
-
- /** {@inheritDoc} */
- public Object clone() throws CloneNotSupportedException {
- Data obj = new Data();
- obj.color = this.color;
- obj.backcolor = this.backcolor;
- obj.paint = this.paint;
- obj.backPaint = this.paint;
- obj.lineCap = this.lineCap;
- obj.lineJoin = this.lineJoin;
- obj.lineWidth = this.lineWidth;
- obj.miterLimit = this.miterLimit;
- obj.text = this.text;
- obj.dashOffset = this.dashOffset;
- obj.dashArray = this.dashArray;
- obj.transform = new AffineTransform(this.transform);
- obj.fontSize = this.fontSize;
- obj.fontName = this.fontName;
- obj.clip = this.clip;
- obj.gstate = this.gstate;
- return obj;
- }
-
- /**
- * Get the current Transform.
- */
- public AffineTransform getTransform() {
- return transform;
- }
-
- public void resetTransform() {
- transform = new AffineTransform();
- }
-
- /**
- * Concatenate the given AffineTransform with the current thus creating
- * a new viewport. Note that all concatenation operations are logged
- * so they can be replayed if necessary (ex. for block-containers with
- * "fixed" positioning.
- * @param at Transformation to perform
- */
- public void concatenate(AffineTransform at) {
- transform.concatenate(at);
- }
-
- /** {@inheritDoc} */
- public String toString() {
- return super.toString() + ", " + this.transform;
- }
- }
-}
-
diff --git a/src/java/org/apache/fop/pdf/package.html b/src/java/org/apache/fop/pdf/package.html
index e86318adc..383f78da1 100644
--- a/src/java/org/apache/fop/pdf/package.html
+++ b/src/java/org/apache/fop/pdf/package.html
@@ -1,3 +1,20 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.pdf Package</TITLE>
<BODY>
diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
index fb62e653d..731f0bae2 100644
--- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
+++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
@@ -21,9 +21,7 @@ package org.apache.fop.render;
// Java
import java.awt.Dimension;
-import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
import java.io.IOException;
import org.w3c.dom.Document;
@@ -37,7 +35,11 @@ import org.apache.batik.gvt.GraphicsNode;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.apache.xmlgraphics.util.QName;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.image.loader.batik.BatikUtil;
+import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl;
import org.apache.fop.render.RendererContext.RendererContextWrapper;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
@@ -54,6 +56,9 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
protected static final QName CONVERSION_MODE = new QName(
ExtensionElementMapping.URI, null, "conversion-mode");
+ /** "bitmap" value for the "conversion-mode" extension attribute. */
+ protected static final String BITMAP = "bitmap";
+
/** {@inheritDoc} */
public void handleXML(RendererContext context,
Document doc, String ns) throws Exception {
@@ -64,65 +69,101 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
}
/**
- * Render the SVG document.
- * @param context the renderer context
- * @param doc the SVG document
- * @throws IOException In case of an I/O error while painting the image
+ * Creates a graphics 2D image painter implementation
+ *
+ * @param root the batik graphics node root
+ * @param ctx the batik bridge context
+ * @param imageSize the image size
+ * @return a new graphics 2D image painter implementation
*/
- protected void renderSVGDocument(final RendererContext context,
- final Document doc) throws IOException {
- updateRendererContext(context);
- final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext(context);
- int x = wrappedContext.getCurrentXPosition();
- int y = wrappedContext.getCurrentYPosition();
+ protected Graphics2DImagePainter createGraphics2DImagePainter(
+ GraphicsNode root, BridgeContext ctx, Dimension imageSize) {
+ return new Graphics2DImagePainterImpl(root, ctx, imageSize);
+ }
- //Prepare
- SVGUserAgent ua = new SVGUserAgent(
- context.getUserAgent(),
- new AffineTransform());
+ /**
+ * Builds the GVT root
+ *
+ * @param rendererContext the renderer context
+ * @param ctx the batik bridge context
+ * @param doc the document
+ * @return a built GVT root tree
+ */
+ protected GraphicsNode buildGraphicsNode(
+ FOUserAgent userAgent, BridgeContext ctx, Document doc) {
GVTBuilder builder = new GVTBuilder();
- final BridgeContext ctx = new BridgeContext(ua);
-
- //Build the GVT tree
final GraphicsNode root;
try {
root = builder.build(ctx, doc);
} catch (Exception e) {
- SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
- context.getUserAgent().getEventBroadcaster());
- eventProducer.svgNotBuilt(this, e, getDocumentURI(doc));
- return;
+ EventBroadcaster eventBroadcaster
+ = userAgent.getEventBroadcaster();
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(eventBroadcaster);
+ final String uri = getDocumentURI(doc);
+ eventProducer.svgNotBuilt(this, e, uri);
+ return null;
}
+ return root;
+ }
- //Create the painter
- Graphics2DImagePainter painter = new Graphics2DImagePainter() {
+ /**
+ * Returns the image size
+ * @param wrappedContext renderer context wrapper
+ *
+ * @return the image size
+ */
+ protected Dimension getImageSize(RendererContextWrapper wrappedContext) {
+ final int width = wrappedContext.getWidth();
+ final int height = wrappedContext.getHeight();
+ return new Dimension(width, height);
+ }
- public void paint(Graphics2D g2d, Rectangle2D area) {
- // If no viewbox is defined in the svg file, a viewbox of 100x100 is
- // assumed, as defined in SVGUserAgent.getViewportSize()
- float iw = (float) ctx.getDocumentSize().getWidth();
- float ih = (float) ctx.getDocumentSize().getHeight();
- float w = (float) area.getWidth();
- float h = (float) area.getHeight();
- g2d.scale(w / iw, h / ih);
+ /**
+ * Render the SVG document.
+ *
+ * @param rendererContext the renderer context
+ * @param doc the SVG document
+ * @throws IOException In case of an I/O error while painting the image
+ */
+ protected void renderSVGDocument(final RendererContext rendererContext,
+ final Document doc) throws IOException {
+ updateRendererContext(rendererContext);
+
+ //Prepare
+ FOUserAgent userAgent = rendererContext.getUserAgent();
+ SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new AffineTransform());
+
+ //Create Batik BridgeContext
+ final BridgeContext bridgeContext = new BridgeContext(svgUserAgent);
- root.paint(g2d);
- }
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+ //to it.
+ Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
- public Dimension getImageSize() {
- return new Dimension(wrappedContext.getWidth(), wrappedContext.getHeight());
- }
+ //Build the GVT tree
+ final GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, clonedDoc);
- };
+ // Create Graphics2DImagePainter
+ final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext(
+ rendererContext);
+ Dimension imageSize = getImageSize(wrappedContext);
+ final Graphics2DImagePainter painter = createGraphics2DImagePainter(
+ root, bridgeContext, imageSize);
//Let the painter paint the SVG on the Graphics2D instance
- Graphics2DAdapter adapter = context.getRenderer().getGraphics2DAdapter();
- adapter.paintImage(painter, context,
- x, y, wrappedContext.getWidth(), wrappedContext.getHeight());
+ Graphics2DAdapter g2dAdapter = rendererContext.getRenderer().getGraphics2DAdapter();
+
+ //Paint the image
+ final int x = wrappedContext.getCurrentXPosition();
+ final int y = wrappedContext.getCurrentYPosition();
+ final int width = wrappedContext.getWidth();
+ final int height = wrappedContext.getHeight();
+ g2dAdapter.paintImage(painter, rendererContext, x, y, width, height);
}
/**
* Gets the document URI from a Document instance if possible.
+ *
* @param doc the Document
* @return the URI or null
*/
@@ -138,6 +179,7 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
/**
* Override this method to update the renderer context if it needs special settings for
* certain conditions.
+ *
* @param context the renderer context
*/
protected void updateRendererContext(RendererContext context) {
diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java
index 5861fb042..ee18dff0d 100644
--- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java
+++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java
@@ -54,8 +54,8 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter {
protected BufferedImage paintToBufferedImage(
org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter,
RendererContextWrapper context, int resolution, boolean gray, boolean withAlpha) {
- int bmw = (int)Math.ceil(UnitConv.mpt2px(context.getWidth(), resolution));
- int bmh = (int)Math.ceil(UnitConv.mpt2px(context.getHeight(), resolution));
+ int bmw = mpt2px(context.getWidth(), resolution);
+ int bmh = mpt2px(context.getHeight(), resolution);
BufferedImage bi;
if (gray) {
if (withAlpha) {
@@ -102,6 +102,17 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter {
return bi;
}
+ /**
+ * Converts millipoints to pixels
+ *
+ * @param unit the unit to convert in mpts
+ * @param resolution the target resolution
+ * @return the converted unit in pixels
+ */
+ protected int mpt2px(int unit, int resolution) {
+ return (int)Math.ceil(UnitConv.mpt2px(unit, resolution));
+ }
+
private static BufferedImage createGrayBufferedImageWithAlpha(int width, int height) {
BufferedImage bi;
boolean alphaPremultiplied = true;
diff --git a/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java
new file mode 100644
index 000000000..4196a1b19
--- /dev/null
+++ b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.util.Service;
+
+/**
+ * This class holds references to various image handlers used by the renderers. It also
+ * supports automatic discovery of additional handlers available through
+ * the class path.
+ */
+public abstract class AbstractImageHandlerRegistry {
+
+ /** the logger */
+ private static Log log = LogFactory.getLog(AbstractImageHandlerRegistry.class);
+
+ private static final Comparator HANDLER_COMPARATOR = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ ImageHandlerBase h1 = (ImageHandlerBase)o1;
+ ImageHandlerBase h2 = (ImageHandlerBase)o2;
+ return h1.getPriority() - h2.getPriority();
+ }
+ };
+
+ /** Map containing image handlers for various MIME types */
+ private final Map/*<Class, ImageHandler>*/ handlers
+ = new java.util.HashMap/*<Class, ImageHandler>*/();
+
+ /** List containing the same handlers as above but ordered by priority */
+ private final List/*<ImageHandler>*/ handlerList
+ = new java.util.LinkedList/*<ImageHandler>*/();
+
+ /** Sorted Set of registered handlers */
+ private ImageFlavor[] supportedFlavors = new ImageFlavor[0];
+
+ private int handlerRegistrations;
+ private int lastSync;
+
+ /**
+ * Default constructor.
+ */
+ public AbstractImageHandlerRegistry() {
+ discoverHandlers();
+ }
+
+ /**
+ * Add an ImageHandler. The handler itself is inspected to find out what it supports.
+ * @param classname the fully qualified class name
+ */
+ public void addHandler(String classname) {
+ try {
+ ImageHandlerBase handlerInstance
+ = (ImageHandlerBase)Class.forName(classname).newInstance();
+ addHandler(handlerInstance);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Could not find "
+ + classname);
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException("Could not instantiate "
+ + classname);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Could not access "
+ + classname);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(classname
+ + " is not an "
+ + getHandlerClass().getName());
+ }
+ }
+
+ /**
+ * Add an image handler. The handler itself is inspected to find out what it supports.
+ * @param handler the ImageHandler instance
+ */
+ public synchronized void addHandler(ImageHandlerBase handler) {
+ this.handlers.put(handler.getSupportedImageClass(), handler);
+
+ //Sorted insert
+ ListIterator iter = this.handlerList.listIterator();
+ while (iter.hasNext()) {
+ ImageHandlerBase h = (ImageHandlerBase)iter.next();
+ if (getHandlerComparator().compare(handler, h) < 0) {
+ iter.previous();
+ break;
+ }
+ }
+ iter.add(handler);
+ this.handlerRegistrations++;
+ }
+
+ /**
+ * Returns an ImageHandler which handles an specific image type given the MIME type
+ * of the image.
+ * @param img the Image to be handled
+ * @return the ImageHandler responsible for handling the image or null if none is available
+ */
+ public ImageHandlerBase getHandler(Image img) {
+ return getHandler(img.getClass());
+ }
+
+ /**
+ * Returns an ImageHandler which handles an specific image type given the MIME type
+ * of the image.
+ * @param imageClass the Image subclass for which to get a handler
+ * @return the ImageHandler responsible for handling the image or null if none is available
+ */
+ public synchronized ImageHandlerBase getHandler(Class imageClass) {
+ ImageHandlerBase handler = null;
+ Class cl = imageClass;
+ while (cl != null) {
+ handler = (ImageHandlerBase)handlers.get(cl);
+ if (handler != null) {
+ break;
+ }
+ cl = cl.getSuperclass();
+ }
+ return handler;
+ }
+
+ /**
+ * Returns the ordered array of supported image flavors.
+ * @return the array of image flavors
+ */
+ public synchronized ImageFlavor[] getSupportedFlavors() {
+ if (this.lastSync != this.handlerRegistrations) {
+ //Extract all ImageFlavors into a single array
+ List flavors = new java.util.ArrayList();
+ Iterator iter = this.handlerList.iterator();
+ while (iter.hasNext()) {
+ ImageFlavor[] f = ((ImageHandlerBase)iter.next()).getSupportedImageFlavors();
+ for (int i = 0; i < f.length; i++) {
+ flavors.add(f[i]);
+ }
+ }
+ this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]);
+ this.lastSync = this.handlerRegistrations;
+ }
+ return this.supportedFlavors;
+ }
+
+ /**
+ * Discovers ImageHandler implementations through the classpath and dynamically
+ * registers them.
+ */
+ private void discoverHandlers() {
+ // add mappings from available services
+ Class imageHandlerClass = getHandlerClass();
+ Iterator providers = Service.providers(imageHandlerClass);
+ if (providers != null) {
+ while (providers.hasNext()) {
+ ImageHandlerBase handler = (ImageHandlerBase)providers.next();
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("Dynamically adding ImageHandler: "
+ + handler.getClass().getName());
+ }
+ addHandler(handler);
+ } catch (IllegalArgumentException e) {
+ log.error("Error while adding ImageHandler", e);
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Returns the ImageHandler comparator
+ *
+ * @return the ImageHandler comparator
+ */
+ public Comparator getHandlerComparator() {
+ return HANDLER_COMPARATOR;
+ }
+
+ /**
+ * Returns the ImageHandler implementing class
+ *
+ * @return the ImageHandler implementing class
+ */
+ public abstract Class getHandlerClass();
+}
diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
index c57a9d566..2e04f2d85 100644
--- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java
@@ -26,13 +26,7 @@ import java.awt.geom.Rectangle2D;
import java.util.List;
import java.util.Map;
-import org.w3c.dom.Document;
-
import org.apache.batik.parser.AWTTransformProducer;
-
-import org.apache.xmlgraphics.image.loader.ImageSize;
-import org.apache.xmlgraphics.util.QName;
-
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.area.BlockViewport;
@@ -48,7 +42,10 @@ import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.fonts.FontMetrics;
import org.apache.fop.traits.BorderProps;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.UnitConv;
+import org.w3c.dom.Document;
/**
* Abstract base class for renderers like PDF and PostScript where many painting operations
@@ -270,6 +267,11 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
}
+ private static final int BEFORE = 0;
+ private static final int END = 1;
+ private static final int AFTER = 2;
+ private static final int START = 3;
+
/**
* Draws borders.
* @param borderRect the border rectangle
@@ -280,45 +282,46 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
*/
protected void drawBorders(Rectangle2D.Float borderRect,
BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) {
+ //TODO generalize each of the four conditions into using a parameterized drawBorder()
+ boolean[] border = new boolean[] {
+ (bpsBefore != null), (bpsEnd != null),
+ (bpsAfter != null), (bpsStart != null)};
float startx = borderRect.x;
float starty = borderRect.y;
float width = borderRect.width;
float height = borderRect.height;
- boolean[] b = new boolean[] {
- (bpsBefore != null), (bpsEnd != null),
- (bpsAfter != null), (bpsStart != null)};
- if (!b[0] && !b[1] && !b[2] && !b[3]) {
- return;
- }
- float[] bw = new float[] {
- (b[0] ? bpsBefore.width / 1000f : 0.0f),
- (b[1] ? bpsEnd.width / 1000f : 0.0f),
- (b[2] ? bpsAfter.width / 1000f : 0.0f),
- (b[3] ? bpsStart.width / 1000f : 0.0f)};
+ float[] borderWidth = new float[] {
+ (border[BEFORE] ? bpsBefore.width / 1000f : 0.0f),
+ (border[END] ? bpsEnd.width / 1000f : 0.0f),
+ (border[AFTER] ? bpsAfter.width / 1000f : 0.0f),
+ (border[START] ? bpsStart.width / 1000f : 0.0f)};
float[] clipw = new float[] {
BorderProps.getClippedWidth(bpsBefore) / 1000f,
BorderProps.getClippedWidth(bpsEnd) / 1000f,
BorderProps.getClippedWidth(bpsAfter) / 1000f,
BorderProps.getClippedWidth(bpsStart) / 1000f};
- starty += clipw[0];
- height -= clipw[0];
- height -= clipw[2];
- startx += clipw[3];
- width -= clipw[3];
- width -= clipw[1];
+ starty += clipw[BEFORE];
+ height -= clipw[BEFORE];
+ height -= clipw[AFTER];
+ startx += clipw[START];
+ width -= clipw[START];
+ width -= clipw[END];
boolean[] slant = new boolean[] {
- (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])};
+ (border[START] && border[BEFORE]),
+ (border[BEFORE] && border[END]),
+ (border[END] && border[AFTER]),
+ (border[AFTER] && border[START])};
if (bpsBefore != null) {
endTextObject();
float sx1 = startx;
- float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1);
+ float sx2 = (slant[BEFORE] ? sx1 + borderWidth[START] - clipw[START] : sx1);
float ex1 = startx + width;
- float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1);
- float outery = starty - clipw[0];
- float clipy = outery + clipw[0];
- float innery = outery + bw[0];
+ float ex2 = (slant[END] ? ex1 - borderWidth[END] + clipw[END] : ex1);
+ float outery = starty - clipw[BEFORE];
+ float clipy = outery + clipw[BEFORE];
+ float innery = outery + borderWidth[BEFORE];
saveGraphicsState();
moveTo(sx1, clipy);
@@ -326,10 +329,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
float ex1a = ex1;
if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- sx1a -= clipw[3];
+ sx1a -= clipw[START];
}
if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- ex1a += clipw[1];
+ ex1a += clipw[END];
}
lineTo(sx1a, outery);
lineTo(ex1a, outery);
@@ -347,12 +350,12 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
endTextObject();
float sy1 = starty;
- float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1);
+ float sy2 = (slant[END] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1);
float ey1 = starty + height;
- float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1);
- float outerx = startx + width + clipw[1];
- float clipx = outerx - clipw[1];
- float innerx = outerx - bw[1];
+ float ey2 = (slant[AFTER] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1);
+ float outerx = startx + width + clipw[END];
+ float clipx = outerx - clipw[END];
+ float innerx = outerx - borderWidth[END];
saveGraphicsState();
moveTo(clipx, sy1);
@@ -360,10 +363,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
float ey1a = ey1;
if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- sy1a -= clipw[0];
+ sy1a -= clipw[BEFORE];
}
if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- ey1a += clipw[2];
+ ey1a += clipw[AFTER];
}
lineTo(outerx, sy1a);
lineTo(outerx, ey1a);
@@ -380,12 +383,12 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
endTextObject();
float sx1 = startx;
- float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1);
+ float sx2 = (slant[START] ? sx1 + borderWidth[AFTER] - clipw[AFTER] : sx1);
float ex1 = startx + width;
- float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1);
- float outery = starty + height + clipw[2];
- float clipy = outery - clipw[2];
- float innery = outery - bw[2];
+ float ex2 = (slant[AFTER] ? ex1 - borderWidth[END] + clipw[END] : ex1);
+ float outery = starty + height + clipw[AFTER];
+ float clipy = outery - clipw[AFTER];
+ float innery = outery - borderWidth[AFTER];
saveGraphicsState();
moveTo(ex1, clipy);
@@ -393,10 +396,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
float ex1a = ex1;
if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- sx1a -= clipw[3];
+ sx1a -= clipw[START];
}
if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- ex1a += clipw[1];
+ ex1a += clipw[END];
}
lineTo(ex1a, outery);
lineTo(sx1a, outery);
@@ -413,12 +416,12 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
endTextObject();
float sy1 = starty;
- float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1);
+ float sy2 = (slant[BEFORE] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1);
float ey1 = sy1 + height;
- float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1);
- float outerx = startx - clipw[3];
- float clipx = outerx + clipw[3];
- float innerx = outerx + bw[3];
+ float ey2 = (slant[START] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1);
+ float outerx = startx - clipw[START];
+ float clipx = outerx + clipw[START];
+ float innerx = outerx + borderWidth[START];
saveGraphicsState();
moveTo(clipx, ey1);
@@ -426,10 +429,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
float ey1a = ey1;
if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- sy1a -= clipw[0];
+ sy1a -= clipw[BEFORE];
}
if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- ey1a += clipw[2];
+ ey1a += clipw[AFTER];
}
lineTo(outerx, ey1a);
lineTo(outerx, sy1a);
@@ -451,10 +454,6 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
* rendered
*/
protected void renderInlineAreaBackAndBorders(InlineArea area) {
- float x = currentIPPosition / 1000f;
- float y = (currentBPPosition + area.getOffset()) / 1000f;
- float width = area.getIPD() / 1000f;
- float height = area.getBPD() / 1000f;
float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f;
float borderPaddingBefore = area.getBorderAndPaddingWidthBefore() / 1000f;
float bpwidth = borderPaddingStart
@@ -462,12 +461,15 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
float bpheight = borderPaddingBefore
+ (area.getBorderAndPaddingWidthAfter() / 1000f);
+ float height = area.getBPD() / 1000f;
if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) {
+ float x = currentIPPosition / 1000f;
+ float y = (currentBPPosition + area.getOffset()) / 1000f;
+ float width = area.getIPD() / 1000f;
drawBackAndBorders(area, x, y - borderPaddingBefore
, width + bpwidth
, height + bpheight);
}
-
}
/** Constant for the fox:transform extension attribute */
@@ -483,26 +485,24 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
int saveBP = currentBPPosition;
CTM ctm = bv.getCTM();
- int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
- //This is the content-rect
- float width = bv.getIPD() / 1000f;
- float height = bv.getBPD() / 1000f;
- if (bv.getPositioning() == Block.ABSOLUTE
- || bv.getPositioning() == Block.FIXED) {
+ int positioning = bv.getPositioning();
+ if (positioning == Block.ABSOLUTE || positioning == Block.FIXED) {
//For FIXED, we need to break out of the current viewports to the
//one established by the page. We save the state stack for restoration
//after the block-container has been painted. See below.
List breakOutList = null;
- if (bv.getPositioning() == Block.FIXED) {
+ if (positioning == Block.FIXED) {
breakOutList = breakOutOfStateStack();
}
AffineTransform positionTransform = new AffineTransform();
positionTransform.translate(bv.getXOffset(), bv.getYOffset());
+ int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
+
//"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle
positionTransform.translate(-borderPaddingStart, -borderPaddingBefore);
@@ -514,39 +514,62 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
positionTransform.concatenate(freeTransform);
}
- saveGraphicsState();
//Viewport position
- concatenateTransformationMatrix(UnitConv.mptToPt(positionTransform));
+ if (!positionTransform.isIdentity()) {
+ establishTransformationMatrix(positionTransform);
+ }
+
+ //This is the content-rect
+ float width = bv.getIPD() / 1000f;
+ float height = bv.getBPD() / 1000f;
//Background and borders
- float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f;
- float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f;
- drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight);
+ float borderPaddingWidth
+ = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f;
+ float borderPaddingHeight
+ = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f;
+ drawBackAndBorders(bv, 0, 0, width + borderPaddingWidth, height + borderPaddingHeight);
//Shift to content rectangle after border painting
AffineTransform contentRectTransform = new AffineTransform();
contentRectTransform.translate(borderPaddingStart, borderPaddingBefore);
- concatenateTransformationMatrix(UnitConv.mptToPt(contentRectTransform));
+
+ if (!contentRectTransform.isIdentity()) {
+ establishTransformationMatrix(contentRectTransform);
+ }
//Clipping
if (bv.getClip()) {
clipRect(0f, 0f, width, height);
}
- saveGraphicsState();
//Set up coordinate system for content rectangle
AffineTransform contentTransform = ctm.toAffineTransform();
- concatenateTransformationMatrix(UnitConv.mptToPt(contentTransform));
+ if (!contentTransform.isIdentity()) {
+ establishTransformationMatrix(contentTransform);
+ }
currentIPPosition = 0;
currentBPPosition = 0;
renderBlocks(bv, children);
- restoreGraphicsState();
- restoreGraphicsState();
+ if (!contentTransform.isIdentity()) {
+ restoreGraphicsState();
+ }
+
+ if (!contentRectTransform.isIdentity()) {
+ restoreGraphicsState();
+ }
+
+ if (!positionTransform.isIdentity()) {
+ restoreGraphicsState();
+ }
- if (breakOutList != null) {
- restoreStateStackAfterBreakOut(breakOutList);
+ //For FIXED, we need to restore break out now we are done
+ if (positioning == Block.FIXED) {
+ if (breakOutList != null) {
+ restoreStateStackAfterBreakOut(breakOutList);
+ }
}
currentIPPosition = saveIP;
@@ -599,8 +622,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
at.translate(0, block.getSpaceBefore());
if (!at.isIdentity()) {
- saveGraphicsState();
- concatenateTransformationMatrix(UnitConv.mptToPt(at));
+ establishTransformationMatrix(at);
}
currentIPPosition = 0;
@@ -632,8 +654,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
at.translate(currentIPPosition, currentBPPosition);
if (!at.isIdentity()) {
- saveGraphicsState();
- concatenateTransformationMatrix(UnitConv.mptToPt(at));
+ establishTransformationMatrix(at);
}
currentIPPosition = 0;
@@ -845,4 +866,16 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
renderDocument(doc, ns, pos, fo.getForeignAttributes());
}
+ /**
+ * Establishes a new coordinate system with the given transformation matrix.
+ * The current graphics state is saved and the new coordinate system is concatenated.
+ * @param block
+ *
+ * @param at the transformation matrix
+ */
+ protected void establishTransformationMatrix(AffineTransform at) {
+ saveGraphicsState();
+ concatenateTransformationMatrix(UnitConv.mptToPt(at));
+ }
+
}
diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java
index 2be9150b0..943c8c9da 100644
--- a/src/java/org/apache/fop/render/AbstractRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractRenderer.java
@@ -29,11 +29,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import org.w3c.dom.Document;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Area;
@@ -69,6 +66,7 @@ import org.apache.fop.area.inline.WordArea;
import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.FontInfo;
+import org.w3c.dom.Document;
/**
* Abstract base class for all renderers. The Abstract renderer does all the
@@ -505,7 +503,7 @@ public abstract class AbstractRenderer
*/
protected void renderBlocks(Block parent, List blocks) {
int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
+// int saveBP = currentBPPosition;
// Calculate the position of the content rectangle.
if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) {
diff --git a/src/java/org/apache/fop/render/ImageHandler.java b/src/java/org/apache/fop/render/ImageHandler.java
index 42ae5fd49..ec5f576aa 100644
--- a/src/java/org/apache/fop/render/ImageHandler.java
+++ b/src/java/org/apache/fop/render/ImageHandler.java
@@ -23,26 +23,11 @@ import java.awt.Rectangle;
import java.io.IOException;
import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
/**
- * This interface is used for handling all sorts of image types for PDF output.
+ * This interface is a service provider interface for image handlers.
*/
-public interface ImageHandler {
-
- /**
- * Returns the priority for this image handler. A lower value means higher priority. This
- * information is used to build the ordered/prioritized list of supported ImageFlavors.
- * The built-in handlers use priorities between 100 and 999.
- * @return a positive integer (>0) indicating the priority
- */
- int getPriority();
-
- /**
- * Returns the {@link ImageFlavor}s supported by this instance
- * @return the supported image flavors
- */
- ImageFlavor[] getSupportedImageFlavors();
+public interface ImageHandler extends ImageHandlerBase {
/**
* Indicates whether the image handler is compatible with the indicated target represented
@@ -58,12 +43,6 @@ public interface ImageHandler {
boolean isCompatible(RenderingContext targetContext, Image image);
/**
- * Returns the {@link Image} subclass supported by this instance.
- * @return the Image type
- */
- Class getSupportedImageClass();
-
- /**
* Handles the given {@link Image} instance painting it at the indicated position in the
* output format being generated.
* @param context the rendering context
diff --git a/src/java/org/apache/fop/render/ImageHandlerBase.java b/src/java/org/apache/fop/render/ImageHandlerBase.java
new file mode 100644
index 000000000..f07c89671
--- /dev/null
+++ b/src/java/org/apache/fop/render/ImageHandlerBase.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render;
+
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+
+/**
+ * This interface is a service provider base interface for image handlers. It only contains
+ * methods necessary for registration and is extended by sub-interfaces with the actual
+ * image handling contract.
+ */
+public interface ImageHandlerBase {
+
+ /**
+ * Returns the priority for this image handler. A lower value means higher priority. This
+ * information is used to build the ordered/prioritized list of supported ImageFlavors.
+ * The built-in handlers use priorities between 100 and 999.
+ * @return a positive integer (>0) indicating the priority
+ */
+ int getPriority();
+
+ /**
+ * Returns the {@link ImageFlavor}s supported by this instance
+ * @return the supported image flavors
+ */
+ ImageFlavor[] getSupportedImageFlavors();
+
+ /**
+ * Returns the {@link Class} subclass supported by this instance.
+ * @return the image Class type
+ */
+ Class getSupportedImageClass();
+}
diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java
index 818e31568..76f727e84 100644
--- a/src/java/org/apache/fop/render/PrintRenderer.java
+++ b/src/java/org/apache/fop/render/PrintRenderer.java
@@ -24,8 +24,6 @@ import java.awt.geom.Rectangle2D;
import java.util.List;
import java.util.Map;
-import org.w3c.dom.Document;
-
import org.apache.fop.apps.FOPException;
import org.apache.fop.area.Area;
import org.apache.fop.area.Trait;
@@ -37,6 +35,7 @@ import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.base14.Base14FontCollection;
+import org.w3c.dom.Document;
/** Abstract base class of "Print" type renderers. */
public abstract class PrintRenderer extends AbstractRenderer {
@@ -109,6 +108,14 @@ public abstract class PrintRenderer extends AbstractRenderer {
}
/**
+ * Instantiates a RendererContext for an image
+ * @return a newly created RendererContext.
+ */
+ protected RendererContext instantiateRendererContext() {
+ return new RendererContext(this, getMimeType());
+ }
+
+ /**
* Creates a RendererContext for an image.
* @param x the x coordinate (in millipoints)
* @param y the y coordinate (in millipoints)
@@ -119,8 +126,7 @@ public abstract class PrintRenderer extends AbstractRenderer {
*/
protected RendererContext createRendererContext(int x, int y, int width, int height,
Map foreignAttributes) {
- RendererContext context;
- context = new RendererContext(this, getMimeType());
+ RendererContext context = instantiateRendererContext();
context.setUserAgent(userAgent);
context.setProperty(RendererContextConstants.WIDTH,
diff --git a/src/java/org/apache/fop/render/RendererContext.java b/src/java/org/apache/fop/render/RendererContext.java
index 595bdd7c2..ac885a44b 100644
--- a/src/java/org/apache/fop/render/RendererContext.java
+++ b/src/java/org/apache/fop/render/RendererContext.java
@@ -20,9 +20,12 @@
package org.apache.fop.render;
//Java
+import java.util.Iterator;
import java.util.Map;
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.xmlgraphics.util.QName;
/**
* The Render Context for external handlers. This provides a rendering context
@@ -30,21 +33,28 @@ import org.apache.fop.apps.FOUserAgent;
* render target.
*/
public class RendererContext {
+ /** conversion-mode extension attribute */
+ protected static final QName CONVERSION_MODE = new QName(
+ ExtensionElementMapping.URI, null, "conversion-mode");
- private String mime;
- private AbstractRenderer renderer;
+ /** "bitmap" value for the "conversion-mode" extension attribute. */
+ protected static final String BITMAP = "bitmap";
+
+ private final String mime;
+ private final AbstractRenderer renderer;
private FOUserAgent userAgent;
- private Map props = new java.util.HashMap();
+
+ private final Map/*<String,Object>*/ props = new java.util.HashMap/*<String,Object>*/();
/**
- * Contructor for this class. It takes a MIME type as parameter.
+ * Constructor for this class. It takes a MIME type as parameter.
*
- * @param renderer The current renderer
- * @param m The MIME type of the output that's generated.
+ * @param renderer the current renderer
+ * @param mime the MIME type of the output that's generated.
*/
- public RendererContext(AbstractRenderer renderer, String m) {
+ public RendererContext(AbstractRenderer renderer, String mime) {
this.renderer = renderer;
- this.mime = m;
+ this.mime = mime;
}
/**
@@ -112,6 +122,19 @@ public class RendererContext {
return wrapper;
}
+ /** {@inheritDoc} **/
+ public String toString() {
+ StringBuffer stringBuffer = new StringBuffer("RendererContext{\n");
+ Iterator it = props.keySet().iterator();
+ while (it.hasNext()) {
+ String key = (String)it.next();
+ Object value = props.get(key);
+ stringBuffer.append("\t" + key + "=" + value + "\n");
+ }
+ stringBuffer.append("}");
+ return stringBuffer.toString();
+ }
+
/**
* Base class for a wrapper around RendererContext to access its properties in a type-safe,
* renderer-specific way.
@@ -158,6 +181,19 @@ public class RendererContext {
public Map getForeignAttributes() {
return (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
}
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "RendererContextWrapper{"
+ + "userAgent=" + getUserAgent()
+ + "x=" + getCurrentXPosition()
+ + "y=" + getCurrentYPosition()
+ + "width=" + getWidth()
+ + "height=" + getHeight()
+ + "foreignAttributes=" + getForeignAttributes()
+ + "}";
+
+ }
}
}
diff --git a/src/java/org/apache/fop/render/afp/AFPEventProducer.xml b/src/java/org/apache/fop/render/afp/AFPEventProducer.xml
index b0eeeb202..23bd9a182 100644
--- a/src/java/org/apache/fop/render/afp/AFPEventProducer.xml
+++ b/src/java/org/apache/fop/render/afp/AFPEventProducer.xml
@@ -1,3 +1 @@
-<?xml version="1.0" encoding="UTF-8"?><catalogue xml:lang="en">
- <message key="org.apache.fop.render.afp.AFPEventProducer.warnDefaultFontSetup">No AFP fonts configured. Using default setup.</message>
-</catalogue>
+<?xml version="1.0" encoding="UTF-8"?><catalogue xml:lang="en"/>
diff --git a/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java b/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java
new file mode 100644
index 000000000..2b5077fe9
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.fop.render.afp.extensions.AFPElementMapping;
+import org.apache.xmlgraphics.util.QName;
+
+/**
+ * Parses any AFP foreign attributes
+ */
+public class AFPForeignAttributeReader {
+ private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
+
+ /** the resource-name attribute */
+ public static final String RESOURCE_NAME = "afp:resource-name";
+
+ /** the resource-level attribute */
+ public static final String RESOURCE_LEVEL = "afp:resource-level";
+
+ /** the resource-group-file attribute */
+ public static final String RESOURCE_GROUP_FILE = "afp:resource-group-file";
+
+ /**
+ * Main constructor
+ */
+ public AFPForeignAttributeReader() {
+ }
+
+ /**
+ * Returns the resource information
+ *
+ * @param foreignAttributes the foreign attributes
+ * @return the resource information
+ */
+ public AFPResourceInfo getResourceInfo(Map/*<QName, String>*/ foreignAttributes) {
+ AFPResourceInfo resourceInfo = new AFPResourceInfo();
+ if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
+ QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME);
+ String resourceName = (String)foreignAttributes.get(resourceNameKey);
+ if (resourceName != null) {
+ resourceInfo.setName(resourceName);
+ }
+ AFPResourceLevel level = getResourceLevel(foreignAttributes);
+ if (level != null) {
+ resourceInfo.setLevel(level);
+ }
+ }
+ return resourceInfo;
+ }
+
+ /**
+ * Returns the resource level
+ *
+ * @param foreignAttributes the foreign attributes
+ * @return the resource level
+ */
+ public AFPResourceLevel getResourceLevel(Map/*<QName, String>*/ foreignAttributes) {
+ AFPResourceLevel resourceLevel = null;
+ if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
+ QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL);
+ if (foreignAttributes.containsKey(resourceLevelKey)) {
+ String levelString = (String)foreignAttributes.get(resourceLevelKey);
+ resourceLevel = AFPResourceLevel.valueOf(levelString);
+ // if external get resource group file attributes
+ if (resourceLevel != null && resourceLevel.isExternal()) {
+ QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE,
+ RESOURCE_GROUP_FILE);
+ String resourceGroupFile
+ = (String)foreignAttributes.get(resourceGroupFileKey);
+ if (resourceGroupFile == null) {
+ String msg = RESOURCE_GROUP_FILE + " not specified";
+ log.error(msg);
+ throw new UnsupportedOperationException(msg);
+ }
+ File resourceExternalGroupFile = new File(resourceGroupFile);
+ SecurityManager security = System.getSecurityManager();
+ try {
+ if (security != null) {
+ security.checkWrite(resourceExternalGroupFile.getPath());
+ }
+ } catch (SecurityException ex) {
+ String msg = "unable to gain write access to external resource file: "
+ + resourceGroupFile;
+ log.error(msg);
+ }
+
+ try {
+ boolean exists = resourceExternalGroupFile.exists();
+ if (exists) {
+ log.warn("overwriting external resource file: "
+ + resourceGroupFile);
+ }
+ resourceLevel.setExternalFilePath(resourceGroupFile);
+ } catch (SecurityException ex) {
+ String msg = "unable to gain read access to external resource file: "
+ + resourceGroupFile;
+ log.error(msg);
+ }
+ }
+ }
+ }
+ return resourceLevel;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java
index 18ac4dbb6..becafda23 100644
--- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java
+++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java
@@ -19,40 +19,87 @@
package org.apache.fop.render.afp;
+import java.awt.Dimension;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
-import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
-
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.afp.AFPGraphicsObjectInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceManager;
import org.apache.fop.render.AbstractGraphics2DAdapter;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererContext.RendererContextWrapper;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
/**
* Graphics2DAdapter implementation for AFP.
*/
public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter {
+ private final AFPPaintingState paintingState;
+
/**
* Main constructor
+ *
+ * @param paintingState the AFP painting state
*/
- public AFPGraphics2DAdapter() {
+ public AFPGraphics2DAdapter(AFPPaintingState paintingState) {
+ this.paintingState = paintingState;
}
/** {@inheritDoc} */
public void paintImage(Graphics2DImagePainter painter,
- RendererContext context,
+ RendererContext rendererContext,
int x, int y, int width, int height) throws IOException {
- RendererContext.RendererContextWrapper wrappedContext
- = new RendererContext.RendererContextWrapper(context);
- AFPRenderer afp = (AFPRenderer)context.getRenderer();
- Boolean grayObj = (Boolean)context.getProperty(AFPRendererContextConstants.AFP_GRAYSCALE);
- boolean gray = (grayObj != null ? grayObj.booleanValue() : false);
- //Paint to a BufferedImage
- int resolution = (int)Math.round(context.getUserAgent().getTargetResolution());
- BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false);
+ AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext;
+ AFPInfo afpInfo = afpRendererContext.getInfo();
+
+ final boolean textAsShapes = false;
+ AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);
+
+ paintingState.save();
+
+ //Fallback solution: Paint to a BufferedImage
+ if (afpInfo.paintAsBitmap()) {
- afp.drawBufferedImage(bi, resolution, x, y, width, height);
+ // paint image
+ RendererContextWrapper rendererContextWrapper
+ = RendererContext.wrapRendererContext(rendererContext);
+ float targetResolution = rendererContext.getUserAgent().getTargetResolution();
+ int resolution = Math.round(targetResolution);
+ boolean colorImages = afpInfo.isColorSupported();
+ BufferedImage bufferedImage = paintToBufferedImage(
+ painter, rendererContextWrapper, resolution, !colorImages, false);
+
+ // draw image
+ AffineTransform at = paintingState.getData().getTransform();
+ at.translate(x, y);
+ g2d.drawImage(bufferedImage, at, null);
+ } else {
+ AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();
+ graphicsObjectInfo.setPainter(painter);
+ graphicsObjectInfo.setGraphics2D(g2d);
+
+ // get the 'width' and 'height' attributes of the SVG document
+ Dimension imageSize = painter.getImageSize();
+ float imw = (float)imageSize.getWidth() / 1000f;
+ float imh = (float)imageSize.getHeight() / 1000f;
+
+ Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
+ graphicsObjectInfo.setArea(area);
+ AFPResourceManager resourceManager = afpInfo.getResourceManager();
+ resourceManager.createObject(graphicsObjectInfo);
+ }
+
+ paintingState.restore();
}
+ /** {@inheritDoc} */
+ protected int mpt2px(int unit, int resolution) {
+ return Math.round(paintingState.getUnitConverter().mpt2units(unit));
+ }
}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandler.java b/src/java/org/apache/fop/render/afp/AFPImageHandler.java
new file mode 100644
index 000000000..a6d2d613d
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandler.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.Point;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPUnitConverter;
+import org.apache.fop.render.ImageHandlerBase;
+
+/**
+ * A base abstract AFP image handler
+ */
+public abstract class AFPImageHandler implements ImageHandlerBase {
+ private static final int X = 0;
+ private static final int Y = 1;
+
+ /** foreign attribute reader */
+ private final AFPForeignAttributeReader foreignAttributeReader
+ = new AFPForeignAttributeReader();
+
+ /**
+ * Generates an intermediate AFPDataObjectInfo that is later used to construct
+ * the appropriate data object in the AFP DataStream.
+ *
+ * @param rendererImageInfo the renderer image info
+ * @return a data object info object
+ * @throws IOException thrown if an I/O exception of some sort has occurred.
+ */
+ public AFPDataObjectInfo generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+ AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();
+
+ // set resource information
+ Map foreignAttributes = rendererImageInfo.getForeignAttributes();
+ AFPResourceInfo resourceInfo
+ = foreignAttributeReader.getResourceInfo(foreignAttributes);
+ resourceInfo.setUri(rendererImageInfo.getURI());
+ dataObjectInfo.setResourceInfo(resourceInfo);
+
+ // set object area
+ AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
+
+ Point origin = rendererImageInfo.getOrigin();
+ Rectangle2D position = rendererImageInfo.getPosition();
+ float srcX = origin.x + (float)position.getX();
+ float srcY = origin.y + (float)position.getY();
+
+ AFPRendererContext rendererContext
+ = (AFPRendererContext)rendererImageInfo.getRendererContext();
+ AFPInfo afpInfo = rendererContext.getInfo();
+ AFPPaintingState paintingState = afpInfo.getPaintingState();
+ AFPUnitConverter unitConv = paintingState.getUnitConverter();
+ int[] coords = unitConv.mpts2units(new float[] {srcX, srcY});
+ objectAreaInfo.setX(coords[X]);
+ objectAreaInfo.setY(coords[Y]);
+
+ int width = Math.round(unitConv.mpt2units((float)position.getWidth()));
+ objectAreaInfo.setWidth(width);
+
+ int height = Math.round(unitConv.mpt2units((float)position.getHeight()));
+ objectAreaInfo.setHeight(height);
+
+ int resolution = paintingState.getResolution();
+ objectAreaInfo.setHeightRes(resolution);
+ objectAreaInfo.setWidthRes(resolution);
+
+ objectAreaInfo.setRotation(paintingState.getRotation());
+
+ dataObjectInfo.setObjectAreaInfo(objectAreaInfo);
+
+ return dataObjectInfo;
+ }
+
+ /**
+ * Creates the data object information object
+ *
+ * @return the data object information object
+ */
+ protected abstract AFPDataObjectInfo createDataObjectInfo();
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
new file mode 100644
index 000000000..0780e8a59
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.io.IOException;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.afp.AFPGraphicsObjectInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * PDFImageHandler implementation which handles Graphics2D images.
+ */
+public class AFPImageHandlerGraphics2D extends AFPImageHandler {
+
+ private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+ ImageFlavor.GRAPHICS2D
+ };
+
+ /** {@inheritDoc} */
+ public AFPDataObjectInfo generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+
+ AFPRendererContext rendererContext
+ = (AFPRendererContext)rendererImageInfo.getRendererContext();
+ AFPInfo afpInfo = rendererContext.getInfo();
+ ImageGraphics2D imageG2D = (ImageGraphics2D)rendererImageInfo.getImage();
+ Graphics2DImagePainter painter = imageG2D.getGraphics2DImagePainter();
+
+ if (afpInfo.paintAsBitmap()) {
+ int x = afpInfo.getX();
+ int y = afpInfo.getY();
+ int width = afpInfo.getWidth();
+ int height = afpInfo.getHeight();
+ AFPPaintingState paintingState = afpInfo.getPaintingState();
+ AFPGraphics2DAdapter g2dAdapter = new AFPGraphics2DAdapter(paintingState);
+ g2dAdapter.paintImage(painter, rendererContext, x, y, width, height);
+ return null;
+ } else {
+ AFPGraphicsObjectInfo graphicsObjectInfo
+ = (AFPGraphicsObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+ AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
+ //level not explicitly set/changed so default to inline for GOCA graphic objects
+ // (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07), hard copy works just fine)
+ if (!resourceInfo.levelChanged()) {
+ resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
+ }
+
+ // set mime type (unsupported by MOD:CA registry)
+ graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);
+
+ // set g2d
+ boolean textAsShapes = false;
+
+ AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);
+
+ graphicsObjectInfo.setGraphics2D(g2d);
+
+ // set painter
+ graphicsObjectInfo.setPainter(painter);
+
+ return graphicsObjectInfo;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 200;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageGraphics2D.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return FLAVORS;
+ }
+
+ /** {@inheritDoc} */
+ protected AFPDataObjectInfo createDataObjectInfo() {
+ return new AFPGraphicsObjectInfo();
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java
new file mode 100644
index 000000000..3ac1d5696
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.io.IOException;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPImageObjectInfo;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+
+/**
+ * AFPImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4).
+ */
+public class AFPImageHandlerRawCCITTFax extends AbstractAFPImageHandlerRawStream {
+
+ private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+ ImageFlavor.RAW_CCITTFAX,
+ };
+
+ /** {@inheritDoc} */
+ public AFPDataObjectInfo generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+ AFPImageObjectInfo imageObjectInfo
+ = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+ ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.getImage();
+ int compression = ccitt.getCompression();
+ imageObjectInfo.setCompression(compression);
+
+ imageObjectInfo.setBitsPerPixel(1);
+ return imageObjectInfo;
+ }
+
+ /** {@inheritDoc} */
+ protected AFPDataObjectInfo createDataObjectInfo() {
+ return new AFPImageObjectInfo();
+ }
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 400;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageRawCCITTFax.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return FLAVORS;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java
new file mode 100644
index 000000000..ded9ec9d5
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
+
+/**
+ * AFPImageHandler implementation which handles raw stream images.
+ */
+public class AFPImageHandlerRawStream extends AbstractAFPImageHandlerRawStream {
+
+ private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+ ImageFlavor.RAW_JPEG,
+ ImageFlavor.RAW_EPS,
+ };
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 200;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageRawStream.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return FLAVORS;
+ }
+
+ /** {@inheritDoc} */
+ protected AFPDataObjectInfo createDataObjectInfo() {
+ return new AFPDataObjectInfo();
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java
new file mode 100644
index 000000000..59ca6cf38
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import org.apache.fop.render.AbstractImageHandlerRegistry;
+
+/**
+ * This class holds references to various image handlers used by the AFP renderer. It also
+ * supports automatic discovery of additional handlers available through
+ * the class path.
+ */
+public class AFPImageHandlerRegistry extends AbstractImageHandlerRegistry {
+
+ /**
+ * Main constructor
+ */
+ public AFPImageHandlerRegistry() {
+ }
+
+ /** {@inheritDoc} */
+ public Class getHandlerClass() {
+ return AFPImageHandler.class;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
new file mode 100644
index 000000000..28c942a08
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.image.RenderedImage;
+import java.io.IOException;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPImageObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.ps.ImageEncodingHelper;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * PDFImageHandler implementation which handles RenderedImage instances.
+ */
+public class AFPImageHandlerRenderedImage extends AFPImageHandler {
+
+ private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+ ImageFlavor.BUFFERED_IMAGE,
+ ImageFlavor.RENDERED_IMAGE
+ };
+
+ /** {@inheritDoc} */
+ public AFPDataObjectInfo generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+ AFPImageObjectInfo imageObjectInfo
+ = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+ AFPRendererContext rendererContext
+ = (AFPRendererContext)rendererImageInfo.getRendererContext();
+ AFPInfo afpInfo = rendererContext.getInfo();
+ AFPPaintingState paintingState = afpInfo.getPaintingState();
+ int resolution = paintingState.getResolution();
+
+ imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
+ imageObjectInfo.setDataHeightRes(resolution);
+ imageObjectInfo.setDataWidthRes(resolution);
+
+ ImageRendered imageRendered = (ImageRendered) rendererImageInfo.img;
+ RenderedImage renderedImage = imageRendered.getRenderedImage();
+
+ int dataHeight = renderedImage.getHeight();
+ imageObjectInfo.setDataHeight(dataHeight);
+
+ int dataWidth = renderedImage.getWidth();
+ imageObjectInfo.setDataWidth(dataWidth);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos);
+ byte[] imageData = baos.toByteArray();
+
+ boolean colorImages = paintingState.isColorImages();
+ imageObjectInfo.setColor(colorImages);
+
+ // convert to grayscale
+ if (!colorImages) {
+ baos.reset();
+ int bitsPerPixel = paintingState.getBitsPerPixel();
+ imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+ ImageEncodingHelper.encodeRGBAsGrayScale(
+ imageData, dataWidth, dataHeight, bitsPerPixel, baos);
+ imageData = baos.toByteArray();
+ }
+ imageObjectInfo.setData(imageData);
+
+ // set object area info
+ AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
+ objectAreaInfo.setWidthRes(resolution);
+ objectAreaInfo.setHeightRes(resolution);
+
+ return imageObjectInfo;
+ }
+
+ /** {@inheritDoc} */
+ protected AFPDataObjectInfo createDataObjectInfo() {
+ return new AFPImageObjectInfo();
+ }
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 300;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageRendered.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return FLAVORS;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java
new file mode 100644
index 000000000..7ea1a7a10
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererContextConstants;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
+import org.w3c.dom.Document;
+
+/**
+ * PDFImageHandler implementation which handles XML-based images.
+ */
+public class AFPImageHandlerXML extends AFPImageHandler {
+
+ private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+ ImageFlavor.XML_DOM,
+ };
+
+ /** {@inheritDoc} */
+ public AFPDataObjectInfo generateDataObjectInfo(AFPRendererImageInfo rendererImageInfo)
+ throws IOException {
+ RendererContext rendererContext = rendererImageInfo.getRendererContext();
+ AFPRenderer renderer = (AFPRenderer)rendererContext.getRenderer();
+ ImageXMLDOM imgXML = (ImageXMLDOM)rendererImageInfo.getImage();
+ Document doc = imgXML.getDocument();
+ String ns = imgXML.getRootNamespace();
+ Map foreignAttributes = (Map)rendererContext.getProperty(
+ RendererContextConstants.FOREIGN_ATTRIBUTES);
+ Rectangle2D pos = rendererImageInfo.getPosition();
+ renderer.renderDocument(doc, ns, pos, foreignAttributes);
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 400;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageXMLDOM.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return FLAVORS;
+ }
+
+ /** {@inheritDoc} */
+ protected AFPDataObjectInfo createDataObjectInfo() {
+ return null;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java
new file mode 100644
index 000000000..fb1ec87a8
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPInfo.java
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceManager;
+import org.apache.fop.fonts.FontInfo;
+
+/**
+ * AFP information structure for drawing the XML document.
+ */
+public final class AFPInfo {
+ /** see WIDTH */
+ private int width;
+
+ /** see HEIGHT */
+ private int height;
+
+ /** see XPOS */
+ private int x;
+
+ /** see YPOS */
+ private int y;
+
+ /** see HANDLER_CONFIGURATION */
+ private Configuration handlerConfiguration;
+
+ /** see AFP_FONT_INFO */
+ private FontInfo fontInfo;
+
+ /** See AFP_PAINTING_STATE */
+ private AFPPaintingState paintingState;
+
+ /** See AFP_RESOURCE_MANAGER */
+ private AFPResourceManager resourceManager;
+
+ /** See AFP_RESOURCE_INFO */
+ private AFPResourceInfo resourceInfo;
+
+ /** true if SVG should be rendered as a bitmap instead of natively */
+ private boolean paintAsBitmap;
+
+ /**
+ * Returns the width.
+ *
+ * @return the width
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the width.
+ *
+ * @param width The pageWidth to set
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * Returns the height.
+ *
+ * @return the height
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the height.
+ *
+ * @param height The height to set
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * Returns the handler configuration
+ *
+ * @return the handler configuration
+ */
+ public Configuration getHandlerConfiguration() {
+ return this.handlerConfiguration;
+ }
+
+ /**
+ * Sets the handler configuration
+ *
+ * @param cfg the handler configuration
+ */
+ public void setHandlerConfiguration(Configuration cfg) {
+ this.handlerConfiguration = cfg;
+ }
+
+ /**
+ * Return the font info
+ *
+ * @return the font info
+ */
+ public FontInfo getFontInfo() {
+ return this.fontInfo;
+ }
+
+ /**
+ * Returns the current AFP state
+ *
+ * @return the current AFP state
+ */
+ public AFPPaintingState getPaintingState() {
+ return this.paintingState;
+ }
+
+ /**
+ * Returns the AFPResourceManager
+ *
+ * @return the AFPResourceManager
+ */
+ public AFPResourceManager getResourceManager() {
+ return this.resourceManager;
+ }
+
+ /**
+ * Returns true if supports color
+ *
+ * @return true if supports color
+ */
+ public boolean isColorSupported() {
+ return getPaintingState().isColorImages();
+ }
+
+ /**
+ * Returns the current x position coordinate
+ *
+ * @return the current x position coordinate
+ */
+ protected int getX() {
+ return x;
+ }
+
+ /**
+ * Returns the current y position coordinate
+ *
+ * @return the current y position coordinate
+ */
+ protected int getY() {
+ return y;
+ }
+
+ /**
+ * Returns the resolution
+ *
+ * @return the resolution
+ */
+ protected int getResolution() {
+ return getPaintingState().getResolution();
+ }
+
+ /**
+ * Returns the number of bits per pixel to use
+ * @return the number of bits per pixel to use
+ */
+ protected int getBitsPerPixel() {
+ return getPaintingState().getBitsPerPixel();
+ }
+
+ /**
+ * Sets the current x position coordinate
+ *
+ * @param x the current x position coordinate
+ */
+ protected void setX(int x) {
+ this.x = x;
+ }
+
+ /**
+ * Sets the current y position coordinate
+ *
+ * @param y the current y position coordinate
+ */
+ protected void setY(int y) {
+ this.y = y;
+ }
+
+ /**
+ * Sets the current font info
+ *
+ * @param fontInfo the current font info
+ */
+ protected void setFontInfo(FontInfo fontInfo) {
+ this.fontInfo = fontInfo;
+ }
+
+ /**
+ * Sets the AFP state
+ *
+ * @param paintingState the AFP state
+ */
+ public void setPaintingState(AFPPaintingState paintingState) {
+ this.paintingState = paintingState;
+ }
+
+ /**
+ * Sets the AFPResourceManager
+ *
+ * @param resourceManager the AFPResourceManager
+ */
+ public void setResourceManager(AFPResourceManager resourceManager) {
+ this.resourceManager = resourceManager;
+ }
+
+ /**
+ * Sets true if SVG should be rendered as a bitmap instead of natively
+ *
+ * @param b boolean value
+ */
+ public void setPaintAsBitmap(boolean b) {
+ this.paintAsBitmap = b;
+ }
+
+ /**
+ * Returns true if SVG should be rendered as a bitmap instead of natively
+ *
+ * @return true if SVG should be rendered as a bitmap instead of natively
+ */
+ public boolean paintAsBitmap() {
+ return this.paintAsBitmap;
+ }
+
+ /**
+ * Returns true if text should be stroked when painted
+ *
+ * @return true if text should be stroked when painted
+ */
+ public boolean strokeText() {
+ boolean strokeText = false;
+ if (handlerConfiguration != null) {
+ strokeText = handlerConfiguration.getChild("stroke-text", true).getValueAsBoolean(strokeText);
+ }
+ return strokeText;
+ }
+
+ /**
+ * Sets the resource information
+ *
+ * @param resourceInfo the resource information
+ */
+ public void setResourceInfo(AFPResourceInfo resourceInfo) {
+ this.resourceInfo = resourceInfo;
+ }
+
+ /**
+ * Returns the resource information
+ *
+ * @return the resource information
+ */
+ public AFPResourceInfo getResourceInfo() {
+ return resourceInfo;
+ }
+
+ /**
+ * Creates an AFPGraphics2D implementation
+ *
+ * @param textAsShapes true when text is painted as shapes
+ * @return a newly created AFPGraphics2D
+ */
+ public AFPGraphics2D createGraphics2D(boolean textAsShapes) {
+ AFPGraphics2D g2d = new AFPGraphics2D(
+ textAsShapes, paintingState, resourceManager, resourceInfo, fontInfo);
+ g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
+ return g2d;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPInfo{width=" + width
+ + ", height=" + height
+ + ", x=" + x
+ + ", y=" + y
+ + ", cfg=" + handlerConfiguration
+ + ", fontInfo=" + fontInfo
+ + ", resourceManager=" + resourceManager
+ + ", paintingState=" + paintingState
+ + ", paintAsBitmap=" + paintAsBitmap
+ + ", resourceInfo=" + resourceInfo
+ + "}";
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java
index d5129f167..8035a9490 100644
--- a/src/java/org/apache/fop/render/afp/AFPRenderer.java
+++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java
@@ -23,56 +23,46 @@ import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.ByteArrayOutputStream;
-
-import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
-import org.apache.xmlgraphics.image.loader.ImageException;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
-import org.apache.xmlgraphics.image.loader.ImageInfo;
-import org.apache.xmlgraphics.image.loader.ImageManager;
-import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
-import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
-import org.apache.xmlgraphics.image.loader.util.ImageUtil;
-import org.apache.xmlgraphics.ps.ImageEncodingHelper;
-
+import org.apache.fop.afp.AFPBorderPainter;
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPEventProducer;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPRectanglePainter;
+import org.apache.fop.afp.AFPResourceManager;
+import org.apache.fop.afp.AFPTextDataInfo;
+import org.apache.fop.afp.AFPUnitConverter;
+import org.apache.fop.afp.BorderPaintingInfo;
+import org.apache.fop.afp.DataStream;
+import org.apache.fop.afp.RectanglePaintingInfo;
+import org.apache.fop.afp.fonts.AFPFont;
+import org.apache.fop.afp.fonts.AFPFontAttributes;
+import org.apache.fop.afp.fonts.AFPFontCollection;
+import org.apache.fop.afp.fonts.AFPPageFonts;
+import org.apache.fop.afp.fonts.CharacterSet;
+import org.apache.fop.afp.modca.PageObject;
+import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.BlockViewport;
-import org.apache.fop.area.BodyRegion;
import org.apache.fop.area.CTM;
-import org.apache.fop.area.NormalFlow;
+import org.apache.fop.area.LineArea;
import org.apache.fop.area.OffDocumentItem;
import org.apache.fop.area.PageViewport;
-import org.apache.fop.area.RegionReference;
-import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.Leader;
-import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.WordArea;
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.events.ResourceEventProducer;
-import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontInfo;
@@ -82,13 +72,13 @@ import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.afp.extensions.AFPElementMapping;
import org.apache.fop.render.afp.extensions.AFPPageSetup;
-import org.apache.fop.render.afp.fonts.AFPFont;
-import org.apache.fop.render.afp.fonts.AFPFontCollection;
-import org.apache.fop.render.afp.modca.AFPConstants;
-import org.apache.fop.render.afp.modca.AFPDataStream;
-import org.apache.fop.render.afp.modca.ImageObject;
-import org.apache.fop.render.afp.modca.PageObject;
-import org.apache.fop.util.ColorUtil;
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.ps.ImageEncodingHelper;
/**
* This is an implementation of a FOP Renderer that renders areas to AFP.
@@ -139,140 +129,55 @@ import org.apache.fop.util.ColorUtil;
* rectangles.
* </p>
*
- * Note: There are specific extensions that have been added to the
- * FO. They are specific to their location within the FO and have to be
- * processed accordingly (ie. at the start or end of the page).
+ * Note: There are specific extensions that have been added to the FO. They are
+ * specific to their location within the FO and have to be processed accordingly
+ * (ie. at the start or end of the page).
*
*/
public class AFPRenderer extends AbstractPathOrientedRenderer {
- /**
- * The default afp renderer output resolution
- */
- private static final int DEFAULT_DPI_RESOLUTION = 240;
-
- /**
- * The afp factor for calculating resolutions (e.g. 72000/240 = 300)
- */
- private static final int DPI_CONVERSION_FACTOR = 72000;
-
- /**
- * The afp data stream object responsible for generating afp data
- */
- private AFPDataStream afpDataStream = null;
+ private static final int X = 0;
+ private static final int Y = 1;
- /**
- * The map of afp root extensions
- */
- // UNUSED
- // private HashMap rootExtensionMap = null;
- /**
- * The map of page segments
- */
- private HashMap pageSegmentsMap = null;
+ /** the resource manager */
+ private AFPResourceManager resourceManager;
- /**
- * The fonts on the current page
- */
- private HashMap currentPageFonts = null;
+ /** the painting state */
+ private final AFPPaintingState paintingState;
- /**
- * The current color object
- */
- private Color currentColor = null;
+ /** unit converter */
+ private final AFPUnitConverter unitConv;
- /**
- * The page font number counter, used to determine the next font reference
- */
- private int pageFontCounter = 0;
+ /** the line painter */
+ private AFPBorderPainter borderPainter;
- /**
- * The current font family
- */
- // UNUSED
- // private String currentFontFamily = "";
- /**
- * The current font size
- */
- private int currentFontSize = 0;
+ /** the map of page segments */
+ private final Map/*<String,String>*/pageSegmentMap
+ = new java.util.HashMap/*<String,String>*/();
- /**
- * The Options to be set on the AFPRenderer
- */
- // UNUSED
- // private Map afpOptions = null;
- /**
- * The page width
- */
- private int pageWidth = 0;
+ /** the map of saved incomplete pages */
+ private final Map pages = new java.util.HashMap/*<PageViewport,PageObject>*/();
- /**
- * The page height
- */
- private int pageHeight = 0;
+ /** the AFP datastream */
+ private DataStream dataStream;
- /**
- * The current page sequence id
- */
- // UNUSED
- // private String pageSequenceId = null;
- /**
- * The portrait rotation
- */
- private int portraitRotation = 0;
+ /** the image handler registry */
+ private final AFPImageHandlerRegistry imageHandlerRegistry;
- /**
- * The landscape rotation
- */
- private int landscapeRotation = 270;
-
- /**
- * The line cache, avoids drawing duplicate lines in tables.
- */
- // UNUSED
- // private HashSet lineCache = null;
- /**
- * The current x position for line drawing
- */
- // UNUSED
- // private float x;
- /**
- * The current y position for line drawing
- */
- // UNUSED
- // private float y;
- /**
- * The map of saved incomplete pages
- */
- private Map pages = null;
-
- /**
- * Flag to the set the output object type for images
- */
- private boolean colorImages = false;
-
- /**
- * Default value for image depth
- */
- private int bitsPerPixel = 8;
-
- /**
- * The output resolution
- */
- private int resolution = DEFAULT_DPI_RESOLUTION;
+ private AFPRectanglePainter rectanglePainter;
/**
* Constructor for AFPRenderer.
*/
public AFPRenderer() {
super();
+ this.imageHandlerRegistry = new AFPImageHandlerRegistry();
+ this.resourceManager = new AFPResourceManager();
+ this.paintingState = new AFPPaintingState();
+ this.unitConv = paintingState.getUnitConverter();
}
- /**
- * Set up the font info
- *
- * @param inFontInfo font info to set up
- */
+ /** {@inheritDoc} */
public void setupFontInfo(FontInfo inFontInfo) {
this.fontInfo = inFontInfo;
FontManager fontManager = userAgent.getFactory().getFontManager();
@@ -282,885 +187,272 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
fontManager.setup(getFontInfo(), fontCollections);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void startRenderer(OutputStream outputStream) throws IOException {
- currentPageFonts = new HashMap();
- currentColor = new Color(255, 255, 255);
- afpDataStream = new AFPDataStream();
- afpDataStream.setPortraitRotation(portraitRotation);
- afpDataStream.setLandscapeRotation(landscapeRotation);
- afpDataStream.startDocument(outputStream);
+ paintingState.setColor(Color.WHITE);
+
+ this.dataStream = resourceManager.createDataStream(paintingState, outputStream);
+ this.borderPainter = new AFPBorderPainter(paintingState, dataStream);
+ this.rectanglePainter = new AFPRectanglePainter(paintingState, dataStream);
+
+ dataStream.startDocument();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void stopRenderer() throws IOException {
- afpDataStream.endDocument();
+ dataStream.endDocument();
+ resourceManager.writeToStream();
+ resourceManager = null;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
+ public void startPageSequence(LineArea seqTitle) {
+ try {
+ dataStream.startPageGroup();
+ } catch (IOException e) {
+ log.error(e.getMessage());
+ }
+ }
+
+ /** {@inheritDoc} */
public boolean supportsOutOfOrder() {
- //return false;
- return true;
+ return false;
}
- /**
- * Prepare a page for rendering. This is called if the renderer supports
- * out of order rendering. The renderer should prepare the page so that a
- * page further on in the set of pages can be rendered. The body of the
- * page should not be rendered. The page will be rendered at a later time
- * by the call to render page.
- *
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void preparePage(PageViewport page) {
- // initializeRootExtensions(page);
-
- // this.currentFontFamily = "";
- this.currentFontSize = 0;
- this.pageFontCounter = 0;
- this.currentPageFonts.clear();
- // this.lineCache = new HashSet();
-
- Rectangle2D bounds = page.getViewArea();
-
- this.pageWidth = mpts2units(bounds.getWidth());
- this.pageHeight = mpts2units(bounds.getHeight());
-
- // renderPageGroupExtensions(page);
-
- final int pageRotation = 0;
- this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation,
- getResolution(), getResolution());
+ int pageRotation = paintingState.getPageRotation();
+ int pageWidth = paintingState.getPageWidth();
+ int pageHeight = paintingState.getPageHeight();
+ int resolution = paintingState.getResolution();
+ dataStream.startPage(pageWidth, pageHeight, pageRotation,
+ resolution, resolution);
renderPageObjectExtensions(page);
- if (this.pages == null) {
- this.pages = new HashMap();
- }
- this.pages.put(page, afpDataStream.savePage());
-
+ PageObject currentPage = dataStream.savePage();
+ pages.put(page, currentPage);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void processOffDocumentItem(OffDocumentItem odi) {
// TODO
+ log.debug("NYI processOffDocumentItem(" + odi + ")");
}
/** {@inheritDoc} */
public Graphics2DAdapter getGraphics2DAdapter() {
- return new AFPGraphics2DAdapter();
+ return new AFPGraphics2DAdapter(paintingState);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void startVParea(CTM ctm, Rectangle2D clippingRect) {
- // dummy not used
- }
-
- /**
- * {@inheritDoc}
- */
- public void endVParea() {
- // dummy not used
- }
-
- /**
- * Renders a region viewport. <p>
- *
- * The region may clip the area and it establishes a position from where
- * the region is placed.</p>
- *
- * @param port The region viewport to be rendered
- */
- public void renderRegionViewport(RegionViewport port) {
- if (port != null) {
- Rectangle2D view = port.getViewArea();
- // The CTM will transform coordinates relative to
- // this region-reference area into page coords, so
- // set origin for the region to 0,0.
- currentBPPosition = 0;
- currentIPPosition = 0;
-
- RegionReference regionReference = port.getRegionReference();
- handleRegionTraits(port);
-
- /*
- _afpDataStream.startOverlay(mpts2units(view.getX())
- , mpts2units(view.getY())
- , mpts2units(view.getWidth())
- , mpts2units(view.getHeight())
- , rotation);
- */
-
- pushViewPortPos(new ViewPortPos(view, regionReference.getCTM()));
-
- if (regionReference.getRegionClass() == FO_REGION_BODY) {
- renderBodyRegion((BodyRegion) regionReference);
- } else {
- renderRegion(regionReference);
- }
- /*
- _afpDataStream.endOverlay();
- */
- popViewPortPos();
+ saveGraphicsState();
+ if (ctm != null) {
+ AffineTransform at = ctm.toAffineTransform();
+ concatenateTransformationMatrix(at);
}
- }
-
- /** {@inheritDoc} */
- protected void renderBlockViewport(BlockViewport bv, List children) {
- // clip and position viewport if necessary
-
- // save positions
- int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
-
- CTM ctm = bv.getCTM();
- int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
- int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
- //This is the content-rect
- float width = (float)bv.getIPD() / 1000f;
- float height = (float)bv.getBPD() / 1000f;
-
- if (bv.getPositioning() == Block.ABSOLUTE
- || bv.getPositioning() == Block.FIXED) {
-
- //For FIXED, we need to break out of the current viewports to the
- //one established by the page. We save the state stack for restoration
- //after the block-container has been painted. See below.
- List breakOutList = null;
- if (bv.getPositioning() == Block.FIXED) {
- breakOutList = breakOutOfStateStack();
- }
-
- AffineTransform positionTransform = new AffineTransform();
- positionTransform.translate(bv.getXOffset(), bv.getYOffset());
-
- //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle
- positionTransform.translate(-borderPaddingStart, -borderPaddingBefore);
-
- //skipping fox:transform here
-
- //saveGraphicsState();
- //Viewport position
- //concatenateTransformationMatrix(mptToPt(positionTransform));
-
- //Background and borders
- float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f;
- float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f;
- Point2D ptSrc = new Point(0, 0);
- Point2D ptDst = positionTransform.transform(ptSrc, null);
- Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(),
- 1000 * (width + bpwidth), 1000 * (height + bpheight));
- pushViewPortPos(new ViewPortPos(borderRect, new CTM(positionTransform)));
- drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight);
-
- //Shift to content rectangle after border painting
- AffineTransform contentRectTransform = new AffineTransform();
- contentRectTransform.translate(borderPaddingStart, borderPaddingBefore);
- //concatenateTransformationMatrix(mptToPt(contentRectTransform));
- ptSrc = new Point(0, 0);
- ptDst = contentRectTransform.transform(ptSrc, null);
- Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(),
- 1000 * width, 1000 * height);
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentRectTransform)));
-
- //Clipping is not supported, yet
- //Rectangle2D clippingRect = null;
- //clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD());
-
- //saveGraphicsState();
- //Set up coordinate system for content rectangle
- AffineTransform contentTransform = ctm.toAffineTransform();
- //concatenateTransformationMatrix(mptToPt(contentTransform));
- contentRect = new Rectangle2D.Double(0, 0, 1000 * width, 1000 * height);
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentTransform)));
-
- currentIPPosition = 0;
- currentBPPosition = 0;
- renderBlocks(bv, children);
-
- popViewPortPos();
- popViewPortPos();
- //restoreGraphicsState();
- popViewPortPos();
- //restoreGraphicsState();
-
- if (breakOutList != null) {
- restoreStateStackAfterBreakOut(breakOutList);
- }
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
- } else {
-
- currentBPPosition += bv.getSpaceBefore();
-
- //borders and background in the old coordinate system
- handleBlockTraits(bv);
-
- //Advance to start of content area
- currentIPPosition += bv.getStartIndent();
-
- CTM tempctm = new CTM(containingIPPosition, currentBPPosition);
- ctm = tempctm.multiply(ctm);
-
- //Now adjust for border/padding
- currentBPPosition += borderPaddingBefore;
-
- Rectangle2D clippingRect = null;
- clippingRect = new Rectangle(currentIPPosition, currentBPPosition,
- bv.getIPD(), bv.getBPD());
-
- //startVParea(ctm, clippingRect);
- pushViewPortPos(new ViewPortPos(clippingRect, ctm));
-
- currentIPPosition = 0;
- currentBPPosition = 0;
- renderBlocks(bv, children);
- //endVParea();
- popViewPortPos();
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
-
- currentBPPosition += (int)(bv.getAllocBPD());
+ if (clippingRect != null) {
+ clipRect((float)clippingRect.getX() / 1000f,
+ (float)clippingRect.getY() / 1000f,
+ (float)clippingRect.getWidth() / 1000f,
+ (float)clippingRect.getHeight() / 1000f);
}
}
/** {@inheritDoc} */
- protected void renderReferenceArea(Block block) {
- //TODO Remove this method once concatenateTransformationMatrix() is implemented
-
- // save position and offset
- int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
-
- //Establish a new coordinate system
- AffineTransform at = new AffineTransform();
- at.translate(currentIPPosition, currentBPPosition);
- at.translate(block.getXOffset(), block.getYOffset());
- at.translate(0, block.getSpaceBefore());
-
- if (!at.isIdentity()) {
- Rectangle2D contentRect
- = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(),
- block.getAllocIPD(), block.getAllocBPD());
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(at)));
- }
-
- currentIPPosition = 0;
- currentBPPosition = 0;
- handleBlockTraits(block);
-
- List children = block.getChildAreas();
- if (children != null) {
- renderBlocks(block, children);
- }
-
- if (!at.isIdentity()) {
- popViewPortPos();
- }
-
- // stacked and relative blocks effect stacking
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
+ public void endVParea() {
+ restoreGraphicsState();
}
/** {@inheritDoc} */
- protected void renderFlow(NormalFlow flow) {
- // save position and offset
- int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
-
- //Establish a new coordinate system
- AffineTransform at = new AffineTransform();
- at.translate(currentIPPosition, currentBPPosition);
-
- if (!at.isIdentity()) {
- Rectangle2D contentRect
- = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(),
- flow.getAllocIPD(), flow.getAllocBPD());
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(at)));
- }
-
- currentIPPosition = 0;
- currentBPPosition = 0;
- super.renderFlow(flow);
-
+ protected void concatenateTransformationMatrix(AffineTransform at) {
if (!at.isIdentity()) {
- popViewPortPos();
+ paintingState.concatenate(at);
}
-
- // stacked and relative blocks effect stacking
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
- }
-
-
- /** {@inheritDoc} */
- protected void concatenateTransformationMatrix(AffineTransform at) {
- //Not used here since AFPRenderer defines its own renderBlockViewport() method.
- throw new UnsupportedOperationException("NYI");
}
/**
- * {@inheritDoc}
+ * Returns the base AFP transform
+ *
+ * @return the base AFP transform
*/
- public void renderPage(PageViewport pageViewport) {
-
- // initializeRootExtensions(page);
+ private AffineTransform getBaseTransform() {
+ AffineTransform baseTransform = new AffineTransform();
+ double scale = unitConv.mpt2units(1);
+ baseTransform.scale(scale, scale);
+ return baseTransform;
+ }
- // this.currentFontFamily = "";
- this.currentFontSize = 0;
- this.pageFontCounter = 0;
- this.currentPageFonts.clear();
- // this.lineCache = new HashSet();
+ /** {@inheritDoc} */
+ public void renderPage(PageViewport pageViewport) throws IOException, FOPException {
+ paintingState.clear();
Rectangle2D bounds = pageViewport.getViewArea();
- this.pageWidth = mpts2units(bounds.getWidth());
- this.pageHeight = mpts2units(bounds.getHeight());
-
- if (pages != null && pages.containsKey(pageViewport)) {
-
- this.afpDataStream.restorePage((PageObject) pages.remove(pageViewport));
+ AffineTransform baseTransform = getBaseTransform();
+ paintingState.concatenate(baseTransform);
+ if (pages.containsKey(pageViewport)) {
+ dataStream.restorePage(
+ (PageObject)pages.remove(pageViewport));
} else {
- // renderPageGroupExtensions(page);
-
- final int pageRotation = 0;
- this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation,
- getResolution(), getResolution());
-
- renderPageObjectExtensions(pageViewport);
-
- }
-
- pushViewPortPos(new ViewPortPos());
+ int pageWidth
+ = Math.round(unitConv.mpt2units((float)bounds.getWidth()));
+ paintingState.setPageWidth(pageWidth);
- renderPageAreas(pageViewport.getPage());
+ int pageHeight
+ = Math.round(unitConv.mpt2units((float)bounds.getHeight()));
+ paintingState.setPageHeight(pageHeight);
- Iterator i = currentPageFonts.values().iterator();
- while (i.hasNext()) {
- AFPFontAttributes afpFontAttributes = (AFPFontAttributes) i.next();
+ int pageRotation = paintingState.getPageRotation();
- afpDataStream.createFont(
- (byte)afpFontAttributes.getFontReference(),
- afpFontAttributes.getFont(),
- afpFontAttributes.getPointSize());
+ int resolution = paintingState.getResolution();
- }
+ dataStream.startPage(pageWidth, pageHeight, pageRotation,
+ resolution, resolution);
- try {
- afpDataStream.endPage();
- } catch (IOException ioex) {
- // TODO What shall we do?
+ renderPageObjectExtensions(pageViewport);
}
- popViewPortPos();
-
- }
-
- /**
- * {@inheritDoc}
- */
- public void clip() {
- // TODO
- }
+ super.renderPage(pageViewport);
- /**
- * {@inheritDoc}
- */
- public void clipRect(float x, float y, float width, float height) {
- // TODO
- }
+ AFPPageFonts pageFonts = paintingState.getPageFonts();
+ if (pageFonts != null && !pageFonts.isEmpty()) {
+ dataStream.addFontsToCurrentPage(pageFonts);
+ }
- /**
- * {@inheritDoc}
- */
- public void moveTo(float x, float y) {
- // TODO
+ dataStream.endPage();
}
- /**
- * {@inheritDoc}
- */
- public void lineTo(float x, float y) {
- // TODO
- }
-
- /**
- * {@inheritDoc}
- */
- public void closePath() {
- // TODO
+ /** {@inheritDoc} */
+ public void drawBorderLine(float x1, float y1, float x2, float y2,
+ boolean horz, boolean startOrBefore, int style, Color col) {
+ BorderPaintingInfo borderPaintInfo = new BorderPaintingInfo(x1, y1, x2, y2, horz, style, col);
+ borderPainter.paint(borderPaintInfo);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void fillRect(float x, float y, float width, float height) {
- /*
- afpDataStream.createShading(
- pts2units(x),
- pts2units(y),
- pts2units(width),
- pts2units(height),
- currentColor.getRed(),
- currentColor.getGreen(),
- currentColor.getBlue());
- */
- afpDataStream.createLine(
- pts2units(x),
- pts2units(y),
- pts2units(x + width),
- pts2units(y),
- pts2units(height),
- currentColor);
+ RectanglePaintingInfo rectanglePaintInfo = new RectanglePaintingInfo(x, y, width, height);
+ rectanglePainter.paint(rectanglePaintInfo);
}
- /**
- * {@inheritDoc}
- */
- public void drawBorderLine(float x1, float y1, float x2, float y2,
- boolean horz, boolean startOrBefore, int style, Color col) {
- float w = x2 - x1;
- float h = y2 - y1;
- if ((w < 0) || (h < 0)) {
- log.error("Negative extent received. Border won't be painted.");
- return;
- }
- switch (style) {
- case Constants.EN_DOUBLE:
- if (horz) {
- float h3 = h / 3;
- float ym1 = y1;
- float ym2 = ym1 + h3 + h3;
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(ym1),
- pts2units(x2),
- pts2units(ym1),
- pts2units(h3),
- col
- );
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(ym2),
- pts2units(x2),
- pts2units(ym2),
- pts2units(h3),
- col
- );
- } else {
- float w3 = w / 3;
- float xm1 = x1;
- float xm2 = xm1 + w3 + w3;
- afpDataStream.createLine(
- pts2units(xm1),
- pts2units(y1),
- pts2units(xm1),
- pts2units(y2),
- pts2units(w3),
- col
- );
- afpDataStream.createLine(
- pts2units(xm2),
- pts2units(y1),
- pts2units(xm2),
- pts2units(y2),
- pts2units(w3),
- col
- );
- }
- break;
- case Constants.EN_DASHED:
- if (horz) {
- float w2 = 2 * h;
- while (x1 + w2 < x2) {
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(y1),
- pts2units(x1 + w2),
- pts2units(y1),
- pts2units(h),
- col
- );
- x1 += 2 * w2;
- }
- } else {
- float h2 = 2 * w;
- while (y1 + h2 < y2) {
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(y1),
- pts2units(x1),
- pts2units(y1 + h2),
- pts2units(w),
- col
- );
- y1 += 2 * h2;
- }
- }
- break;
- case Constants.EN_DOTTED:
- if (horz) {
- while (x1 + h < x2) {
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(y1),
- pts2units(x1 + h),
- pts2units(y1),
- pts2units(h),
- col
- );
- x1 += 2 * h;
- }
- } else {
- while (y1 + w < y2) {
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(y1),
- pts2units(x1),
- pts2units(y1 + w),
- pts2units(w),
- col
- );
- y1 += 2 * w;
- }
- }
- break;
- case Constants.EN_GROOVE:
- case Constants.EN_RIDGE:
- {
- float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f);
- if (horz) {
- Color uppercol = ColorUtil.lightenColor(col, -colFactor);
- Color lowercol = ColorUtil.lightenColor(col, colFactor);
- float h3 = h / 3;
- float ym1 = y1;
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(ym1),
- pts2units(x2),
- pts2units(ym1),
- pts2units(h3),
- uppercol
- );
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(ym1 + h3),
- pts2units(x2),
- pts2units(ym1 + h3),
- pts2units(h3),
- col
- );
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(ym1 + h3 + h3),
- pts2units(x2),
- pts2units(ym1 + h3 + h3),
- pts2units(h3),
- lowercol
- );
- } else {
- Color leftcol = ColorUtil.lightenColor(col, -colFactor);
- Color rightcol = ColorUtil.lightenColor(col, colFactor);
- float w3 = w / 3;
- float xm1 = x1 + (w3 / 2);
- afpDataStream.createLine(
- pts2units(xm1),
- pts2units(y1),
- pts2units(xm1),
- pts2units(y2),
- pts2units(w3),
- leftcol
- );
- afpDataStream.createLine(
- pts2units(xm1 + w3),
- pts2units(y1),
- pts2units(xm1 + w3),
- pts2units(y2),
- pts2units(w3),
- col
- );
- afpDataStream.createLine(
- pts2units(xm1 + w3 + w3),
- pts2units(y1),
- pts2units(xm1 + w3 + w3),
- pts2units(y2),
- pts2units(w3),
- rightcol
- );
- }
- break;
- }
- case Constants.EN_HIDDEN:
- break;
- case Constants.EN_INSET:
- case Constants.EN_OUTSET:
- default:
- afpDataStream.createLine(
- pts2units(x1),
- pts2units(y1),
- pts2units(horz ? x2 : x1),
- pts2units(horz ? y1 : y2),
- pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))),
- col
- );
- }
+ /** {@inheritDoc} */
+ protected RendererContext instantiateRendererContext() {
+ return new AFPRendererContext(this, getMimeType());
}
- /**
- * {@inheritDoc}
- */
- protected RendererContext createRendererContext(int x, int y, int width, int height,
- Map foreignAttributes) {
+ /** {@inheritDoc} */
+ protected RendererContext createRendererContext(int x, int y, int width,
+ int height, Map foreignAttributes) {
RendererContext context;
- context = super.createRendererContext(x, y, width, height, foreignAttributes);
- context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE,
- Boolean.valueOf(!this.colorImages));
+ context = super.createRendererContext(x, y, width, height,
+ foreignAttributes);
+ context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO,
+ this.fontInfo);
+ context.setProperty(AFPRendererContextConstants.AFP_RESOURCE_MANAGER,
+ this.resourceManager);
+ context.setProperty(AFPRendererContextConstants.AFP_PAINTING_STATE, paintingState);
return context;
}
- private static final ImageFlavor[] FLAVORS = new ImageFlavor[]
- {ImageFlavor.RAW_CCITTFAX,
- ImageFlavor.GRAPHICS2D,
- ImageFlavor.BUFFERED_IMAGE,
- ImageFlavor.RENDERED_IMAGE,
- ImageFlavor.XML_DOM};
+ private static final ImageFlavor[] NATIVE_FLAVORS = new ImageFlavor[] {
+ ImageFlavor.XML_DOM,
+ /*ImageFlavor.RAW_PNG, */ // PNG not natively supported in AFP
+ ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS,
+ ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };
+
+ private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+ ImageFlavor.XML_DOM,
+ ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };
/** {@inheritDoc} */
public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
uri = URISpecification.getURL(uri);
- Rectangle posInt = new Rectangle(
- (int)pos.getX(),
- (int)pos.getY(),
- (int)pos.getWidth(),
- (int)pos.getHeight());
+ paintingState.setImageUri(uri);
+
Point origin = new Point(currentIPPosition, currentBPPosition);
+ Rectangle posInt = new Rectangle(
+ (int)Math.round(pos.getX()),
+ (int)Math.round(pos.getY()),
+ (int)Math.round(pos.getWidth()),
+ (int)Math.round(pos.getHeight())
+ );
int x = origin.x + posInt.x;
int y = origin.y + posInt.y;
- String name = null;
- if (pageSegmentsMap != null) {
- name = (String) pageSegmentsMap.get(uri);
- }
+ String name = (String)pageSegmentMap.get(uri);
if (name != null) {
- afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y));
+ float[] srcPts = {x, y};
+ int[] coords = unitConv.mpts2units(srcPts);
+ dataStream.createIncludePageSegment(name, coords[X], coords[Y]);
} else {
- ImageManager manager = getUserAgent().getFactory().getImageManager();
+ ImageManager manager = userAgent.getFactory().getImageManager();
ImageInfo info = null;
try {
- ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
+ ImageSessionContext sessionContext = userAgent
+ .getImageSessionContext();
info = manager.getImageInfo(uri, sessionContext);
- //Only now fully load/prepare the image
+ // Only now fully load/prepare the image
Map hints = ImageUtil.getDefaultHints(sessionContext);
+
+ boolean nativeImagesSupported = paintingState.isNativeImagesSupported();
+ ImageFlavor[] flavors = nativeImagesSupported ? NATIVE_FLAVORS : FLAVORS;
+
+ // Load image
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
- info, FLAVORS, hints, sessionContext);
-
- //...and process the image
- if (img instanceof ImageGraphics2D) {
- ImageGraphics2D imageG2D = (ImageGraphics2D)img;
- RendererContext context = createRendererContext(
- posInt.x, posInt.y,
- posInt.width, posInt.height, foreignAttributes);
- getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(),
- context,
- origin.x + posInt.x, origin.y + posInt.y,
- posInt.width, posInt.height);
- } else if (img instanceof ImageRendered) {
- ImageRendered imgRend = (ImageRendered)img;
- RenderedImage ri = imgRend.getRenderedImage();
-
- drawBufferedImage(ri, getResolution(),
- posInt.x + currentIPPosition,
- posInt.y + currentBPPosition,
- posInt.width,
- posInt.height);
- } else if (img instanceof ImageRawCCITTFax) {
- ImageRawCCITTFax ccitt = (ImageRawCCITTFax)img;
- int afpx = mpts2units(posInt.x + currentIPPosition);
- int afpy = mpts2units(posInt.y + currentBPPosition);
- int afpw = mpts2units(posInt.getWidth());
- int afph = mpts2units(posInt.getHeight());
- int afpres = getResolution();
- ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph,
- afpres, afpres);
- io.setImageParameters(
- (int) (ccitt.getSize().getDpiHorizontal() * 10),
- (int) (ccitt.getSize().getDpiVertical() * 10),
- ccitt.getSize().getWidthPx(),
- ccitt.getSize().getHeightPx());
- int compression = ccitt.getCompression();
- switch (compression) {
- case TIFFImage.COMP_FAX_G3_1D :
- io.setImageEncoding((byte) 0x80);
- break;
- case TIFFImage.COMP_FAX_G3_2D :
- io.setImageEncoding((byte) 0x81);
- break;
- case TIFFImage.COMP_FAX_G4_2D :
- io.setImageEncoding((byte) 0x82);
- break;
- default:
- throw new IllegalStateException(
- "Invalid compression scheme: " + compression);
- }
- InputStream in = ccitt.createInputStream();
+ info, flavors, hints, sessionContext);
+
+ // Handle image
+ AFPImageHandler imageHandler
+ = (AFPImageHandler)imageHandlerRegistry.getHandler(img);
+ if (imageHandler != null) {
+ RendererContext rendererContext = createRendererContext(
+ x, y, posInt.width, posInt.height, foreignAttributes);
+ AFPRendererImageInfo rendererImageInfo = new AFPRendererImageInfo(
+ uri, pos, origin, info, img, rendererContext, foreignAttributes);
+ AFPDataObjectInfo dataObjectInfo = null;
try {
- byte[] buf = IOUtils.toByteArray(in);
- io.setImageData(buf);
- } finally {
- IOUtils.closeQuietly(in);
+ dataObjectInfo = imageHandler.generateDataObjectInfo(rendererImageInfo);
+ // Create image
+ if (dataObjectInfo != null) {
+ resourceManager.createObject(dataObjectInfo);
+ }
+ } catch (IOException ioe) {
+ ResourceEventProducer eventProducer
+ = ResourceEventProducer.Provider.get(userAgent.getEventBroadcaster());
+ eventProducer.imageWritingError(this, ioe);
+ throw ioe;
}
- } else if (img instanceof ImageXMLDOM) {
- ImageXMLDOM imgXML = (ImageXMLDOM)img;
- renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(),
- pos, foreignAttributes);
} else {
- throw new UnsupportedOperationException("Unsupported image type: " + img);
+ throw new UnsupportedOperationException(
+ "No AFPImageHandler available for image: "
+ + info + " (" + img.getClass().getName() + ")");
}
} catch (ImageException ie) {
- ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
- getUserAgent().getEventBroadcaster());
- eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider
+ .get(userAgent.getEventBroadcaster());
+ eventProducer.imageError(this, (info != null ? info.toString()
+ : uri), ie, null);
} catch (FileNotFoundException fe) {
- ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
- getUserAgent().getEventBroadcaster());
- eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider
+ .get(userAgent.getEventBroadcaster());
+ eventProducer.imageNotFound(this, (info != null ? info.toString()
+ : uri), fe, null);
} catch (IOException ioe) {
- ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
- getUserAgent().getEventBroadcaster());
- eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider
+ .get(userAgent.getEventBroadcaster());
+ eventProducer.imageIOError(this, (info != null ? info.toString()
+ : uri), ioe, null);
}
-
- /*
- ImageFactory fact = userAgent.getFactory().getImageFactory();
- FopImage fopimage = fact.getImage(url, userAgent);
- if (fopimage == null) {
- return;
- }
- if (!fopimage.load(FopImage.DIMENSIONS)) {
- return;
- }
- String mime = fopimage.getMimeType();
- if ("text/xml".equals(mime) || MimeConstants.MIME_SVG.equals(mime)) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
- }
- Document doc = ((XMLImage) fopimage).getDocument();
- String ns = ((XMLImage) fopimage).getNameSpace();
-
- renderDocument(doc, ns, pos, foreignAttributes);
- } else if (MimeConstants.MIME_EPS.equals(mime)) {
- log.warn("EPS images are not supported by this renderer");
- */
- /*
- * } else if (MimeConstants.MIME_JPEG.equals(mime)) { if
- * (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; }
- * fact.releaseImage(url, userAgent);
- *
- * int x = mpts2units(pos.getX() + currentIPPosition); int y =
- * mpts2units(pos.getY() + currentBPPosition); int w =
- * mpts2units(pos.getWidth()); int h =
- * mpts2units(pos.getHeight()); ImageObject io =
- * _afpDataStream.getImageObject(); io.setImageViewport(x, y, w,
- * h); io.setImageParameters(
- * (int)(fopimage.getHorizontalResolution() * 10),
- * (int)(fopimage.getVerticalResolution() * 10),
- * fopimage.getWidth(), fopimage.getHeight() );
- * io.setImageIDESize((byte)fopimage.getBitsPerPixel());
- * io.setImageEncoding((byte)0x83);
- * io.setImageData(fopimage.getRessourceBytes());
- *//*
- } else if (MimeConstants.MIME_TIFF.equals(mime)
- && fopimage instanceof TIFFImage) {
- TIFFImage tiffImage = (TIFFImage) fopimage;
- int x = mpts2units(pos.getX() + currentIPPosition);
- int y = mpts2units(pos.getY() + currentBPPosition);
- int w = mpts2units(pos.getWidth());
- int h = mpts2units(pos.getHeight());
- ImageObject io = afpDataStream.getImageObject(x, y, w, h,
- getResolution(), getResolution());
- io.setImageParameters(
- (int)(fopimage.getHorizontalResolution() * 10),
- (int)(fopimage.getVerticalResolution() * 10),
- fopimage.getWidth(),
- fopimage.getHeight()
- );
- if (tiffImage.getStripCount() == 1) {
- int comp = tiffImage.getCompression();
- if (comp == 3) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
- }
- io.setImageEncoding((byte)0x81);
- io.setImageData(fopimage.getRessourceBytes());
- } else if (comp == 4) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
- }
- io.setImageEncoding((byte)0x82);
- io.setImageData(fopimage.getRessourceBytes());
- } else {
- if (!fopimage.load(FopImage.BITMAP)) {
- return;
- }
- convertToGrayScaleImage(io, fopimage.getBitmaps(),
- fopimage.getWidth(), fopimage.getHeight());
- }
- } else {
- if (!fopimage.load(FopImage.BITMAP)) {
- return;
- }
- convertToGrayScaleImage(io, fopimage.getBitmaps(),
- fopimage.getWidth(), fopimage.getHeight());
- }
- } else {
- if (!fopimage.load(FopImage.BITMAP)) {
- return;
- }
- fact.releaseImage(url, userAgent);
-
- int x = mpts2units(pos.getX() + currentIPPosition);
- int y = mpts2units(pos.getY() + currentBPPosition);
- int w = mpts2units(pos.getWidth());
- int h = mpts2units(pos.getHeight());
- ImageObject io = afpDataStream.getImageObject(x, y, w, h,
- getResolution(), getResolution());
- io.setImageParameters(
- (int)(fopimage.getHorizontalResolution() * 10),
- (int)(fopimage.getVerticalResolution() * 10),
- fopimage.getWidth(),
- fopimage.getHeight()
- );
- if (colorImages) {
- io.setImageIDESize((byte)24);
- io.setImageData(fopimage.getBitmaps());
- } else {
- convertToGrayScaleImage(io, fopimage.getBitmaps(),
- fopimage.getWidth(), fopimage.getHeight());
- }
- }*/
}
}
@@ -1173,364 +465,155 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
* the OutputStream
* @throws IOException
* In case of an I/O error.
+ * @deprecated use ImageEncodingHelper.encodeRenderedImageAsRGB(image, out)
+ * directly instead
*/
public static void writeImage(RenderedImage image, OutputStream out)
throws IOException {
ImageEncodingHelper.encodeRenderedImageAsRGB(image, out);
}
- /**
- * Draws a BufferedImage to AFP.
- *
- * @param image
- * the RenderedImage
- * @param imageResolution
- * the resolution of the BufferedImage
- * @param x
- * the x coordinate (in mpt)
- * @param y
- * the y coordinate (in mpt)
- * @param w
- * the width of the viewport (in mpt)
- * @param h
- * the height of the viewport (in mpt)
- */
- public void drawBufferedImage(RenderedImage image, int imageResolution, int x,
- int y, int w, int h) {
- int afpx = mpts2units(x);
- int afpy = mpts2units(y);
- int afpw = mpts2units(w);
- int afph = mpts2units(h);
- int afpres = getResolution();
- ByteArrayOutputStream baout = new ByteArrayOutputStream();
- try {
- // Serialize image
- //TODO Eventually, this should be changed not to buffer as this increases the
- //memory consumption (see PostScript output)
- writeImage(image, baout);
- byte[] buf = baout.toByteArray();
-
- // Generate image
- ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw,
- afph, afpres, afpres);
- io.setImageParameters(imageResolution, imageResolution,
- image.getWidth(), image.getHeight());
- if (colorImages) {
- io.setImageIDESize((byte)24);
- io.setImageData(buf);
- } else {
- // TODO Teach it how to handle grayscale BufferedImages directly
- // because this is pretty inefficient
- convertToGrayScaleImage(io, buf,
- image.getWidth(), image.getHeight(), this.bitsPerPixel);
- }
- } catch (IOException ioe) {
- ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
- getUserAgent().getEventBroadcaster());
- eventProducer.imageWritingError(this, ioe);
- }
- }
-
- /**
- * Establishes a new foreground or fill color.
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void updateColor(Color col, boolean fill) {
if (fill) {
- currentColor = col;
+ paintingState.setColor(col);
}
}
/** {@inheritDoc} */
- public List breakOutOfStateStack() {
- log.debug("Block.FIXED --> break out");
- List breakOutList = new java.util.ArrayList();
- //Don't pop the last ViewPortPos (created by renderPage())
- while (this.viewPortPositions.size() > 1) {
- breakOutList.add(0, popViewPortPos());
- }
- return breakOutList;
+ public void restoreStateStackAfterBreakOut(List breakOutList) {
+ log.debug("Block.FIXED --> restoring context after break-out");
+ paintingState.saveAll(breakOutList);
}
/** {@inheritDoc} */
- public void restoreStateStackAfterBreakOut(List breakOutList) {
- log.debug("Block.FIXED --> restoring context after break-out");
- for (int i = 0, c = breakOutList.size(); i < c; i++) {
- ViewPortPos vps = (ViewPortPos)breakOutList.get(i);
- pushViewPortPos(vps);
- }
+ protected List breakOutOfStateStack() {
+ log.debug("Block.FIXED --> break out");
+ return paintingState.restoreAll();
}
- /** Saves the graphics state of the rendering engine. */
+ /** {@inheritDoc} */
public void saveGraphicsState() {
-
+ paintingState.save();
}
- /** Restores the last graphics state of the rendering engine. */
+ /** {@inheritDoc} */
public void restoreGraphicsState() {
-
+ paintingState.restore();
}
- /** Indicates the beginning of a text object. */
- public void beginTextObject() {
-
- }
-
- /** Indicates the end of a text object. */
- public void endTextObject() {
-
- }
-
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void renderImage(Image image, Rectangle2D pos) {
- String url = image.getURL();
- drawImage(url, pos);
+ drawImage(image.getURL(), pos, image.getForeignAttributes());
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void renderText(TextArea text) {
renderInlineAreaBackAndBorders(text);
- String name = getInternalFontNameForArea(text);
- currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
- AFPFont tf = (AFPFont) fontInfo.getFonts().get(name);
+ // set font size
+ int fontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
+ paintingState.setFontSize(fontSize);
- Color col = (Color) text.getTrait(Trait.COLOR);
+ // register font as necessary
+ String internalFontName = getInternalFontNameForArea(text);
+ Map/*<String,FontMetrics>*/ fontMetricMap = fontInfo.getFonts();
+ AFPFont font = (AFPFont)fontMetricMap.get(internalFontName);
+ AFPPageFonts pageFonts = paintingState.getPageFonts();
+ AFPFontAttributes fontAttributes = pageFonts.registerFont(internalFontName, font, fontSize);
- int vsci = mpts2units(tf.getWidth(' ', currentFontSize) / 1000
- + text.getTextWordSpaceAdjust()
- + text.getTextLetterSpaceAdjust());
+ // create text data info
+ AFPTextDataInfo textDataInfo = new AFPTextDataInfo();
- // word.getOffset() = only height of text itself
- // currentBlockIPPosition: 0 for beginning of line; nonzero
- // where previous line area failed to take up entire allocated space
- int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
- int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
+ int fontReference = fontAttributes.getFontReference();
+ textDataInfo.setFontReference(fontReference);
- // Set letterSpacing
- //float ls = fs.getLetterSpacing() / this.currentFontSize;
+ int x = (currentIPPosition + text.getBorderAndPaddingWidthStart());
+ int y = (currentBPPosition + text.getOffset() + text.getBaselineOffset());
- String worddata = text.getText();
+ int[] coords = unitConv.mpts2units(new float[] {x, y} );
+ textDataInfo.setX(coords[X]);
+ textDataInfo.setY(coords[Y]);
- // Create an AFPFontAttributes object from the current font details
- AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, tf, currentFontSize);
+ Color color = (Color) text.getTrait(Trait.COLOR);
+ textDataInfo.setColor(color);
- if (!currentPageFonts.containsKey(afpFontAttributes.getFontKey())) {
- // Font not found on current page, so add the new one
- pageFontCounter++;
- afpFontAttributes.setFontReference(pageFontCounter);
- currentPageFonts.put(
- afpFontAttributes.getFontKey(),
- afpFontAttributes);
+ int textWordSpaceAdjust = text.getTextWordSpaceAdjust();
+ int textLetterSpaceAdjust = text.getTextLetterSpaceAdjust();
+ int textWidth = font.getWidth(' ', fontSize) / 1000;
+ int variableSpaceCharacterIncrement
+ = textWidth + textWordSpaceAdjust + textLetterSpaceAdjust;
- } else {
- // Use the previously stored font attributes
- afpFontAttributes = (AFPFontAttributes) currentPageFonts.get(
- afpFontAttributes.getFontKey());
- }
+ variableSpaceCharacterIncrement
+ = Math.round(unitConv.mpt2units(variableSpaceCharacterIncrement));
+ textDataInfo.setVariableSpaceCharacterIncrement(variableSpaceCharacterIncrement);
- // Try and get the encoding to use for the font
- String encoding = null;
+ int interCharacterAdjustment
+ = Math.round(unitConv.mpt2units(textLetterSpaceAdjust));
+ textDataInfo.setInterCharacterAdjustment(interCharacterAdjustment);
- try {
- encoding = tf.getCharacterSet(currentFontSize).getEncoding();
- } catch (Throwable ex) {
- encoding = AFPConstants.EBCIDIC_ENCODING;
- log.warn(
- "renderText():: Error getting encoding for font '"
- + tf.getFullName()
- + "' - using default encoding "
- + encoding);
- }
+ CharacterSet charSet = font.getCharacterSet(fontSize);
+ String encoding = charSet.getEncoding();
+ textDataInfo.setEncoding(encoding);
+
+ String textString = text.getText();
+ textDataInfo.setString(textString);
try {
- afpDataStream.createText(
- afpFontAttributes.getFontReference(),
- mpts2units(rx),
- mpts2units(bl),
- col,
- vsci,
- mpts2units(text.getTextLetterSpaceAdjust()),
- worddata.getBytes(encoding));
- } catch (UnsupportedEncodingException usee) {
- log.error(
- "renderText:: Font "
- + afpFontAttributes.getFontKey()
- + " caused UnsupportedEncodingException");
+ dataStream.createText(textDataInfo);
+ } catch (UnsupportedEncodingException e) {
+ AFPEventProducer eventProducer
+ = AFPEventProducer.Provider.get(userAgent.getEventBroadcaster());
+ eventProducer.characterSetEncodingError(this, charSet.getName(), encoding);
}
+ // word.getOffset() = only height of text itself
+ // currentBlockIPPosition: 0 for beginning of line; nonzero
+ // where previous line area failed to take up entire allocated space
super.renderText(text);
- renderTextDecoration(tf, currentFontSize, text, bl, rx);
+ renderTextDecoration(font, fontSize, text, y, x);
}
/**
- * {@inheritDoc}
- */
- public void renderWord(WordArea word) {
- // UNUSED
- // String name = getInternalFontNameForArea(word.getParentArea());
- // int size = ((Integer)
- // word.getParentArea().getTrait(Trait.FONT_SIZE)).intValue();
- // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name);
- //
- // String s = word.getWord();
- //
- // FontMetrics metrics = fontInfo.getMetricsFor(name);
-
- super.renderWord(word);
- }
-
- /**
- * {@inheritDoc}
- */
- public void renderSpace(SpaceArea space) {
- // UNUSED
- // String name = getInternalFontNameForArea(space.getParentArea());
- // int size = ((Integer)
- // space.getParentArea().getTrait(Trait.FONT_SIZE)).intValue();
- // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name);
- //
- // String s = space.getSpace();
- //
- // FontMetrics metrics = fontInfo.getMetricsFor(name);
-
- super.renderSpace(space);
- }
-
- /**
- * Render leader area.
- * This renders a leader area which is an area with a rule.
- * @param area the leader area to render
+ * Render leader area. This renders a leader area which is an area with a
+ * rule.
+ *
+ * @param area
+ * the leader area to render
*/
public void renderLeader(Leader area) {
renderInlineAreaBackAndBorders(area);
int style = area.getRuleStyle();
- float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f;
+ float startx = (currentIPPosition + area
+ .getBorderAndPaddingWidthStart()) / 1000f;
float starty = (currentBPPosition + area.getOffset()) / 1000f;
- float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart()
- + area.getIPD()) / 1000f;
+ float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + area
+ .getIPD()) / 1000f;
float ruleThickness = area.getRuleThickness() / 1000f;
- Color col = (Color)area.getTrait(Trait.COLOR);
+ Color col = (Color) area.getTrait(Trait.COLOR);
switch (style) {
- case EN_SOLID:
- case EN_DASHED:
- case EN_DOUBLE:
- case EN_DOTTED:
- case EN_GROOVE:
- case EN_RIDGE:
- drawBorderLine(startx, starty, endx, starty + ruleThickness,
- true, true, style, col);
- break;
- default:
- throw new UnsupportedOperationException("rule style not supported");
+ case EN_SOLID:
+ case EN_DASHED:
+ case EN_DOUBLE:
+ case EN_DOTTED:
+ case EN_GROOVE:
+ case EN_RIDGE:
+ drawBorderLine(startx, starty, endx, starty + ruleThickness, true,
+ true, style, col);
+ break;
+ default:
+ throw new UnsupportedOperationException("rule style not supported");
}
super.renderLeader(area);
}
/**
- * Sets the AFPRenderer options
- * @param options the <code>Map</code> containing the options
- */
-// UNUSED
-// public void setOptions(Map options) {
-//
-// this.afpOptions = options;
-//
-// }
- /**
- * Determines the orientation from the string representation, this method
- * guarantees to return a value of either 0, 90, 180 or 270.
- *
- * @return the orientation
- */
-// UNUSED
-// private int getOrientation(String orientationString) {
-//
-// int orientation = 0;
-// if (orientationString != null && orientationString.length() > 0) {
-// try {
-// orientation = Integer.parseInt(orientationString);
-// } catch (NumberFormatException nfe) {
-// log.error("Cannot use orientation of " + orientation
-// + " defaulting to zero.");
-// orientation = 0;
-// }
-// } else {
-// orientation = 0;
-// }
-// switch (orientation) {
-// case 0:
-// break;
-// case 90:
-// break;
-// case 180:
-// break;
-// case 270:
-// break;
-// default:
-// log.error("Cannot use orientation of " + orientation
-// + " defaulting to zero.");
-// orientation = 0;
-// break;
-// }
-//
-// return orientation;
-//
-// }
- /**
- * Sets the rotation to be used for portrait pages, valid values are 0
- * (default), 90, 180, 270.
- *
- * @param rotation
- * The rotation in degrees.
- */
- public void setPortraitRotation(int rotation) {
-
- if (rotation == 0
- || rotation == 90
- || rotation == 180
- || rotation == 270) {
- portraitRotation = rotation;
- } else {
- throw new IllegalArgumentException("The portrait rotation must be one"
- + " of the values 0, 90, 180, 270");
-
- }
-
- }
-
- /**
- * Sets the rotation to be used for landsacpe pages, valid values are 0, 90,
- * 180, 270 (default).
- *
- * @param rotation
- * The rotation in degrees.
- */
- public void setLandscapeRotation(int rotation) {
-
- if (rotation == 0
- || rotation == 90
- || rotation == 180
- || rotation == 270) {
- landscapeRotation = rotation;
- } else {
- throw new IllegalArgumentException("The landscape rotation must be one"
- + " of the values 0, 90, 180, 270");
- }
-
- }
-
- /**
* Get the MIME type of the renderer.
*
- * @return The MIME type of the renderer
+ * @return The MIME type of the renderer
*/
public String getMimeType() {
return MimeConstants.MIME_AFP;
@@ -1540,46 +623,40 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
* Method to render the page extension.
* <p>
*
- * @param pageViewport the page object
+ * @param pageViewport
+ * the page object
*/
private void renderPageObjectExtensions(PageViewport pageViewport) {
-
- pageSegmentsMap = null;
+ pageSegmentMap.clear();
if (pageViewport.getExtensionAttachments() != null
&& pageViewport.getExtensionAttachments().size() > 0) {
// Extract all AFPPageSetup instances from the attachment list on
// the s-p-m
- Iterator i = pageViewport.getExtensionAttachments().iterator();
- while (i.hasNext()) {
- ExtensionAttachment attachment = (ExtensionAttachment)i.next();
+ Iterator it = pageViewport.getExtensionAttachments().iterator();
+ while (it.hasNext()) {
+ ExtensionAttachment attachment = (ExtensionAttachment) it.next();
if (AFPPageSetup.CATEGORY.equals(attachment.getCategory())) {
AFPPageSetup aps = (AFPPageSetup) attachment;
String element = aps.getElementName();
if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) {
String overlay = aps.getName();
if (overlay != null) {
- afpDataStream.createIncludePageOverlay(overlay);
+ dataStream.createIncludePageOverlay(overlay);
}
} else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT
.equals(element)) {
String name = aps.getName();
String source = aps.getValue();
- if (pageSegmentsMap == null) {
- pageSegmentsMap = new HashMap();
- }
- pageSegmentsMap.put(source, name);
+ pageSegmentMap.put(source, name);
} else if (AFPElementMapping.TAG_LOGICAL_ELEMENT
.equals(element)) {
String name = aps.getName();
String value = aps.getValue();
- if (pageSegmentsMap == null) {
- pageSegmentsMap = new HashMap();
- }
- afpDataStream.createTagLogicalElement(name, value);
+ dataStream.createTagLogicalElement(name, value);
} else if (AFPElementMapping.NO_OPERATION.equals(element)) {
String content = aps.getContent();
if (content != null) {
- afpDataStream.createNoOperation(content);
+ dataStream.createNoOperation(content);
}
}
}
@@ -1589,206 +666,25 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
}
/**
- * Converts FOP mpt measurement to afp measurement units
- * @param mpt the millipoints value
- */
- private int mpts2units(int mpt) {
- return mpts2units((double) mpt);
- }
-
- /**
- * Converts FOP pt measurement to afp measurement units
- * @param mpt the millipoints value
- */
- private int pts2units(float mpt) {
- return mpts2units(mpt * 1000d);
- }
-
- /**
- * Converts FOP mpt measurement to afp measurement units
+ * Sets the rotation to be used for portrait pages, valid values are 0
+ * (default), 90, 180, 270.
*
- * @param mpt
- * the millipoints value
- * @return afp measurement unit value
+ * @param rotation
+ * The rotation in degrees.
*/
- private int mpts2units(double mpt) {
- return (int)Math.round(mpt / (DPI_CONVERSION_FACTOR / getResolution()));
+ public void setPortraitRotation(int rotation) {
+ paintingState.setPortraitRotation(rotation);
}
/**
- * Converts a byte array containing 24 bit RGB image data to a grayscale
- * image.
+ * Sets the rotation to be used for landsacpe pages, valid values are 0, 90,
+ * 180, 270 (default).
*
- * @param io
- * the target image object
- * @param raw
- * the buffer containing the RGB image data
- * @param width
- * the width of the image in pixels
- * @param height
- * the height of the image in pixels
- * @param bitsPerPixel
- * the number of bits to use per pixel
+ * @param rotation
+ * The rotation in degrees.
*/
- protected static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width,
- int height, int bitsPerPixel) {
- int pixelsPerByte = 8 / bitsPerPixel;
- int bytewidth = (width / pixelsPerByte);
- if ((width % pixelsPerByte) != 0) {
- bytewidth++;
- }
- byte[] bw = new byte[height * bytewidth];
- byte ib;
- for (int y = 0; y < height; y++) {
- ib = 0;
- int i = 3 * y * width;
- for (int x = 0; x < width; x++, i += 3) {
-
- // see http://www.jguru.com/faq/view.jsp?EID=221919
- double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d
- * ((int) raw[i + 1] & 0xff) + 0.072169d
- * ((int) raw[i + 2] & 0xff);
- switch (bitsPerPixel) {
- case 1:
- if (greyVal < 128) {
- ib |= (byte) (1 << (7 - (x % 8)));
- }
- break;
- case 4:
- greyVal /= 16;
- ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4));
- break;
- case 8:
- ib = (byte) greyVal;
- break;
- default:
- throw new UnsupportedOperationException(
- "Unsupported bits per pixel: " + bitsPerPixel);
- }
-
- if ((x % pixelsPerByte) == (pixelsPerByte - 1)
- || ((x + 1) == width)) {
- bw[(y * bytewidth) + (x / pixelsPerByte)] = ib;
- ib = 0;
- }
- }
- }
- io.setImageIDESize((byte) bitsPerPixel);
- io.setImageData(bw);
- }
-
- private final class ViewPortPos {
- private int x = 0;
-
- private int y = 0;
-
- private int rot = 0;
-
- private ViewPortPos() {
- }
-
- private ViewPortPos(Rectangle2D view, CTM ctm) {
- ViewPortPos currentVP = (ViewPortPos) viewPortPositions
- .get(viewPortPositions.size() - 1);
- int xOrigin;
- int yOrigin;
- int width;
- int height;
- switch (currentVP.rot) {
- case 90:
- width = mpts2units(view.getHeight());
- height = mpts2units(view.getWidth());
- xOrigin = pageWidth - width - mpts2units(view.getY())
- - currentVP.y;
- yOrigin = mpts2units(view.getX()) + currentVP.x;
- break;
- case 180:
- width = mpts2units(view.getWidth());
- height = mpts2units(view.getHeight());
- xOrigin = pageWidth - width - mpts2units(view.getX())
- - currentVP.x;
- yOrigin = pageHeight - height - mpts2units(view.getY())
- - currentVP.y;
- break;
- case 270:
- width = mpts2units(view.getHeight());
- height = mpts2units(view.getWidth());
- xOrigin = mpts2units(view.getY()) + currentVP.y;
- yOrigin = pageHeight - height - mpts2units(view.getX())
- - currentVP.x;
- break;
- default:
- xOrigin = mpts2units(view.getX()) + currentVP.x;
- yOrigin = mpts2units(view.getY()) + currentVP.y;
- width = mpts2units(view.getWidth());
- height = mpts2units(view.getHeight());
- break;
- }
- this.rot = currentVP.rot;
- double[] ctmf = ctm.toArray();
- if (ctmf[0] == 0.0d && ctmf[1] == -1.0d && ctmf[2] == 1.0d
- && ctmf[3] == 0.d) {
- this.rot += 270;
- } else if (ctmf[0] == -1.0d && ctmf[1] == 0.0d && ctmf[2] == 0.0d
- && ctmf[3] == -1.0d) {
- this.rot += 180;
- } else if (ctmf[0] == 0.0d && ctmf[1] == 1.0d && ctmf[2] == -1.0d
- && ctmf[3] == 0.0d) {
- this.rot += 90;
- }
- this.rot %= 360;
- switch (this.rot) {
- /*
- * case 0: this.x = mpts2units(view.getX()) + x; this.y =
- * mpts2units(view.getY()) + y; break; case 90: this.x =
- * mpts2units(view.getY()) + y; this.y = _pageWidth -
- * mpts2units(view.getX() + view.getWidth()) - x; break; case 180:
- * this.x = _pageWidth - mpts2units(view.getX() + view.getWidth()) -
- * x; this.y = _pageHeight - mpts2units(view.getY() +
- * view.getHeight()) - y; break; case 270: this.x = _pageHeight -
- * mpts2units(view.getY() + view.getHeight()) - y; this.y =
- * mpts2units(view.getX()) + x; break;
- */
- case 0:
- this.x = xOrigin;
- this.y = yOrigin;
- break;
- case 90:
- this.x = yOrigin;
- this.y = pageWidth - width - xOrigin;
- break;
- case 180:
- this.x = pageWidth - width - xOrigin;
- this.y = pageHeight - height - yOrigin;
- break;
- case 270:
- this.x = pageHeight - height - yOrigin;
- this.y = xOrigin;
- break;
- default:
- }
- }
-
- public String toString() {
- return "x:" + x + " y:" + y + " rot:" + rot;
- }
-
- }
-
- private List viewPortPositions = new ArrayList();
-
- private void pushViewPortPos(ViewPortPos vpp) {
- viewPortPositions.add(vpp);
- afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot);
- }
-
- private ViewPortPos popViewPortPos() {
- ViewPortPos current = (ViewPortPos)viewPortPositions.remove(viewPortPositions.size() - 1);
- if (viewPortPositions.size() > 0) {
- ViewPortPos vpp = (ViewPortPos)viewPortPositions.get(viewPortPositions.size() - 1);
- afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot);
- }
- return current;
+ public void setLandscapeRotation(int rotation) {
+ paintingState.setLandscapeRotation(rotation);
}
/**
@@ -1798,17 +694,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
* number of bits per pixel
*/
public void setBitsPerPixel(int bitsPerPixel) {
- this.bitsPerPixel = bitsPerPixel;
- switch (bitsPerPixel) {
- case 1:
- case 4:
- case 8:
- break;
- default:
- log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
- bitsPerPixel = 8;
- break;
- }
+ paintingState.setBitsPerPixel(bitsPerPixel);
}
/**
@@ -1818,7 +704,17 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
* color image output
*/
public void setColorImages(boolean colorImages) {
- this.colorImages = colorImages;
+ paintingState.setColorImages(colorImages);
+ }
+
+ /**
+ * Sets whether images are supported natively or not
+ *
+ * @param nativeImages
+ * native image support
+ */
+ public void setNativeImagesSupported(boolean nativeImages) {
+ paintingState.setNativeImagesSupported(nativeImages);
}
/**
@@ -1828,17 +724,73 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
* the output resolution (dpi)
*/
public void setResolution(int resolution) {
- if (log.isDebugEnabled()) {
- log.debug("renderer-resolution set to: " + resolution + "dpi");
- }
- this.resolution = resolution;
+ paintingState.setResolution(resolution);
}
/**
* Returns the output/device resolution.
+ *
* @return the resolution in dpi
*/
public int getResolution() {
- return this.resolution;
+ return paintingState.getResolution();
+ }
+
+ /**
+ * Sets the default resource group file path
+ * @param filePath the default resource group file path
+ */
+ public void setDefaultResourceGroupFilePath(String filePath) {
+ resourceManager.setDefaultResourceGroupFilePath(filePath);
+ }
+
+ /** {@inheritDoc} */
+ protected void establishTransformationMatrix(AffineTransform at) {
+ saveGraphicsState();
+ concatenateTransformationMatrix(at);
}
+
+ /** {@inheritDoc} */
+ public void clip() {
+ // TODO
+// log.debug("NYI clip()");
+ }
+
+ /** {@inheritDoc} */
+ public void clipRect(float x, float y, float width, float height) {
+ // TODO
+// log.debug("NYI clipRect(x=" + x + ",y=" + y
+// + ",width=" + width + ", height=" + height + ")");
+ }
+
+ /** {@inheritDoc} */
+ public void moveTo(float x, float y) {
+ // TODO
+// log.debug("NYI moveTo(x=" + x + ",y=" + y + ")");
+ }
+
+ /** {@inheritDoc} */
+ public void lineTo(float x, float y) {
+ // TODO
+// log.debug("NYI lineTo(x=" + x + ",y=" + y + ")");
+ }
+
+ /** {@inheritDoc} */
+ public void closePath() {
+ // TODO
+// log.debug("NYI closePath()");
+ }
+
+ /** Indicates the beginning of a text object. */
+ public void beginTextObject() {
+ //TODO PDF specific maybe?
+// log.debug("NYI beginTextObject()");
+ }
+
+ /** Indicates the end of a text object. */
+ public void endTextObject() {
+ //TODO PDF specific maybe?
+// log.debug("NYI endTextObject()");
+ }
+
}
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
index 65e39daad..5982ae5b0 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
@@ -19,10 +19,17 @@
package org.apache.fop.render.afp;
+import java.io.File;
import java.util.List;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
+
+import org.apache.fop.afp.fonts.AFPFontInfo;
+import org.apache.fop.afp.fonts.CharacterSet;
+import org.apache.fop.afp.fonts.FopCharacterSet;
+import org.apache.fop.afp.fonts.OutlineFont;
+import org.apache.fop.afp.fonts.RasterFont;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontTriplet;
@@ -30,11 +37,6 @@ import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;
-import org.apache.fop.render.afp.fonts.AFPFontInfo;
-import org.apache.fop.render.afp.fonts.CharacterSet;
-import org.apache.fop.render.afp.fonts.FopCharacterSet;
-import org.apache.fop.render.afp.fonts.OutlineFont;
-import org.apache.fop.render.afp.fonts.RasterFont;
import org.apache.fop.util.LogUtil;
/**
@@ -44,6 +46,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
/**
* Default constructor
+ *
* @param userAgent user agent
*/
public AFPRendererConfigurator(FOUserAgent userAgent) {
@@ -54,16 +57,17 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
throws ConfigurationException {
Configuration[] triple = fontCfg.getChildren("font-triplet");
- List tripleList = new java.util.ArrayList();
+ List/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/();
if (triple.length == 0) {
log.error("Mandatory font configuration element '<font-triplet...' is missing");
return null;
}
for (int j = 0; j < triple.length; j++) {
int weight = FontUtil.parseCSS2FontWeight(triple[j].getAttribute("weight"));
- tripleList.add(new FontTriplet(triple[j].getAttribute("name"),
- triple[j].getAttribute("style"),
- weight));
+ FontTriplet triplet = new FontTriplet(triple[j].getAttribute("name"),
+ triple[j].getAttribute("style"),
+ weight);
+ tripletList.add(triplet);
}
//build the fonts
@@ -121,7 +125,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
try {
Typeface tf = (Typeface)clazz.newInstance();
font.addCharacterSet(size, new FopCharacterSet(
- codepage, encoding, characterset, size, tf));
+ codepage, encoding, characterset, tf));
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
+ " could not be instantiated";
@@ -137,21 +141,17 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
codepage, encoding, characterset, path));
}
}
- return new AFPFontInfo(font, tripleList);
+ return new AFPFontInfo(font, tripletList);
} else if ("outline".equalsIgnoreCase(type)) {
-
String characterset = afpFontCfg.getAttribute("characterset");
if (characterset == null) {
log.error("Mandatory afp-font configuration attribute 'characterset=' is missing");
return null;
}
String name = afpFontCfg.getAttribute("name", characterset);
-
CharacterSet characterSet = null;
-
String base14 = afpFontCfg.getAttribute("base14-font", null);
-
if (base14 != null) {
try {
Class clazz = Class.forName("org.apache.fop.fonts.base14."
@@ -159,7 +159,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
try {
Typeface tf = (Typeface)clazz.newInstance();
characterSet = new FopCharacterSet(
- codepage, encoding, characterset, 1, tf);
+ codepage, encoding, characterset, tf);
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
+ " could not be instantiated";
@@ -175,7 +175,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
}
// Create a new font object
OutlineFont font = new OutlineFont(name, characterSet);
- return new AFPFontInfo(font, tripleList);
+ return new AFPFontInfo(font, tripletList);
} else {
log.error("No or incorrect type attribute");
}
@@ -184,36 +184,45 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
/**
* Builds a list of AFPFontInfo objects for use with the setup() method.
+ *
* @param cfg Configuration object
* @return List the newly created list of fonts
* @throws ConfigurationException if something's wrong with the config data
*/
- private List buildFontListFromConfiguration(Configuration cfg)
+ private List/*<AFPFontInfo>*/ buildFontListFromConfiguration(Configuration cfg)
throws ConfigurationException {
- List fontList = new java.util.ArrayList();
+ List/*<AFPFontInfo>*/ fontList = new java.util.ArrayList();
Configuration[] font = cfg.getChild("fonts").getChildren("font");
+ final String fontPath = null;
for (int i = 0; i < font.length; i++) {
- AFPFontInfo afi = buildFont(font[i], null);
+ AFPFontInfo afi = buildFont(font[i], fontPath);
if (afi != null) {
if (log.isDebugEnabled()) {
log.debug("Adding font " + afi.getAFPFont().getFontName());
- for (int j = 0; j < afi.getFontTriplets().size(); ++j) {
- FontTriplet triplet = (FontTriplet) afi.getFontTriplets().get(j);
+ List/*<FontTriplet>*/ fontTriplets = afi.getFontTriplets();
+ for (int j = 0; j < fontTriplets.size(); ++j) {
+ FontTriplet triplet = (FontTriplet) fontTriplets.get(j);
log.debug(" Font triplet "
+ triplet.getName() + ", "
+ triplet.getStyle() + ", "
+ triplet.getWeight());
}
}
-
fontList.add(afi);
}
}
return fontList;
}
+ /** images are converted to grayscale bitmapped IOCA */
+ private static final String IMAGES_MODE_GRAYSCALE = "b+w";
+
+ /** images are converted to color bitmapped IOCA */
+ private static final String IMAGES_MODE_COLOR = "color";
+
/**
* Configure the AFP renderer.
+ *
* @param renderer AFP renderer
* @throws FOPException fop exception
* @see org.apache.fop.render.PrintRendererConfigurator#configure(Renderer)
@@ -223,24 +232,56 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
if (cfg != null) {
AFPRenderer afpRenderer = (AFPRenderer)renderer;
try {
- List fontList = buildFontListFromConfiguration(cfg);
+ List/*<AFPFontInfo>*/ fontList = buildFontListFromConfiguration(cfg);
afpRenderer.setFontList(fontList);
} catch (ConfigurationException e) {
LogUtil.handleException(log, e,
userAgent.getFactory().validateUserConfigStrictly());
}
+ // image information
Configuration imagesCfg = cfg.getChild("images");
- if (!"color".equalsIgnoreCase(imagesCfg.getAttribute("mode", "b+w"))) {
- afpRenderer.setBitsPerPixel(imagesCfg.getAttributeAsInteger("bits-per-pixel", 8));
- } else {
+
+ // default to grayscale images
+ String imagesMode = imagesCfg.getAttribute("mode", IMAGES_MODE_GRAYSCALE);
+ if (IMAGES_MODE_COLOR.equals(imagesMode)) {
afpRenderer.setColorImages(true);
+ } else {
+ afpRenderer.setColorImages(false);
+ // default to 8 bits per pixel
+ int bitsPerPixel = imagesCfg.getAttributeAsInteger("bits-per-pixel", 8);
+ afpRenderer.setBitsPerPixel(bitsPerPixel);
}
+ // native image support
+ boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false);
+ afpRenderer.setNativeImagesSupported(nativeImageSupport);
+
+ // renderer resolution
Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false);
if (rendererResolutionCfg != null) {
afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240));
}
+
+ // a default external resource group file setting
+ Configuration resourceGroupFileCfg
+ = cfg.getChild("resource-group-file", false);
+ if (resourceGroupFileCfg != null) {
+ String resourceGroupDest = null;
+ try {
+ resourceGroupDest = resourceGroupFileCfg.getValue();
+ } catch (ConfigurationException e) {
+ LogUtil.handleException(log, e,
+ userAgent.getFactory().validateUserConfigStrictly());
+ }
+ File resourceGroupFile = new File(resourceGroupDest);
+ if (resourceGroupFile.canWrite()) {
+ afpRenderer.setDefaultResourceGroupFilePath(resourceGroupDest);
+ } else {
+ log.warn("Unable to write to default external resource group file '"
+ + resourceGroupDest + "'");
+ }
+ }
}
}
}
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererContext.java b/src/java/org/apache/fop/render/afp/AFPRendererContext.java
new file mode 100644
index 000000000..8d544a7c4
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPRendererContext.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.fop.afp.AFPResourceManager;
+import org.apache.fop.render.AbstractRenderer;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererContextConstants;
+
+public class AFPRendererContext extends RendererContext {
+
+ /**
+ * Main constructor
+ *
+ * @param renderer the current renderer
+ * @param mime the MIME type of the output that's generated.
+ */
+ public AFPRendererContext(AbstractRenderer renderer, String mime) {
+ super(renderer, mime);
+ }
+
+ /**
+ * Returns a new AFPInfo for this renderer context
+ *
+ * @return an AFPInfo for this renderer context
+ */
+ public AFPInfo getInfo() {
+ AFPInfo info = new AFPInfo();
+ info.setWidth(((Integer)getProperty(RendererContextConstants.WIDTH)).intValue());
+ info.setHeight(((Integer)getProperty(RendererContextConstants.HEIGHT)).intValue());
+ info.setX(((Integer)getProperty(RendererContextConstants.XPOS)).intValue());
+ info.setY(((Integer)getProperty(RendererContextConstants.YPOS)).intValue());
+ info.setHandlerConfiguration((Configuration)getProperty(
+ RendererContextConstants.HANDLER_CONFIGURATION));
+ info.setFontInfo((org.apache.fop.fonts.FontInfo)getProperty(
+ AFPRendererContextConstants.AFP_FONT_INFO));
+ info.setPaintingState((AFPPaintingState)getProperty(
+ AFPRendererContextConstants.AFP_PAINTING_STATE));
+ info.setResourceManager(((AFPResourceManager)getProperty(
+ AFPRendererContextConstants.AFP_RESOURCE_MANAGER)));
+
+ Map foreignAttributes = (Map)getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
+ if (foreignAttributes != null) {
+ String conversionMode = (String)foreignAttributes.get(CONVERSION_MODE);
+ boolean paintAsBitmap = BITMAP.equalsIgnoreCase(conversionMode);
+ info.setPaintAsBitmap(paintAsBitmap);
+
+ AFPForeignAttributeReader foreignAttributeReader
+ = new AFPForeignAttributeReader();
+ AFPResourceInfo resourceInfo
+ = foreignAttributeReader.getResourceInfo(foreignAttributes);
+ // default to inline level if painted as GOCA
+ if (!resourceInfo.levelChanged() && !paintAsBitmap) {
+ resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
+ }
+ info.setResourceInfo(resourceInfo);
+ }
+ return info;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java b/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java
index 428e5b1ca..3302b7f3c 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java
@@ -32,4 +32,12 @@ public interface AFPRendererContextConstants extends RendererContextConstants {
*/
String AFP_GRAYSCALE = "afpGrayscale";
+ /** The font information for the AFP renderer. */
+ String AFP_FONT_INFO = "afpFontInfo";
+
+ /** The afp resource manager */
+ String AFP_RESOURCE_MANAGER = "afpResourceManager";
+
+ /** The afp painting state */
+ String AFP_PAINTING_STATE = "afpPaintingState";
}
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java
new file mode 100644
index 000000000..2687d9071
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.Point;
+import java.awt.geom.Rectangle2D;
+import java.util.Map;
+
+import org.apache.fop.render.RendererContext;
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+
+/**
+ * The AFP image information
+ */
+public class AFPRendererImageInfo {
+
+ /** the image uri */
+ protected final String uri;
+
+ /** the current pos */
+ protected final Rectangle2D pos;
+
+ /** the origin */
+ protected final Point origin;
+
+ /** the foreign attributes */
+ protected final Map foreignAttributes;
+
+ /** the image info */
+ protected final ImageInfo info;
+
+ /** the image */
+ protected final Image img;
+
+ /** the renderer context */
+ protected RendererContext rendererContext;
+
+ /**
+ * Main constructor
+ *
+ * @param uri the image uri
+ * @param pos the image content area
+ * @param origin the current position
+ * @param info the image info
+ * @param img the image
+ * @param rendererContext the renderer context
+ * @param foreignAttributes the foreign attributes
+ */
+ public AFPRendererImageInfo(String uri, Rectangle2D pos, Point origin,
+ ImageInfo info, Image img, RendererContext rendererContext, Map foreignAttributes) {
+ this.uri = uri;
+ this.pos = pos;
+ this.origin = origin;
+ this.info = info;
+ this.img = img;
+ this.rendererContext = rendererContext;
+ this.foreignAttributes = foreignAttributes;
+ }
+
+ /**
+ * Sets the renderer context
+ *
+ * @param rendererContext the renderer context
+ */
+ public void setRendererContext(RendererContext rendererContext) {
+ this.rendererContext = rendererContext;
+ }
+
+ /**
+ * Returns the image info
+ *
+ * @return the image info
+ */
+ public ImageInfo getImageInfo() {
+ return this.info;
+ }
+
+ /**
+ * Returns the image
+ *
+ * @return the image
+ */
+ public Image getImage() {
+ return this.img;
+ }
+
+ /**
+ * Returns the renderer context
+ *
+ * @return the renderer context
+ */
+ public RendererContext getRendererContext() {
+ return this.rendererContext;
+ }
+
+ /**
+ * Return the foreign attributes
+ * @return the foreign attributes
+ */
+ public Map getForeignAttributes() {
+ return this.foreignAttributes;
+ }
+
+ /**
+ * Return the uri
+ *
+ * @return the uri
+ */
+ public String getURI() {
+ return this.uri;
+ }
+
+ /**
+ * Return the origin
+ *
+ * @return the origin
+ */
+ public Point getOrigin() {
+ return this.origin;
+ }
+
+ /**
+ * Return the position
+ *
+ * @return the position
+ */
+ public Rectangle2D getPosition() {
+ return this.pos;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPRendererImageInfo{\n"
+ + "\turi=" + uri + ",\n"
+ + "\tinfo=" + info + ",\n"
+ + "\tpos=" + pos + ",\n"
+ + "\torigin=" + origin + ",\n"
+ + "\timg=" + img + ",\n"
+ + "\tforeignAttributes=" + foreignAttributes + ",\n"
+ + "\trendererContext=" + rendererContext + "\n"
+ + "}";
+
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
index 5f077fdc6..161217a54 100644
--- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
@@ -20,9 +20,39 @@
package org.apache.fop.render.afp;
// FOP
+import java.awt.Dimension;
+import java.awt.geom.AffineTransform;
+import java.io.IOException;
+
+import org.w3c.dom.Document;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.gvt.GraphicsNode;
+
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.afp.AFPGraphicsObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceManager;
+import org.apache.fop.afp.AFPUnitConverter;
+import org.apache.fop.afp.svg.AFPBridgeContext;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.image.loader.batik.BatikUtil;
+import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl;
import org.apache.fop.render.AbstractGenericSVGHandler;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererContext.RendererContextWrapper;
+import org.apache.fop.svg.SVGEventProducer;
+import org.apache.fop.svg.SVGUserAgent;
/**
* AFP XML handler for SVG. Uses Apache Batik for SVG processing.
@@ -31,6 +61,151 @@ import org.apache.fop.render.RendererContext;
*/
public class AFPSVGHandler extends AbstractGenericSVGHandler {
+ private boolean paintAsBitmap = false;
+
+ /** {@inheritDoc} */
+ public void handleXML(RendererContext context,
+ Document doc, String ns) throws Exception {
+ if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) {
+ renderSVGDocument(context, doc);
+ }
+ }
+
+ /**
+ * Render the SVG document.
+ *
+ * @param rendererContext the renderer context
+ * @param doc the SVG document
+ * @throws IOException In case of an I/O error while painting the image
+ */
+ protected void renderSVGDocument(final RendererContext rendererContext,
+ final Document doc) throws IOException {
+
+ AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext;
+ AFPInfo afpInfo = afpRendererContext.getInfo();
+
+ this.paintAsBitmap = afpInfo.paintAsBitmap();
+
+ FOUserAgent userAgent = rendererContext.getUserAgent();
+
+ // fallback paint as bitmap
+ String uri = getDocumentURI(doc);
+ if (paintAsBitmap) {
+ try {
+ super.renderSVGDocument(rendererContext, doc);
+ } catch (IOException ioe) {
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+ userAgent.getEventBroadcaster());
+ eventProducer.svgRenderingError(this, ioe, uri);
+ }
+ return;
+ }
+
+ // Create a new AFPGraphics2D
+ final boolean textAsShapes = afpInfo.strokeText();
+ AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);
+
+ AFPPaintingState paintingState = g2d.getPaintingState();
+ paintingState.setImageUri(uri);
+
+ // Create an AFPBridgeContext
+ BridgeContext bridgeContext = createBridgeContext(userAgent, g2d);
+
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+ //to it.
+ Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
+
+ // Build the SVG DOM and provide the painter with it
+ GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, clonedDoc);
+
+ // Create Graphics2DImagePainter
+ final RendererContextWrapper wrappedContext
+ = RendererContext.wrapRendererContext(rendererContext);
+ Dimension imageSize = getImageSize(wrappedContext);
+ Graphics2DImagePainter painter
+ = createGrapics2DImagePainter(bridgeContext, root, imageSize);
+
+ // Create AFPObjectAreaInfo
+ RendererContextWrapper rctx = RendererContext.wrapRendererContext(rendererContext);
+ int x = rctx.getCurrentXPosition();
+ int y = rctx.getCurrentYPosition();
+ int width = afpInfo.getWidth();
+ int height = afpInfo.getHeight();
+ int resolution = afpInfo.getResolution();
+
+ paintingState.save(); // save
+
+ AFPObjectAreaInfo objectAreaInfo
+ = createObjectAreaInfo(paintingState, x, y, width, height, resolution);
+
+ // Create AFPGraphicsObjectInfo
+ AFPResourceInfo resourceInfo = afpInfo.getResourceInfo();
+ AFPGraphicsObjectInfo graphicsObjectInfo = createGraphicsObjectInfo(
+ paintingState, painter, userAgent, resourceInfo, g2d);
+ graphicsObjectInfo.setObjectAreaInfo(objectAreaInfo);
+
+ // Create the GOCA GraphicsObject in the DataStream
+ AFPResourceManager resourceManager = afpInfo.getResourceManager();
+ resourceManager.createObject(graphicsObjectInfo);
+
+ paintingState.restore(); // resume
+ }
+
+ private AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState,
+ int x, int y, int width, int height, int resolution) {
+ // set the data object parameters
+ AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
+
+ AffineTransform at = paintingState.getData().getTransform();
+ at.translate(x, y);
+ objectAreaInfo.setX((int)Math.round(at.getTranslateX()));
+ objectAreaInfo.setY((int)Math.round(at.getTranslateY()));
+
+ objectAreaInfo.setWidthRes(resolution);
+ objectAreaInfo.setHeightRes(resolution);
+
+ AFPUnitConverter unitConv = paintingState.getUnitConverter();
+ objectAreaInfo.setWidth(Math.round(unitConv.mpt2units(width)));
+ objectAreaInfo.setHeight(Math.round(unitConv.mpt2units(height)));
+
+ int rotation = paintingState.getRotation();
+ objectAreaInfo.setRotation(rotation);
+
+ return objectAreaInfo;
+ }
+
+ private AFPGraphicsObjectInfo createGraphicsObjectInfo(AFPPaintingState paintingState, Graphics2DImagePainter painter,
+ FOUserAgent userAgent, AFPResourceInfo resourceInfo, AFPGraphics2D g2d) {
+ AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();
+
+ String uri = paintingState.getImageUri();
+ graphicsObjectInfo.setUri(uri);
+
+ graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);
+
+ graphicsObjectInfo.setResourceInfo(resourceInfo);
+
+ graphicsObjectInfo.setPainter(painter);
+
+ // Set the afp graphics 2d implementation
+ graphicsObjectInfo.setGraphics2D(g2d);
+
+ return graphicsObjectInfo;
+ }
+
+ public static BridgeContext createBridgeContext(FOUserAgent userAgent, AFPGraphics2D g2d) {
+ ImageManager imageManager = userAgent.getFactory().getImageManager();
+
+ SVGUserAgent svgUserAgent
+ = new SVGUserAgent(userAgent, new AffineTransform());
+
+ ImageSessionContext imageSessionContext = userAgent.getImageSessionContext();
+
+ FontInfo fontInfo = g2d.getFontInfo();
+ return new AFPBridgeContext(svgUserAgent, fontInfo, imageManager, imageSessionContext,
+ new AffineTransform(), g2d);
+ }
+
/** {@inheritDoc} */
public boolean supportsRenderer(Renderer renderer) {
return (renderer instanceof AFPRenderer);
@@ -39,9 +214,29 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler {
/** {@inheritDoc} */
protected void updateRendererContext(RendererContext context) {
//Work around a problem in Batik: Gradients cannot be done in ColorSpace.CS_GRAY
- context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE,
- Boolean.FALSE);
+ context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, Boolean.FALSE);
}
-}
+ /** {@inheritDoc} */
+ protected Graphics2DImagePainter createGrapics2DImagePainter(BridgeContext ctx, GraphicsNode root, Dimension imageSize) {
+ Graphics2DImagePainter painter = null;
+ if (paintAsBitmap()) {
+ // paint as IOCA Image
+ painter = super.createGraphics2DImagePainter(root, ctx, imageSize);
+ } else {
+ // paint as GOCA Graphics
+ painter = new Graphics2DImagePainterImpl(root, ctx, imageSize);
+ }
+ return painter;
+ }
+ /**
+ * Returns true if the SVG is to be painted as a bitmap
+ *
+ * @return true if the SVG is to be painted as a bitmap
+ */
+ private boolean paintAsBitmap() {
+ return paintAsBitmap;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AbstractAFPImageHandlerRawStream.java b/src/java/org/apache/fop/render/afp/AbstractAFPImageHandlerRawStream.java
new file mode 100644
index 000000000..ae8ac9950
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AbstractAFPImageHandlerRawStream.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
+
+/**
+ * A base abstract AFP raw stream image handler
+ */
+public abstract class AbstractAFPImageHandlerRawStream extends AFPImageHandler {
+
+ /** {@inheritDoc} */
+ public AFPDataObjectInfo generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+ AFPDataObjectInfo dataObjectInfo = super.generateDataObjectInfo(rendererImageInfo);
+
+ ImageInfo imageInfo = rendererImageInfo.getImageInfo();
+ String mimeType = imageInfo.getMimeType();
+ if (mimeType != null) {
+ dataObjectInfo.setMimeType(mimeType);
+ }
+ ImageRawStream rawStream = (ImageRawStream) rendererImageInfo.getImage();
+ InputStream inputStream = rawStream.createInputStream();
+ try {
+ dataObjectInfo.setData(IOUtils.toByteArray(inputStream));
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ }
+
+ int dataHeight = rawStream.getSize().getHeightPx();
+ dataObjectInfo.setDataHeight(dataHeight);
+
+ int dataWidth = rawStream.getSize().getWidthPx();
+ dataObjectInfo.setDataWidth(dataWidth);
+
+ ImageSize imageSize = rawStream.getSize();
+ dataObjectInfo.setDataHeightRes((int) (imageSize.getDpiHorizontal() * 10));
+ dataObjectInfo.setDataWidthRes((int) (imageSize.getDpiVertical() * 10));
+
+ // set object area info
+ AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
+ AFPRendererContext rendererContext
+ = (AFPRendererContext)rendererImageInfo.getRendererContext();
+ AFPInfo afpInfo = rendererContext.getInfo();
+ AFPPaintingState paintingState = afpInfo.getPaintingState();
+ int resolution = paintingState.getResolution();
+ objectAreaInfo.setWidthRes(resolution);
+ objectAreaInfo.setHeightRes(resolution);
+
+ return dataObjectInfo;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java
index 665a77562..6b4bc4eb9 100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java
@@ -19,14 +19,13 @@
package org.apache.fop.render.afp.extensions;
-import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.StringProperty;
/**
* This class extends the org.apache.fop.fo.StringProperty.Maker inner class
- * in order to provide a static property maker. The object faciliates
+ * in order to provide a static property maker. The object facilitates
* extraction of attributes from formatted objects based on the static list
* as defined in the AFPElementMapping implementation.
* <p/>
@@ -58,5 +57,4 @@ public class AFPAttribute extends StringProperty.Maker {
}
return property;
}
-
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java
index b8bfa74b6..2fdd32649 100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java
@@ -23,6 +23,7 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.extensions.ExtensionAttachment;
/**
* This class extends the org.apache.fop.extensions.ExtensionObj class. The
@@ -45,13 +46,13 @@ public class AFPElement extends AbstractAFPExtensionObject {
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
super.startOfNode();
- //if (!AFPElementMapping.NAMESPACE.equals(parent.getNamespaceURI())
- // || !AFPElementMapping.PAGE.equals(parent.getLocalName())) {
- // throw new ValidationException(getName() + " must be a child of afp:page.");
- //}
if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
throw new ValidationException(getName() + " must be a child of fo:simple-page-master.");
}
}
+ /** {@inheritDoc} */
+ protected ExtensionAttachment instantiateExtensionAttachment() {
+ return new AFPPageSetup(getName());
+ }
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
index 216379cc0..c3ba2c43b 100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
@@ -19,8 +19,6 @@
package org.apache.fop.render.afp.extensions;
-import java.util.HashMap;
-
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.FONode;
@@ -39,7 +37,7 @@ public class AFPElementMapping extends ElementMapping {
public static final String PAGE = "page";
/** page group element */
- public static final String PAGE_GROUP = "page-group";
+// public static final String PAGE_GROUP = "page-group";
/** tag logical element */
public static final String TAG_LOGICAL_ELEMENT = "tag-logical-element";
@@ -53,6 +51,9 @@ public class AFPElementMapping extends ElementMapping {
/** NOP */
public static final String NO_OPERATION = "no-operation";
+ /** resource information (name, level, dest) */
+// public static final String RESOURCE_INFO = "resource-info";
+
/**
* The namespace used for AFP extensions
*/
@@ -69,15 +70,18 @@ public class AFPElementMapping extends ElementMapping {
}
/**
- * Private static synchronized method to set up the element and atribute
+ * Private static synchronized method to set up the element and attribute
* HashMaps, this defines what elements and attributes are extracted.
*/
protected void initialize() {
if (foObjs == null) {
- foObjs = new HashMap();
+ super.foObjs = new java.util.HashMap();
foObjs.put(PAGE, new AFPPageSetupMaker());
- // foObjs.put(PAGE_GROUP, new AFPMaker());
+// foObjs.put(
+// PAGE_GROUP,
+// new AFPPageGroupMaker()
+// );
foObjs.put(
TAG_LOGICAL_ELEMENT,
new AFPTagLogicalElementMaker());
@@ -90,8 +94,10 @@ public class AFPElementMapping extends ElementMapping {
foObjs.put(
NO_OPERATION,
new AFPNoOperationMaker());
+// foObjs.put(
+// RESOURCE_INFO,
+// new AFPResourceInfoMaker());
}
-
}
static class AFPPageSetupMaker extends ElementMapping.Maker {
@@ -123,4 +129,16 @@ public class AFPElementMapping extends ElementMapping {
return new AFPElement(parent, NO_OPERATION);
}
}
+
+// static class AFPResourceInfoMaker extends ElementMapping.Maker {
+// public FONode make(FONode parent) {
+// return new AFPResourceInfoElement(parent);
+// }
+// }
+
+// static class AFPPageGroupMaker extends ElementMapping.Maker {
+// public FONode make(FONode parent) {
+// return new AFPElement(parent, PAGE_GROUP);
+// }
+// }
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java
new file mode 100644
index 000000000..9a8429b00
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.render.afp.extensions;
+
+import java.io.Serializable;
+
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+import org.apache.xmlgraphics.util.XMLizable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * This is the pass-through value object for the AFP extension.
+ */
+public abstract class AFPExtensionAttachment
+ implements ExtensionAttachment, Serializable, XMLizable {
+ private static final long serialVersionUID = 7190606822558332901L;
+
+ /** The category URI for this extension attachment. */
+ public static final String CATEGORY = "apache:fop:extensions:afp";
+
+ /**
+ * the extension element name
+ */
+ protected String elementName;
+
+ /**
+ * the extension content
+ */
+ protected String content;
+
+ /**
+ * the extension name attribute
+ */
+ protected String name;
+
+ /**
+ * the extension value attribute
+ */
+ protected String value;
+
+ /**
+ * Default constructor.
+ *
+ * @param elementName the name of the afp extension attachment, may be null
+ */
+ public AFPExtensionAttachment(String elementName) {
+ this.elementName = elementName;
+ }
+
+ /** @return the name */
+ public String getElementName() {
+ return elementName;
+ }
+
+ /**
+ * @return true if this element has a name attribute
+ */
+ protected boolean hasName() {
+ return name != null;
+ }
+
+ /** @return the name */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name of the setup code object.
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value
+ * @param source The value name to set.
+ */
+ public void setValue(String source) {
+ this.value = source;
+ }
+
+ /** {@inheritDoc} */
+ public String getCategory() {
+ return CATEGORY;
+ }
+
+ /**
+ * @return the data
+ */
+ public String getContent() {
+ return content;
+ }
+
+ /**
+ * Sets the data
+ * @param content The byte data to set.
+ */
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ /**
+ * name attribute
+ */
+ protected static final String ATT_NAME = "name";
+
+ /**
+ * value attribute
+ */
+ protected static final String ATT_VALUE = "value";
+
+ /** {@inheritDoc} */
+ public void toSAX(ContentHandler handler) throws SAXException {
+ AttributesImpl atts = new AttributesImpl();
+ if (name != null && name.length() > 0) {
+ atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name);
+ }
+ if (value != null && value.length() > 0) {
+ atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value);
+ }
+ handler.startElement(CATEGORY, elementName, elementName, atts);
+ if (content != null && content.length() > 0) {
+ char[] chars = content.toCharArray();
+ handler.characters(chars, 0, chars.length);
+ }
+ handler.endElement(CATEGORY, elementName, elementName);
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
index 61ad9c1e7..08989c03c 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
@@ -54,7 +54,7 @@ public class AFPExtensionHandler extends DefaultHandler
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY)
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT)
|| localName.equals(AFPElementMapping.PAGE)
- || localName.equals(AFPElementMapping.PAGE_GROUP)) {
+ /*|| localName.equals(AFPElementMapping.PAGE_GROUP)*/) {
//handled in endElement
} else {
handled = false;
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
index 30bc217e7..998ce6921 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
@@ -19,33 +19,10 @@
package org.apache.fop.render.afp.extensions;
-import java.io.Serializable;
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-import org.apache.xmlgraphics.util.XMLizable;
-
-import org.apache.fop.fo.extensions.ExtensionAttachment;
-
/**
* This is the pass-through value object for the PostScript extension.
*/
-public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizable {
-
- private static final long serialVersionUID = 7190606822558332901L;
-
- /** The category URI for this extension attachment. */
- public static final String CATEGORY = "apache:fop:extensions:afp";
-
- private String elementName;
-
- private String name;
-
- private String value;
-
- private String content;
+public class AFPPageSetup extends AFPExtensionAttachment {
/**
* Default constructor.
@@ -53,85 +30,16 @@ public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizabl
* @param elementName the name of the setup code object, may be null
*/
public AFPPageSetup(String elementName) {
- this.elementName = elementName;
- }
-
- /** @return the name */
- public String getElementName() {
- return elementName;
- }
-
- /** @return the name */
- public String getName() {
- return name;
- }
-
- /**
- * Sets the name of the setup code object.
- * @param name The name to set.
- */
- public void setName(String name) {
- this.name = name;
+ super(elementName);
}
- /**
- * @return the value
- */
- public String getValue() {
- return value;
- }
-
- /**
- * Sets the value
- * @param source The value name to set.
- */
- public void setValue(String source) {
- this.value = source;
- }
-
- /** {@inheritDoc} */
- public String getCategory() {
- return CATEGORY;
- }
+ private static final long serialVersionUID = -549941295384013190L;
/**
- * @return the data
+ * {@inheritDoc}
*/
- public String getContent() {
- return content;
- }
-
- /**
- * Sets the data
- * @param content The byte data to set.
- */
- public void setContent(String content) {
- this.content = content;
- }
-
- /** {@inheritDoc} */
public String toString() {
return "AFPPageSetup(element-name=" + getElementName()
+ " name=" + getName() + " value=" + getValue() + ")";
}
-
- private static final String ATT_NAME = "name";
- private static final String ATT_VALUE = "value";
-
- /** {@inheritDoc} */
- public void toSAX(ContentHandler handler) throws SAXException {
- AttributesImpl atts = new AttributesImpl();
- if (name != null && name.length() > 0) {
- atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name);
- }
- if (value != null && value.length() > 0) {
- atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value);
- }
- handler.startElement(CATEGORY, elementName, elementName, atts);
- if (content != null && content.length() > 0) {
- char[] chars = content.toCharArray();
- handler.characters(chars, 0, chars.length);
- }
- handler.endElement(CATEGORY, elementName, elementName);
- }
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
index 4971928f8..d167a8d4b 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
@@ -23,9 +23,10 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.extensions.ExtensionAttachment;
/**
- * Extension element for fox:ps-page-setup-code.
+ * Extension element for afp:ps-page-setup-code.
*/
public class AFPPageSetupElement extends AbstractAFPExtensionObject {
@@ -45,4 +46,10 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject {
}
}
+ /**
+ * {@inheritDoc}
+ */
+ protected ExtensionAttachment instantiateExtensionAttachment() {
+ return new AFPPageSetup(this.name);
+ }
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
index a92687aab..c0e9c2c89 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
@@ -35,11 +35,14 @@ import org.apache.fop.fo.extensions.ExtensionAttachment;
public abstract class AbstractAFPExtensionObject extends FONode {
/**
- * AFP setup code
+ * the AFP extension attachment
*/
- private AFPPageSetup setupCode;
+ protected AFPExtensionAttachment extensionAttachment;
- private String name;
+ /**
+ * the element name of this extension
+ */
+ protected String name;
/**
* @see org.apache.fop.fo.FONode#FONode(FONode)
@@ -49,10 +52,11 @@ public abstract class AbstractAFPExtensionObject extends FONode {
public AbstractAFPExtensionObject(FONode parent, String name) {
super(parent);
this.name = name;
- this.setupCode = new AFPPageSetup(name);
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI)) {
@@ -60,60 +64,85 @@ public abstract class AbstractAFPExtensionObject extends FONode {
}
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
protected void characters(char[] data, int start, int length,
- PropertyList pList, Locator locator) {
- setupCode.setContent(new String(data, start, length));
+ PropertyList pList, Locator locator) throws FOPException {
+ ((AFPExtensionAttachment)getExtensionAttachment()).setContent(
+ new String(data, start, length));
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getNamespaceURI() {
return AFPElementMapping.NAMESPACE;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getNormalNamespacePrefix() {
return AFPElementMapping.NAMESPACE_PREFIX;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public void processNode(String elementName, Locator locator,
Attributes attlist, PropertyList propertyList)
throws FOPException {
- String name = attlist.getValue("name");
- if (name != null && name.length() > 0) {
- setupCode.setName(name);
+ getExtensionAttachment();
+ String attr = attlist.getValue("name");
+ if (attr != null && attr.length() > 0) {
+ extensionAttachment.setName(attr);
} else {
throw new FOPException(elementName + " must have a name attribute.");
}
if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) {
- name = attlist.getValue("src");
- if (name != null && name.length() > 0) {
- setupCode.setValue(name);
+ attr = attlist.getValue("src");
+ if (attr != null && attr.length() > 0) {
+ extensionAttachment.setValue(attr);
} else {
throw new FOPException(elementName + " must have a src attribute.");
}
} else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
- name = attlist.getValue("value");
- if (name != null && name.length() > 0) {
- setupCode.setValue(name);
+ attr = attlist.getValue("value");
+ if (attr != null && attr.length() > 0) {
+ extensionAttachment.setValue(attr);
} else {
throw new FOPException(elementName + " must have a value attribute.");
}
}
}
-
- /** {@inheritDoc} */
+
+ /**
+ * {@inheritDoc}
+ */
protected void endOfNode() throws FOPException {
super.endOfNode();
}
- /** {@inheritDoc} */
+ /**
+ * Instantiates extension attachment object
+ * @return extension attachment
+ */
+ protected abstract ExtensionAttachment instantiateExtensionAttachment();
+
+ /**
+ * {@inheritDoc}
+ */
public ExtensionAttachment getExtensionAttachment() {
- return this.setupCode;
+ if (extensionAttachment == null) {
+ this.extensionAttachment = (AFPExtensionAttachment)instantiateExtensionAttachment();
+ }
+ return this.extensionAttachment;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getLocalName() {
return name;
}
diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontCollection.java b/src/java/org/apache/fop/render/afp/fonts/AFPFontCollection.java
deleted file mode 100644
index 03b5580cf..000000000
--- a/src/java/org/apache/fop/render/afp/fonts/AFPFontCollection.java
+++ /dev/null
@@ -1,110 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.fonts;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.fop.events.EventBroadcaster;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontCollection;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontTriplet;
-import org.apache.fop.fonts.base14.Courier;
-import org.apache.fop.fonts.base14.Helvetica;
-import org.apache.fop.fonts.base14.TimesRoman;
-import org.apache.fop.render.afp.AFPEventProducer;
-
-/**
- * A base collection of AFP fonts
- */
-public class AFPFontCollection implements FontCollection {
-
- private EventBroadcaster eventBroadcaster;
- private List/*<EmbedFontInfo>*/ embedFontInfoList;
-
- /**
- * Main constructor
- *
- * @param eventBroadcaster the event broadcaster
- * @param embedFontInfoList the embed font info list
- */
- public AFPFontCollection(EventBroadcaster eventBroadcaster,
- List/*<EmbedFontInfo>*/ embedFontInfoList) {
- this.eventBroadcaster = eventBroadcaster;
- this.embedFontInfoList = embedFontInfoList;
- }
-
- /** {@inheritDoc} */
- public int setup(int start, FontInfo fontInfo) {
- int num = 1;
- if (embedFontInfoList != null && embedFontInfoList.size() > 0) {
- for (Iterator it = embedFontInfoList.iterator(); it.hasNext();) {
- AFPFontInfo afi = (AFPFontInfo)it.next();
- AFPFont bf = (AFPFont)afi.getAFPFont();
- for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) {
- FontTriplet ft = (FontTriplet)it2.next();
- fontInfo.addFontProperties("F" + num, ft.getName()
- , ft.getStyle(), ft.getWeight());
- fontInfo.addMetrics("F" + num, bf);
- num++;
- }
- }
- } else {
- AFPEventProducer eventProducer = AFPEventProducer.Provider.get(eventBroadcaster);
- eventProducer.warnDefaultFontSetup(this);
- }
- if (fontInfo.fontLookup("sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) {
- CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZH200 ",
- 1, new Helvetica());
- AFPFont bf = new OutlineFont("Helvetica", cs);
- fontInfo.addFontProperties(
- "F" + num, "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
- fontInfo.addMetrics("F" + num, bf);
- num++;
- }
- if (fontInfo.fontLookup("serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) {
- CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZN200 ",
- 1, new TimesRoman());
- AFPFont bf = new OutlineFont("Helvetica", cs);
- fontInfo.addFontProperties("F" + num, "serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
- fontInfo.addMetrics("F" + num, bf);
- num++;
- }
- if (fontInfo.fontLookup("monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) {
- CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZ4200 ",
- 1, new Courier());
- AFPFont bf = new OutlineFont("Helvetica", cs);
- fontInfo.addFontProperties(
- "F" + num, "monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
- fontInfo.addMetrics("F" + num, bf);
- num++;
- }
- if (fontInfo.fontLookup("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) {
- FontTriplet ft = fontInfo.fontLookup(
- "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
- fontInfo.addFontProperties(
- fontInfo.getInternalFontKey(ft), "any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
- num++;
- }
- return num;
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java
deleted file mode 100644
index 0c60ec1d7..000000000
--- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java
+++ /dev/null
@@ -1,701 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.awt.Color;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.render.afp.fonts.AFPFont;
-import org.apache.fop.render.afp.tools.StringUtils;
-
-/**
- * A data stream is a continuous ordered stream of data elements and objects
- * conforming to a given format. Application programs can generate data streams
- * destined for a presentation service, archive library, presentation device or
- * another application program. The strategic presentation data stream
- * architectures used is Mixed Object Document Content Architecture (MO:DCA�).
- *
- * The MO:DCA architecture defines the data stream used by applications to
- * describe documents and object envelopes for interchange with other
- * applications and application services. Documents defined in the MO:DCA format
- * may be archived in a database, then later retrieved, viewed, annotated and
- * printed in local or distributed systems environments. Presentation fidelity
- * is accommodated by including resource objects in the documents that reference
- * them.
- *
- */
-public class AFPDataStream {
-
- /**
- * Static logging instance
- */
- protected static Log log = LogFactory.getLog("org.apache.fop.render.afp.modca");
-
- /**
- * Boolean completion indicator
- */
- private boolean complete = false;
-
- /**
- * The application producing the AFP document
- */
-// not used
-// private String producer = null;
-
- /**
- * The AFP document object
- */
- private Document document = null;
-
- /**
- * The current page group object
- */
- private PageGroup currentPageGroup = null;
-
- /**
- * The current page object
- */
- private PageObject currentPageObject = null;
-
- /**
- * The current overlay object
- */
- private Overlay currentOverlay = null;
-
- /**
- * The current page
- */
- private AbstractPageObject currentPage = null;
-
- /**
- * The page count
- */
- private int pageCount = 0;
-
- /**
- * The page group count
- */
-// not used
-// private int pageGroupCount = 0;
-
- /**
- * The overlay count
- */
- private int ovlCount = 0;
-
- /**
- * The portrait rotation
- */
- private int portraitRotation = 0;
-
- /**
- * The landscape rotation
- */
- private int landscapeRotation = 270;
-
- /**
- * The x offset
- */
- private int xOffset = 0;
-
- /**
- * The y offset
- */
- private int yOffset = 0;
-
- /**
- * The rotation
- */
- private int rotation;
-
- /**
- * The outputstream for the data stream
- */
- private OutputStream outputStream = null;
-
- /**
- * Default constructor for the AFPDataStream.
- */
- public AFPDataStream() {
- }
-
- /**
- * The document is started by invoking this method which creates an instance
- * of the AFP Document object.
- *
- * @param docOutputStream
- * the outputStream which the document is written to.
- */
- public void startDocument(OutputStream docOutputStream) {
-
- if (document != null) {
- String msg = "Invalid state - document already started.";
- log.warn("startDocument():: " + msg);
- throw new IllegalStateException(msg);
- }
-
- this.document = new Document();
- this.outputStream = docOutputStream;
-
- }
-
- /**
- * The document is ended by invoking this method which creates an instance
- * of the AFP Document object and registers the start with a validation map
- * which ensures that methods are not invoked out of the correct sequence.
- *
- * @throws java.io.IOException
- * throws an I/O exception of some sort has occurred
- */
- public void endDocument() throws IOException {
-
- if (complete) {
- String msg = "Invalid state - document already ended.";
- log.warn("endDocument():: " + msg);
- throw new IllegalStateException(msg);
- }
-
- if (currentPageObject != null) {
- // End the current page if necessary
- endPage();
- }
-
- if (currentPageGroup != null) {
- // End the current page group if necessary
- endPageGroup();
- }
-
- document.endDocument();
- document.writeDataStream(this.outputStream);
- this.outputStream.flush();
-
- complete = true;
-
- document = null;
-
- this.outputStream = null;
- }
-
- /**
- * Start a new page. When processing has finished on the current page, the
- * {@link #endPage()}method must be invoked to mark the page ending.
- *
- * @param pageWidth
- * the width of the page
- * @param pageHeight
- * the height of the page
- * @param pageRotation
- * the rotation of the page
- * @param pageWidthResolution
- * the width resolution of the page
- * @param pageHeightResolution
- * the height resolution of the page
- */
- public void startPage(int pageWidth, int pageHeight, int pageRotation,
- int pageWidthResolution, int pageHeightResolution) {
-
- String pageName = "PGN"
- + StringUtils.lpad(String.valueOf(pageCount++), '0', 5);
-
- currentPageObject = new PageObject(pageName, pageWidth, pageHeight,
- pageRotation, pageWidthResolution, pageHeightResolution);
- currentPage = currentPageObject;
- currentOverlay = null;
- setOffsets(0, 0, 0);
- }
-
- /**
- * Start a new overlay. When processing has finished on the current overlay,
- * the {@link #endOverlay()}method must be invoked to mark the overlay
- * ending.
- *
- * @param overlayX
- * the x position of the overlay on the page
- * @param overlayY
- * the y position of the overlay on the page
- * @param overlayWidth
- * the width of the overlay
- * @param overlayHeight
- * the height of the overlay
- * @param overlayWidthResolution
- * the width resolution of the overlay
- * @param overlayHeightResolution
- * the height resolution of the overlay
- * @param overlayRotation
- * the rotation of the overlay
- */
- public void startOverlay(int overlayX, int overlayY, int overlayWidth,
- int overlayHeight, int overlayWidthResolution,
- int overlayHeightResolution, int overlayRotation) {
-
- String overlayName = "OVL"
- + StringUtils.lpad(String.valueOf(ovlCount++), '0', 5);
-
- currentOverlay = new Overlay(overlayName, overlayWidth, overlayHeight,
- overlayWidthResolution, overlayHeightResolution,
- overlayRotation);
- currentPageObject.addOverlay(currentOverlay);
- currentPageObject.createIncludePageOverlay(overlayName, overlayX,
- overlayY, 0);
- currentPage = currentOverlay;
- setOffsets(0, 0, 0);
- }
-
- /**
- * Helper method to mark the end of the current overlay.
- */
- public void endOverlay() {
-
- currentOverlay.endPage();
- currentOverlay = null;
- currentPage = currentPageObject;
-
- }
-
- /**
- * Helper method to save the current page.
- *
- * @return current page object that was saved
- */
- public PageObject savePage() {
-
- PageObject pageObject = currentPageObject;
- if (currentPageGroup != null) {
- currentPageGroup.addPage(currentPageObject);
- } else {
- document.addPage(currentPageObject);
- }
- currentPageObject = null;
- currentPage = null;
- return pageObject;
-
- }
-
- /**
- * Helper method to restore the current page.
- *
- * @param pageObject
- * page object
- */
- public void restorePage(PageObject pageObject) {
-
- currentPageObject = pageObject;
- currentPage = pageObject;
-
- }
-
- /**
- * Helper method to mark the end of the current page.
- *
- * @throws java.io.IOException
- * thrown when an I/O exception of some sort has occurred
- */
- public void endPage() throws IOException {
-
- currentPageObject.endPage();
- if (currentPageGroup != null) {
- currentPageGroup.addPage(currentPageObject);
- } else {
- document.addPage(currentPageObject);
- document.writeDataStream(this.outputStream);
- }
-
- currentPageObject = null;
- currentPage = null;
-
- }
-
- /**
- * Sets the offsets to be used for element positioning
- *
- * @param xOff
- * the offset in the x direction
- * @param yOff
- * the offset in the y direction
- * @param rot
- * the rotation
- */
- public void setOffsets(int xOff, int yOff, int rot) {
- this.xOffset = xOff;
- this.yOffset = yOff;
- this.rotation = rot;
- }
-
- /**
- * Helper method to create a map coded font object on the current page, this
- * method delegates the construction of the map coded font object to the
- * active environment group on the current page.
- *
- * @param fontReference
- * the font number used as the resource identifier
- * @param font
- * the font
- * @param size
- * the point size of the font
- */
- public void createFont(byte fontReference, AFPFont font, int size) {
-
- currentPage.createFont(fontReference, font, size);
-
- }
-
- /**
- * Helper method to create text on the current page, this method delegates
- * to the current presentation text object in order to construct the text.
- *
- * @param fontNumber
- * the font number used as the resource identifier
- * @param x
- * the x coordinate of the text
- * @param y
- * the y coordinate of the text
- * @param col
- * the text color
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * the text data to create
- */
- public void createText(int fontNumber, int x, int y, Color col, int vsci,
- int ica, byte[] data) {
-
- currentPage.createText(fontNumber, x + xOffset, y + yOffset, rotation,
- col, vsci, ica, data);
-
- }
-
- /**
- * Returns an ImageObject used to create an image in the datastream.
- *
- * @param x
- * the x position of the image
- * @param y
- * the y position of the image
- * @param w
- * the width of the image
- * @param h
- * the height of the image
- * @param wr
- * the width resolution of the image
- * @param hr
- * the height resolution of the image
- * @return ImageObject used to create an image in the datastream
- */
- public ImageObject getImageObject(int x, int y, int w, int h, int wr, int hr) {
-
- int xOrigin;
- int yOrigin;
- int width;
- int height;
- int widthResolution;
- int heightResolution;
-
- switch (rotation) {
- case 90:
- xOrigin = currentPage.getWidth() - y - yOffset;
- yOrigin = x + xOffset;
- width = h;
- height = w;
- widthResolution = hr;
- heightResolution = wr;
- break;
- case 180:
- xOrigin = currentPage.getWidth() - x - xOffset;
- yOrigin = currentPage.getHeight() - y - yOffset;
- width = w;
- height = h;
- widthResolution = wr;
- heightResolution = hr;
- break;
- case 270:
- xOrigin = y + yOffset;
- yOrigin = currentPage.getHeight() - x - xOffset;
- width = h;
- height = w;
- widthResolution = hr;
- heightResolution = wr;
- break;
- default:
- xOrigin = x + xOffset;
- yOrigin = y + yOffset;
- width = w;
- height = h;
- widthResolution = wr;
- heightResolution = hr;
- break;
- }
- ImageObject io = currentPage.getImageObject();
- io.setImageViewport(xOrigin, yOrigin, width, height, rotation,
- widthResolution, heightResolution);
- return io;
-
- }
-
- /**
- * Method to create a line on the current page.
- *
- * @param x1
- * the first x coordinate of the line
- * @param y1
- * the first y coordinate of the line
- * @param x2
- * the second x coordinate of the line
- * @param y2
- * the second y coordinate of the line
- * @param thickness
- * the thickness of the line
- * @param col
- * The text color.
- */
- public void createLine(int x1, int y1, int x2, int y2, int thickness,
- Color col) {
-
- currentPage.createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset, y2
- + yOffset, thickness, rotation, col);
-
- }
-
- /**
- * This method will create shading on the page using the specified
- * coordinates (the shading contrast is controlled via the red, green, blue
- * parameters, by converting this to grey scale).
- *
- * @param x
- * the x coordinate of the shading
- * @param y
- * the y coordinate of the shading
- * @param w
- * the width of the shaded area
- * @param h
- * the height of the shaded area
- * @param red
- * the red value
- * @param green
- * the green value
- * @param blue
- * the blue value
- */
- public void createShading(int x, int y, int w, int h, int red, int green,
- int blue) {
-
- currentPage.createShading(x + xOffset, y + xOffset, w, h, red, green,
- blue);
-
- }
-
- /**
- * Helper method which allows creation of the MPO object, via the AEG. And
- * the IPO via the Page. (See actual object for descriptions.)
- *
- * @param name
- * the name of the static overlay
- */
- public void createIncludePageOverlay(String name) {
-
- currentPageObject.createIncludePageOverlay(name, 0, 0, rotation);
- ActiveEnvironmentGroup aeg = currentPageObject
- .getActiveEnvironmentGroup();
- aeg.createOverlay(name);
-
- }
-
- /**
- * Helper method which allows creation of the IMM object.
- *
- * @param name
- * the name of the medium map
- */
- public void createInvokeMediumMap(String name) {
-
- if (currentPageGroup == null) {
- startPageGroup();
- }
- currentPageGroup.createInvokeMediumMap(name);
-
- }
-
- /**
- * Creates an IncludePageSegment on the current page.
- *
- * @param name
- * the name of the include page segment
- * @param x
- * the x coordinate for the overlay
- * @param y
- * the y coordinate for the overlay
- */
- public void createIncludePageSegment(String name, int x, int y) {
-
- int xOrigin;
- int yOrigin;
- switch (rotation) {
- case 90:
- xOrigin = currentPage.getWidth() - y - yOffset;
- yOrigin = x + xOffset;
- break;
- case 180:
- xOrigin = currentPage.getWidth() - x - xOffset;
- yOrigin = currentPage.getHeight() - y - yOffset;
- break;
- case 270:
- xOrigin = y + yOffset;
- yOrigin = currentPage.getHeight() - x - xOffset;
- break;
- default:
- xOrigin = x + xOffset;
- yOrigin = y + yOffset;
- break;
- }
- currentPage.createIncludePageSegment(name, xOrigin, yOrigin);
-
- }
-
- /**
- * Creates a TagLogicalElement on the current page.
- *
- * @param attributes
- * the array of key value pairs.
- */
- public void createPageTagLogicalElement(TagLogicalElementBean[] attributes) {
-
- for (int i = 0; i < attributes.length; i++) {
- String name = (String) attributes[i].getKey();
- String value = (String) attributes[i].getValue();
- currentPage.createTagLogicalElement(name, value);
- }
-
- }
-
- /**
- * Creates a TagLogicalElement on the current page group.
- *
- * @param attributes
- * the array of key value pairs.
- */
- public void createPageGroupTagLogicalElement(
- TagLogicalElementBean[] attributes) {
-
- for (int i = 0; i < attributes.length; i++) {
- String name = (String) attributes[i].getKey();
- String value = (String) attributes[i].getValue();
- currentPageGroup.createTagLogicalElement(name, value);
- }
-
- }
-
- /**
- * Creates a TagLogicalElement on the current page or page group
- *
- * @param name
- * The tag name
- * @param value
- * The tag value
- */
- public void createTagLogicalElement(String name, String value) {
-
- if (currentPageGroup != null) {
- currentPageGroup.createTagLogicalElement(name, value);
- } else {
- currentPage.createTagLogicalElement(name, value);
- }
-
- }
-
- /**
- * Creates a NoOperation item
- *
- * @param content
- * byte data
- */
- public void createNoOperation(String content) {
- currentPage.createNoOperation(content);
- }
-
- /**
- * Start a new page group. When processing has finished on the current page
- * group the {@link #endPageGroup()}method must be invoked to mark the page
- * group ending.
- */
- public void startPageGroup() {
-
- String pageGroupName = "PGP"
- + StringUtils.lpad(String.valueOf(pageCount++), '0', 5);
-
- currentPageGroup = new PageGroup(pageGroupName);
-
- }
-
- /**
- * Helper method to mark the end of the page group.
- * @throws IOException thrown if an I/O exception of some sort has occurred
- */
- public void endPageGroup() throws IOException {
-
- currentPageGroup.endPageGroup();
- document.addPageGroup(currentPageGroup);
- document.writeDataStream(outputStream);
- currentPageGroup = null;
-
- }
-
- /**
- * Sets the rotation to be used for portrait pages, valid values are 0
- * (default), 90, 180, 270.
- *
- * @param pageRotation
- * The rotation in degrees.
- */
- public void setPortraitRotation(int pageRotation) {
-
- if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180
- || pageRotation == 270) {
- this.portraitRotation = pageRotation;
- } else {
- throw new IllegalArgumentException(
- "The portrait rotation must be one of the values 0, 90, 180, 270");
- }
-
- }
-
- /**
- * Sets the rotation to be used for landscape pages, valid values are 0, 90,
- * 180, 270 (default).
- *
- * @param pageRotation
- * The rotation in degrees.
- */
- public void setLandscapeRotation(int pageRotation) {
-
- if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180
- || pageRotation == 270) {
- this.landscapeRotation = pageRotation;
- } else {
- throw new IllegalArgumentException(
- "The landscape rotation must be one of the values 0, 90, 180, 270");
- }
-
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java
deleted file mode 100644
index ef1b988c0..000000000
--- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java
+++ /dev/null
@@ -1,66 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * This is the base class for all data stream objects. Page objects are
- * responsible for building and generating the binary datastream in an
- * AFP format.
- *
- */
-public abstract class AbstractAFPObject {
-
- /**
- * Static logging instance
- */
- protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.modca");
-
- /**
- * DataStream objects must implement the writeDataStream()
- * method to write its data to the given OutputStream
- * @param os The outputsteam stream
- * @throws java.io.IOException
- */
- public abstract void writeDataStream(OutputStream os) throws IOException;
-
- /**
- * Help method to write a set of AFPObjects to the AFP datastream.
- * @param afpObjects a list of AFPObjects
- * @param os The stream to write to
- * @throws java.io.IOException
- */
- protected void writeObjectList(List afpObjects, OutputStream os)
- throws IOException {
-
- for (Iterator it = afpObjects.iterator(); it.hasNext(); ) {
- ((AbstractAFPObject)it.next()).writeDataStream(os);
- }
-
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java
deleted file mode 100644
index 85552a9e9..000000000
--- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java
+++ /dev/null
@@ -1,69 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.UnsupportedEncodingException;
-
-/**
- * This is the base class for all named data stream objects.
- * A named data stream object has an 8 byte EBCIDIC name.
- */
-public abstract class AbstractNamedAFPObject extends AbstractAFPObject {
-
- /**
- * The actual name of the object
- */
- protected String name = null;
-
- /**
- * The name of the object in EBCIDIC bytes
- */
- protected byte[] nameBytes;
-
- /**
- * Constructor for the ActiveEnvironmentGroup, this takes a
- * name parameter which should be 8 characters long.
- * @param name the object name
- */
- public AbstractNamedAFPObject(String name) {
-
- this.name = name;
- if (name.length() < 8) {
- name = (name + " ").substring(0, 8);
- } else if (name.length() > 8) {
- log.warn("Constructor:: name truncated to 8 chars" + name);
- name = name.substring(0, 8);
- }
-
- try {
-
- nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
-
- } catch (UnsupportedEncodingException usee) {
-
- nameBytes = name.getBytes();
- log.warn(
- "Constructor:: UnsupportedEncodingException translating the name "
- + name);
-
- }
-
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
deleted file mode 100644
index a99b28107..000000000
--- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
+++ /dev/null
@@ -1,435 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.fop.render.afp.fonts.AFPFont;
-import org.apache.fop.render.afp.tools.StringUtils;
-
-/**
- * Pages contain the data objects that comprise a presentation document. Each
- * page has a set of data objects associated with it. Each page within a
- * document is independent from any other page, and each must establish its own
- * environment parameters.
- *
- * The page is the level in the document component hierarchy that is used for
- * printing or displaying a document's content. The data objects contained in
- * the page envelope in the data stream are presented when the page is
- * presented. Each data object has layout information associated with it that
- * directs the placement and orientation of the data on the page. In addition,
- * each page contains layout information that specifies the measurement units,
- * page width, and page depth.
- *
- * A page is initiated by a begin page structured field and terminated by an end
- * page structured field. Structured fields that define objects and active
- * environment groups or that specify attributes of the page may be encountered
- * in page state.
- *
- */
-public abstract class AbstractPageObject extends AbstractNamedAFPObject {
-
- /**
- * The active environment group for the page
- */
- protected ActiveEnvironmentGroup activeEnvironmentGroup = null;
-
- /**
- * The presentation text object, we only have one per page
- */
- private PresentationTextObject presentationTextObject = null;
-
- /**
- * The list of objects within the page
- */
- protected List objects = new ArrayList();
-
- /**
- * The list of tag logical elements
- */
- protected ArrayList tagLogicalElements = new ArrayList();
-
- /**
- * The list of the include page segments
- */
- protected ArrayList segments = new ArrayList();
-
- /**
- * The page width
- */
- private int width;
-
- /**
- * The page height
- */
- private int height;
-
- /**
- * The page rotation
- */
- private int rotation = 0;
-
- /**
- * The page state
- */
- private boolean complete = false;
-
- /**
- * Construct a new page object for the specified name argument, the page
- * name should be an 8 character identifier.
- *
- * @param name
- * the name of the page.
- * @param width
- * the width of the page.
- * @param height
- * the height of the page.
- * @param rotation
- * the rotation of the page.
- * @param widthResolution
- * the width resolution of the page.
- * @param heightResolution
- * the height resolution of the page.
- */
- public AbstractPageObject(String name, int width, int height, int rotation,
- int widthResolution, int heightResolution) {
-
- super(name);
- this.width = width;
- this.height = height;
- this.rotation = rotation;
-
- /**
- * Every page object must have an ActiveEnvironmentGroup
- */
- activeEnvironmentGroup = new ActiveEnvironmentGroup(width, height,
- widthResolution, heightResolution);
-
- if (rotation != 0) {
- switch (rotation) {
- case 90:
- activeEnvironmentGroup.setPosition(width, 0, rotation);
- break;
- case 180:
- activeEnvironmentGroup.setPosition(width, height, rotation);
- break;
- case 270:
- activeEnvironmentGroup.setPosition(0, height, rotation);
- break;
- default:
- }
- }
-
- /**
- * We have a presentation text object per page
- */
- presentationTextObject = new PresentationTextObject();
- objects.add(presentationTextObject);
-
- }
-
- /**
- * Helper method to create a map coded font object on the current page, this
- * method delegates the construction of the map coded font object to the
- * active environment group on the page.
- *
- * @param fontReference
- * the font number used as the resource identifier
- * @param font
- * the font
- * @param size
- * the point size of the font
- */
- public void createFont(byte fontReference, AFPFont font, int size) {
-
- activeEnvironmentGroup.createFont(fontReference, font, size, 0);
-
- }
-
- /**
- * Helper method to create a line on the current page, this method delegates
- * to the presentation text object in order to construct the line.
- *
- * @param x1
- * the first x coordinate of the line
- * @param y1
- * the first y coordinate of the line
- * @param x2
- * the second x coordinate of the line
- * @param y2
- * the second y coordinate of the line
- * @param thickness
- * the thickness of the line
- * @param lineRotation
- * the rotation of the line
- * @param col
- * The text color.
- */
- public void createLine(int x1, int y1, int x2, int y2, int thickness,
- int lineRotation, Color col) {
-
- if (presentationTextObject == null) {
- presentationTextObject = new PresentationTextObject();
- objects.add(presentationTextObject);
- }
- presentationTextObject.createLineData(x1, y1, x2, y2, thickness, lineRotation, col);
-
- }
-
- /**
- * Helper method to create text on the current page, this method delegates
- * to the presentation text object in order to construct the text.
- *
- * @param fontNumber
- * the font number used as the resource identifier
- * @param x
- * the x coordinate of the text data
- * @param y
- * the y coordinate of the text data
- * @param textRotation
- * the rotation of the text data
- * @param col
- * the text color
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * the text data to create
- */
- public void createText(int fontNumber, int x, int y, int textRotation, Color col,
- int vsci, int ica, byte[] data) {
-
- if (presentationTextObject == null) {
- presentationTextObject = new PresentationTextObject();
- objects.add(presentationTextObject);
- }
- presentationTextObject.createTextData(fontNumber, x, y, textRotation, col, vsci, ica, data);
-
- }
-
- /**
- * Helper method to mark the end of the page. This should end the control
- * sequence on the current presenation text object.
- */
- public void endPage() {
-
- if (presentationTextObject != null) {
- presentationTextObject.endControlSequence();
- }
-
- complete = true;
-
- }
-
- /**
- * This method will create shading on the page using the specified
- * coordinates (the shading contrast is controlled via the red, green blue
- * parameters, by converting this to grey scale).
- *
- * @param x
- * the x coordinate of the shading
- * @param y
- * the y coordinate of the shading
- * @param w
- * the width of the shaded area
- * @param h
- * the height of the shaded area
- * @param red
- * the red value
- * @param green
- * the green value
- * @param blue
- * the blue value
- */
- public void createShading(int x, int y, int w, int h, int red, int green,
- int blue) {
-
- int xCoord = 0;
- int yCoord = 0;
- int areaWidth = 0;
- int areaHeight = 0;
-
- switch (rotation) {
- case 90:
- xCoord = areaWidth - y - h;
- yCoord = x;
- areaWidth = h;
- areaHeight = w;
- break;
- case 180:
- xCoord = areaWidth - x - w;
- yCoord = areaHeight - y - h;
- areaWidth = w;
- areaHeight = h;
- break;
- case 270:
- xCoord = y;
- yCoord = areaHeight - x - w;
- areaWidth = h;
- areaHeight = w;
- break;
- default:
- xCoord = x;
- yCoord = y;
- areaWidth = w;
- areaHeight = h;
- break;
- }
-
- // Convert the color to grey scale
- float shade = (float) ((red * 0.3) + (green * 0.59) + (blue * 0.11));
-
- int greyscale = Math.round((shade / 255) * 16);
-
- String imageName = "IMG"
- + StringUtils.lpad(String.valueOf(objects.size() + 1),
- '0', 5);
-
- IMImageObject io = new IMImageObject(imageName);
- ImageOutputControl ioc = new ImageOutputControl(0, 0);
- ImageInputDescriptor iid = new ImageInputDescriptor();
- ImageCellPosition icp = new ImageCellPosition(xCoord, yCoord);
- icp.setXFillSize(areaWidth);
- icp.setYFillSize(areaHeight);
- icp.setXSize(64);
- icp.setYSize(8);
-
- //defining this as a resource
- ImageRasterData ird = new ImageRasterData(ImageRasterPattern
- .getRasterData(greyscale));
-
- io.setImageOutputControl(ioc);
- io.setImageInputDescriptor(iid);
- io.setImageCellPosition(icp);
- io.setImageRasterData(ird);
- objects.add(io);
-
- }
-
- /**
- * Helper method to create an image on the current page and to return
- * the object.
- * @return the image object
- */
- public ImageObject getImageObject() {
-
- if (presentationTextObject != null) {
- presentationTextObject.endControlSequence();
- }
- presentationTextObject = null;
-
- String imageName = "IMG"
- + StringUtils.lpad(String.valueOf(objects.size() + 1),
- '0', 5);
-
- ImageObject io = new ImageObject(imageName);
- objects.add(io);
- return io;
- }
-
- /**
- * Creates a TagLogicalElement on the page.
- *
- * @param name
- * the name of the tag
- * @param value
- * the value of the tag
- */
- public void createTagLogicalElement(String name, String value) {
-
- TagLogicalElement tle = new TagLogicalElement(name, value);
- tagLogicalElements.add(tle);
-
- }
-
- /**
- * Creates a NoOperation on the page.
- *
- * @param content the byte data
- */
- public void createNoOperation(String content) {
-
- NoOperation noOp = new NoOperation(content);
- objects.add(noOp);
-
- }
-
- /**
- * Creates an IncludePageSegment on the current page.
- *
- * @param name
- * the name of the page segment
- * @param xCoor
- * the x cooridinate of the page segment.
- * @param yCoor
- * the y cooridinate of the page segment.
- */
- public void createIncludePageSegment(String name, int xCoor, int yCoor) {
-
- IncludePageSegment ips = new IncludePageSegment(name, xCoor, yCoor);
- segments.add(ips);
-
- }
-
- /**
- * Returns the ActiveEnvironmentGroup associated with this page.
- *
- * @return the ActiveEnvironmentGroup object
- */
- public ActiveEnvironmentGroup getActiveEnvironmentGroup() {
- return activeEnvironmentGroup;
- }
-
- /**
- * Returns an indication if the page is complete
- * @return whether this page is complete
- */
- public boolean isComplete() {
- return complete;
- }
-
- /**
- * Returns the height of the page
- * @return the height of the page
- */
- public int getHeight() {
- return height;
- }
-
- /**
- * Returns the width of the page
- * @return the width of the page
- */
- public int getWidth() {
- return width;
- }
-
- /**
- * Returns the rotation of the page
- * @return the rotation of the page
- */
- public int getRotation() {
- return rotation;
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java
deleted file mode 100644
index 3e341c735..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java
+++ /dev/null
@@ -1,353 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-
-import org.apache.fop.render.afp.fonts.AFPFont;
-
-/**
- * An Active Environment Group (AEG) is associated with each page,
- * and is contained in the page's begin-end envelope in the data stream.
- * The active environment group contains layout and formatting information
- * that defines the measurement units and size of the page, and may contain
- * resource information.
- *
- * Any objects that are required for page presentation and that are to be
- * treated as resource objects must be mapped with a map structured field
- * in the AEG. The scope of an active environment group is the scope of its
- * containing page or overlay.
- *
- */
-public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject {
-
- /**
- * Default name for the active environment group
- */
- private static final String DEFAULT_NAME = "AEG00001";
-
- /**
- * The collection of MapCodedFont objects
- */
- private ArrayList mapCodedFonts = new ArrayList();
-
- /**
- * The Object Area Descriptor for the active environment group
- */
- private ObjectAreaDescriptor objectAreaDescriptor = null;
-
- /**
- * The Object Area Position for the active environment group
- */
- private ObjectAreaPosition objectAreaPosition = null;
-
- /**
- * The PresentationTextDescriptor for the active environment group
- */
- private PresentationTextDescriptor presentationTextDataDescriptor = null;
-
- /**
- * The PageDescriptor for the active environment group
- */
- private PageDescriptor pageDescriptor = null;
-
- /**
- * The collection of MapPageOverlay objects
- */
- private ArrayList mapPageOverlays = new ArrayList();
-
- /**
- * Default constructor for the ActiveEnvironmentGroup.
- * @param width the page width
- * @param height the page height
- * @param widthResolution the page width resolution
- * @param heightResolution the page height resolution
- */
- public ActiveEnvironmentGroup(int width, int height,
- int widthResolution, int heightResolution) {
-
- this(DEFAULT_NAME, width, height, widthResolution, heightResolution);
-
- }
-
- /**
- * Constructor for the ActiveEnvironmentGroup, this takes a
- * name parameter which must be 8 characters long.
- * @param name the active environment group name
- * @param width the page width
- * @param height the page height
- * @param widthResolution the page width resolution
- * @param heightResolution the page height resolution
- */
- public ActiveEnvironmentGroup(String name, int width, int height,
- int widthResolution, int heightResolution) {
-
- super(name);
-
- // Create PageDescriptor
- pageDescriptor = new PageDescriptor(width, height, widthResolution, heightResolution);
-
- // Create ObjectAreaDescriptor
- objectAreaDescriptor = new ObjectAreaDescriptor(width, height,
- widthResolution, heightResolution);
-
- // Create PresentationTextDataDescriptor
- presentationTextDataDescriptor = new PresentationTextDescriptor(width, height,
- widthResolution, heightResolution);
-
- }
-
- /**
- * Set the position of the object area
- * @param x the x offset
- * @param y the y offset
- * @param rotation the rotation
- */
- public void setPosition(int x, int y, int rotation) {
-
- // Create ObjectAreaPosition
- objectAreaPosition = new ObjectAreaPosition(x, y, rotation);
-
- }
-
- /**
- * Accessor method to obtain the PageDescriptor object of the
- * active environment group.
- * @return the page descriptor object
- */
- public PageDescriptor getPageDescriptor() {
-
- return pageDescriptor;
-
- }
-
- /**
- * Accessor method to obtain the PresentationTextDataDescriptor object of
- * the active environment group.
- * @return the presentation text descriptor
- */
- public PresentationTextDescriptor getPresentationTextDataDescriptor() {
-
- return presentationTextDataDescriptor;
-
- }
-
- /**
- * Accessor method to write the AFP datastream for the active environment group.
- * @param os The stream to write to
- * @throws java.io.IOException throws if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- writeObjectList(mapCodedFonts, os);
-
- writeObjectList(mapPageOverlays, os);
-
- pageDescriptor.writeDataStream(os);
-
- if (objectAreaDescriptor != null && objectAreaPosition != null) {
- objectAreaDescriptor.writeDataStream(os);
- objectAreaPosition.writeDataStream(os);
- }
-
- presentationTextDataDescriptor.writeDataStream(os);
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the active environment group.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0xC9; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the active environment group.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xC9; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Method to create a map coded font object
- * @param fontReference the font number used as the resource identifier
- * @param font the font
- * @param size the point size of the font
- * @param orientation the orientation of the font (e.g. 0, 90, 180, 270)
- */
- public void createFont(
- byte fontReference,
- AFPFont font,
- int size,
- int orientation) {
-
- MapCodedFont mcf = getCurrentMapCodedFont();
-
- if (mcf == null) {
- mcf = new MapCodedFont();
- mapCodedFonts.add(mcf);
- }
-
- try {
-
- mcf.addFont(
- fontReference,
- font,
- size,
- orientation);
-
- } catch (MaximumSizeExceededException msee) {
-
- mcf = new MapCodedFont();
- mapCodedFonts.add(mcf);
-
- try {
-
- mcf.addFont(
- fontReference,
- font,
- size,
- orientation);
-
- } catch (MaximumSizeExceededException ex) {
-
- // Should never happen (but log just in case)
- log.error("createFont():: resulted in a MaximumSizeExceededException");
-
- }
-
- }
-
- }
-
- /**
- * Actually creates the MPO object.
- * Also creates the supporting object (an IPO)
- * @param name the name of the overlay to be used
- */
- public void createOverlay(String name) {
-
- MapPageOverlay mpo = getCurrentMapPageOverlay();
-
- if (mpo == null) {
- mpo = new MapPageOverlay();
- mapPageOverlays.add(mpo);
- }
-
- try {
-
- mpo.addOverlay(name);
-
- } catch (MaximumSizeExceededException msee) {
- mpo = new MapPageOverlay();
- mapPageOverlays.add(mpo);
- try {
- mpo.addOverlay(name);
- } catch (MaximumSizeExceededException ex) {
- // Should never happen (but log just in case)
- log.error("createOverlay():: resulted in a MaximumSizeExceededException");
- }
- }
- }
-
- /**
- * Getter method for the most recent MapCodedFont added to the
- * Active Environment Group (returns null if no MapCodedFonts exist)
- * @return the most recent Map Coded Font.
- */
- private MapCodedFont getCurrentMapCodedFont() {
-
- int size = mapCodedFonts.size();
- if (size > 0) {
- return (MapCodedFont) mapCodedFonts.get(mapCodedFonts.size() - 1);
- } else {
- return null;
- }
-
- }
-
- /**
- * Getter method for the most recent MapPageOverlay added to the
- * Active Environment Group (returns null if no MapPageOverlay exist)
- * @return the most recent Map Coded Font
- */
- private MapPageOverlay getCurrentMapPageOverlay() {
-
- int size = mapPageOverlays.size();
- if (size > 0) {
- return (MapPageOverlay) mapPageOverlays.get(
- mapPageOverlays.size() - 1);
- } else {
- return null;
- }
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/Document.java b/src/java/org/apache/fop/render/afp/modca/Document.java
deleted file mode 100644
index 3d2d40a3a..000000000
--- a/src/java/org/apache/fop/render/afp/modca/Document.java
+++ /dev/null
@@ -1,213 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * The document is the highest level of the MO:DCA data-stream document
- * component hierarchy. Documents can be made up of pages, and the pages,
- * which are at the intermediate level, can be made up of objects. Objects
- * are at the lowest level, and can be bar codes, graphics, images, and
- * presentation text.
- *
- * At each level of the hierarchy certain sets of MO:DCA data structures,
- * called structured fields, are permissible. The document, pages and objects
- * are bounded by structured fields that define their beginnings and their ends.
- * These structured fields, called begin-end pairs, provide an envelope for the
- * data-stream components. This feature enables a processor of the data stream
- * that is not fully compliant with the architecture to bypass those objects
- * that are beyond its scope, and to process the data stream to the best of its
- * abilities.
- *
- * A presentation document is one that has been formatted and is intended for
- * presentation, usually on a printer or display device. A data stream containing
- * a presentation document should produce the same document content in the
- * same format on different printers or display devices dependent, however,
- * on the capabilities of each of the printers or display devices. A presentation
- * document can reference resources that are to be included as part of the
- * document to be presented.
- *
- */
-public final class Document extends AbstractNamedAFPObject {
-
- /**
- * Ststic default name reference
- */
- private static final String DEFAULT_NAME = "DOC00001";
-
- /**
- * A list of the objects in the document
- */
- private List objects = new java.util.ArrayList();
-
- /**
- * The document started state
- */
- private boolean started = false;
-
- /**
- * The document completion state
- */
- private boolean complete = false;
-
- /**
- * Default constructor for the document object.
- */
- public Document() {
- this(DEFAULT_NAME);
- }
-
- /**
- * Constructor for the document object.
- * @param name The name of the document
- */
- public Document(String name) {
-
- super(name);
-
- }
-
- /**
- * Adds a page to the document.
- * @param page - the Page object
- */
- public void addPage(PageObject page) {
- if (!objects.contains(page)) {
- objects.add(page);
- }
- }
-
- /**
- * Adds a PageGroup to the document.
- * @param pageGroup the PageGroup object
- */
- public void addPageGroup(PageGroup pageGroup) {
- objects.add(pageGroup);
- }
-
- /**
- * Method to mark the end of the page group.
- */
- public void endDocument() {
-
- complete = true;
-
- }
-
- /**
- * Returns an indication if the page group is complete
- * @return whether or not this page group is complete
- */
- public boolean isComplete() {
- return complete;
- }
-
- /**
- * Accessor method to write the AFP datastream for document.
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- if (!started) {
- writeStart(os);
- started = true;
- }
-
- for (Iterator it = objects.iterator(); it.hasNext();) {
- AbstractAFPObject ao = (AbstractAFPObject)it.next();
- if (ao instanceof PageObject && ((PageObject)ao).isComplete()
- || ao instanceof PageGroup && ((PageGroup)ao).isComplete()) {
- ao.writeDataStream(os);
- it.remove();
- } else {
- break;
- }
- }
-
- if (complete) {
- writeEnd(os);
- }
-
- }
-
- /**
- * Helper method to write the start of the Document
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0xA8; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the Document.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xA8; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java
deleted file mode 100644
index e6f9f1857..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java
+++ /dev/null
@@ -1,295 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.IOException;
-import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
-
-/**
- */
-public class ImageContent extends AbstractAFPObject {
-
- /**
- * The image size parameter
- */
- private ImageSizeParameter _imageSizeParameter = null;
-
- /**
- * The image encoding
- */
- private byte _encoding = 0x03;
-
- /**
- * The image ide size
- */
- private byte _size = 1;
-
- /**
- * The image compression
- */
- private byte _compression = (byte)0xC0;
-
- /**
- * The image color model
- */
- private byte _colorModel = 0x01;
-
- /**
- * The image data
- */
- private byte _data[] = null;
-
- /**
- * Constructor for the image content
- */
- public ImageContent() {
-
- }
-
- /**
- * Sets the image size parameters
- * resolution, hsize and vsize.
- * @param hresol The horizontal resolution of the image.
- * @param vresol The vertical resolution of the image.
- * @param hsize The horizontal size of the image.
- * @param vsize The vertival size of the image.
- */
- public void setImageSize(int hresol, int vresol, int hsize, int vsize) {
- _imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize);
- }
-
- /**
- * Sets the image encoding.
- * @param encoding The image encoding.
- */
- public void setImageEncoding(byte encoding) {
- _encoding = encoding;
- }
-
- /**
- * Sets the image compression.
- * @param compression The image compression.
- */
- public void setImageCompression(byte compression) {
- _compression = compression;
- }
-
- /**
- * Sets the image IDE size.
- * @param size The IDE size.
- */
- public void setImageIDESize(byte size) {
- _size = size;
- }
-
- /**
- * Sets the image IDE color model.
- * @param colorModel the IDE color model.
- */
- public void setImageIDEColorModel(byte colorModel) {
- _colorModel = colorModel;
- }
-
- /**
- * Set the data of the image.
- */
- public void setImageData(byte data[]) {
- _data = data;
- }
-
- /**
- * Accessor method to write the AFP datastream for the Image Content
- * @param os The stream to write to
- * @throws java.io.IOException
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- if (_imageSizeParameter != null) {
- _imageSizeParameter.writeDataStream(os);
- }
-
- os.write(getImageEncodingParameter());
-
- os.write(getImageIDESizeParameter());
-
- os.write(getIDEStructureParameter());
-
- os.write(getExternalAlgorithmParameter());
-
- if (_data != null) {
- int off = 0;
- while (off < _data.length) {
- int len = Math.min(30000, _data.length - off);
- os.write(getImageDataStart(len));
- os.write(_data, off, len);
- off += len;
- }
- }
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the Image Content.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
- (byte)0x91, // ID
- 0x01, // Length
- (byte)0xff, // Object Type = IOCA Image Object
- };
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the Image Content.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
- (byte)0x93, // ID
- 0x00, // Length
- };
-
- os.write(data);
-
- }
-
- /**
- * Helper method to return the start of the image segment.
- * @return byte[] The data stream.
- */
- private byte[] getImageDataStart(int len) {
-
- byte[] data = new byte[] {
- (byte)0xFE, // ID
- (byte)0x92, // ID
- 0x00, // Length
- 0x00, // Length
- };
-
- byte[] l = BinaryUtils.convert(len, 2);
- data[2] = l[0];
- data[3] = l[1];
-
-
- return data;
-
- }
-
- /**
- * Helper method to return the image encoding parameter.
- * @return byte[] The data stream.
- */
- private byte[] getImageEncodingParameter() {
-
- byte[] data = new byte[] {
- (byte)0x95, // ID
- 0x02, // Length
- _encoding,
- 0x01, // RECID
- };
-
- return data;
-
- }
-
- /**
- * Helper method to return the external algorithm parameter.
- * @return byte[] The data stream.
- */
- private byte[] getExternalAlgorithmParameter() {
-
- if (_encoding == (byte)0x83 && _compression != 0) {
- byte[] data = new byte[] {
- (byte)0x95, // ID
- 0x00, // Length
- 0x10, // ALGTYPE = Compression Algorithm
- 0x00, // Reserved
- (byte)0x83, // COMPRID = JPEG
- 0x00, // Reserved
- 0x00, // Reserved
- 0x00, // Reserved
- _compression, // MARKER
- 0x00, // Reserved
- 0x00, // Reserved
- 0x00, // Reserved
- };
- data[1] = (byte)(data.length - 2);
- return data;
- }
- return new byte[0];
- }
-
- /**
- * Helper method to return the image encoding parameter.
- * @return byte[] The data stream.
- */
- private byte[] getImageIDESizeParameter() {
-
- byte[] data = new byte[] {
- (byte)0x96, // ID
- 0x01, // Length
- _size,
- };
-
- return data;
-
- }
-
- /**
- * Helper method to return the external algorithm parameter.
- * @return byte[] The data stream.
- */
- private byte[] getIDEStructureParameter() {
-
- if (_colorModel != 0 && _size == 24) {
- byte bits = (byte)(_size / 3);
- byte[] data = new byte[] {
- (byte)0x9B, // ID
- 0x00, // Length
- 0x00, // FLAGS
- 0x00, // Reserved
- _colorModel, // COLOR MODEL
- 0x00, // Reserved
- 0x00, // Reserved
- 0x00, // Reserved
- bits,
- bits,
- bits,
- };
- data[1] = (byte)(data.length - 2);
- return data;
- }
- return new byte[0];
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
deleted file mode 100644
index 9250f0c7f..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
+++ /dev/null
@@ -1,109 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
-
-/**
- */
-public class ImageDataDescriptor extends AbstractAFPObject {
-
- private int _xresol = 0;
- private int _yresol = 0;
- private int _width = 0;
- private int _height = 0;
-
- /**
- * Constructor for a ImageDataDescriptor for the specified
- * resolution, width and height.
- * @param xresol The horizontal resolution of the image.
- * @param yresol The vertical resolution of the image.
- * @param width The width of the image.
- * @param height The height of the height.
- */
- public ImageDataDescriptor(int xresol, int yresol, int width, int height) {
-
- _xresol = xresol;
- _yresol = yresol;
- _width = width;
- _height = height;
-
- }
-
- /**
- * Accessor method to write the AFP datastream for the Image Data Descriptor
- * @param os The stream to write to
- * @throws java.io.IOException
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
- 0x5A,
- 0x00,
- 0x20,
- (byte) 0xD3,
- (byte) 0xA6,
- (byte) 0xFB,
- 0x00, // Flags
- 0x00, // Reserved
- 0x00, // Reserved
- 0x00, // Unit base - 10 Inches
- 0x00, // XRESOL
- 0x00, //
- 0x00, // YRESOL
- 0x00, //
- 0x00, // XSIZE
- 0x00, //
- 0x00, // YSIZE
- 0x00, //
- (byte)0xF7, // ID = Set IOCA Function Set
- 0x02, // Length
- 0x01, // Category = Function set identifier
- 0x0B, // FCNSET = IOCA FS 11
- };
-
- byte[] l = BinaryUtils.convert(data.length - 1, 2);
- data[1] = l[0];
- data[2] = l[1];
-
- byte[] x = BinaryUtils.convert(_xresol, 2);
- data[10] = x[0];
- data[11] = x[1];
-
- byte[] y = BinaryUtils.convert(_yresol, 2);
- data[12] = y[0];
- data[13] = y[1];
-
- byte[] w = BinaryUtils.convert(_width, 2);
- data[14] = w[0];
- data[15] = w[1];
-
- byte[] h = BinaryUtils.convert(_height, 2);
- data[16] = h[0];
- data[17] = h[1];
-
- os.write(data);
-
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageObject.java b/src/java/org/apache/fop/render/afp/modca/ImageObject.java
deleted file mode 100644
index 66c46c872..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ImageObject.java
+++ /dev/null
@@ -1,275 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
-
-/**
- * An IOCA Image Data Object
- */
-public class ImageObject extends AbstractNamedAFPObject {
-
- /**
- * The object environment group
- */
- private ObjectEnvironmentGroup objectEnvironmentGroup = null;
-
- /**
- * The image segment
- */
- private ImageSegment imageSegment = null;
-
- /**
- * Constructor for the image object with the specified name,
- * the name must be a fixed length of eight characters.
- * @param name The name of the image.
- */
- public ImageObject(String name) {
-
- super(name);
-
- }
-
- /**
- * Sets the image display area position and size.
- *
- * @param x
- * the x position of the image
- * @param y
- * the y position of the image
- * @param w
- * the width of the image
- * @param h
- * the height of the image
- * @param r
- * the rotation of the image
- * @param wr
- * the width resolution of the image
- * @param hr
- * the height resolution of the image
- */
- public void setImageViewport(int x, int y, int w, int h, int r, int wr, int hr) {
- if (objectEnvironmentGroup == null) {
- objectEnvironmentGroup = new ObjectEnvironmentGroup();
- }
- objectEnvironmentGroup.setObjectArea(x, y, w, h, r, wr, hr);
- }
-
- /**
- * Set the dimensions of the image.
- * @param xresol the x resolution of the image
- * @param yresol the y resolution of the image
- * @param width the image width
- * @param height the image height
- */
- public void setImageParameters(int xresol, int yresol, int width, int height) {
- if (objectEnvironmentGroup == null) {
- objectEnvironmentGroup = new ObjectEnvironmentGroup();
- }
- objectEnvironmentGroup.setImageData(xresol, yresol, width, height);
- if (imageSegment == null) {
- imageSegment = new ImageSegment();
- }
- imageSegment.setImageSize(xresol, yresol, width, height);
- }
-
- /**
- * Sets the image encoding.
- * @param encoding The image encoding.
- */
- public void setImageEncoding(byte encoding) {
- if (imageSegment == null) {
- imageSegment = new ImageSegment();
- }
- imageSegment.setImageEncoding(encoding);
- }
-
- /**
- * Sets the image compression.
- * @param compression The image compression.
- */
- public void setImageCompression(byte compression) {
- if (imageSegment == null) {
- imageSegment = new ImageSegment();
- }
- imageSegment.setImageCompression(compression);
- }
-
- /**
- * Sets the image IDE size.
- * @param size The IDE size.
- */
- public void setImageIDESize(byte size) {
- if (imageSegment == null) {
- imageSegment = new ImageSegment();
- }
- imageSegment.setImageIDESize(size);
- }
-
- /**
- * Sets the image IDE color model.
- * @param colorModel the IDE color model.
- */
- public void setImageIDEColorModel(byte colorModel) {
- if (imageSegment == null) {
- imageSegment = new ImageSegment();
- }
- imageSegment.setImageIDEColorModel(colorModel);
- }
-
- /**
- * Set the data of the image.
- * @param data The image data
- */
- public void setImageData(byte[] data) {
- if (imageSegment == null) {
- imageSegment = new ImageSegment();
- }
- imageSegment.setImageData(data);
- }
-
- /**
- * Sets the ObjectEnvironmentGroup.
- * @param objectEnvironmentGroup The objectEnvironmentGroup to set
- */
- public void setObjectEnvironmentGroup(ObjectEnvironmentGroup objectEnvironmentGroup) {
- this.objectEnvironmentGroup = objectEnvironmentGroup;
- }
-
- /**
- * Helper method to return the start of the image object.
- * @return byte[] The data stream.
- */
- private byte[] getIPDStart(int len) {
-
- byte[] data = new byte[] {
-
- 0x5A, // Structured field identifier
- 0x00, // Length byte 1
- 0x10, // Length byte 2
- (byte) 0xD3, // Structured field id byte 1
- (byte) 0xEE, // Structured field id byte 2
- (byte) 0xFB, // Structured field id byte 3
- 0x00, // Flags
- 0x00, // Reserved
- 0x00, // Reserved
- };
-
- byte[] l = BinaryUtils.convert(len + 8, 2);
- data[1] = l[0];
- data[2] = l[1];
-
- return data;
-
- }
-
- /**
- * Accessor method to write the AFP datastream for the Image Object
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- if (objectEnvironmentGroup != null) {
- objectEnvironmentGroup.writeDataStream(os);
- }
-
- if (imageSegment != null) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- imageSegment.writeDataStream(baos);
- byte[] b = baos.toByteArray();
- int off = 0;
- while (off < b.length) {
- int len = Math.min(30000, b.length - off);
- os.write(getIPDStart(len));
- os.write(b, off, len);
- off += len;
- }
- }
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the Image Object.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0xFB; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the Image Object.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xFB; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
deleted file mode 100644
index 7d6cc18aa..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
+++ /dev/null
@@ -1,214 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-
-/**
- * An Image Segment is represented by a set of self-defining fields, fields
- * that describe their own contents. It starts with a Begin Segment, and
- * ends with an End Segment.
- *
- * Between the Begin Segment and End Segment is the image information to
- * be processed, called the Image Content.
- *
- * Only one Image Content can exist within a single IOCA Image Segment.
- */
-public class ImageSegment extends AbstractAFPObject {
-
- /**
- * Default name for the object environment group
- */
- private static final String DEFAULT_NAME = "IS01";
-
- /**
- * The name of the image segment
- */
- private String name;
-
- /**
- * The name of the image segment as EBCIDIC bytes
- */
- private byte[] nameBytes;
-
- /**
- * The ImageContent for the image segment
- */
- private ImageContent imageContent = null;
-
- /**
- * Default constructor for the ImageSegment.
- */
- public ImageSegment() {
- this(DEFAULT_NAME);
- }
-
- /**
- * Constructor for the image segment with the specified name,
- * the name must be a fixed length of eight characters.
- * @param name The name of the image.
- */
- public ImageSegment(String name) {
-
- if (name.length() != 4) {
- String msg = "Image segment name must be 4 characters long " + name;
- log.error("Constructor:: " + msg);
- throw new IllegalArgumentException(msg);
- }
-
- this.name = name;
-
- try {
- this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
- } catch (UnsupportedEncodingException usee) {
- this.nameBytes = name.getBytes();
- log.warn(
- "Constructor:: UnsupportedEncodingException translating the name "
- + name);
- }
- }
-
- /**
- * Sets the image size parameters
- * resolution, hsize and vsize.
- * @param hresol The horizontal resolution of the image.
- * @param vresol The vertical resolution of the image.
- * @param hsize The horizontal size of the image.
- * @param vsize The vertival size of the image.
- */
- public void setImageSize(int hresol, int vresol, int hsize, int vsize) {
- if (imageContent == null) {
- imageContent = new ImageContent();
- }
- imageContent.setImageSize(hresol, vresol, hsize, vsize);
- }
-
- /**
- * Sets the image encoding.
- * @param encoding The image encoding.
- */
- public void setImageEncoding(byte encoding) {
- if (imageContent == null) {
- imageContent = new ImageContent();
- }
- imageContent.setImageEncoding(encoding);
- }
-
- /**
- * Sets the image compression.
- * @param compression The image compression.
- */
- public void setImageCompression(byte compression) {
- if (imageContent == null) {
- imageContent = new ImageContent();
- }
- imageContent.setImageCompression(compression);
- }
-
- /**
- * Sets the image IDE size.
- * @param size The IDE size.
- */
- public void setImageIDESize(byte size) {
- if (imageContent == null) {
- imageContent = new ImageContent();
- }
- imageContent.setImageIDESize(size);
- }
-
- /**
- * Sets the image IDE color model.
- * @param colorModel the IDE color model.
- */
- public void setImageIDEColorModel(byte colorModel) {
- if (imageContent == null) {
- imageContent = new ImageContent();
- }
- imageContent.setImageIDEColorModel(colorModel);
- }
-
- /**
- * Set the data of the image.
- * @param data the image data
- */
- public void setImageData(byte[] data) {
- if (imageContent == null) {
- imageContent = new ImageContent();
- }
- imageContent.setImageData(data);
- }
-
- /**
- * Accessor method to write the AFP datastream for the Image Segment
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occurred
- */
- public void writeDataStream(OutputStream os) throws IOException {
-
- writeStart(os);
-
- if (imageContent != null) {
- imageContent.writeDataStream(os);
- }
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the Image Segment.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
- 0x70, // ID
- 0x04, // Length
- 0x00, // Name byte 1
- 0x00, // Name byte 2
- 0x00, // Name byte 3
- 0x00, // Name byte 4
- };
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[2 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the Image Segment.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os) throws IOException {
-
- byte[] data = new byte[] {
- 0x71, // ID
- 0x00, // Length
- };
- os.write(data);
- }
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java
deleted file mode 100644
index 890fdcd9d..000000000
--- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java
+++ /dev/null
@@ -1,171 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.fop.render.afp.tools.BinaryUtils;
-
-/**
- * An Include Object structured field references an object on a page or overlay.
- * It optionally contains parameters that identify the object and that specify
- * presentation parameters such as object position, size, orientation, mapping,
- * and default color.
- * <p>
- * Where the presentation parameters conflict with parameters specified in the
- * object's environment group (OEG), the parameters in the Include Object
- * structured field override. If the referenced object is a page segment, the
- * IOB parameters override the corresponding environment group parameters on all
- * data objects in the page segment.
- * </p>
- */
-public class IncludeObject extends AbstractNamedAFPObject {
-
- /**
- * The object type
- */
- private byte objectType = (byte) 0x92;
-
- /**
- * The orientation on the include object
- */
- private int orientation = 0;
-
- /**
- * Constructor for the include object with the specified name, the name must
- * be a fixed length of eight characters and is the name of the referenced
- * object.
- *
- * @param name
- * the name of the image
- */
- public IncludeObject(String name) {
-
- super(name);
- objectType = (byte) 0xFB;
-
- }
-
- /**
- * Sets the orientation to use for the Include Object.
- *
- * @param orientation
- * The orientation (0,90, 180, 270)
- */
- public void setOrientation(int orientation) {
-
- if (orientation == 0 || orientation == 90 || orientation == 180
- || orientation == 270) {
- this.orientation = orientation;
- } else {
- throw new IllegalArgumentException(
- "The orientation must be one of the values 0, 90, 180, 270");
- }
-
- }
-
- /**
- * Accessor method to write the AFP datastream for the Include Object
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[37];
-
- data[0] = 0x5A;
-
- // Set the total record length
- byte[] rl1 = BinaryUtils.convert(36, 2); //Ignore first byte
- data[1] = rl1[0];
- data[2] = rl1[1];
-
- // Structured field ID for a IOB
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xAF;
- data[5] = (byte) 0xC3;
-
- data[6] = 0x00; // Reserved
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
- data[9 + i] = nameBytes[i];
- }
-
- data[17] = 0x00;
- data[18] = objectType;
-
- // XoaOset
- data[20] = (byte) 0xFF;
- data[21] = (byte) 0xFF;
- data[22] = (byte) 0xFF;
-
- // YoaOset
- data[23] = (byte) 0xFF;
- data[24] = (byte) 0xFF;
- data[25] = (byte) 0xFF;
-
- switch (orientation) {
- case 90:
- data[26] = 0x2D;
- data[27] = 0x00;
- data[28] = 0x5A;
- data[29] = 0x00;
- break;
- case 180:
- data[26] = 0x5A;
- data[27] = 0x00;
- data[28] = (byte) 0x87;
- data[29] = 0x00;
- break;
- case 270:
- data[26] = (byte) 0x87;
- data[27] = 0x00;
- data[28] = 0x00;
- data[29] = 0x00;
- break;
- default:
- data[26] = 0x00;
- data[27] = 0x00;
- data[28] = 0x2D;
- data[29] = 0x00;
- break;
- }
-
- // XocaOset
- data[30] = (byte) 0xFF;
- data[31] = (byte) 0xFF;
- data[32] = (byte) 0xFF;
-
- // YocaOset
- data[33] = (byte) 0xFF;
- data[34] = (byte) 0xFF;
- data[35] = (byte) 0xFF;
-
- data[36] = 0x01;
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
deleted file mode 100644
index 561c8c6fe..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
+++ /dev/null
@@ -1,102 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
-
-/**
- * The Object Area Descriptor structured field specifies the size and attributes
- * of an object area presentation space.
- *
- */
-public class ObjectAreaDescriptor extends AbstractDescriptor {
-
- /**
- * Construct an object area descriptor for the specified object width
- * and object height.
- * @param width The page width.
- * @param height The page height.
- * @param widthResolution The page width resolution.
- * @param heightResolution The page height resolution.
- */
- public ObjectAreaDescriptor(int width, int height, int widthResolution, int heightResolution) {
- super(width, height, widthResolution, heightResolution);
- }
-
- /**
- * Accessor method to write the AFP datastream for the Object Area Descriptor
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[29];
- data[0] = 0x5A;
-
- byte[] len = BinaryUtils.convert(data.length - 1, 2);
- data[1] = len[0]; // Length
- data[2] = len[1];
-
- data[3] = (byte) 0xD3;
- data[4] = (byte) 0xA6;
- data[5] = (byte) 0x6B;
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
- data[9] = 0x03; // Triplet length
- data[10] = 0x43; // tid = Descriptor Position Triplet
- data[11] = 0x01; // DesPosId = 1
- data[12] = 0x08; // Triplet length
- data[13] = 0x4B; // tid = Measurement Units Triplet
- data[14] = 0x00; // XaoBase = 10 inches
- data[15] = 0x00; // YaoBase = 10 inches
-
- // XaoUnits
- byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
- data[16] = xdpi[0];
- data[17] = xdpi[1];
-
- // YaoUnits
- byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
- data[18] = ydpi[0];
- data[19] = ydpi[1];
-
- data[20] = 0x09; // Triplet length
- data[21] = 0x4C; // tid = Object Area Size
- data[22] = 0x02; // Size Type
-
- byte[] x = BinaryUtils.convert(width, 3);
- data[23] = x[0];
- data[24] = x[1];
- data[25] = x[2];
-
- byte[] y = BinaryUtils.convert(height, 3);
- data[26] = y[0];
- data[27] = y[1];
- data[28] = y[2];
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java
deleted file mode 100644
index e500c1269..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java
+++ /dev/null
@@ -1,112 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import org.apache.fop.render.afp.tools.BinaryUtils;
-
-/**
- * The Object Area Position structured field specifies the origin and
- * orientation of the object area, and the origin and orientation of the
- * object content within the object area.
- */
-public class ObjectAreaPosition extends AbstractAFPObject {
-
- private int _x = 0;
- private int _y = 0;
- private int _rot = 0;
-
- /**
- * Construct an object area position for the specified object y, y position.
- * @param x The x coordinate.
- * @param y The y coordinate.
- * @param rotation The coordinate system rotation (must be 0, 90, 180, 270).
- */
- public ObjectAreaPosition(int x, int y, int rotation) {
-
- _x = x;
- _y = y;
- _rot = rotation;
- }
-
- /**
- * Accessor method to write the AFP datastream for the Object Area Position
- * @param os The stream to write to
- * @throws java.io.IOException
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
- 0x5A,
- 0x00, // Length
- 0x20, // Length
- (byte) 0xD3,
- (byte) 0xAC,
- (byte) 0x6B,
- 0x00, // Flags
- 0x00, // Reserved
- 0x00, // Reserved
- 0x01, // OAPosID = 1
- 0x17, // RGLength = 23
- 0x00, // XoaOSet
- 0x00,
- 0x00,
- 0x00, // YoaOSet
- 0x00,
- 0x00,
- (byte)(_rot / 2), // XoaOrent
- 0x00,
- (byte)(_rot / 2 + 45), // YoaOrent
- 0x00,
- 0x00, // Reserved
- 0x00, // XocaOSet
- 0x00,
- 0x00,
- 0x00, // YocaOSet
- 0x00,
- 0x00,
- 0x00, // XocaOrent
- 0x00,
- 0x2D, // YocaOrent
- 0x00,
- 0x01, // RefCSys
- };
-
- byte[] l = BinaryUtils.convert(data.length - 1, 2);
- data[1] = l[0];
- data[2] = l[1];
-
- byte[] x = BinaryUtils.convert(_x, 3);
- data[11] = x[0];
- data[12] = x[1];
- data[13] = x[2];
-
- byte[] y = BinaryUtils.convert(_y, 3);
- data[14] = y[0];
- data[15] = y[1];
- data[16] = y[2];
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java
deleted file mode 100644
index d6b029122..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java
+++ /dev/null
@@ -1,198 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.IOException;
-import java.io.OutputStream;
-
-
-/**
- * An Object Environment Group (OEG) may be associated with an object and is contained
- * within the object's begin-end envelope.
- * The object environment group defines the object's origin and orientation on the page,
- * and can contain font and color attribute table information. The scope of an object
- * environment group is the scope of its containing object.
- *
- * An application that creates a data-stream document may omit some of the parameters
- * normally contained in the object environment group, or it may specify that one or
- * more default values are to be used.
- */
-public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
-
- /**
- * Default name for the object environment group
- */
- private static final String DEFAULT_NAME = "OEG00001";
-
- /**
- * The ObjectAreaDescriptor for the object environment group
- */
- private ObjectAreaDescriptor objectAreaDescriptor = null;
-
- /**
- * The ObjectAreaPosition for the object environment group
- */
- private ObjectAreaPosition objectAreaPosition = null;
-
- /**
- * The ImageDataDescriptor for the object environment group
- */
- private ImageDataDescriptor imageDataDescriptor = null;
-
- /**
- * Default constructor for the ObjectEnvironmentGroup.
- */
- public ObjectEnvironmentGroup() {
-
- this(DEFAULT_NAME);
-
- }
-
- /**
- * Constructor for the ObjectEnvironmentGroup, this takes a
- * name parameter which must be 8 characters long.
- * @param name the object environment group name
- */
- public ObjectEnvironmentGroup(String name) {
-
- super(name);
-
- }
-
- /**
- * Sets the object area parameters.
- * @param x the x position of the object
- * @param y the y position of the object
- * @param width the object width
- * @param height the object height
- * @param rotation the object orientation
- * @param widthResolution the object resolution width
- * @param heightResolution the object resolution height
- */
- public void setObjectArea(int x, int y, int width, int height, int rotation,
- int widthResolution, int heightResolution) {
-
- objectAreaDescriptor = new ObjectAreaDescriptor(width, height,
- widthResolution, heightResolution);
- objectAreaPosition = new ObjectAreaPosition(x, y, rotation);
-
- }
-
- /**
- * Set the dimensions of the image.
- * @param xresol the x resolution of the image
- * @param yresol the y resolution of the image
- * @param width the image width
- * @param height the image height
- */
- public void setImageData(int xresol, int yresol, int width, int height) {
- imageDataDescriptor = new ImageDataDescriptor(xresol, yresol, width, height);
- }
-
- /**
- * Accessor method to obtain write the AFP datastream for
- * the object environment group.
- * @param os The stream to write to
- * @throws java.io.IOException throw if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
-
- writeStart(os);
-
- objectAreaDescriptor.writeDataStream(os);
-
- objectAreaPosition.writeDataStream(os);
-
- if (imageDataDescriptor != null) {
- imageDataDescriptor.writeDataStream(os);
- }
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the object environment group.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
- 0x5A, // Structured field identifier
- 0x00, // Length byte 1
- 0x10, // Length byte 2
- (byte) 0xD3, // Structured field id byte 1
- (byte) 0xA8, // Structured field id byte 2
- (byte) 0xC7, // Structured field id byte 3
- 0x00, // Flags
- 0x00, // Reserved
- 0x00, // Reserved
- 0x00, // Name
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
- };
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the object environment group.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xC7; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/Overlay.java b/src/java/org/apache/fop/render/afp/modca/Overlay.java
deleted file mode 100644
index 3a4cdfb11..000000000
--- a/src/java/org/apache/fop/render/afp/modca/Overlay.java
+++ /dev/null
@@ -1,139 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * An overlay is a MO:DCA-P resource object.
- *
- * It may be stored in an external resource library or it may be
- * carried in a resource group. An overlay is similar to a page in
- * that it defines its own environment and carries the same data objects.
- */
-public class Overlay extends AbstractPageObject {
-
- /**
- * Construct a new overlay object for the specified name argument, the overlay
- * name should be an 8 character identifier.
- *
- * @param name
- * the name of the page.
- * @param width
- * the width of the page.
- * @param height
- * the height of the page.
- * @param rotation
- * the rotation of the page.
- * @param widthResolution
- * the width resolution of the page.
- * @param heightResolution
- * the height resolution of the page.
- */
- public Overlay(String name, int width, int height, int rotation,
- int widthResolution, int heightResolution) {
-
- super(name, width, height, rotation, widthResolution, heightResolution);
-
- }
-
- /**
- * Accessor method to write the AFP datastream for the overlay.
- *
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- activeEnvironmentGroup.writeDataStream(os);
-
- writeObjectList(segments, os);
-
- writeObjectList(tagLogicalElements, os);
-
- writeObjectList(objects, os);
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the overlay.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0xDF; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the overlay.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xDF; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/modca/PageGroup.java b/src/java/org/apache/fop/render/afp/modca/PageGroup.java
deleted file mode 100644
index 0b40a83c5..000000000
--- a/src/java/org/apache/fop/render/afp/modca/PageGroup.java
+++ /dev/null
@@ -1,208 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A page group is used in the data stream to define a named, logical grouping
- * of sequential pages. Page groups are delimited by begin-end structured fields
- * that carry the name of the page group. Page groups are defined so that the
- * pages that comprise the group can be referenced or processed as a single
- * entity. Page groups are often processed in stand-alone fashion; that is, they
- * are indexed, retrieved, and presented outside the context of the containing
- * document.
- *
- * @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a>
- */
-public class PageGroup extends AbstractNamedAFPObject {
-
- /**
- * The pages contained within this group
- */
- private List objects = new ArrayList();
-
- /**
- * The tag logical elements contained within this group
- */
- private List tagLogicalElements = new ArrayList();
-
- /**
- * The page state
- */
- private boolean complete = false;
-
- /**
- * Constructor for the PageGroup.
- *
- * @param name
- * the name of the page group
- */
- public PageGroup(String name) {
-
- super(name);
-
- }
-
- /**
- * Adds a page object to the group.
- *
- * @param page
- * the page object to add
- */
- public void addPage(PageObject page) {
-
- if (!objects.contains(page)) {
- objects.add(page);
- }
-
- }
-
- /**
- * @return the name of the page group
- */
- public String getName() {
- return name;
- }
-
- /**
- * Creates a TagLogicalElement on the page.
- *
- * @param name
- * the name of the tag
- * @param value
- * the value of the tag
- */
- public void createTagLogicalElement(String name, String value) {
-
- TagLogicalElement tle = new TagLogicalElement(name, value);
- tagLogicalElements.add(tle);
-
- }
-
- /**
- * Creates an InvokeMediaMap on the page.
- *
- * @param name
- * the name of the media map
- */
- public void createInvokeMediumMap(String name) {
-
- InvokeMediumMap imm = new InvokeMediumMap(name);
- objects.add(imm);
-
- }
-
- /**
- * Method to mark the end of the page group.
- */
- public void endPageGroup() {
-
- complete = true;
-
- }
-
- /**
- * Returns an indication if the page group is complete
- * @return whether or not this page group is complete or not
- */
- public boolean isComplete() {
- return complete;
- }
-
- /**
- * Accessor method to write the AFP datastream for the page group.
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- writeObjectList(tagLogicalElements, os);
-
- writeObjectList(objects, os);
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the page group.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0xAD; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the page group.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xAD; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java
deleted file mode 100644
index 5b9a00a89..000000000
--- a/src/java/org/apache/fop/render/afp/modca/PageObject.java
+++ /dev/null
@@ -1,191 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-import java.io.IOException;
-import java.io.OutputStream;
-
-
-
-/**
- * Pages contain the data objects that comprise a presentation document. Each
- * page has a set of data objects associated with it. Each page within a
- * document is independent from any other page, and each must establish its own
- * environment parameters.
- *
- * The page is the level in the document component hierarchy that is used for
- * printing or displaying a document's content. The data objects contained in
- * the page envelope in the data stream are presented when the page is
- * presented. Each data object has layout information associated with it that
- * directs the placement and orientation of the data on the page. In addition,
- * each page contains layout information that specifies the measurement units,
- * page width, and page depth.
- *
- * A page is initiated by a begin page structured field and terminated by an end
- * page structured field. Structured fields that define objects and active
- * environment groups or that specify attributes of the page may be encountered
- * in page state.
- *
- */
-public class PageObject extends AbstractPageObject {
-
- /**
- * The resource group object
- */
- private ResourceGroup resourceGroup = null;
-
- /**
- * Construct a new page object for the specified name argument, the page
- * name should be an 8 character identifier.
- *
- * @param name
- * the name of the page.
- * @param width
- * the width of the page.
- * @param height
- * the height of the page.
- * @param rotation
- * the rotation of the page.
- * @param widthResolution
- * the width resolution of the page.
- * @param heightResolution
- * the height resolution of the page.
- */
- public PageObject(String name, int width, int height, int rotation,
- int widthResolution, int heightResolution) {
-
- super(name, width, height, rotation, widthResolution, heightResolution);
-
- }
-
- /**
- * Adds an overlay to the page resources
- * @param overlay the overlay to add
- */
- public void addOverlay(Overlay overlay) {
- if (resourceGroup == null) {
- resourceGroup = new ResourceGroup();
- }
- resourceGroup.addOverlay(overlay);
- }
-
- /**
- * Creates an IncludePageOverlay on the page.
- *
- * @param name
- * the name of the overlay
- * @param x
- * the x position of the overlay
- * @param y
- * the y position of the overlay
- * @param orientation
- * the orientation required for the overlay
- */
- public void createIncludePageOverlay(String name, int x, int y, int orientation) {
-
- IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation);
- objects.add(ipo);
-
- }
-
- /**
- * Accessor method to write the AFP datastream for the page.
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- if (resourceGroup != null) {
- resourceGroup.writeDataStream(os);
- }
-
- activeEnvironmentGroup.writeDataStream(os);
-
- writeObjectList(segments, os);
-
- writeObjectList(tagLogicalElements, os);
-
- writeObjectList(objects, os);
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the page.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0xAF; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the page.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xAF; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
deleted file mode 100644
index c0f06439e..000000000
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
+++ /dev/null
@@ -1,337 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.awt.Color;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-
-/**
- * The Presentation Text object is the data object used in document processing
- * environments for representing text which has been prepared for presentation.
- * Text, as used here, means an ordered string of characters, such as graphic
- * symbols, numbers, and letters, that are suitable for the specific purpose of
- * representing coherent information. Text which has been prepared for
- * presentation has been reduced to a primitive form through explicit
- * specification of the characters and their placement in the presentation
- * space. Control sequences which designate specific control functions may be
- * embedded within the text. These functions extend the primitive form by
- * applying specific characteristics to the text when it is presented. The
- * collection of the graphic characters and control codes is called Presentation
- * Text, and the object that contains the Presentation Text is called the
- * PresentationText object.
- *
- */
-public class PresentationTextObject extends AbstractNamedAFPObject {
-
- /**
- * Default name for the presentation text object
- */
- private static final String DEFAULT_NAME = "PTO00001";
-
- private PresentationTextData currentPresentationTextData = null;
-
- private ArrayList presentationTextData = new ArrayList();
-
- /**
- * Default constructor for the PresentationTextObject
- */
- public PresentationTextObject() {
-
- this(DEFAULT_NAME);
-
- }
-
- /**
- * Construct a new PresentationTextObject for the specified name argument,
- * the name should be an 8 character identifier.
- * @param name the name of this presentation object
- */
- public PresentationTextObject(String name) {
-
- super(name);
-
- }
-
- /**
- * Create the presentation text data for the byte array of data.
- *
- * @param fontNumber
- * The font resource identifier.
- * @param x
- * The x coordinate for the text data.
- * @param y
- * The y coordinate for the text data.
- * @param col
- * The text color.
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character increment.
- * @param data
- * The text data to be created.
- */
- public void createTextData(int fontNumber, int x, int y, Color col,
- int vsci, int ica, byte[] data) {
-
- // Use a default orientation of zero
- createTextData(fontNumber, x, y, 0, col, vsci, ica, data);
-
- }
-
- /**
- * Create the presentation text data for the byte array of data.
- *
- * @param fontNumber
- * The font resource identifier.
- * @param x
- * The x coordinate for the text data.
- * @param y
- * The y coordinate for the text data.
- * @param orientation
- * The orientation of the text data.
- * @param col
- * The text color.
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * The text data to be created.
- */
- public void createTextData(int fontNumber, int x, int y, int orientation,
- Color col, int vsci, int ica, byte[] data) {
-
- if (currentPresentationTextData == null) {
- startPresentationTextData();
- }
-
- try {
-
- currentPresentationTextData.createTextData(fontNumber, x, y,
- orientation, col, vsci, ica, data);
-
- } catch (MaximumSizeExceededException msee) {
-
- endPresentationTextData();
- createTextData(fontNumber, x, y, orientation, col, vsci, ica, data);
-
- }
-
- }
-
- /**
- * Drawing of lines using the starting and ending coordinates, thickness.
- *
- * @param x1
- * The first x coordinate of the line.
- * @param y1
- * The first y coordinate of the line.
- * @param x2
- * The second x coordinate of the line.
- * @param y2
- * The second y coordinate of the line.
- * @param thickness
- * The thickness of the line.
- * @param col
- * The text color.
- */
- public void createLineData(int x1, int y1, int x2, int y2, int thickness, Color col) {
- // Default orientation
- createLineData(x1, y1, x2, y2, thickness, 0, col);
- }
-
- /**
- * Drawing of lines using the starting and ending coordinates, thickness and
- * orientation arguments.
- *
- * @param x1
- * The first x coordinate of the line.
- * @param y1
- * The first y coordinate of the line.
- * @param x2
- * The second x coordinate of the line.
- * @param y2
- * The second y coordinate of the line.
- * @param thickness
- * The thickness of the line.
- * @param orientation
- * The orientation of the line.
- * @param col
- * The text color.
- */
- public void createLineData(int x1, int y1, int x2, int y2, int thickness,
- int orientation, Color col) {
-
- if (currentPresentationTextData == null) {
- startPresentationTextData();
- }
-
- try {
-
- currentPresentationTextData.createLineData(x1, y1, x2, y2,
- thickness, orientation, col);
-
- } catch (MaximumSizeExceededException msee) {
-
- endPresentationTextData();
- createLineData(x1, y1, x2, y2, thickness, orientation, col);
-
- }
-
- }
-
- /**
- * Helper method to mark the start of the presentation text data
- */
- private void startPresentationTextData() {
-
- if (presentationTextData.size() == 0) {
- currentPresentationTextData = new PresentationTextData(true);
- } else {
- currentPresentationTextData = new PresentationTextData();
- }
-
- presentationTextData.add(currentPresentationTextData);
-
- }
-
- /**
- * Helper method to mark the end of the presentation text data
- */
- private void endPresentationTextData() {
-
- currentPresentationTextData = null;
-
- }
-
- /**
- * Accessor method to write the AFP datastream for the PresentationTextObject.
- * @param os The stream to write to
- * @throws java.io.IOException thrown if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- writeObjectList(presentationTextData, os);
-
- writeEnd(os);
-
- }
-
- /**
- * Returns the name of this presentation text object
- * @return the name of this presentation text object
- */
- public String getName() {
-
- return name;
-
- }
-
- /**
- * Helper method to write the start of the presenation text object.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0x9B; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the presenation text object.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0x9B; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * A control sequence is a sequence of bytes that specifies a control
- * function. A control sequence consists of a control sequence introducer
- * and zero or more parameters. The control sequence can extend multiple
- * presentation text data objects, but must eventually be terminated. This
- * method terminates the control sequence.
- */
- public void endControlSequence() {
-
- if (currentPresentationTextData == null) {
- startPresentationTextData();
- }
-
- try {
-
- currentPresentationTextData.endControlSequence();
-
- } catch (MaximumSizeExceededException msee) {
-
- endPresentationTextData();
- endControlSequence();
-
- }
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java
deleted file mode 100644
index 07043dcf1..000000000
--- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java
+++ /dev/null
@@ -1,154 +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.
- */
-
-/* $Id$ */
-
-package org.apache.fop.render.afp.modca;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A Resource Group contains a set of overlays.
- */
-public final class ResourceGroup extends AbstractNamedAFPObject {
-
- /**
- * Default name for the resource group
- */
- private static final String DEFAULT_NAME = "RG000001";
-
-
- /**
- * The overlays contained in this resource group
- */
- private List overlays = new ArrayList();
-
- /**
- * Default constructor
- */
- public ResourceGroup() {
-
- this(DEFAULT_NAME);
-
- }
-
- /**
- * Constructor for the ResourceGroup, this takes a
- * name parameter which must be 8 characters long.
- * @param name the resource group name
- */
- public ResourceGroup(String name) {
-
- super(name);
-
- }
-
- /**
- * Adds an overlay to the resource group
- * @param overlay the overlay to add
- */
- public void addOverlay(Overlay overlay) {
- overlays.add(overlay);
- }
-
- /**
- * Returns the list of overlays
- * @return the list of overlays
- */
- public List getOverlays() {
- return overlays;
- }
-
- /**
- * Accessor method to obtain write the AFP datastream for
- * the resource group.
- * @param os The stream to write to
- * @throws java.io.IOException if an I/O exception of some sort has occurred
- */
- public void writeDataStream(OutputStream os)
- throws IOException {
-
- writeStart(os);
-
- writeObjectList(overlays, os);
-
- writeEnd(os);
-
- }
-
- /**
- * Helper method to write the start of the resource group.
- * @param os The stream to write to
- */
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA8; // Structured field id byte 2
- data[5] = (byte) 0xC6; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
- /**
- * Helper method to write the end of the resource group.
- * @param os The stream to write to
- */
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[17];
-
- data[0] = 0x5A; // Structured field identifier
- data[1] = 0x00; // Length byte 1
- data[2] = 0x10; // Length byte 2
- data[3] = (byte) 0xD3; // Structured field id byte 1
- data[4] = (byte) 0xA9; // Structured field id byte 2
- data[5] = (byte) 0xC6; // Structured field id byte 3
- data[6] = 0x00; // Flags
- data[7] = 0x00; // Reserved
- data[8] = 0x00; // Reserved
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
- os.write(data);
-
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/package.html b/src/java/org/apache/fop/render/afp/package.html
new file mode 100644
index 000000000..3e611d964
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/package.html
@@ -0,0 +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.
+-->
+<!-- $Id: package.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.render.afp Package</TITLE>
+<BODY>
+<P>An AFP Renderer implementation and supporting classes.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java
index f67c2c7a2..5b4c6b13a 100644
--- a/src/java/org/apache/fop/render/awt/AWTRenderer.java
+++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java
@@ -149,14 +149,11 @@ public class AWTRenderer extends Java2DRenderer implements Pageable {
Rectangle2D bounds = getPageViewport(pageNum).getViewArea();
pageWidth = (int) Math.round(bounds.getWidth() / 1000f);
pageHeight = (int) Math.round(bounds.getHeight() / 1000f);
- double scaleX = scaleFactor
+ double scale = scaleFactor
* (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION)
/ userAgent.getTargetPixelUnitToMillimeter();
- double scaleY = scaleFactor
- * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION)
- / userAgent.getTargetPixelUnitToMillimeter();
- int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5);
- int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5);
+ int bitmapWidth = (int) ((pageWidth * scale) + 0.5);
+ int bitmapHeight = (int) ((pageHeight * scale) + 0.5);
return new Dimension(bitmapWidth, bitmapHeight);
}
diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
index 65e6ac0fe..933398125 100644
--- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
@@ -135,7 +135,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
/** The current state, holds a Graphics2D and its context */
protected Java2DGraphicsState state;
- private Stack stateStack = new Stack();
+ private final Stack stateStack = new Stack();
/** true if the renderer has finished rendering all the pages */
private boolean renderingDone;
@@ -146,9 +146,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
public Java2DRenderer() {
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void setUserAgent(FOUserAgent foUserAgent) {
super.setUserAgent(foUserAgent);
userAgent.setRendererOverride(this); // for document regeneration
@@ -164,9 +162,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
return userAgent;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void setupFontInfo(FontInfo inFontInfo) {
//Don't call super.setupFontInfo() here! Java2D needs a special font setup
// create a temp Image to test font metrics on
@@ -437,16 +433,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
state.transform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void endVParea() {
restoreGraphicsState();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected List breakOutOfStateStack() {
log.debug("Block.FIXED --> break out");
List breakOutList;
@@ -459,10 +451,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
return breakOutList;
}
- /**
- * {@inheritDoc}
- * java.util.List)
- */
+ /** {@inheritDoc} */
protected void restoreStateStackAfterBreakOut(List breakOutList) {
log.debug("Block.FIXED --> restoring context after break-out");
@@ -474,16 +463,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void updateColor(Color col, boolean fill) {
state.updateColor(col);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void clip() {
if (currentPath == null) {
throw new IllegalStateException("No current path available!");
@@ -492,16 +477,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
currentPath = null;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void closePath() {
currentPath.closePath();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void lineTo(float x, float y) {
if (currentPath == null) {
currentPath = new GeneralPath();
@@ -509,9 +490,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
currentPath.lineTo(x, y);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void moveTo(float x, float y) {
if (currentPath == null) {
currentPath = new GeneralPath();
@@ -519,23 +498,17 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
currentPath.moveTo(x, y);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void clipRect(float x, float y, float width, float height) {
state.updateClip(new Rectangle2D.Float(x, y, width, height));
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void fillRect(float x, float y, float width, float height) {
state.getGraph().fill(new Rectangle2D.Float(x, y, width, height));
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void drawBorderLine(float x1, float y1, float x2, float y2,
boolean horz, boolean startOrBefore, int style, Color col) {
Graphics2D g2d = state.getGraph();
@@ -706,9 +679,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void renderText(TextArea text) {
renderInlineAreaBackAndBorders(text);
@@ -890,18 +861,20 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
super.renderLeader(area);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void renderImage(Image image, Rectangle2D pos) {
// endTextObject();
String url = image.getURL();
drawImage(url, pos);
}
- /**
- * {@inheritDoc}
- */
+ private static final ImageFlavor[] FLAVOURS = new ImageFlavor[]
+ {ImageFlavor.GRAPHICS2D,
+ ImageFlavor.BUFFERED_IMAGE,
+ ImageFlavor.RENDERED_IMAGE,
+ ImageFlavor.XML_DOM};
+
+ /** {@inheritDoc} */
protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
int x = currentIPPosition + (int)Math.round(pos.getX());
@@ -913,14 +886,9 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
try {
ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
info = manager.getImageInfo(uri, sessionContext);
- final ImageFlavor[] flavors = new ImageFlavor[]
- {ImageFlavor.GRAPHICS2D,
- ImageFlavor.BUFFERED_IMAGE,
- ImageFlavor.RENDERED_IMAGE,
- ImageFlavor.XML_DOM};
Map hints = ImageUtil.getDefaultHints(sessionContext);
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
- info, flavors, hints, sessionContext);
+ info, FLAVOURS, hints, sessionContext);
if (img instanceof ImageGraphics2D) {
ImageGraphics2D imageG2D = (ImageGraphics2D)img;
int width = (int)pos.getWidth();
diff --git a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java
index 12b269a44..99502096c 100644
--- a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java
@@ -20,6 +20,8 @@
package org.apache.fop.render.java2d;
import java.awt.geom.AffineTransform;
+import java.io.IOException;
+import java.util.Map;
import org.w3c.dom.Document;
@@ -29,9 +31,11 @@ import org.apache.batik.gvt.GraphicsNode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.render.AbstractGenericSVGHandler;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererContextConstants;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
@@ -66,6 +70,11 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler
pdfi.height = ((Integer)context.getProperty(HEIGHT)).intValue();
pdfi.currentXPosition = ((Integer)context.getProperty(XPOS)).intValue();
pdfi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue();
+ Map foreign = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
+ if (foreign != null
+ && BITMAP.equalsIgnoreCase((String)foreign.get(CONVERSION_MODE))) {
+ pdfi.paintAsBitmap = true;
+ }
return pdfi;
}
@@ -83,6 +92,7 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler
public int currentXPosition;
/** see Java2D_YPOS */
public int currentYPosition;
+ public boolean paintAsBitmap;
/** {@inheritDoc} */
public String toString() {
@@ -91,7 +101,8 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler
+ "width = " + width + ", "
+ "height = " + height + ", "
+ "currentXPosition = " + currentXPosition + ", "
- + "currentYPosition = " + currentYPosition + "}";
+ + "currentYPosition = " + currentYPosition + ", "
+ + "paintAsBitmap = " + paintAsBitmap + "}";
}
}
@@ -103,17 +114,33 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler
log.debug("renderSVGDocument(" + context + ", " + doc + ", " + info + ")");
}
+ // fallback paint as bitmap
+ if (info.paintAsBitmap) {
+ try {
+ super.renderSVGDocument(context, doc);
+ } catch (IOException ioe) {
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+ context.getUserAgent().getEventBroadcaster());
+ eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc));
+ }
+ return;
+ }
+
int x = info.currentXPosition;
int y = info.currentYPosition;
SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
- GVTBuilder builder = new GVTBuilder();
BridgeContext ctx = new BridgeContext(ua);
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+ //to it.
+ Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
+
GraphicsNode root;
try {
- root = builder.build(ctx, doc);
+ GVTBuilder builder = new GVTBuilder();
+ root = builder.build(ctx, clonedDoc);
} catch (Exception e) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
context.getUserAgent().getEventBroadcaster());
@@ -126,8 +153,8 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler
float iw = (float) ctx.getDocumentSize().getWidth() * 1000f;
float ih = (float) ctx.getDocumentSize().getHeight() * 1000f;
- float w = (float) info.width;
- float h = (float) info.height;
+ float w = info.width;
+ float h = info.height;
AffineTransform origTransform = info.state.getGraph().getTransform();
diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java
index 509d4538e..b492f1b07 100644
--- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java
+++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java
@@ -534,7 +534,7 @@ public class PCLRenderer extends PrintRenderer implements PCLConstants {
public Dimension getImageSize() {
return paintRect.getSize();
}
-
+
};
g2a.paintImage(painter, rc,
paintRect.x, paintRect.y, paintRect.width, paintRect.height);
diff --git a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
index 70e0f7eb5..4b0f35bec 100644
--- a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
+++ b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
@@ -29,8 +29,8 @@ import org.apache.fop.pdf.PDFColor;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFNumber;
+import org.apache.fop.pdf.PDFPaintingState;
import org.apache.fop.pdf.PDFResourceContext;
-import org.apache.fop.pdf.PDFState;
import org.apache.fop.pdf.PDFStream;
import org.apache.fop.pdf.PDFTextUtil;
import org.apache.fop.pdf.PDFXObject;
@@ -52,7 +52,7 @@ public class PDFContentGenerator {
private PDFStream currentStream;
/** drawing state */
- protected PDFState currentState = null;
+ protected PDFPaintingState currentState = null;
/** Text generation utility holding the current font status */
protected PDFTextUtil textutil;
@@ -77,7 +77,7 @@ public class PDFContentGenerator {
}
};
- this.currentState = new PDFState();
+ this.currentState = new PDFPaintingState();
}
/**
@@ -116,7 +116,7 @@ public class PDFContentGenerator {
* Returns the {@code PDFState} associated with this instance.
* @return the PDF state
*/
- public PDFState getState() {
+ public PDFPaintingState getState() {
return this.currentState;
}
@@ -149,7 +149,7 @@ public class PDFContentGenerator {
/** {@inheritDoc} */
protected void saveGraphicsState() {
endTextObject();
- currentState.push();
+ currentState.save();
currentStream.add("q\n");
}
@@ -162,7 +162,7 @@ public class PDFContentGenerator {
endTextObject();
currentStream.add("Q\n");
if (popState) {
- currentState.pop();
+ currentState.restore();
}
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
index 4da7f13cb..102c1ab45 100644
--- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
+++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
@@ -98,7 +98,7 @@ public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter {
AffineTransform transform = new AffineTransform();
transform.translate(fx, fy);
generator.getState().concatenate(transform);
- graphics.setPDFState(generator.getState());
+ graphics.setPaintingState(generator.getState());
graphics.setOutputStream(pdfInfo.outputStream);
if (pdfInfo.paintAsBitmap) {
diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java
index f93ee5a97..934d306b9 100644
--- a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java
@@ -24,35 +24,15 @@ import java.awt.Rectangle;
import java.io.IOException;
import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.fop.pdf.PDFXObject;
+import org.apache.fop.render.ImageHandlerBase;
import org.apache.fop.render.RendererContext;
/**
* This interface is used for handling all sorts of image type for PDF output.
*/
-public interface PDFImageHandler {
-
- /**
- * Returns the priority for this image handler. A lower value means higher priority. This
- * information is used to build the ordered/prioritized list of supported ImageFlavors for
- * the PDF renderer. The built-in handlers use priorities between 100 and 999.
- * @return a positive integer (>0) indicating the priority
- */
- int getPriority();
-
- /**
- * Returns the {@link ImageFlavor}s supported by this instance
- * @return the supported image flavors
- */
- ImageFlavor[] getSupportedImageFlavors();
-
- /**
- * Returns the {@link Image} subclass supported by this instance.
- * @return the Image type
- */
- Class getSupportedImageClass();
+public interface PDFImageHandler extends ImageHandlerBase {
/**
* Generates the PDF objects for the given {@link Image} instance. If the handler generates
diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java
index 610fa274f..18717809d 100644
--- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java
+++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java
@@ -108,7 +108,7 @@ public class PDFImageHandlerGraphics2D extends AbstractImageHandlerGraphics2D
AffineTransform transform = new AffineTransform();
transform.translate(fx, fy);
generator.getState().concatenate(transform);
- graphics.setPDFState(generator.getState());
+ graphics.setPaintingState(generator.getState());
graphics.setOutputStream(generator.getOutputStream());
Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java
index b664a0a24..1d4c733a3 100644
--- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java
+++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java
@@ -19,171 +19,18 @@
package org.apache.fop.render.pdf;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
-import org.apache.xmlgraphics.util.Service;
+import org.apache.fop.render.AbstractImageHandlerRegistry;
/**
* This class holds references to various image handlers used by the PDF renderer. It also
* supports automatic discovery of additional handlers available through
* the class path.
*/
-public class PDFImageHandlerRegistry {
-
- /** the logger */
- private static Log log = LogFactory.getLog(PDFImageHandlerRegistry.class);
-
- private static final Comparator HANDLER_COMPARATOR = new Comparator() {
- public int compare(Object o1, Object o2) {
- PDFImageHandler h1 = (PDFImageHandler)o1;
- PDFImageHandler h2 = (PDFImageHandler)o2;
- return h1.getPriority() - h2.getPriority();
- }
- };
-
- /** Map containing PDF image handlers for various MIME types */
- private Map handlers = new java.util.HashMap();
- /** List containing the same handlers as above but ordered by priority */
- private List handlerList = new java.util.LinkedList();
+public class PDFImageHandlerRegistry extends AbstractImageHandlerRegistry {
- /** Sorted Set of registered handlers */
- private ImageFlavor[] supportedFlavors = new ImageFlavor[0];
- private int handlerRegistrations;
- private int lastSync;
-
- /**
- * Default constructor.
- */
- public PDFImageHandlerRegistry() {
- discoverHandlers();
- }
-
- /**
- * Add an PDFImageHandler. The handler itself is inspected to find out what it supports.
- * @param classname the fully qualified class name
- */
- public void addHandler(String classname) {
- try {
- PDFImageHandler handlerInstance
- = (PDFImageHandler)Class.forName(classname).newInstance();
- addHandler(handlerInstance);
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("Could not find "
- + classname);
- } catch (InstantiationException e) {
- throw new IllegalArgumentException("Could not instantiate "
- + classname);
- } catch (IllegalAccessException e) {
- throw new IllegalArgumentException("Could not access "
- + classname);
- } catch (ClassCastException e) {
- throw new IllegalArgumentException(classname
- + " is not an "
- + PDFImageHandler.class.getName());
- }
+ /** {@inheritDoc} */
+ public Class getHandlerClass() {
+ return PDFImageHandler.class;
}
- /**
- * Add an image handler. The handler itself is inspected to find out what it supports.
- * @param handler the PDFImageHandler instance
- */
- public synchronized void addHandler(PDFImageHandler handler) {
- Class imageClass = handler.getSupportedImageClass();
- this.handlers.put(imageClass, handler);
-
- //Sorted insert
- ListIterator iter = this.handlerList.listIterator();
- while (iter.hasNext()) {
- PDFImageHandler h = (PDFImageHandler)iter.next();
- if (HANDLER_COMPARATOR.compare(handler, h) < 0) {
- iter.previous();
- break;
- }
- }
- iter.add(handler);
- this.handlerRegistrations++;
- }
-
- /**
- * Returns an PDFImageHandler which handles an specific image type given the MIME type
- * of the image.
- * @param img the Image to be handled
- * @return the PDFImageHandler responsible for handling the image or null if none is available
- */
- public PDFImageHandler getHandler(Image img) {
- return getHandler(img.getClass());
- }
-
- /**
- * Returns an PDFImageHandler which handles an specific image type given the MIME type
- * of the image.
- * @param imageClass the Image subclass for which to get a handler
- * @return the PDFImageHandler responsible for handling the image or null if none is available
- */
- protected synchronized PDFImageHandler getHandler(Class imageClass) {
- PDFImageHandler handler = null;
- Class cl = imageClass;
- while (cl != null) {
- handler = (PDFImageHandler)handlers.get(cl);
- if (handler != null) {
- break;
- }
- cl = cl.getSuperclass();
- }
- return handler;
- }
-
- /**
- * Returns the ordered array of supported image flavors.
- * @return the array of image flavors
- */
- public synchronized ImageFlavor[] getSupportedFlavors() {
- if (this.lastSync != this.handlerRegistrations) {
- //Extract all ImageFlavors into a single array
- List flavors = new java.util.ArrayList();
- Iterator iter = this.handlerList.iterator();
- while (iter.hasNext()) {
- ImageFlavor[] f = ((PDFImageHandler)iter.next()).getSupportedImageFlavors();
- for (int i = 0; i < f.length; i++) {
- flavors.add(f[i]);
- }
- }
- this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]);
- this.lastSync = this.handlerRegistrations;
- }
- return this.supportedFlavors;
- }
-
- /**
- * Discovers PDFImageHandler implementations through the classpath and dynamically
- * registers them.
- */
- private void discoverHandlers() {
- // add mappings from available services
- Iterator providers = Service.providers(PDFImageHandler.class);
- if (providers != null) {
- while (providers.hasNext()) {
- PDFImageHandler handler = (PDFImageHandler)providers.next();
- try {
- if (log.isDebugEnabled()) {
- log.debug("Dynamically adding PDFImageHandler: "
- + handler.getClass().getName());
- }
- addHandler(handler);
- } catch (IllegalArgumentException e) {
- log.error("Error while adding PDFImageHandler", e);
- }
-
- }
- }
- }
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
index 3764486b7..d1b7aa986 100644
--- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
+++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
@@ -148,7 +148,7 @@ public class PDFImageHandlerSVG implements ImageHandler {
generator.comment("SVG start");
//Save state and update coordinate system for the SVG image
- generator.getState().push();
+ generator.getState().save();
generator.getState().concatenate(imageTransform);
//Now that we have the complete transformation matrix for the image, we can update the
@@ -157,7 +157,7 @@ public class PDFImageHandlerSVG implements ImageHandler {
SVGDOMImplementation.SVG_NAMESPACE_URI, SVGConstants.SVG_A_TAG);
aBridge.getCurrentTransform().setTransform(generator.getState().getTransform());
- graphics.setPDFState(generator.getState());
+ graphics.setPaintingState(generator.getState());
graphics.setOutputStream(generator.getOutputStream());
try {
root.paint(graphics);
@@ -167,7 +167,7 @@ public class PDFImageHandlerSVG implements ImageHandler {
context.getUserAgent().getEventBroadcaster());
eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
}
- generator.getState().pop();
+ generator.getState().restore();
generator.restoreGraphicsState();
generator.comment("SVG end");
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java
index d111e733f..26ba83371 100644
--- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java
+++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java
@@ -24,14 +24,12 @@ import java.awt.Rectangle;
import java.io.IOException;
import java.util.Map;
-import org.w3c.dom.Document;
-
+import org.apache.fop.pdf.PDFXObject;
+import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
-
-import org.apache.fop.pdf.PDFXObject;
-import org.apache.fop.render.RendererContext;
+import org.w3c.dom.Document;
/**
* PDFImageHandler implementation which handles XML-based images.
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 730acb540..e0e1bab69 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -82,9 +82,9 @@ import org.apache.fop.pdf.PDFLink;
import org.apache.fop.pdf.PDFNumber;
import org.apache.fop.pdf.PDFOutline;
import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFPaintingState;
import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFResources;
-import org.apache.fop.pdf.PDFState;
import org.apache.fop.pdf.PDFTextUtil;
import org.apache.fop.pdf.PDFXMode;
import org.apache.fop.pdf.PDFXObject;
@@ -92,8 +92,9 @@ import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.traits.RuleStyle;
+import org.apache.fop.util.AbstractPaintingState;
import org.apache.fop.util.CharUtilities;
-import org.apache.fop.util.ColorUtil;
+import org.apache.fop.util.AbstractPaintingState.AbstractData;
/**
* Renderer that renders areas to PDF.
@@ -190,7 +191,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
protected int pageHeight;
/** Image handler registry */
- private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();
+ private final PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();
/**
@@ -213,7 +214,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
return this.generator;
}
- PDFState getState() {
+ PDFPaintingState getState() {
return getGenerator().getState();
}
@@ -262,11 +263,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
//pvReferences.clear();
pdfResources = null;
this.generator = null;
- //currentStream = null;
currentContext = null;
currentPage = null;
- //currentState = null;
- //this.textutil = null;
idPositions.clear();
idGoTos.clear();
@@ -505,7 +503,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
}
// multiply with current CTM
generator.concatenate(new AffineTransform(CTMHelper.toPDFArray(ctm)));
- //currentStream.add(CTMHelper.toPDFString(ctm) + " cm\n");
}
/** {@inheritDoc} */
@@ -516,11 +513,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
/** {@inheritDoc} */
protected void concatenateTransformationMatrix(AffineTransform at) {
generator.concatenate(at);
- /*
- if (!at.isIdentity()) {
- currentState.concatenate(at);
- currentStream.add(CTMHelper.toPDFString(at, false) + " cm\n");
- }*/
}
/**
@@ -582,10 +574,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
/**
* {@inheritDoc}
*/
- protected void fillRect(float x, float y, float w, float h) {
- if (w != 0 && h != 0) {
+ protected void fillRect(float x, float y, float width, float height) {
+ if (width > 0 && height > 0) {
generator.add(format(x) + " " + format(y) + " "
- + format(w) + " " + format(h) + " re f\n");
+ + format(width) + " " + format(height) + " re f\n");
}
}
@@ -607,11 +599,12 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
* @return the saved state stack to recreate later
*/
protected List breakOutOfStateStack() {
+ PDFPaintingState paintingState = getState();
List breakOutList = new java.util.ArrayList();
- PDFState.Data data;
+ AbstractPaintingState.AbstractData data;
while (true) {
- data = getState().getData();
- if (getState().pop() == null) {
+ data = paintingState.getData();
+ if (paintingState.restore() == null) {
break;
}
if (breakOutList.size() == 0) {
@@ -629,10 +622,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
*/
protected void restoreStateStackAfterBreakOut(List breakOutList) {
generator.comment("------ restoring context after break-out...");
- PDFState.Data data;
+// currentState.pushAll(breakOutList);
+ AbstractData data;
Iterator i = breakOutList.iterator();
while (i.hasNext()) {
- data = (PDFState.Data)i.next();
+ data = (AbstractData)i.next();
saveGraphicsState();
AffineTransform at = data.getTransform();
concatenateTransformationMatrix(at);
@@ -1131,7 +1125,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
info, supportedFlavors, hints, sessionContext);
//First check for a dynamically registered handler
- PDFImageHandler handler = imageHandlerRegistry.getHandler(img.getClass());
+ PDFImageHandler handler
+ = (PDFImageHandler)imageHandlerRegistry.getHandler(img.getClass());
if (handler != null) {
if (log.isDebugEnabled()) {
log.debug("Using PDFImageHandler: " + handler.getClass().getName());
@@ -1170,6 +1165,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
this.generator.flushPDFDoc();
} catch (IOException ioe) {
// ioexception will be caught later
+ log.error(ioe.getMessage());
}
}
@@ -1198,7 +1194,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
x, y, width, height, foreignAttributes);
context.setProperty(PDFRendererContextConstants.PDF_DOCUMENT, pdfDoc);
context.setProperty(PDFRendererContextConstants.OUTPUT_STREAM, ostream);
- context.setProperty(PDFRendererContextConstants.PDF_STATE, getState());
context.setProperty(PDFRendererContextConstants.PDF_PAGE, currentPage);
context.setProperty(PDFRendererContextConstants.PDF_CONTEXT,
currentContext == null ? currentPage : currentContext);
diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
index d416f1147..fccba1c25 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
@@ -54,6 +54,7 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator
/**
* Default constructor
+ *
* @param userAgent user agent
*/
public PDFRendererConfigurator(FOUserAgent userAgent) {
@@ -64,6 +65,7 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator
* Configure the PDF renderer.
* Get the configuration to be used for pdf stream filters,
* fonts etc.
+ *
* @param renderer pdf renderer
* @throws FOPException fop exception
*/
@@ -97,7 +99,8 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator
if (s != null) {
pdfUtil.setXMode(PDFXMode.valueOf(s));
}
- Configuration encryptionParamsConfig = cfg.getChild(PDFRenderer.ENCRYPTION_PARAMS, false);
+ Configuration encryptionParamsConfig
+ = cfg.getChild(PDFRenderer.ENCRYPTION_PARAMS, false);
if (encryptionParamsConfig != null) {
PDFEncryptionParams encryptionParams = new PDFEncryptionParams();
Configuration ownerPasswordConfig = encryptionParamsConfig.getChild(
@@ -142,8 +145,8 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator
if (s != null) {
pdfUtil.setOutputProfileURI(s);
}
- Configuration disableColorSpaceConfig
- = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false);
+ Configuration disableColorSpaceConfig = cfg.getChild(
+ PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false);
if (disableColorSpaceConfig != null) {
pdfUtil.setDisableSRGBColorSpace(
disableColorSpaceConfig.getValueAsBoolean(false));
@@ -152,6 +155,7 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator
/**
* Builds a filter map from an Avalon Configuration object.
+ *
* @param cfg the Configuration object
* @return Map the newly built filter map
* @throws ConfigurationException if a filter list is defined twice
diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java b/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java
index de51aabc7..11380bf59 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java
@@ -29,9 +29,6 @@ public interface PDFRendererContextConstants extends RendererContextConstants {
/** The PDF document that this image is being drawn into. */
String PDF_DOCUMENT = "pdfDoc";
- /** The current pdf state. */
- String PDF_STATE = "pdfState";
-
/** The current PDF page for page renference and as a resource context. */
String PDF_PAGE = "pdfPage";
diff --git a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java
index 11d9b1c3f..8f7aad300 100644
--- a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java
@@ -36,11 +36,9 @@ import org.apache.batik.util.SVGConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.xmlgraphics.util.QName;
-
import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFPage;
import org.apache.fop.pdf.PDFResourceContext;
@@ -89,9 +87,9 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
pdfi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue();
pdfi.cfg = (Configuration)context.getProperty(HANDLER_CONFIGURATION);
Map foreign = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
- QName qName = new QName(ExtensionElementMapping.URI, null, "conversion-mode");
+
if (foreign != null
- && "bitmap".equalsIgnoreCase((String)foreign.get(qName))) {
+ && BITMAP.equalsIgnoreCase((String)foreign.get(CONVERSION_MODE))) {
pdfi.paintAsBitmap = true;
}
return pdfi;
@@ -105,8 +103,6 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
public PDFDocument pdfDoc;
/** see OUTPUT_STREAM */
public OutputStream outputStream;
- /** see PDF_STATE */
- //public PDFState pdfState;
/** see PDF_PAGE */
public PDFPage pdfPage;
/** see PDF_CONTEXT */
@@ -167,8 +163,6 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
AffineTransform resolutionScaling = new AffineTransform();
resolutionScaling.scale(s, s);
- GVTBuilder builder = new GVTBuilder();
-
//Controls whether text painted by Batik is generated using text or path operations
boolean strokeText = false;
Configuration cfg = pdfInfo.cfg;
@@ -182,10 +176,14 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
userAgent.getImageSessionContext(),
new AffineTransform());
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+ //to it.
+ Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
+
GraphicsNode root;
try {
- root = builder.build(ctx, doc);
- builder = null;
+ GVTBuilder builder = new GVTBuilder();
+ root = builder.build(ctx, clonedDoc);
} catch (Exception e) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
context.getUserAgent().getEventBroadcaster());
@@ -196,8 +194,8 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
- float sx = pdfInfo.width / (float)w;
- float sy = pdfInfo.height / (float)h;
+ float sx = pdfInfo.width / w;
+ float sy = pdfInfo.height / h;
//Scaling and translation for the bounding box of the image
AffineTransform scaling = new AffineTransform(
@@ -247,7 +245,7 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
generator.comment("SVG start");
//Save state and update coordinate system for the SVG image
- generator.getState().push();
+ generator.getState().save();
generator.getState().concatenate(imageTransform);
//Now that we have the complete transformation matrix for the image, we can update the
@@ -256,7 +254,7 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
SVGDOMImplementation.SVG_NAMESPACE_URI, SVGConstants.SVG_A_TAG);
aBridge.getCurrentTransform().setTransform(generator.getState().getTransform());
- graphics.setPDFState(generator.getState());
+ graphics.setPaintingState(generator.getState());
graphics.setOutputStream(pdfInfo.outputStream);
try {
root.paint(graphics);
@@ -266,7 +264,7 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
context.getUserAgent().getEventBroadcaster());
eventProducer.svgRenderingError(this, e, getDocumentURI(doc));
}
- generator.getState().pop();
+ generator.getState().restore();
generator.restoreGraphicsState();
generator.comment("SVG end");
}
diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java
index e5d8200b7..542a69a4a 100644
--- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java
+++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java
@@ -33,6 +33,7 @@ import org.apache.xmlgraphics.util.QName;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.render.AbstractGraphics2DAdapter;
+import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RendererContextConstants;
import org.apache.fop.render.RendererContext.RendererContextWrapper;
diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java
index 1e65dfb98..7171efb4e 100644
--- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java
+++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java
@@ -37,6 +37,7 @@ import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.render.AbstractGenericSVGHandler;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
@@ -258,7 +259,6 @@ public class PSSVGHandler extends AbstractGenericSVGHandler
PSGraphics2D graphics = new PSGraphics2D(strokeText, gen);
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
- GVTBuilder builder = new GVTBuilder();
NativeTextHandler nativeTextHandler = null;
BridgeContext ctx = new BridgeContext(ua);
if (!strokeText) {
@@ -271,9 +271,14 @@ public class PSSVGHandler extends AbstractGenericSVGHandler
ctx.putBridge(tBridge);
}
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+ //to it.
+ Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
+
GraphicsNode root;
try {
- root = builder.build(ctx, doc);
+ GVTBuilder builder = new GVTBuilder();
+ root = builder.build(ctx, clonedDoc);
} catch (Exception e) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
context.getUserAgent().getEventBroadcaster());
@@ -288,7 +293,6 @@ public class PSSVGHandler extends AbstractGenericSVGHandler
float sy = psInfo.getHeight() / h;
ctx = null;
- builder = null;
try {
gen.commentln("%FOPBeginSVG");
diff --git a/src/java/org/apache/fop/render/ps/PSTextPainter.java b/src/java/org/apache/fop/render/ps/PSTextPainter.java
index 31cb4b605..a318c6465 100644
--- a/src/java/org/apache/fop/render/ps/PSTextPainter.java
+++ b/src/java/org/apache/fop/render/ps/PSTextPainter.java
@@ -19,41 +19,35 @@
package org.apache.fop.render.ps;
+import java.awt.Color;
import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.font.TextAttribute;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-/* java.awt.Font is not imported to avoid confusion with
- org.apache.fop.fonts.Font */
-
+import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
-import java.awt.font.TextAttribute;
-import java.awt.Shape;
-import java.awt.Paint;
-import java.awt.Stroke;
-import java.awt.Color;
-import java.io.IOException;
-import java.util.List;
import java.util.Iterator;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
-import org.apache.xmlgraphics.java2d.TextHandler;
+import java.util.List;
import org.apache.batik.dom.svg.SVGOMTextElement;
-import org.apache.batik.gvt.text.Mark;
-import org.apache.batik.gvt.TextPainter;
import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
-import org.apache.batik.gvt.text.TextPaintInfo;
+import org.apache.batik.gvt.TextPainter;
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.renderer.StrokingTextPainter;
-
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.Mark;
+import org.apache.batik.gvt.text.TextPaintInfo;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
+import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
+
/**
* Renders the attributed character iterator of a <tt>TextNode</tt>.
@@ -74,8 +68,8 @@ public class PSTextPainter implements TextPainter {
/** the logger for this class */
protected Log log = LogFactory.getLog(PSTextPainter.class);
- private NativeTextHandler nativeTextHandler;
- private FontInfo fontInfo;
+ private final NativeTextHandler nativeTextHandler;
+ private final FontInfo fontInfo;
/**
* Use the stroking text painter to get the bounds and shape.
@@ -317,7 +311,7 @@ public class PSTextPainter implements TextPainter {
}
drawPrimitiveString(g2d, loc, font, txt, tx);
- loc.setLocation(loc.getX() + (double)advance, loc.getY());
+ loc.setLocation(loc.getX() + advance, loc.getY());
return loc;
}
@@ -422,7 +416,7 @@ public class PSTextPainter implements TextPainter {
fStyle |= java.awt.Font.ITALIC;
}
return new java.awt.Font(font.getFontName(), fStyle,
- (int)(font.getFontSize() / 1000));
+ (font.getFontSize() / 1000));
}
private float getStringWidth(String str, Font font) {
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java
index c47649eb1..eb0f4d833 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java
@@ -43,7 +43,7 @@ public class PSCommentAfterElement extends AbstractPSCommentElement {
* @see org.apache.fop.fo.FONode#getLocalName()
*/
public String getLocalName() {
- return ELEMENT;
+ return PSCommentAfter.ELEMENT;
}
/**
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java
index f441553b7..951e685b3 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java
@@ -43,7 +43,7 @@ public class PSCommentBeforeElement extends AbstractPSCommentElement {
* @see org.apache.fop.fo.FONode#getLocalName()
*/
public String getLocalName() {
- return ELEMENT;
+ return PSCommentBefore.ELEMENT;
}
/**
diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java
index d1a1ede37..2044385a8 100644
--- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java
+++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java
@@ -42,8 +42,8 @@ public class PSExtensionElementMapping extends ElementMapping {
foObjs.put(PSSetupCodeElement.ELEMENT, new PSSetupCodeMaker());
foObjs.put(PSPageSetupCodeElement.ELEMENT, new PSPageSetupCodeMaker());
foObjs.put(PSSetPageDeviceElement.ELEMENT, new PSSetPageDeviceMaker());
- foObjs.put(PSCommentBeforeElement.ELEMENT, new PSCommentBeforeMaker());
- foObjs.put(PSCommentAfterElement.ELEMENT, new PSCommentAfterMaker());
+ foObjs.put(PSCommentBefore.ELEMENT, new PSCommentBeforeMaker());
+ foObjs.put(PSCommentAfter.ELEMENT, new PSCommentAfterMaker());
}
}
diff --git a/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java b/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java
new file mode 100644
index 000000000..ae4d67516
--- /dev/null
+++ b/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg;
+
+import java.awt.geom.AffineTransform;
+import java.lang.reflect.Constructor;
+
+import org.apache.batik.bridge.Bridge;
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.DocumentLoader;
+import org.apache.batik.bridge.UserAgent;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+
+/**
+ * A FOP base implementation of a Batik BridgeContext.
+ */
+public abstract class AbstractFOPBridgeContext extends BridgeContext {
+
+ /** The font list. */
+ protected final FontInfo fontInfo;
+
+ protected final ImageManager imageManager;
+ protected final ImageSessionContext imageSessionContext;
+
+ protected final AffineTransform linkTransform;
+
+ /**
+ * Constructs a new bridge context.
+ * @param userAgent the user agent
+ * @param loader the Document Loader to use for referenced documents.
+ * @param fontInfo the font list for the text painter, may be null
+ * in which case text is painted as shapes
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
+ */
+ public AbstractFOPBridgeContext(UserAgent userAgent,
+ DocumentLoader loader,
+ FontInfo fontInfo,
+ ImageManager imageManager,
+ ImageSessionContext imageSessionContext,
+ AffineTransform linkTransform) {
+ super(userAgent, loader);
+ this.fontInfo = fontInfo;
+ this.imageManager = imageManager;
+ this.imageSessionContext = imageSessionContext;
+ this.linkTransform = linkTransform;
+ }
+
+ /**
+ * Constructs a new bridge context.
+ * @param userAgent the user agent
+ * @param fontInfo the font list for the text painter, may be null
+ * in which case text is painted as shapes
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
+ */
+ public AbstractFOPBridgeContext(UserAgent userAgent,
+ FontInfo fontInfo,
+ ImageManager imageManager,
+ ImageSessionContext imageSessionContext,
+ AffineTransform linkTransform) {
+ super(userAgent);
+ this.fontInfo = fontInfo;
+ this.imageManager = imageManager;
+ this.imageSessionContext = imageSessionContext;
+ this.linkTransform = linkTransform;
+ }
+
+ /**
+ * Constructs a new bridge context.
+ * @param userAgent the user agent
+ * @param fontInfo the font list for the text painter, may be null
+ * in which case text is painted as shapes
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
+ */
+ public AbstractFOPBridgeContext(UserAgent userAgent,
+ FontInfo fontInfo,
+ ImageManager imageManager,
+ ImageSessionContext imageSessionContext) {
+ this(userAgent, fontInfo, imageManager, imageSessionContext, null);
+ }
+
+ /**
+ * Returns the ImageManager to be used by the ImageElementBridge.
+ * @return the image manager
+ */
+ public ImageManager getImageManager() {
+ return this.imageManager;
+ }
+
+ /**
+ * Returns the ImageSessionContext to be used by the ImageElementBridge.
+ * @return the image session context
+ */
+ public ImageSessionContext getImageSessionContext() {
+ return this.imageSessionContext;
+ }
+
+ protected void putElementBridgeConditional(String className, String testFor) {
+ try {
+ Class.forName(testFor);
+ //if we get here the test class is available
+
+ Class clazz = Class.forName(className);
+ Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class});
+ putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo}));
+ } catch (Throwable t) {
+ //simply ignore (bridges instantiated over this method are optional)
+ }
+ }
+
+ // Make sure any 'sub bridge contexts' also have our bridges.
+ //TODO There's no matching method in the super-class here
+ public abstract BridgeContext createBridgeContext();
+
+}
diff --git a/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java b/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java
new file mode 100644
index 000000000..31895cebe
--- /dev/null
+++ b/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.SVGImageElementBridge;
+import org.apache.batik.gvt.AbstractGraphicsNode;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.util.ParsedURL;
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.w3c.dom.Element;
+import org.w3c.dom.svg.SVGDocument;
+
+/**
+ * Bridge class for the &lt;image> element when jpeg images.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+public abstract class AbstractFOPImageElementBridge extends SVGImageElementBridge {
+
+ /**
+ * Constructs a new bridge for the &lt;image> element.
+ */
+ public AbstractFOPImageElementBridge() { }
+
+ /**
+ * Create the raster image node.
+ * THis checks if it is a jpeg file and creates a jpeg node
+ * so the jpeg can be inserted directly into the pdf document.
+ * @param ctx the bridge context
+ * @param imageElement the svg element for the image
+ * @param purl the parsed url for the image resource
+ * @return a new graphics node
+ */
+ protected GraphicsNode createImageGraphicsNode
+ (BridgeContext ctx, Element imageElement, ParsedURL purl) {
+ AbstractFOPBridgeContext bridgeCtx = (AbstractFOPBridgeContext)ctx;
+
+ ImageManager manager = bridgeCtx.getImageManager();
+ ImageSessionContext sessionContext = bridgeCtx.getImageSessionContext();
+ try {
+ ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext);
+ ImageFlavor[] supportedFlavors = getSupportedFlavours();
+ Image image = manager.getImage(info, supportedFlavors, sessionContext);
+
+ //TODO color profile overrides aren't handled, yet!
+ //ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx);
+ AbstractGraphicsNode specializedNode = null;
+ if (image instanceof ImageXMLDOM) {
+ ImageXMLDOM xmlImage = (ImageXMLDOM)image;
+ if (xmlImage.getDocument() instanceof SVGDocument) {
+ return createSVGImageNode(ctx, imageElement,
+ (SVGDocument)xmlImage.getDocument());
+ } else {
+ //Convert image to Graphics2D
+ image = manager.convertImage(xmlImage,
+ new ImageFlavor[] {ImageFlavor.GRAPHICS2D});
+ }
+ }
+ if (image instanceof ImageRawJPEG) {
+ specializedNode = createLoaderImageNode(image, ctx, imageElement, purl);
+ } else if (image instanceof ImageRawCCITTFax) {
+ specializedNode = createLoaderImageNode(image, ctx, imageElement, purl);
+ } else if (image instanceof ImageGraphics2D) {
+ ImageGraphics2D g2dImage = (ImageGraphics2D)image;
+ specializedNode = new Graphics2DNode(g2dImage);
+ } else {
+ ctx.getUserAgent().displayError(
+ new ImageException("Cannot convert an image to a usable format: " + purl));
+ }
+
+ Rectangle2D imgBounds = getImageBounds(ctx, imageElement);
+ Rectangle2D bounds = specializedNode.getPrimitiveBounds();
+ float [] vb = new float[4];
+ vb[0] = 0; // x
+ vb[1] = 0; // y
+ vb[2] = (float) bounds.getWidth(); // width
+ vb[3] = (float) bounds.getHeight(); // height
+
+ // handles the 'preserveAspectRatio', 'overflow' and 'clip'
+ // and sets the appropriate AffineTransform to the image node
+ initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds);
+ return specializedNode;
+ } catch (Exception e) {
+ ctx.getUserAgent().displayError(e);
+ }
+
+ return superCreateGraphicsNode(ctx, imageElement, purl);
+ }
+
+ /**
+ * Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode.
+ * @param ctx the bridge context
+ * @param imageElement the image element
+ * @param purl the parsed URL
+ * @return the newly created graphics node
+ * @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element)
+ */
+ protected GraphicsNode superCreateGraphicsNode
+ (BridgeContext ctx, Element imageElement, ParsedURL purl) {
+ return super.createImageGraphicsNode(ctx, imageElement, purl);
+ }
+
+ /**
+ * Returns an array of supported image flavours
+ *
+ * @return an array of supported image flavours
+ */
+ protected abstract ImageFlavor[] getSupportedFlavours();
+
+ /**
+ * Creates a loader image node implementation
+ * @param purl the parsed url
+ * @param imageElement the image element
+ * @param ctx the batik bridge context
+ * @param image the image
+ *
+ * @return a loader image node implementation
+ */
+ protected LoaderImageNode createLoaderImageNode(
+ Image image, BridgeContext ctx, Element imageElement, ParsedURL purl) {
+ return new LoaderImageNode(image, ctx, imageElement, purl);
+ }
+
+ /**
+ * An image node for natively handled Image instance.
+ * This holds a natively handled image so that it can be drawn into
+ * the PDFGraphics2D.
+ */
+ public class LoaderImageNode extends AbstractGraphicsNode {
+
+ protected final Image image;
+ protected final BridgeContext ctx;
+ protected final Element imageElement;
+ protected final ParsedURL purl;
+ protected GraphicsNode origGraphicsNode = null;
+
+ /**
+ * Create a new image node for drawing natively handled images
+ * into PDF graphics.
+ * @param image the JPEG image
+ * @param ctx the bridge context
+ * @param imageElement the SVG image element
+ * @param purl the URL to the image
+ */
+ public LoaderImageNode(Image image, BridgeContext ctx,
+ Element imageElement, ParsedURL purl) {
+ this.image = image;
+ this.ctx = ctx;
+ this.imageElement = imageElement;
+ this.purl = purl;
+ }
+
+ /** {@inheritDoc} */
+ public Shape getOutline() {
+ return getPrimitiveBounds();
+ }
+
+ /** {@inheritDoc} */
+ public void primitivePaint(Graphics2D g2d) {
+ if (g2d instanceof NativeImageHandler) {
+ NativeImageHandler nativeImageHandler = (NativeImageHandler) g2d;
+ float x = 0;
+ float y = 0;
+ try {
+ float width = image.getSize().getWidthPx();
+ float height = image.getSize().getHeightPx();
+ nativeImageHandler.addNativeImage(image, x, y, width, height);
+ } catch (Exception e) {
+ ctx.getUserAgent().displayError(e);
+ }
+ } else {
+ // Not going directly into PDF so use
+ // original implementation so filters etc work.
+ if (origGraphicsNode == null) {
+ // Haven't constructed base class Graphics Node,
+ // so do so now.
+ origGraphicsNode
+ = superCreateGraphicsNode(ctx, imageElement, purl);
+ }
+ origGraphicsNode.primitivePaint(g2d);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle2D getGeometryBounds() {
+ return getPrimitiveBounds();
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle2D getPrimitiveBounds() {
+ return new Rectangle2D.Double(0, 0,
+ image.getSize().getWidthPx(),
+ image.getSize().getHeightPx());
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle2D getSensitiveBounds() {
+ //No interactive features, just return primitive bounds
+ return getPrimitiveBounds();
+ }
+
+ }
+
+ /**
+ * A node that holds a Graphics2D image.
+ */
+ public class Graphics2DNode extends AbstractGraphicsNode {
+
+ private final ImageGraphics2D image;
+
+ /**
+ * Create a new Graphics2D node.
+ * @param g2d the Graphics2D image
+ */
+ public Graphics2DNode(ImageGraphics2D g2d) {
+ this.image = g2d;
+ }
+
+ /** {@inheritDoc} */
+ public Shape getOutline() {
+ return getPrimitiveBounds();
+ }
+
+ /** {@inheritDoc} */
+ public void primitivePaint(Graphics2D g2d) {
+ int width = image.getSize().getWidthPx();
+ int height = image.getSize().getHeightPx();
+ Rectangle2D area = new Rectangle2D.Double(0, 0, width, height);
+ Graphics2DImagePainter painter = image.getGraphics2DImagePainter();
+ painter.paint(g2d, area);
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle2D getGeometryBounds() {
+ return getPrimitiveBounds();
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle2D getPrimitiveBounds() {
+ return new Rectangle2D.Double(0, 0,
+ image.getSize().getWidthPx(),
+ image.getSize().getHeightPx());
+ }
+
+ /** {@inheritDoc} */
+ public Rectangle2D getSensitiveBounds() {
+ //No interactive features, just return primitive bounds
+ return getPrimitiveBounds();
+ }
+
+ }
+}
diff --git a/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java b/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java
new file mode 100644
index 000000000..53b8e2ad5
--- /dev/null
+++ b/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.SVGTextElementBridge;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.TextPainter;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Bridge class for the &lt;text> element.
+ * This bridge will use the direct text painter if the text
+ * for the element is simple.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+public abstract class AbstractFOPTextElementBridge extends SVGTextElementBridge {
+
+ /** text painter */
+ protected TextPainter textPainter;
+
+ /**
+ * Main constructor
+ *
+ * @param textPainter the text painter
+ */
+ public AbstractFOPTextElementBridge(TextPainter textPainter) {
+ this.textPainter = textPainter;
+ }
+
+ /**
+ * Create a text element bridge.
+ *
+ * This set the text painter on the node if the text is simple.
+ * @param ctx the bridge context
+ * @param e the svg element
+ * @return the text graphics node created by the super class
+ */
+ public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
+ GraphicsNode node = super.createGraphicsNode(ctx, e);
+ if (node != null) {
+ //Set our own text painter
+ ((TextNode)node).setTextPainter(textPainter);
+ }
+ return node;
+ }
+
+ /**
+ * Check if text element contains simple text.
+ * This checks the children of the text element to determine
+ * if the text is simple. The text is simple if it can be rendered
+ * with basic text drawing algorithms. This means there are no
+ * alternate characters, the font is known and there are no effects
+ * applied to the text.
+ *
+ * @param ctx the bridge context
+ * @param element the svg text element
+ * @param node the graphics node
+ * @return true if this text is simple of false if it cannot be
+ * easily rendered using normal drawString on the Graphics2D
+ */
+ protected boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
+ for (Node n = element.getFirstChild();
+ n != null;
+ n = n.getNextSibling()) {
+
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+
+ if (n.getLocalName().equals(SVG_TSPAN_TAG)
+ || n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
+ return false;
+ } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
+ return false;
+ } else if (n.getLocalName().equals(SVG_TREF_TAG)) {
+ return false;
+ }
+ break;
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ default:
+ }
+ }
+
+ /*if (CSSUtilities.convertFilter(element, node, ctx) != null) {
+ return false;
+ }*/
+
+ return true;
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java
new file mode 100644
index 000000000..560c76cb5
--- /dev/null
+++ b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java
@@ -0,0 +1,528 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.font.TextAttribute;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.TextPainter;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.Mark;
+import org.apache.batik.gvt.text.TextPaintInfo;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+
+
+/**
+ * Renders the attributed character iterator of a <tt>TextNode</tt>.
+ * This class draws the text directly into the Graphics2D so that
+ * the text is not drawn using shapes.
+ * If the text is simple enough to draw then it sets the font and calls
+ * drawString. If the text is complex or the cannot be translated
+ * into a simple drawString the StrokingTextPainter is used instead.
+ */
+public abstract class AbstractFOPTextPainter implements TextPainter {
+
+ /** the logger for this class */
+ protected Log log = LogFactory.getLog(AbstractFOPTextPainter.class);
+
+ private final FOPTextHandler nativeTextHandler;
+
+ /**
+ * Use the stroking text painter to get the bounds and shape.
+ * Also used as a fallback to draw the string with strokes.
+ */
+ protected static final TextPainter
+ PROXY_PAINTER = StrokingTextPainter.getInstance();
+
+ /**
+ * Create a new PS text painter with the given font information.
+ * @param nativeTextHandler the NativeTextHandler instance used for text painting
+ */
+ public AbstractFOPTextPainter(FOPTextHandler nativeTextHandler) {
+ this.nativeTextHandler = nativeTextHandler;
+ }
+
+ /**
+ * Paints the specified attributed character iterator using the
+ * specified Graphics2D and context and font context.
+ *
+ * @param node the TextNode to paint
+ * @param g2d the Graphics2D to use
+ */
+ public void paint(TextNode node, Graphics2D g2d) {
+ Point2D loc = node.getLocation();
+ log.debug("painting text node " + node);
+ if (hasUnsupportedAttributes(node)) {
+ log.debug("hasUnsuportedAttributes");
+ PROXY_PAINTER.paint(node, g2d);
+ } else {
+ log.debug("allAttributesSupported");
+ paintTextRuns(node.getTextRuns(), g2d, loc);
+ }
+ }
+
+ private boolean hasUnsupportedAttributes(TextNode node) {
+ Iterator iter = node.getTextRuns().iterator();
+ while (iter.hasNext()) {
+ StrokingTextPainter.TextRun
+ run = (StrokingTextPainter.TextRun)iter.next();
+ AttributedCharacterIterator aci = run.getACI();
+ boolean hasUnsupported = hasUnsupportedAttributes(aci);
+ if (hasUnsupported) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
+ boolean hasUnsupported = false;
+
+ Font font = getFont(aci);
+ String text = getText(aci);
+ if (hasUnsupportedGlyphs(text, font)) {
+ log.trace("-> Unsupported glyphs found");
+ hasUnsupported = true;
+ }
+
+ TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+ if ((tpi != null)
+ && ((tpi.strokeStroke != null && tpi.strokePaint != null)
+ || (tpi.strikethroughStroke != null)
+ || (tpi.underlineStroke != null)
+ || (tpi.overlineStroke != null))) {
+ log.trace("-> under/overlines etc. found");
+ hasUnsupported = true;
+ }
+
+ //Alpha is not supported
+ Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
+ if (foreground instanceof Color) {
+ Color col = (Color)foreground;
+ if (col.getAlpha() != 255) {
+ log.trace("-> transparency found");
+ hasUnsupported = true;
+ }
+ }
+
+ Object letSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
+ if (letSpace != null) {
+ log.trace("-> letter spacing found");
+ hasUnsupported = true;
+ }
+
+ Object wordSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
+ if (wordSpace != null) {
+ log.trace("-> word spacing found");
+ hasUnsupported = true;
+ }
+
+ Object lengthAdjust = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
+ if (lengthAdjust != null) {
+ log.trace("-> length adjustments found");
+ hasUnsupported = true;
+ }
+
+ Object writeMod = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
+ if (writeMod != null
+ && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
+ writeMod)) {
+ log.trace("-> Unsupported writing modes found");
+ hasUnsupported = true;
+ }
+
+ Object vertOr = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
+ if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
+ vertOr)) {
+ log.trace("-> vertical orientation found");
+ hasUnsupported = true;
+ }
+
+ Object rcDel = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
+ //Batik 1.6 returns null here which makes it impossible to determine whether this can
+ //be painted or not, i.e. fall back to stroking. :-(
+ if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
+ log.trace("-> spans found");
+ hasUnsupported = true; //Filter spans
+ }
+
+ if (hasUnsupported) {
+ log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
+ }
+ return hasUnsupported;
+ }
+
+ /**
+ * Paint a list of text runs on the Graphics2D at a given location.
+ * @param textRuns the list of text runs
+ * @param g2d the Graphics2D to paint to
+ * @param loc the current location of the "cursor"
+ */
+ protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
+ Point2D currentloc = loc;
+ Iterator i = textRuns.iterator();
+ while (i.hasNext()) {
+ StrokingTextPainter.TextRun
+ run = (StrokingTextPainter.TextRun)i.next();
+ currentloc = paintTextRun(run, g2d, currentloc);
+ }
+ }
+
+ /**
+ * Paint a single text run on the Graphics2D at a given location.
+ * @param run the text run to paint
+ * @param g2d the Graphics2D to paint to
+ * @param loc the current location of the "cursor"
+ * @return the new location of the "cursor" after painting the text run
+ */
+ protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
+ AttributedCharacterIterator aci = run.getACI();
+ aci.first();
+
+ updateLocationFromACI(aci, loc);
+ AffineTransform at = g2d.getTransform();
+ loc = at.transform(loc, null);
+
+ // font
+ Font font = getFont(aci);
+ if (font != null) {
+ nativeTextHandler.setOverrideFont(font);
+ }
+
+ // color
+ TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+ if (tpi == null) {
+ return loc;
+ }
+ Paint foreground = tpi.fillPaint;
+ if (foreground instanceof Color) {
+ Color col = (Color)foreground;
+ g2d.setColor(col);
+ }
+ g2d.setPaint(foreground);
+
+ // text
+ String txt = getText(aci);
+ float advance = getStringWidth(txt, font);
+ float tx = 0;
+ TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+ if (anchor != null) {
+ switch (anchor.getType()) {
+ case TextNode.Anchor.ANCHOR_MIDDLE:
+ tx = -advance / 2;
+ break;
+ case TextNode.Anchor.ANCHOR_END:
+ tx = -advance;
+ break;
+ default: //nop
+ }
+ }
+
+ // draw string
+ double x = loc.getX();
+ double y = loc.getY();
+ try {
+ try {
+ nativeTextHandler.drawString(g2d, txt, (float)x + tx, (float)y);
+ } catch (IOException ioe) {
+ if (g2d instanceof AFPGraphics2D) {
+ ((AFPGraphics2D)g2d).handleIOException(ioe);
+ }
+ }
+ } finally {
+ nativeTextHandler.setOverrideFont(null);
+ }
+ loc.setLocation(loc.getX() + advance, loc.getY());
+ return loc;
+ }
+
+ /**
+ * Extract the raw text from an ACI.
+ * @param aci ACI to inspect
+ * @return the extracted text
+ */
+ protected String getText(AttributedCharacterIterator aci) {
+ StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
+ for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ private void updateLocationFromACI(
+ AttributedCharacterIterator aci,
+ Point2D loc) {
+ //Adjust position of span
+ Float xpos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.X);
+ Float ypos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.Y);
+ Float dxpos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DX);
+ Float dypos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DY);
+ if (xpos != null) {
+ loc.setLocation(xpos.doubleValue(), loc.getY());
+ }
+ if (ypos != null) {
+ loc.setLocation(loc.getX(), ypos.doubleValue());
+ }
+ if (dxpos != null) {
+ loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
+ }
+ if (dypos != null) {
+ loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
+ }
+ }
+
+ private String getStyle(AttributedCharacterIterator aci) {
+ Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
+ return ((posture != null) && (posture.floatValue() > 0.0))
+ ? Font.STYLE_ITALIC
+ : Font.STYLE_NORMAL;
+ }
+
+ private int getWeight(AttributedCharacterIterator aci) {
+ Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
+ return ((taWeight != null) && (taWeight.floatValue() > 1.0))
+ ? Font.WEIGHT_BOLD
+ : Font.WEIGHT_NORMAL;
+ }
+
+ private Font getFont(AttributedCharacterIterator aci) {
+ Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
+ String style = getStyle(aci);
+ int weight = getWeight(aci);
+
+ FontInfo fontInfo = nativeTextHandler.getFontInfo();
+ String fontFamily = null;
+ List gvtFonts = (List) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+ if (gvtFonts != null) {
+ Iterator i = gvtFonts.iterator();
+ while (i.hasNext()) {
+ GVTFontFamily fam = (GVTFontFamily) i.next();
+ /* (todo) Enable SVG Font painting
+ if (fam instanceof SVGFontFamily) {
+ PROXY_PAINTER.paint(node, g2d);
+ return;
+ }*/
+ fontFamily = fam.getFamilyName();
+ if (fontInfo.hasFont(fontFamily, style, weight)) {
+ FontTriplet triplet = fontInfo.fontLookup(
+ fontFamily, style, weight);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ return fontInfo.getFontInstance(triplet, fsize);
+ }
+ }
+ }
+ FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ return fontInfo.getFontInstance(triplet, fsize);
+ }
+
+ private float getStringWidth(String str, Font font) {
+ float wordWidth = 0;
+ float whitespaceWidth = font.getWidth(font.mapChar(' '));
+
+ for (int i = 0; i < str.length(); i++) {
+ float charWidth;
+ char c = str.charAt(i);
+ if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+ charWidth = font.getWidth(font.mapChar(c));
+ if (charWidth <= 0) {
+ charWidth = whitespaceWidth;
+ }
+ } else {
+ charWidth = whitespaceWidth;
+ }
+ wordWidth += charWidth;
+ }
+ return wordWidth / 1000f;
+ }
+
+ private boolean hasUnsupportedGlyphs(String str, Font font) {
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+ if (!font.hasChar(c)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the outline shape of the text characters.
+ * This uses the StrokingTextPainter to get the outline
+ * shape since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the outline shape of the text characters
+ */
+ public Shape getOutline(TextNode node) {
+ return PROXY_PAINTER.getOutline(node);
+ }
+
+ /**
+ * Get the bounds.
+ * This uses the StrokingTextPainter to get the bounds
+ * since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the bounds of the text
+ */
+ public Rectangle2D getBounds2D(TextNode node) {
+ /* (todo) getBounds2D() is too slow
+ * because it uses the StrokingTextPainter. We should implement this
+ * method ourselves. */
+ return PROXY_PAINTER.getBounds2D(node);
+ }
+
+ /**
+ * Get the geometry bounds.
+ * This uses the StrokingTextPainter to get the bounds
+ * since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the bounds of the text
+ */
+ public Rectangle2D getGeometryBounds(TextNode node) {
+ return PROXY_PAINTER.getGeometryBounds(node);
+ }
+
+ // Methods that have no purpose for PS
+
+ /**
+ * Get the mark.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param node the text node
+ * @param pos the position
+ * @param all select all
+ * @return null
+ */
+ public Mark getMark(TextNode node, int pos, boolean all) {
+ return null;
+ }
+
+ /**
+ * Select at.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param x the x position
+ * @param y the y position
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectAt(double x, double y, TextNode node) {
+ return null;
+ }
+
+ /**
+ * Select to.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param x the x position
+ * @param y the y position
+ * @param beginMark the start mark
+ * @return null
+ */
+ public Mark selectTo(double x, double y, Mark beginMark) {
+ return null;
+ }
+
+ /**
+ * Selec first.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectFirst(TextNode node) {
+ return null;
+ }
+
+ /**
+ * Select last.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectLast(TextNode node) {
+ return null;
+ }
+
+ /**
+ * Get selected.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param start the start mark
+ * @param finish the finish mark
+ * @return null
+ */
+ public int[] getSelected(Mark start, Mark finish) {
+ return null;
+ }
+
+ /**
+ * Get the highlighted shape.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param beginMark the start mark
+ * @param endMark the end mark
+ * @return null
+ */
+ public Shape getHighlightShape(Mark beginMark, Mark endMark) {
+ return null;
+ }
+
+}
diff --git a/src/java/org/apache/fop/svg/FOPTextHandler.java b/src/java/org/apache/fop/svg/FOPTextHandler.java
new file mode 100644
index 000000000..8fa9eeedd
--- /dev/null
+++ b/src/java/org/apache/fop/svg/FOPTextHandler.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg;
+
+public interface FOPTextHandler extends org.apache.xmlgraphics.java2d.TextHandler {
+
+ void setOverrideFont(org.apache.fop.fonts.Font font);
+
+ org.apache.fop.fonts.FontInfo getFontInfo();
+}
diff --git a/src/java/org/apache/fop/svg/GraphicsConfiguration.java b/src/java/org/apache/fop/svg/GraphicsConfiguration.java
index ca3b3363c..881096b9a 100644
--- a/src/java/org/apache/fop/svg/GraphicsConfiguration.java
+++ b/src/java/org/apache/fop/svg/GraphicsConfiguration.java
@@ -17,7 +17,6 @@
/* $Id$ */
-
package org.apache.fop.svg;
import java.awt.image.VolatileImage;
diff --git a/src/java/org/apache/fop/svg/NativeImageHandler.java b/src/java/org/apache/fop/svg/NativeImageHandler.java
new file mode 100644
index 000000000..8e74cba1d
--- /dev/null
+++ b/src/java/org/apache/fop/svg/NativeImageHandler.java
@@ -0,0 +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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg;
+
+public interface NativeImageHandler {
+
+ /**
+ * Add a natively handled image directly to the document.
+ * This is used by the ImageElementBridge to draw a natively handled image
+ * (like JPEG or CCITT images)
+ * directly into the document rather than converting the image into
+ * a bitmap and increasing the size.
+ *
+ * @param image the image to draw
+ * @param x the x position
+ * @param y the y position
+ * @param width the width to draw the image
+ * @param height the height to draw the image
+ */
+ void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
+ float width, float height);
+
+}
diff --git a/src/java/org/apache/fop/svg/PDFBridgeContext.java b/src/java/org/apache/fop/svg/PDFBridgeContext.java
index fdf83784f..364c7a6f3 100644
--- a/src/java/org/apache/fop/svg/PDFBridgeContext.java
+++ b/src/java/org/apache/fop/svg/PDFBridgeContext.java
@@ -20,30 +20,20 @@
package org.apache.fop.svg;
import java.awt.geom.AffineTransform;
-import java.lang.reflect.Constructor;
-import org.apache.batik.bridge.Bridge;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
+import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.bridge.UserAgent;
-
+import org.apache.batik.gvt.TextPainter;
+import org.apache.fop.fonts.FontInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.fop.fonts.FontInfo;
-
/**
* BridgeContext which registers the custom bridges for PDF output.
*/
-public class PDFBridgeContext extends BridgeContext {
-
- /** The font list. */
- private final FontInfo fontInfo;
-
- private final ImageManager imageManager;
- private final ImageSessionContext imageSessionContext;
-
- private AffineTransform linkTransform;
+public class PDFBridgeContext extends AbstractFOPBridgeContext {
/**
* Constructs a new bridge context.
@@ -53,18 +43,16 @@ public class PDFBridgeContext extends BridgeContext {
* in which case text is painted as shapes
* @param linkTransform AffineTransform to properly place links,
* may be null
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
*/
- public PDFBridgeContext(UserAgent userAgent,
- DocumentLoader loader,
- FontInfo fontInfo,
- ImageManager imageManager,
- ImageSessionContext imageSessionContext,
- AffineTransform linkTransform) {
- super(userAgent, loader);
- this.fontInfo = fontInfo;
- this.imageManager = imageManager;
- this.imageSessionContext = imageSessionContext;
- this.linkTransform = linkTransform;
+ public PDFBridgeContext(UserAgent userAgent, DocumentLoader documentLoader,
+ FontInfo fontInfo, ImageManager imageManager,
+ ImageSessionContext imageSessionContext,
+ AffineTransform linkTransform) {
+ super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform);
}
/**
@@ -72,19 +60,12 @@ public class PDFBridgeContext extends BridgeContext {
* @param userAgent the user agent
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
- * @param linkTransform AffineTransform to properly place links,
- * may be null
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
*/
- public PDFBridgeContext(UserAgent userAgent,
- FontInfo fontInfo,
- ImageManager imageManager,
- ImageSessionContext imageSessionContext,
- AffineTransform linkTransform) {
- super(userAgent);
- this.fontInfo = fontInfo;
- this.imageManager = imageManager;
- this.imageSessionContext = imageSessionContext;
- this.linkTransform = linkTransform;
+ public PDFBridgeContext(UserAgent userAgent, FontInfo fontInfo,
+ ImageManager imageManager, ImageSessionContext imageSessionContext) {
+ super(userAgent, fontInfo, imageManager, imageSessionContext);
}
/**
@@ -92,41 +73,15 @@ public class PDFBridgeContext extends BridgeContext {
* @param userAgent the user agent
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
+ * @param imageManager an image manager
+ * @param imageSessionContext an image session context
+ * @param linkTransform AffineTransform to properly place links,
+ * may be null
*/
- public PDFBridgeContext(UserAgent userAgent,
- FontInfo fontInfo,
- ImageManager imageManager,
- ImageSessionContext imageSessionContext) {
- this(userAgent, fontInfo, imageManager, imageSessionContext, null);
- }
-
- /**
- * Returns the ImageManager to be used by the ImageElementBridge.
- * @return the image manager
- */
- public ImageManager getImageManager() {
- return this.imageManager;
- }
-
- /**
- * Returns the ImageSessionContext to be used by the ImageElementBridge.
- * @return the image session context
- */
- public ImageSessionContext getImageSessionContext() {
- return this.imageSessionContext;
- }
-
- private void putPDFElementBridgeConditional(String className, String testFor) {
- try {
- Class.forName(testFor);
- //if we get here the test class is available
-
- Class clazz = Class.forName(className);
- Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class});
- putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo}));
- } catch (Throwable t) {
- //simply ignore (bridges instantiated over this method are optional)
- }
+ public PDFBridgeContext(SVGUserAgent userAgent, FontInfo fontInfo,
+ ImageManager imageManager, ImageSessionContext imageSessionContext,
+ AffineTransform linkTransform) {
+ super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform);
}
/** {@inheritDoc} */
@@ -134,23 +89,24 @@ public class PDFBridgeContext extends BridgeContext {
super.registerSVGBridges();
if (fontInfo != null) {
- PDFTextElementBridge textElementBridge = new PDFTextElementBridge(fontInfo);
+ TextPainter textPainter = new PDFTextPainter(fontInfo);
+ SVGTextElementBridge textElementBridge = new PDFTextElementBridge(textPainter);
putBridge(textElementBridge);
//Batik flow text extension (may not always be available)
//putBridge(new PDFBatikFlowTextElementBridge(fontInfo);
- putPDFElementBridgeConditional(
+ putElementBridgeConditional(
"org.apache.fop.svg.PDFBatikFlowTextElementBridge",
"org.apache.batik.extension.svg.BatikFlowTextElementBridge");
//SVG 1.2 flow text support
//putBridge(new PDFSVG12TextElementBridge(fontInfo)); //-->Batik 1.7
- putPDFElementBridgeConditional(
+ putElementBridgeConditional(
"org.apache.fop.svg.PDFSVG12TextElementBridge",
"org.apache.batik.bridge.svg12.SVG12TextElementBridge");
//putBridge(new PDFSVGFlowRootElementBridge(fontInfo));
- putPDFElementBridgeConditional(
+ putElementBridgeConditional(
"org.apache.fop.svg.PDFSVGFlowRootElementBridge",
"org.apache.batik.bridge.svg12.SVGFlowRootElementBridge");
}
diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java
index dd13df1c4..cc6e06978 100644
--- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java
+++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java
@@ -19,30 +19,30 @@
package org.apache.fop.svg;
-import org.apache.fop.Version;
-import org.apache.fop.pdf.PDFDocument;
-import org.apache.fop.pdf.PDFFilterList;
-import org.apache.fop.pdf.PDFPage;
-import org.apache.fop.pdf.PDFStream;
-import org.apache.fop.pdf.PDFState;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.pdf.PDFResources;
-import org.apache.fop.pdf.PDFColor;
-import org.apache.fop.pdf.PDFAnnotList;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontSetup;
-
-import java.awt.Graphics;
-import java.awt.Font;
import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
-import java.io.OutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.StringWriter;
+import org.apache.fop.Version;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontSetup;
+import org.apache.fop.pdf.PDFAnnotList;
+import org.apache.fop.pdf.PDFColor;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFFilterList;
+import org.apache.fop.pdf.PDFNumber;
+import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFPaintingState;
+import org.apache.fop.pdf.PDFResources;
+import org.apache.fop.pdf.PDFStream;
+
/**
* This class is a wrapper for the <tt>PDFGraphics2D</tt> that
* is used to create a full document around the pdf rendering from
@@ -52,7 +52,7 @@ import java.io.StringWriter;
*/
public class PDFDocumentGraphics2D extends PDFGraphics2D {
- private PDFContext pdfContext;
+ private final PDFContext pdfContext;
private int width;
private int height;
@@ -296,7 +296,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D {
throw new IllegalStateException("Close page first before starting another");
}
//Start page
- graphicsState = new PDFState();
+ paintingState = new PDFPaintingState();
if (this.initialTransform == null) {
//Save initial transformation matrix
this.initialTransform = getTransform();
@@ -322,7 +322,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D {
pageRef = page.referencePDF();
AffineTransform at = new AffineTransform(1.0, 0.0, 0.0, -1.0,
- 0.0, (double)height);
+ 0.0, height);
currentStream.write("1 0 0 -1 0 " + height + " cm\n");
if (svgWidth != 0) {
double scaleX = width / svgWidth;
@@ -340,7 +340,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D {
scale(1 / s, 1 / s);
}
// Remember the transform we installed.
- graphicsState.concatenate(at);
+ paintingState.concatenate(at);
pdfContext.increasePageCount();
}
diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java
index 08655fd47..554d26798 100644
--- a/src/java/org/apache/fop/svg/PDFGraphics2D.java
+++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java
@@ -59,19 +59,9 @@ import org.apache.batik.ext.awt.RadialGradientPaint;
import org.apache.batik.ext.awt.RenderingHintsKeyExt;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.PatternPaint;
-
-import org.apache.xmlgraphics.image.loader.ImageInfo;
-import org.apache.xmlgraphics.image.loader.ImageSize;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
-import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
-import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
-import org.apache.xmlgraphics.java2d.GraphicContext;
-
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
-import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.pdf.BitmapImage;
import org.apache.fop.pdf.PDFAnnotList;
import org.apache.fop.pdf.PDFColor;
@@ -83,16 +73,23 @@ import org.apache.fop.pdf.PDFImage;
import org.apache.fop.pdf.PDFImageXObject;
import org.apache.fop.pdf.PDFLink;
import org.apache.fop.pdf.PDFNumber;
+import org.apache.fop.pdf.PDFPaintingState;
import org.apache.fop.pdf.PDFPattern;
import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFResources;
-import org.apache.fop.pdf.PDFState;
import org.apache.fop.pdf.PDFText;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter;
import org.apache.fop.render.pdf.ImageRawJPEGAdapter;
import org.apache.fop.render.pdf.ImageRenderedAdapter;
import org.apache.fop.util.ColorExt;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
+import org.apache.xmlgraphics.java2d.GraphicContext;
/**
* PDF Graphics 2D.
@@ -103,8 +100,7 @@ import org.apache.fop.util.ColorExt;
* @version $Id$
* @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D
*/
-public class PDFGraphics2D extends AbstractGraphics2D {
-
+public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHandler {
private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();
/** The number of decimal places. */
@@ -129,9 +125,9 @@ public class PDFGraphics2D extends AbstractGraphics2D {
protected String pageRef;
/**
- * the current state of the pdf graphics
+ * The PDF painting state
*/
- protected PDFState graphicsState;
+ protected PDFPaintingState paintingState;
/**
* The PDF graphics state level that this svg is being drawn into.
@@ -200,7 +196,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
currentFontSize = size;
fontInfo = fi;
pageRef = pref;
- graphicsState = new PDFState();
+ paintingState = new PDFPaintingState();
}
/**
@@ -226,7 +222,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
this.currentFontSize = g.currentFontSize;
this.fontInfo = g.fontInfo;
this.pageRef = g.pageRef;
- this.graphicsState = g.graphicsState;
+ this.paintingState = g.paintingState;
this.currentStream = g.currentStream;
this.nativeCount = g.nativeCount;
this.outputStream = g.outputStream;
@@ -266,9 +262,9 @@ public class PDFGraphics2D extends AbstractGraphics2D {
*
* @param state the PDF state
*/
- public void setPDFState(PDFState state) {
- graphicsState = state;
- baseLevel = graphicsState.getStackLevel();
+ public void setPaintingState(PDFPaintingState state) {
+ paintingState = state;
+ baseLevel = paintingState.getStackLevel();
}
/**
@@ -369,7 +365,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
* @return the transformation matrix that established the basic user space for this document
*/
protected AffineTransform getBaseTransform() {
- AffineTransform at = new AffineTransform(graphicsState.getTransform());
+ AffineTransform at = new AffineTransform(paintingState.getTransform());
return at;
}
@@ -417,7 +413,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
* @param width the width to draw the image
* @param height the height to draw the image
*/
- void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
+ public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
float width, float height) {
preparePainting();
String key = image.getInfo().getOriginalURI();
@@ -522,10 +518,14 @@ public class PDFGraphics2D extends AbstractGraphics2D {
g.setBackground(new Color(1, 1, 1, 0));
g.setPaint(new Color(1, 1, 1, 0));
g.fillRect(0, 0, width, height);
- g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));
+
+ int imageWidth = buf.getWidth();
+ int imageHeight = buf.getHeight();
+ g.clip(new Rectangle(0, 0, imageWidth, imageHeight));
g.setComposite(gc.getComposite());
- if (!g.drawImage(img, 0, 0, buf.getWidth(), buf.getHeight(), observer)) {
+ boolean drawn = g.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
+ if (!drawn) {
return false;
}
g.dispose();
@@ -606,13 +606,13 @@ public class PDFGraphics2D extends AbstractGraphics2D {
trans.getMatrix(tranvals);
Shape imclip = getClip();
- boolean newClip = graphicsState.checkClip(imclip);
- boolean newTransform = graphicsState.checkTransform(trans)
+ boolean newClip = paintingState.checkClip(imclip);
+ boolean newTransform = paintingState.checkTransform(trans)
&& !trans.isIdentity();
if (newClip || newTransform) {
currentStream.write("q\n");
- graphicsState.push();
+ paintingState.save();
if (newTransform) {
concatMatrix(tranvals);
}
@@ -629,7 +629,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
applyColor(c, true);
Paint paint = getPaint();
- if (graphicsState.setPaint(paint)) {
+ if (paintingState.setPaint(paint)) {
if (!applyPaint(paint, false)) {
// Stroke the shape and use it to 'clip'
// the paint contents.
@@ -638,7 +638,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
if (newClip || newTransform) {
currentStream.write("Q\n");
- graphicsState.pop();
+ paintingState.restore();
}
return;
}
@@ -650,7 +650,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
doDrawing(false, true, false);
if (newClip || newTransform) {
currentStream.write("Q\n");
- graphicsState.pop();
+ paintingState.restore();
}
}
@@ -1304,7 +1304,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
if (ovFontState == null) {
java.awt.Font gFont = getFont();
fontTransform = gFont.getTransform();
- fontState = getInternalFontForAWTFont(gFont);
+ fontState = fontInfo.getFontInstanceForAWTFont(gFont);
} else {
fontState = fontInfo.getFontInstance(
ovFontState.getFontTriplet(), ovFontState.getFontSize());
@@ -1360,7 +1360,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
if (!useMultiByte) {
if (ch > 127) {
currentStream.write("\\");
- currentStream.write(Integer.toOctalString((int)ch));
+ currentStream.write(Integer.toOctalString(ch));
} else {
switch (ch) {
case '(':
@@ -1377,8 +1377,8 @@ public class PDFGraphics2D extends AbstractGraphics2D {
}
if (kerningAvailable && (i + 1) < l) {
- addKerning(currentStream, (new Integer((int)ch)),
- (new Integer((int)fontState.mapChar(s.charAt(i + 1)))),
+ addKerning(currentStream, (new Integer(ch)),
+ (new Integer(fontState.mapChar(s.charAt(i + 1)))),
kerning, startText, endText);
}
@@ -1406,7 +1406,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
vals.put(PDFGState.GSTATE_ALPHA_STROKE, new Float(strokeAlpha / 255f));
}
PDFGState gstate = pdfDoc.getFactory().makeGState(
- vals, graphicsState.getGState());
+ vals, paintingState.getGState());
resourceContext.addGState(gstate);
currentStream.write("/" + gstate.getName() + " gs\n");
}
@@ -1418,7 +1418,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
*/
protected void updateCurrentFont(Font font) {
String name = font.getFontName();
- float size = (float)font.getFontSize() / 1000f;
+ float size = font.getFontSize() / 1000f;
//Only update if necessary
if ((!name.equals(this.currentFontName))
@@ -1433,19 +1433,10 @@ public class PDFGraphics2D extends AbstractGraphics2D {
* Returns a suitable internal font given an AWT Font instance.
* @param awtFont the AWT font
* @return the internal Font
+ * @deprecated use FontInfo.getFontInstanceForAWTFont(java.awt.Font awtFont) instead
*/
protected Font getInternalFontForAWTFont(java.awt.Font awtFont) {
- Font fontState;
- String n = awtFont.getFamily();
- if (n.equals("sanserif")) {
- n = "sans-serif";
- }
- float siz = awtFont.getSize2D();
- String style = awtFont.isItalic() ? "italic" : "normal";
- int weight = awtFont.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL;
- FontTriplet triplet = fontInfo.fontLookup(n, style, weight);
- fontState = fontInfo.getFontInstance(triplet, (int)(siz * 1000 + 0.5));
- return fontState;
+ return fontInfo.getFontInstanceForAWTFont(awtFont);
}
/**
@@ -1597,13 +1588,13 @@ public class PDFGraphics2D extends AbstractGraphics2D {
trans.getMatrix(tranvals);
Shape imclip = getClip();
- boolean newClip = graphicsState.checkClip(imclip);
- boolean newTransform = graphicsState.checkTransform(trans)
+ boolean newClip = paintingState.checkClip(imclip);
+ boolean newTransform = paintingState.checkTransform(trans)
&& !trans.isIdentity();
if (newClip || newTransform) {
currentStream.write("q\n");
- graphicsState.push();
+ paintingState.save();
if (newTransform) {
concatMatrix(tranvals);
}
@@ -1620,14 +1611,14 @@ public class PDFGraphics2D extends AbstractGraphics2D {
applyColor(c, false);
Paint paint = getPaint();
- if (graphicsState.setPaint(paint)) {
+ if (paintingState.setPaint(paint)) {
if (!applyPaint(paint, true)) {
// Use the shape to 'clip' the paint contents.
applyUnknownPaint(paint, s);
if (newClip || newTransform) {
currentStream.write("Q\n");
- graphicsState.pop();
+ paintingState.restore();
}
return;
}
@@ -1640,7 +1631,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
if (newClip || newTransform) {
currentStream.write("Q\n");
- graphicsState.pop();
+ paintingState.restore();
}
}
diff --git a/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java b/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java
index 83a431d5e..0204a2756 100644
--- a/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java
+++ b/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java
@@ -26,6 +26,7 @@ import java.awt.image.ColorModel;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
+
/**
* Our implementation of the class that returns information about
* roughly what we can handle and want to see (alpha for example).
diff --git a/src/java/org/apache/fop/svg/PDFImageElementBridge.java b/src/java/org/apache/fop/svg/PDFImageElementBridge.java
index 7eb89d2b1..1a17aa410 100644
--- a/src/java/org/apache/fop/svg/PDFImageElementBridge.java
+++ b/src/java/org/apache/fop/svg/PDFImageElementBridge.java
@@ -19,36 +19,14 @@
package org.apache.fop.svg;
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.geom.Rectangle2D;
-
-import org.w3c.dom.Element;
-import org.w3c.dom.svg.SVGDocument;
-
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.SVGImageElementBridge;
-import org.apache.batik.gvt.AbstractGraphicsNode;
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.util.ParsedURL;
-
-import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
-import org.apache.xmlgraphics.image.loader.ImageInfo;
-import org.apache.xmlgraphics.image.loader.ImageManager;
-import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
-import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
/**
- * Bridge class for the &lt;image> element when jpeg images.
+ * PDF Image Element Bridge class for the &lt;image> element when jpeg images.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
-public class PDFImageElementBridge extends SVGImageElementBridge {
+public class PDFImageElementBridge extends AbstractFOPImageElementBridge {
/**
* Constructs a new bridge for the &lt;image> element.
@@ -60,210 +38,9 @@ public class PDFImageElementBridge extends SVGImageElementBridge {
ImageFlavor.RAW_CCITTFAX,
ImageFlavor.GRAPHICS2D,
ImageFlavor.XML_DOM};
- /**
- * Create the raster image node.
- * THis checks if it is a jpeg file and creates a jpeg node
- * so the jpeg can be inserted directly into the pdf document.
- * @param ctx the bridge context
- * @param imageElement the svg element for the image
- * @param purl the parsed url for the image resource
- * @return a new graphics node
- */
- protected GraphicsNode createImageGraphicsNode
- (BridgeContext ctx, Element imageElement, ParsedURL purl) {
- PDFBridgeContext pdfCtx = (PDFBridgeContext)ctx;
-
- ImageManager manager = pdfCtx.getImageManager();
- ImageSessionContext sessionContext = pdfCtx.getImageSessionContext();
- try {
- ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext);
- Image image = manager.getImage(info, supportedFlavors, sessionContext);
-
- //TODO color profile overrides aren't handled, yet!
- //ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx);
- AbstractGraphicsNode specializedNode = null;
- if (image instanceof ImageXMLDOM) {
- ImageXMLDOM xmlImage = (ImageXMLDOM)image;
- if (xmlImage.getDocument() instanceof SVGDocument) {
- return createSVGImageNode(ctx, imageElement,
- (SVGDocument)xmlImage.getDocument());
- } else {
- //Convert image to Graphics2D
- image = manager.convertImage(xmlImage,
- new ImageFlavor[] {ImageFlavor.GRAPHICS2D});
- }
- }
- if (image instanceof ImageRawJPEG) {
- specializedNode = new LoaderImageNode(image, ctx, imageElement, purl);
- } else if (image instanceof ImageRawCCITTFax) {
- specializedNode = new LoaderImageNode(image, ctx, imageElement, purl);
- } else if (image instanceof ImageGraphics2D) {
- ImageGraphics2D g2dImage = (ImageGraphics2D)image;
- specializedNode = new Graphics2DNode(g2dImage);
- } else {
- ctx.getUserAgent().displayError(
- new ImageException("Cannot convert an image to a usable format: " + purl));
- }
-
- Rectangle2D imgBounds = getImageBounds(ctx, imageElement);
- Rectangle2D bounds = specializedNode.getPrimitiveBounds();
- float [] vb = new float[4];
- vb[0] = 0; // x
- vb[1] = 0; // y
- vb[2] = (float) bounds.getWidth(); // width
- vb[3] = (float) bounds.getHeight(); // height
-
- // handles the 'preserveAspectRatio', 'overflow' and 'clip'
- // and sets the appropriate AffineTransform to the image node
- initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds);
- return specializedNode;
- } catch (Exception e) {
- ctx.getUserAgent().displayError(e);
- }
-
- return superCreateGraphicsNode(ctx, imageElement, purl);
- }
-
- /**
- * Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode.
- * @param ctx the bridge context
- * @param imageElement the image element
- * @param purl the parsed URL
- * @return the newly created graphics node
- * @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element)
- */
- protected GraphicsNode superCreateGraphicsNode
- (BridgeContext ctx, Element imageElement, ParsedURL purl) {
- return super.createImageGraphicsNode(ctx, imageElement, purl);
- }
-
-
- /**
- * An image node for natively handled Image instance.
- * This holds a natively handled image so that it can be drawn into
- * the PDFGraphics2D.
- */
- public class LoaderImageNode extends AbstractGraphicsNode {
-
- private Image image;
- private BridgeContext ctx;
- private Element imageElement;
- private ParsedURL purl;
- private GraphicsNode origGraphicsNode = null;
-
- /**
- * Create a new image node for drawing natively handled images
- * into PDF graphics.
- * @param image the JPEG image
- * @param ctx the bridge context
- * @param imageElement the SVG image element
- * @param purl the URL to the image
- */
- public LoaderImageNode(Image image, BridgeContext ctx,
- Element imageElement, ParsedURL purl) {
- this.image = image;
- this.ctx = ctx;
- this.imageElement = imageElement;
- this.purl = purl;
- }
-
- /** {@inheritDoc} */
- public Shape getOutline() {
- return getPrimitiveBounds();
- }
-
- /** {@inheritDoc} */
- public void primitivePaint(Graphics2D g2d) {
- if (g2d instanceof PDFGraphics2D) {
- PDFGraphics2D pdfg = (PDFGraphics2D) g2d;
- float x = 0;
- float y = 0;
- try {
- float width = image.getSize().getWidthPx();
- float height = image.getSize().getHeightPx();
- pdfg.addNativeImage(image, x, y, width, height);
- } catch (Exception e) {
- ctx.getUserAgent().displayError(e);
- }
- } else {
- // Not going directly into PDF so use
- // original implementation so filters etc work.
- if (origGraphicsNode == null) {
- // Haven't constructed baseclass Graphics Node,
- // so do so now.
- origGraphicsNode
- = PDFImageElementBridge.this.superCreateGraphicsNode
- (ctx, imageElement, purl);
- }
- origGraphicsNode.primitivePaint(g2d);
- }
- }
-
- /** {@inheritDoc} */
- public Rectangle2D getGeometryBounds() {
- return getPrimitiveBounds();
- }
-
- /** {@inheritDoc} */
- public Rectangle2D getPrimitiveBounds() {
- return new Rectangle2D.Double(0, 0,
- image.getSize().getWidthPx(),
- image.getSize().getHeightPx());
- }
-
- /** {@inheritDoc} */
- public Rectangle2D getSensitiveBounds() {
- //No interactive features, just return primitive bounds
- return getPrimitiveBounds();
- }
-
- }
-
- /**
- * A node that holds a Graphics2D image.
- */
- public class Graphics2DNode extends AbstractGraphicsNode {
-
- private ImageGraphics2D image;
-
- /**
- * Create a new Graphics2D node.
- * @param g2d the Graphics2D image
- */
- public Graphics2DNode(ImageGraphics2D g2d) {
- this.image = g2d;
- }
-
- /** {@inheritDoc} */
- public Shape getOutline() {
- return getPrimitiveBounds();
- }
-
- /** {@inheritDoc} */
- public void primitivePaint(Graphics2D g2d) {
- int width = image.getSize().getWidthPx();
- int height = image.getSize().getHeightPx();
- Rectangle2D area = new Rectangle2D.Double(0, 0, width, height);
- image.getGraphics2DImagePainter().paint(g2d, area);
- }
-
- /** {@inheritDoc} */
- public Rectangle2D getGeometryBounds() {
- return getPrimitiveBounds();
- }
-
- /** {@inheritDoc} */
- public Rectangle2D getPrimitiveBounds() {
- return new Rectangle2D.Double(0, 0,
- image.getSize().getWidthPx(),
- image.getSize().getHeightPx());
- }
-
- /** {@inheritDoc} */
- public Rectangle2D getSensitiveBounds() {
- //No interactive features, just return primitive bounds
- return getPrimitiveBounds();
- }
+ /** {@inheritDoc} */
+ protected ImageFlavor[] getSupportedFlavours() {
+ return supportedFlavors;
}
}
diff --git a/src/java/org/apache/fop/svg/PDFTextElementBridge.java b/src/java/org/apache/fop/svg/PDFTextElementBridge.java
index 4c11aa97e..c983d2b45 100644
--- a/src/java/org/apache/fop/svg/PDFTextElementBridge.java
+++ b/src/java/org/apache/fop/svg/PDFTextElementBridge.java
@@ -19,13 +19,7 @@
package org.apache.fop.svg;
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.SVGTextElementBridge;
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.TextPainter;
-import org.apache.fop.fonts.FontInfo;
-import org.w3c.dom.Element;
/**
* Bridge class for the &lt;text> element.
@@ -34,41 +28,15 @@ import org.w3c.dom.Element;
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
-public class PDFTextElementBridge extends SVGTextElementBridge {
-
- private PDFTextPainter pdfTextPainter;
+public class PDFTextElementBridge extends AbstractFOPTextElementBridge {
/**
* Constructs a new bridge for the &lt;text> element.
- * @param fi the font information
- */
- public PDFTextElementBridge(FontInfo fi) {
- pdfTextPainter = new PDFTextPainter(fi);
- }
-
- /**
- * Create a text element bridge.
- * This set the text painter on the node if the text is simple.
- * @param ctx the bridge context
- * @param e the svg element
- * @return the text graphics node created by the super class
+ *
+ * @param textPainter the text painter to use
*/
- public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
- GraphicsNode node = super.createGraphicsNode(ctx, e);
- if (node != null) {
- //Set our own text painter
- ((TextNode)node).setTextPainter(getTextPainter());
- }
- return node;
+ public PDFTextElementBridge(TextPainter textPainter) {
+ super(textPainter);
}
-
- /**
- * Returns the TextPainter instance used by this bridge.
- * @return the text painter
- */
- public TextPainter getTextPainter() {
- return pdfTextPainter;
- }
-
}
diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java
index 06fea54cc..85447a4f9 100644
--- a/src/java/org/apache/fop/svg/PDFTextPainter.java
+++ b/src/java/org/apache/fop/svg/PDFTextPainter.java
@@ -63,8 +63,8 @@ public class PDFTextPainter extends StrokingTextPainter {
private static final boolean DEBUG = false;
- private boolean strokeText = false;
- private FontInfo fontInfo;
+ private final boolean strokeText = false;
+ private final FontInfo fontInfo;
/**
* Create a new PDF text painter with the given font information.
@@ -280,12 +280,12 @@ public class PDFTextPainter extends StrokingTextPainter {
Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);
String style = ((posture != null) && (posture.floatValue() > 0.0))
- ? "italic" : "normal";
+ ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
int weight = ((taWeight != null)
&& (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
: Font.WEIGHT_NORMAL;
- String fontFamily = null;
+ String firstFontFamily = null;
//GVT_FONT can sometimes be different from the fonts in GVT_FONT_FAMILIES
//or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set
@@ -307,6 +307,7 @@ public class PDFTextPainter extends StrokingTextPainter {
int fsize = (int)(fontSize.floatValue() * 1000);
fonts.add(fontInfo.getFontInstance(triplet, fsize));
}
+ firstFontFamily = gvtFontFamily;
} catch (Exception e) {
//Most likely NoSuchMethodError here when using Batik 1.6
//Just skip this section in this case
@@ -320,7 +321,7 @@ public class PDFTextPainter extends StrokingTextPainter {
if (fam instanceof SVGFontFamily) {
return null; //Let Batik paint this text!
}
- fontFamily = fam.getFamilyName();
+ String fontFamily = fam.getFamilyName();
if (DEBUG) {
System.out.print(fontFamily + ", ");
}
@@ -330,15 +331,20 @@ public class PDFTextPainter extends StrokingTextPainter {
int fsize = (int)(fontSize.floatValue() * 1000);
fonts.add(fontInfo.getFontInstance(triplet, fsize));
}
+ if (firstFontFamily == null) {
+ firstFontFamily = fontFamily;
+ }
}
}
if (fonts.size() == 0) {
- FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
+ if (firstFontFamily == null) {
+ //This will probably never happen. Just to be on the safe side.
+ firstFontFamily = "any";
+ }
+ //lookup with fallback possibility (incl. substitution notification)
+ FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, weight);
int fsize = (int)(fontSize.floatValue() * 1000);
fonts.add(fontInfo.getFontInstance(triplet, fsize));
- if (DEBUG) {
- System.out.print("fallback to 'any' font");
- }
}
if (DEBUG) {
System.out.println();
diff --git a/src/java/org/apache/fop/util/AbstractPaintingState.java b/src/java/org/apache/fop/util/AbstractPaintingState.java
new file mode 100644
index 000000000..4fb6b173c
--- /dev/null
+++ b/src/java/org/apache/fop/util/AbstractPaintingState.java
@@ -0,0 +1,531 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.util;
+
+import java.awt.Color;
+import java.awt.geom.AffineTransform;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * A base class which holds information about the current painting state.
+ */
+public abstract class AbstractPaintingState implements Cloneable, Serializable {
+
+ private static final long serialVersionUID = 5998356138437094188L;
+
+ /** current state data */
+ private AbstractData data = null;
+
+ /** the state stack */
+ private StateStack/*<AbstractData>*/ stateStack = new StateStack/*<AbstractData>*/();
+
+ /**
+ * Instantiates a new state data object
+ *
+ * @return a new state data object
+ */
+ protected abstract AbstractData instantiateData();
+
+ /**
+ * Instantiates a new state object
+ *
+ * @return a new state object
+ */
+ protected abstract AbstractPaintingState instantiate();
+
+ /**
+ * Returns the currently valid state
+ *
+ * @return the currently valid state
+ */
+ public AbstractData getData() {
+ if (data == null) {
+ data = instantiateData();
+ }
+ return data;
+ }
+
+ /**
+ * Set the current color.
+ * Check if the new color is a change and then set the current color.
+ *
+ * @param col the color to set
+ * @return true if the color has changed
+ */
+ public boolean setColor(Color col) {
+ if (!col.equals(getData().color)) {
+ getData().color = col;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the color.
+ *
+ * @return the color
+ */
+ public Color getColor() {
+ if (getData().color == null) {
+ getData().color = Color.black;
+ }
+ return getData().color;
+ }
+
+ /**
+ * Get the background color.
+ *
+ * @return the background color
+ */
+ public Color getBackColor() {
+ if (getData().backColor == null) {
+ getData().backColor = Color.white;
+ }
+ return getData().backColor;
+ }
+
+ /**
+ * Set the current background color.
+ * Check if the new background color is a change and then set the current background color.
+ *
+ * @param col the background color to set
+ * @return true if the color has changed
+ */
+ public boolean setBackColor(Color col) {
+ if (!col.equals(getData().backColor)) {
+ getData().backColor = col;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set the current font name
+ *
+ * @param internalFontName the internal font name
+ * @return true if the font name has changed
+ */
+ public boolean setFontName(String internalFontName) {
+ if (!internalFontName.equals(getData().fontName)) {
+ getData().fontName = internalFontName;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the current font name
+ *
+ * @return the current font name
+ */
+ public String getFontName() {
+ return getData().fontName;
+ }
+
+ /**
+ * Gets the current font size
+ *
+ * @return the current font size
+ */
+ public int getFontSize() {
+ return getData().fontSize;
+ }
+
+ /**
+ * Set the current font size.
+ * Check if the font size is a change and then set the current font size.
+ *
+ * @param size the font size to set
+ * @return true if the font size has changed
+ */
+ public boolean setFontSize(int size) {
+ if (size != getData().fontSize) {
+ getData().fontSize = size;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set the current line width.
+ *
+ * @param width the line width in points
+ * @return true if the line width has changed
+ */
+ public boolean setLineWidth(float width) {
+ if (getData().lineWidth != width) {
+ getData().lineWidth = width;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the current line width
+ *
+ * @return the current line width
+ */
+ public float getLineWidth() {
+ return getData().lineWidth;
+ }
+
+ /**
+ * Sets the dash array (line type) for the current basic stroke
+ *
+ * @param dash the line dash array
+ * @return true if the dash array has changed
+ */
+ public boolean setDashArray(float[] dash) {
+ if (!Arrays.equals(dash, getData().dashArray)) {
+ getData().dashArray = dash;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the current transform.
+ * This gets the combination of all transforms in the
+ * current state.
+ *
+ * @return the calculate combined transform for the current state
+ */
+ public AffineTransform getTransform() {
+ AffineTransform at = new AffineTransform();
+ for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
+ AbstractData data = (AbstractData)iter.next();
+ AffineTransform stackTrans = data.getTransform();
+ at.concatenate(stackTrans);
+ }
+ AffineTransform currentTrans = getData().getTransform();
+ at.concatenate(currentTrans);
+ return at;
+ }
+
+ /**
+ * Check the current transform.
+ * The transform for the current state is the combination of all
+ * transforms in the current state. The parameter is compared
+ * against this current transform.
+ *
+ * @param tf the transform the check against
+ * @return true if the new transform is different then the current transform
+ */
+ public boolean checkTransform(AffineTransform tf) {
+ return !tf.equals(getData().getTransform());
+ }
+
+ /**
+ * Get a copy of the base transform for the page. Used to translate
+ * IPP/BPP values into X,Y positions when positioning is "fixed".
+ *
+ * @return the base transform, or null if the state stack is empty
+ */
+ public AffineTransform getBaseTransform() {
+ if (stateStack.isEmpty()) {
+ return null;
+ } else {
+ AbstractData baseData = (AbstractData)stateStack.get(0);
+ return (AffineTransform) baseData.getTransform().clone();
+ }
+ }
+
+ /**
+ * Concatenates the given AffineTransform to the current one.
+ *
+ * @param at the transform to concatenate to the current level transform
+ */
+ public void concatenate(AffineTransform at) {
+ getData().concatenate(at);
+ }
+
+ /**
+ * Resets the current AffineTransform to the Base AffineTransform.
+ */
+ public void resetTransform() {
+ getData().setTransform(getBaseTransform());
+ }
+
+ /**
+ * Clears the current AffineTransform to the Identity AffineTransform
+ */
+ public void clearTransform() {
+ getData().clearTransform();
+ }
+
+
+ /**
+ * Save the current painting state.
+ * This pushes the current painting state onto the stack.
+ * This call should be used when the Q operator is used
+ * so that the state is known when popped.
+ */
+ public void save() {
+ AbstractData copy = (AbstractData)getData().clone();
+ stateStack.push(copy);
+ }
+
+ /**
+ * Restore the current painting state.
+ * This pops the painting state from the stack and sets current values to popped state.
+ *
+ * @return the restored state, null if the stack is empty
+ */
+ public AbstractData restore() {
+ if (!stateStack.isEmpty()) {
+ setData((AbstractData)stateStack.pop());
+ return this.data;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Save all painting state data.
+ * This pushes all painting state data in the given list to the stack
+ *
+ * @param dataList a state data list
+ */
+ public void saveAll(List/*<AbstractData>*/ dataList) {
+ Iterator it = dataList.iterator();
+ while (it.hasNext()) {
+ // save current data on stack
+ save();
+ setData((AbstractData)it.next());
+ }
+ }
+
+ /**
+ * Restore all painting state data.
+ * This pops all painting state data from the stack
+ *
+ * @return a list of state data popped from the stack
+ */
+ public List/*<AbstractData>*/ restoreAll() {
+ List/*<AbstractData>*/ dataList = new java.util.ArrayList/*<AbstractData>*/();
+ AbstractData data;
+ while (true) {
+ data = getData();
+ if (restore() == null) {
+ break;
+ }
+ // insert because of stack-popping
+ dataList.add(0, data);
+ }
+ return dataList;
+ }
+
+ /**
+ * Sets the current state data
+ *
+ * @param currentData state data
+ */
+ protected void setData(AbstractData data) {
+ this.data = data;
+ }
+
+ /**
+ * Clears the state stack
+ */
+ public void clear() {
+ stateStack.clear();
+ setData(null);
+ }
+
+ /**
+ * Return the state stack
+ *
+ * @return the state stack
+ */
+ protected Stack/*<AbstractData>*/ getStateStack() {
+ return this.stateStack;
+ }
+
+ /** {@inheritDoc} */
+ public Object clone() {
+ AbstractPaintingState state = instantiate();
+ state.stateStack = new StateStack(this.stateStack);
+ state.data = (AbstractData)this.data.clone();
+ return state;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return ", stateStack=" + stateStack
+ + ", currentData=" + data;
+ }
+
+
+ /**
+ * A stack implementation which holds state objects
+ */
+ public class StateStack extends java.util.Stack {
+
+ private static final long serialVersionUID = 4897178211223823041L;
+
+ /**
+ * Default constructor
+ */
+ public StateStack() {
+ super();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c initial contents of stack
+ */
+ public StateStack(Collection c) {
+ elementCount = c.size();
+ // 10% for growth
+ elementData = new Object[
+ (int)Math.min((elementCount * 110L) / 100, Integer.MAX_VALUE)];
+ c.toArray(elementData);
+ }
+ }
+
+
+ /**
+ * A base painting state data holding object
+ */
+ public abstract class AbstractData implements Cloneable, Serializable {
+
+ private static final long serialVersionUID = 5208418041189828624L;
+
+ /** The current color */
+ protected Color color = null;
+
+ /** The current background color */
+ protected Color backColor = null;
+
+ /** The current font name */
+ protected String fontName = null;
+
+ /** The current font size */
+ protected int fontSize = 0;
+
+ /** The current line width */
+ protected float lineWidth = 0;
+
+ /** The dash array for the current basic stroke (line type) */
+ protected float[] dashArray = null;
+
+ /** The current transform */
+ protected AffineTransform transform = null;
+
+ /**
+ * Returns a newly create data object
+ *
+ * @return a new data object
+ */
+ protected abstract AbstractData instantiate();
+
+ /**
+ * Concatenate the given AffineTransform with the current thus creating
+ * a new viewport. Note that all concatenation operations are logged
+ * so they can be replayed if necessary (ex. for block-containers with
+ * "fixed" positioning.
+ *
+ * @param at Transformation to perform
+ */
+ public void concatenate(AffineTransform at) {
+ getTransform().concatenate(at);
+ }
+
+ /**
+ * Get the current AffineTransform.
+ *
+ * @return the current transform
+ */
+ public AffineTransform getTransform() {
+ if (transform == null) {
+ transform = new AffineTransform();
+ }
+ return transform;
+ }
+
+ /**
+ * Sets the current AffineTransform.
+ */
+ public void setTransform(AffineTransform baseTransform) {
+ this.transform = baseTransform;
+ }
+
+ /**
+ * Resets the current AffineTransform.
+ */
+ public void clearTransform() {
+ transform = new AffineTransform();
+ }
+
+ /**
+ * Returns the derived rotation from the current transform
+ *
+ * @return the derived rotation from the current transform
+ */
+ public int getDerivedRotation() {
+ AffineTransform at = getTransform();
+ double sx = at.getScaleX();
+ double sy = at.getScaleY();
+ double shx = at.getShearX();
+ double shy = at.getShearY();
+ int rotation = 0;
+ if (sx == 0 && sy == 0 && shx > 0 && shy < 0) {
+ rotation = 270;
+ } else if (sx < 0 && sy < 0 && shx == 0 && shy == 0) {
+ rotation = 180;
+ } else if (sx == 0 && sy == 0 && shx < 0 && shy > 0) {
+ rotation = 90;
+ } else {
+ rotation = 0;
+ }
+ return rotation;
+ }
+
+ /** {@inheritDoc} */
+ public Object clone() {
+ AbstractData data = instantiate();
+ data.color = this.color;
+ data.backColor = this.backColor;
+ data.fontName = this.fontName;
+ data.fontSize = this.fontSize;
+ data.lineWidth = this.lineWidth;
+ data.dashArray = this.dashArray;
+ data.transform = new AffineTransform(this.transform);
+ return data;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "color=" + color
+ + ", backColor=" + backColor
+ + ", fontName=" + fontName
+ + ", fontSize=" + fontSize
+ + ", lineWidth=" + lineWidth
+ + ", dashArray=" + dashArray
+ + ", transform=" + transform;
+ }
+ }
+}