Bug 49355

Summary: Text renderer does not output correctly when margin is set
Product: Fop - Now in Jira Reporter: Vu <vu_k_tran>
Component: generalAssignee: fop-dev
Status: NEW ---    
Severity: normal    
Priority: P3    
Version: 0.95   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Attachments: This file contains sample .fo files for margin-top and margin-bottom settings

Description Vu 2010-05-28 11:10:10 UTC
Created attachment 25493 [details]
This file contains sample .fo files for margin-top and margin-bottom settings

1. Configure FO to use text/plain as the output format

2. Generates an .fo file with margin-top sets (to create header)
3. If multiple page is generated, the margin-top value is compounded on the next pages and push the body text down until no more output for body text.

3. Generates an .fo file with margin-bottom sets (to create footer)
4. Body of text is not output

There are 2 attachments:
1) TextMarginTop.fo: This file contains 2 pages with header information set.
2) TextMarginBottom.fo: This file contains 2 pages with footer information set.
Comment 1 Vu 2010-05-28 11:24:00 UTC
Looking at the source file, I've noticed the following:

- The TXTRenderer uses TXTState as graphic state and TXTState implements as a stack (LinkedList)
- The CTM is pushed on to this graphic state in 2 cases:
   1) TXTRenderer.startVPArea()
   2) TXTRenderer.concatenateTransformationMatrix()

- But the CTM is popped out from this graphic state only when:
   1) TXTRenderer.endVPArea() is called

- There is no counterpart for TXTRenderer.concatenateTransformationMatrix() to popped the CTM out of the graphic state and that state accumulates all CTM and causes issue when rendering content.

My proposed approach is:
In TXTRenderer, create a new variable to keep a stack trace of when CTM is pushed, popped from the stack and whether it is pushed using the concatenateTransformationMatrix() method call.  When it is time for popping the CTM, check this new stack and pop the CTM out of the stack when the CTM is pushed on it using the concatenateTransformationMatrix() call.

-- Code example:

private LinkedList ctmTransformStack = new LinkedList();

protected void startVParea(CTM ctm, Rectangle2D clippingRect) {

protected void endVParea() {
    Boolean transformMatrix = (Boolean) ctmTransformStack.removeLast();
     * Perform compensation pop for concatenateTransformationMatrix()'s push
    while (transformMatrix.booleanValue()) {
      	transformMatrix = (Boolean) ctmTransformStack.removeLast();

protected void concatenateTransformationMatrix(AffineTransform at) {
   currentState.push(new CTM(ptToMpt(at)));
Comment 2 Glenn Adams 2012-04-07 01:37:15 UTC
resetting severity from major to normal pending further review
Comment 3 Glenn Adams 2012-04-07 01:43:26 UTC
resetting P2 open bugs to P3 pending further review