// save positions
int saveIP = currentIPPosition;
int saveBP = currentBPPosition;
CTM ctm = bv.getCTM();
int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
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 (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);
//Free transformation for the block-container viewport
String transf;
transf = bv.getForeignAttributeValue(FOX_TRANSFORM);
if (transf != null) {
AffineTransform freeTransform = AWTTransformProducer.createAffineTransform(transf);
positionTransform.concatenate(freeTransform);
}
//Viewport position
if (!positionTransform.isIdentity()) {
establishTransformationMatrix(positionTransform);
}
//This is the content-rect
float width = bv.getIPD() / 1000f;
float height = bv.getBPD() / 1000f;
//Background and borders
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);
if (!contentRectTransform.isIdentity()) {
establishTransformationMatrix(contentRectTransform);
}
//Clipping
if (bv.getClip()) {
clipRect(0f, 0f, width, height);
}
//Set up coordinate system for content rectangle
AffineTransform contentTransform = ctm.toAffineTransform();
if (!contentTransform.isIdentity()) {
establishTransformationMatrix(contentTransform);
}
currentIPPosition = 0;
currentBPPosition = 0;
renderBlocks(bv, children);
if (!contentTransform.isIdentity()) {
restoreGraphicsState();
}
if (!contentRectTransform.isIdentity()) {
restoreGraphicsState();
}
if (!positionTransform.isIdentity()) {
restoreGraphicsState();
}
//For FIXED, we need to restore break out now we are done
if (positioning == Block.FIXED) {
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;