public List getNextKnuthElements()

in fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java [763:919]


    public List<KnuthSequence> getNextKnuthElements(final LayoutContext context, final int alignment) {

        lineStartBAP = context.getLineStartBorderAndPaddingWidth();
        lineEndBAP = context.getLineEndBorderAndPaddingWidth();
        alignmentContext = context.getAlignmentContext();

        final List returnList = new LinkedList();
        KnuthSequence sequence = new InlineKnuthSequence();
        GlyphMapping mapping = null;
        GlyphMapping prevMapping = null;
        returnList.add(sequence);

        if (LOG.isDebugEnabled()) {
            LOG.debug("GK: [" + nextStart + "," + foText.length() + "]");
        }
        LineBreakStatus lineBreakStatus = new LineBreakStatus();
        thisStart = nextStart;
        boolean inWord = false;
        boolean inWhitespace = false;
        char ch = 0;
        int level = -1;
        int prevLevel = -1;
        boolean retainControls = false;
        Font lastFont = null;
        int lastFontPos = -1;
        while (nextStart < foText.length()) {
            ch = foText.charAt(nextStart);
            level = foText.bidiLevelAt(nextStart);
            boolean breakOpportunity = false;
            byte breakAction = keepTogether
                    ? LineBreakStatus.PROHIBITED_BREAK
                    : lineBreakStatus.nextChar(ch);
            switch (breakAction) {
                case LineBreakStatus.COMBINING_PROHIBITED_BREAK:
                case LineBreakStatus.PROHIBITED_BREAK:
                    break;
                case LineBreakStatus.EXPLICIT_BREAK:
                    break;
                case LineBreakStatus.COMBINING_INDIRECT_BREAK:
                case LineBreakStatus.DIRECT_BREAK:
                case LineBreakStatus.INDIRECT_BREAK:
                    breakOpportunity = true;
                    break;
                default:
                    TextLayoutManager.LOG.error("Unexpected breakAction: " + breakAction);
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug("GK: {"
                            + " index = " + nextStart
                            + ", char = " + CharUtilities.charToNCRef(ch)
                            + ", level = " + level
                            + ", levelPrev = " + prevLevel
                            + ", inWord = " + inWord
                            + ", inSpace = " + inWhitespace
                            + "}");
            }
            if (inWord) {
                boolean processWord = breakOpportunity
                        || GlyphMapping.isSpace(ch)
                        || CharUtilities.isExplicitBreak(ch)
                        || ((prevLevel != -1) && (level != prevLevel));
                if (!processWord && foText.getCommonFont().getFontSelectionStrategy() == EN_CHARACTER_BY_CHARACTER) {
                    if (lastFont == null || lastFontPos != nextStart - 1) {
                        lastFont = FontSelector.selectFontForCharactersInText(
                                foText, nextStart - 1, nextStart, foText, this);
                    }
                    Font font = FontSelector.selectFontForCharactersInText(
                            foText, nextStart, nextStart + 1, foText, this);
                    processWord = font != lastFont;
                    lastFont = font;
                    lastFontPos = nextStart;
                }
                if (processWord) {
                    // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN
                    prevMapping = processWord(alignment, sequence, prevMapping, ch,
                        breakOpportunity, true, prevLevel, retainControls);
                }
            } else if (inWhitespace) {
                if (ch != CharUtilities.SPACE || breakOpportunity) {
                    prevMapping = processWhitespace(alignment, sequence,
                                                     breakOpportunity, prevLevel);
                }
            } else {
                if (mapping != null) {
                    prevMapping = mapping;
                    processLeftoverGlyphMapping(alignment, sequence, mapping,
                            ch == CharUtilities.SPACE || breakOpportunity);
                    mapping = null;
                }
                if (breakAction == LineBreakStatus.EXPLICIT_BREAK) {
                    sequence = processLinebreak(returnList, sequence);
                }
            }

            if (ch == CharUtilities.SPACE
                    && foText.getWhitespaceTreatment() == Constants.EN_PRESERVE
                    || ch == CharUtilities.NBSPACE) {
                final Font font = FontSelector.selectFontForCharacterInText(ch,
                        this.foText, this);
                font.mapChar(ch);
                // preserved space or non-breaking space:
                // create the GlyphMapping object
                MinOptMax areaIPD;
                if (prevMapping != null && prevMapping.isSpace) {
                    areaIPD = wordSpaceIPD.minus(letterSpaceIPD);
                } else {
                    areaIPD = wordSpaceIPD;
                }

                mapping = new GlyphMapping(nextStart, nextStart + 1, 1, 0, areaIPD, false, true,
                        breakOpportunity, spaceFont, level, null);
                thisStart = nextStart + 1;
            } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) {
                // create the GlyphMapping object
                Font font = FontSelector.selectFontForCharacterInText(ch, foText, this);
                MinOptMax ipd = MinOptMax.getInstance(font.getCharWidth(ch));
                mapping = new GlyphMapping(nextStart, nextStart + 1, 0, 0, ipd, false, true,
                                        breakOpportunity, font, level, null);
                thisStart = nextStart + 1;
            } else if (CharUtilities.isExplicitBreak(ch)) {
                //mandatory break-character: only advance index
                thisStart = nextStart + 1;
            }

            inWord = !GlyphMapping.isSpace(ch) && !CharUtilities.isExplicitBreak(ch);
            inWhitespace = ch == CharUtilities.SPACE
                    && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE;
            prevLevel = level;
            nextStart++;
        }

        // Process any last elements
        if (inWord) {
            processWord(alignment, sequence, prevMapping, ch, false, false, prevLevel, retainControls);
        } else if (inWhitespace) {
            processWhitespace(alignment, sequence, !keepTogether, prevLevel);
        } else if (mapping != null) {
            processLeftoverGlyphMapping(alignment, sequence, mapping,
                    ch == CharUtilities.ZERO_WIDTH_SPACE);
        } else if (CharUtilities.isExplicitBreak(ch)) {
            this.processLinebreak(returnList, sequence);
        }

        if (((List) ListUtil.getLast(returnList)).isEmpty()) {
            //Remove an empty sequence because of a trailing newline
            ListUtil.removeLast(returnList);
        }

        setFinished(true);
        if (returnList.isEmpty()) {
            return null;
        } else {
            return returnList;
        }


    }