You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-dev@xmlgraphics.apache.org by "Dan Caprioara (Jira)" <ji...@apache.org> on 2019/09/06 13:25:00 UTC

[jira] [Commented] (FOP-2809) Excessive wrap when having linefeed-treatment="preserve" and inlines

    [ https://issues.apache.org/jira/browse/FOP-2809?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16924243#comment-16924243 ] 

Dan Caprioara commented on FOP-2809:
------------------------------------

Possible fix in the LineLayoutManager. Add these methods:
{code:java}
  /**
     * <p>
     * The collectInlineKnuthElements method creates some paragraphs based on the assumption that 
     * the child layout managers (that can be one ore more TextLayoutManager or InlineLayoutManagers)
     * are returning a KnuthSequence for each line. By line is understood a sequence ending in a new line. 
     * In the Knuth terms, a forced line break is represented by an auxiliary box with a negative infinite penalty .
     * </p>
     * <p>
     * The assuption proved false when a block like:
     * <pre>
     *  &lt;inline>
     *  alpha &lt;inline>beta&lt;/inline>
     *  &lt;inline>gamma&lt;/inline>
     *  &lt;/inline>
     * </pre>
     * was broken into:
     * <pre>
     *  &lt;inline>
     *  alpha 
     *  &lt;inline>beta&lt;/inline>
     *  &lt;inline>gamma&lt;/inline>
     *  &lt;/inline>
     * </pre>
     * because the LineLayoutManager had a single child 
     * InlineLayoutManager, that concatenated all the subtree LM boxes into a single sequence.
     * The {@link LineLayoutManager#collectInlineKnuthElements(LayoutContext)} is looking for line breaks only at the end of sequences, and
     * misses the newlines from the middle of the preformatted text.
     * </p>
     * <p>The solution is to pre-process each of the sequences and split it if it is the case.
     *   
     * 
     * 
     * @param inlineElements The list of sequences, each representing a line. Each of the sequence will be analysed and split into multiple ones if a hard line break is detected.
     * @return The list with the sequences.
     */
    private List supplementalBreakOfSequences(List<KnuthSequence> inlineElements) {
      List<KnuthSequence> result = new ArrayList<>();
      
      for (KnuthSequence sequence : inlineElements) {
        // The 'line' that may need to be split in multiple lines.
        if (sequence.isInlineSequence()) {
          while(sequence.size() > 0) {
            int idx = findNextLineBreakIndex(0, sequence);
            if (idx != -1 && idx != sequence.size() - 1) {
              result.add(new InlineKnuthSequence(sequence.subList(0, idx + 1)));
              sequence = new InlineKnuthSequence(sequence.subList(idx + 1, sequence.size()));
            } else {
              result.add(sequence);
              break;
            }
          }
        } else {
          result.add(sequence);          
        }      
      }
      
      return result;
    }

    private int findNextLineBreakIndex(int start, KnuthSequence sequence) {
      int idx = -1;
      boolean previousIsBox = false;
      for (int i = 0; i < sequence.size() - 1; i++) {
        ListElement current = (ListElement) sequence.get(i);
        if (previousIsBox && current.isForcedBreak()) {
          idx = i;
          break;
        }
        
        previousIsBox = current.isBox()
            && !((KnuthElement) current).isAuxiliary()
            && ((KnuthElement) current).getWidth() != 0;
      }
      return idx;
    }
    
{code}

Invoke the first one in the org.apache.fop.layoutmgr.inline.LineLayoutManager.collectInlineKnuthElements(LayoutContext) method after the inlineElements checking:

{code:java}
  InlineLevelLayoutManager curLM;
        while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
            List inlineElements = curLM.getNextKnuthElements(inlineLC, effectiveAlignment);
            if (inlineElements == null || inlineElements.size() == 0) {
                /* curLM.getNextKnuthElements() returned null or an empty list;
                 * this can happen if there is nothing more to layout,
                 * so just iterate once more to see if there are other children */
                continue;
            }

            // PATCH START
            inlineElements = supplementalBreakOfSequences(inlineElements);
            // PATCH END
{code}

> Excessive wrap when having linefeed-treatment="preserve" and inlines
> --------------------------------------------------------------------
>
>                 Key: FOP-2809
>                 URL: https://issues.apache.org/jira/browse/FOP-2809
>             Project: FOP
>          Issue Type: Bug
>          Components: layout/line
>    Affects Versions: 2.3
>            Reporter: Dan Caprioara
>            Priority: Major
>
> The text should be presented on two lines (they are separated by line breaks - not by wrapping - is plenty of space in the page):
> {quote}
> line1 line1 line1 line1 LINE1
> line2
> {quote}
> Instead it is  on three lines.
> {quote}
> line1 line1 line1 line1
> LINE1
> line2
> {quote}
> The snippet:
> {code:xml}
> <?xml version="1.0" encoding="UTF-8"?>
> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
>   xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" xml:lang="en-us">
>   <fo:layout-master-set>
>     <fo:simple-page-master master-name="css2fo-default" page-width="8.5in" page-height="11in">
>       <fo:region-body margin="1in"/>
>     </fo:simple-page-master>
>   </fo:layout-master-set>
>   <fo:page-sequence master-reference="css2fo-default" force-page-count="no-force"
>     id="last-page-sequence" line-height-shift-adjustment="disregard-shifts">
>     <fo:flow flow-name="xsl-region-body">
>         <fo:block-container>
>           <fo:block linefeed-treatment="preserve" wrap-option="wrap"><fo:inline>line1 line1 <fo:inline>line1 line1 LINE1</fo:inline>
> <fo:inline>line2</fo:inline></fo:inline></fo:block>
>         </fo:block-container>
>     </fo:flow>
>   </fo:page-sequence>
> </fo:root>
> {code}
> If you add more words to the example, you will see that it always add a break before the second-to-last word.
> If you remove the inline: {{<fo:inline>line2</fo:inline>}} and leave just the {{line2}} text, this corrects the problem.  The same if you remove the tags of any inline.



--
This message was sent by Atlassian Jira
(v8.3.2#803003)