GraphicsNode paintedNode,
float opacity) {
// extract pattern content
CompositeGraphicsNode patternContentNode
= extractPatternContent(patternElement, ctx);
if (patternContentNode == null) {
return null; // no content means no paint
}
// get pattern region using 'patternUnits'. Pattern region is in tile pace.
Rectangle2D patternRegion = SVGUtilities.convertPatternRegion
(patternElement, paintedElement, paintedNode, ctx);
String s;
// 'patternTransform' attribute - default is an Identity matrix
AffineTransform patternTransform;
s = SVGUtilities.getChainableAttributeNS
(patternElement, null, SVG_PATTERN_TRANSFORM_ATTRIBUTE, ctx);
if (s.length() != 0) {
patternTransform = SVGUtilities.convertTransform
(patternElement, SVG_PATTERN_TRANSFORM_ATTRIBUTE, s);
} else {
patternTransform = new AffineTransform();
}
// 'overflow' on the pattern element
boolean overflowIsHidden = CSSUtilities.convertOverflow(patternElement);
// 'patternContentUnits' - default is userSpaceOnUse
short contentCoordSystem;
s = SVGUtilities.getChainableAttributeNS
(patternElement, null, SVG_PATTERN_CONTENT_UNITS_ATTRIBUTE, ctx);
if (s.length() == 0) {
contentCoordSystem = SVGUtilities.USER_SPACE_ON_USE;
} else {
contentCoordSystem = SVGUtilities.parseCoordinateSystem
(patternElement, SVG_PATTERN_CONTENT_UNITS_ATTRIBUTE, s);
}
// Compute a transform according to viewBox, preserveAspectRatio
// and patternContentUnits and the pattern transform attribute.
//
// The stack of transforms is:
//
// +-------------------------------+
// | viewPortTranslation |
// +-------------------------------+
// | preserveAspectRatioTransform |
// +-------------------------------+
// + patternContentUnitsTransform |
// +-------------------------------+
//
// where:
// - viewPortTranslation is the transform that translate to
// the viewPort's origin.
// - preserveAspectRatioTransform is the transformed implied by the
// preserveAspectRatio attribute.
// - patternContentUnitsTransform is the transform implied by the
// patternContentUnits attribute.
//
// Note that there is an additional transform from the tiling
// space to the user space (patternTransform) that is passed
// separately to the PatternPaintContext.
//
AffineTransform patternContentTransform = new AffineTransform();
//
// Process viewPortTranslation
//
patternContentTransform.translate(patternRegion.getX(),
patternRegion.getY());
//
// Process preserveAspectRatioTransform
//
// 'viewBox' attribute
String viewBoxStr = SVGUtilities.getChainableAttributeNS
(patternElement, null, SVG_VIEW_BOX_ATTRIBUTE, ctx);
if (viewBoxStr.length() > 0) {
// There is a viewBox attribute. Then, take
// preserveAspectRatio into account.
String aspectRatioStr = SVGUtilities.getChainableAttributeNS
(patternElement, null, SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE, ctx);
float w = (float)patternRegion.getWidth();
float h = (float)patternRegion.getHeight();
AffineTransform preserveAspectRatioTransform
= ViewBox.getPreserveAspectRatioTransform
(patternElement, viewBoxStr, aspectRatioStr, w, h);
patternContentTransform.concatenate(preserveAspectRatioTransform);
}
//
// Process patternContentUnitsTransform
//
if(contentCoordSystem == SVGUtilities.OBJECT_BOUNDING_BOX){
AffineTransform patternContentUnitsTransform
= new AffineTransform();
Rectangle2D objectBoundingBox = paintedNode.getGeometryBounds();
patternContentUnitsTransform.translate
(objectBoundingBox.getX(),
objectBoundingBox.getY());
patternContentUnitsTransform.scale
(objectBoundingBox.getWidth(),
objectBoundingBox.getHeight());
patternContentTransform.concatenate
(patternContentUnitsTransform);
}
//
// Apply transform
//
patternContentNode.setTransform(patternContentTransform);
// take the opacity into account. opacity is implemented by a Filter
if (opacity != 1) {
Filter filter = patternContentNode.getGraphicsNodeRable(true);
filter = new ComponentTransferRable8Bit
(filter,
ConcreteComponentTransferFunction.getLinearTransfer
(opacity, 0), //alpha
ConcreteComponentTransferFunction.getIdentityTransfer(), //Red
ConcreteComponentTransferFunction.getIdentityTransfer(), //Grn
ConcreteComponentTransferFunction.getIdentityTransfer());//Blu
patternContentNode.setFilter(filter);
}
return new PatternPaint(patternContentNode,
patternRegion,
!overflowIsHidden,