DrawRun.java 11.3 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.xfa.text;

import com.adobe.xfa.font.FontInstance;
import com.adobe.xfa.gfx.GFXDriver;
import com.adobe.xfa.gfx.GFXMappingList;
import com.adobe.xfa.text.ABXY;
import com.adobe.xfa.text.DispLine;
import com.adobe.xfa.text.DispLineWrapped;
import com.adobe.xfa.text.DispMapItem;
import com.adobe.xfa.text.DispPosn;
import com.adobe.xfa.text.DrawAttr;
import com.adobe.xfa.text.DrawParm;
import com.adobe.xfa.text.GlyphLoc;
import com.adobe.xfa.text.MultiMapper;
import com.adobe.xfa.text.RenderInfo;
import com.adobe.xfa.text.TextAttr;
import com.adobe.xfa.text.TextContext;
import com.adobe.xfa.text.TextDisplay;
import com.adobe.xfa.text.TextFrame;
import com.adobe.xfa.text.TextMeasurement;
import com.adobe.xfa.text.Units;
import com.adobe.xfa.ut.CoordPair;
import com.adobe.xfa.ut.UniCharIterator;
import com.adobe.xfa.ut.UnitSpan;

class DrawRun {
    private final DispLineWrapped mpoLine;
    private final DrawParm moParm;
    private final DrawAttr moAttr;
    private boolean mbAttrChange;
    private final DrawAttr.ClipRect moClipRect;
    private final StringBuilder msChar = new StringBuilder();
    private int mnRunStart;
    private int mnRunLength;
    private int mnGlyphCount;
    private boolean mbGlyphMode;
    private boolean mbIsRTL;
    private final GFXMappingList moMappingList;
    private final int meMappingType;
    private float moX;
    private float moY;
    private float moPrevX;
    private float moPrevY;
    private boolean mbUnknownWidth;
    private float moCharSpacing;
    private final boolean mbCharSpacingSupported;
    private float moWordSpacing;
    private final boolean mbWordSpacingSupported;
    private final MultiMapper moMultiple = new MultiMapper();

    DrawRun(DispLineWrapped poLine, DrawParm oParm) {
        this.mpoLine = poLine;
        this.moParm = oParm;
        this.moAttr = new DrawAttr(poLine, oParm);
        this.mbAttrChange = true;
        this.moClipRect = new DrawAttr.ClipRect(oParm);
        this.moMappingList = poLine.display().getContext().getMappingList();
        this.meMappingType = oParm.driver().getMappingLevel();
        this.mbCharSpacingSupported = oParm.driver().charSpacingSupported();
        this.mbWordSpacingSupported = oParm.driver().wordSpacingSupported();
        if (this.meMappingType == 1) {
            this.moMappingList.reset();
        }
    }

    void addGlyph(DrawAttr oCurrentAttr, RenderInfo oRenderInfo, float oX, float oY, boolean bIsRTL) {
        boolean bNewGlyphMode;
        boolean bl = bNewGlyphMode = oRenderInfo.mcGlyph == 0;
        if (bNewGlyphMode != this.mbGlyphMode) {
            this.flush();
            this.mbGlyphMode = bNewGlyphMode;
        }
        this.setupRun(oCurrentAttr, oRenderInfo, oX, oY, bIsRTL);
        int nRunStart = oRenderInfo.mpoGlyphLoc.getMapIndex();
        int nRunLength = oRenderInfo.mpoGlyphLoc.getMapLength();
        if (this.mpoLine.hasAXTEMappings()) {
            int nAdjustedRunStart = nRunStart;
            DispMapItem poPosition = null;
            for (int nPosnIndex = 0; nPosnIndex < this.mpoLine.getPositionCount(); ++nPosnIndex) {
                DispPosn oPosition = this.mpoLine.getPosition(nPosnIndex);
                if (oPosition.getMapIndex() + oPosition.getMapLength() > nRunStart) {
                    poPosition = oPosition;
                    break;
                }
                nAdjustedRunStart += DispLine.getPositionStreamCount(oPosition);
                nAdjustedRunStart -= oPosition.getMapLength();
            }
            assert (poPosition != null);
            nRunStart = nAdjustedRunStart;
            switch (DispLine.getPositionType((DispPosn)poPosition)) {
                case 2: {
                    assert (poPosition.getMapLength() == 1);
                    nRunLength = DispLine.getPositionStreamCount((DispPosn)poPosition);
                    break;
                }
                case 3: {
                    nRunStart -= oRenderInfo.mpoGlyphLoc.getMapIndex() - poPosition.getMapIndex();
                    nRunLength = 1;
                }
            }
        }
        if (this.mbGlyphMode) {
            int[] oGlyphArray = this.mpoLine.display().getContext().getGlyphArray(this.mnGlyphCount + 1);
            oGlyphArray[this.mnGlyphCount] = oRenderInfo.mnGlyphID;
            if (this.mnRunLength == 0) {
                this.mnRunStart = nRunStart;
                this.mnRunLength = nRunLength;
            } else {
                int nGlyphStart = nRunStart;
                int nGlyphMax = nGlyphStart + nRunLength;
                int nRunMax = this.mnRunStart + this.mnRunLength;
                if (nGlyphStart < this.mnRunStart) {
                    this.mnRunStart = nGlyphStart;
                }
                if (nGlyphMax > nRunMax) {
                    nRunMax = nGlyphMax;
                }
                this.mnRunLength = nRunMax - this.mnRunStart;
            }
            this.accumulateMapping(nRunStart, this.mnGlyphCount, nRunLength);
            this.updatePosition(oRenderInfo.mpoGlyphLoc, oX, oY, oRenderInfo.mnGlyphID, true);
        } else {
            this.msChar.append((char)oRenderInfo.mcGlyph);
            this.updatePosition(oRenderInfo.mpoGlyphLoc, oX, oY, oRenderInfo.mnGlyphID, false);
            this.accumulateMapping(nRunStart, this.mnGlyphCount);
            ++this.mnRunLength;
        }
        ++this.mnGlyphCount;
    }

    void flush() {
        if (this.mnGlyphCount > 0) {
            StringBuilder debugMsg = null;
            TextContext context = this.mpoLine.display().getContext();
            if (context.debug()) {
                debugMsg = new StringBuilder();
            }
            if (this.mbGlyphMode) {
                int[] oGlyphArray = context.getGlyphArray();
                if (this.flushCommon(debugMsg)) {
                    if (debugMsg != null) {
                        debugMsg.append(" Glyphs:");
                        for (int i = 0; i < this.mnGlyphCount; ++i) {
                            debugMsg.append(' ');
                            debugMsg.append(Integer.toString(oGlyphArray[i]));
                        }
                        context.debug(debugMsg.toString());
                    }
                    this.moParm.driver().relGlyphs(oGlyphArray, this.mnGlyphCount);
                }
            } else {
                if (this.flushCommon(debugMsg)) {
                    if (debugMsg != null) {
                        debugMsg.append(" Chars:");
                        UniCharIterator iter = new UniCharIterator(this.msChar);
                        int c = iter.next();
                        while (c != 0) {
                            debugMsg.append(' ');
                            debugMsg.append(Integer.toString(c));
                            c = iter.next();
                        }
                        context.debug(debugMsg.toString());
                    }
                    this.moParm.driver().relText(this.msChar.toString());
                }
                this.msChar.delete(0, this.msChar.length());
            }
            this.mnRunLength = 0;
            this.mnGlyphCount = 0;
        }
    }

    void clear() {
        this.moClipRect.detach();
    }

    void forceAttrChange() {
        this.mbAttrChange = true;
    }

    private void setupRun(DrawAttr oCurrentAttr, RenderInfo oRenderInfo, float oX, float oY, boolean bIsRTL) {
        if (!(this.mnGlyphCount <= 0 || this.mbUnknownWidth || this.mpoLine.legacyPositioning() || this.moAttr.getFontOverride() == null && (this.moAttr.getAttr() == null || this.moAttr.getAttr().fontInstance() == null) || oX == this.moPrevX && oY == this.moPrevY || (double)Math.abs(oX - this.moPrevX) <= 0.001 && (double)Math.abs(oY - this.moPrevY) <= 0.001)) {
            this.flush();
        }
        if (this.mnGlyphCount == 0) {
            this.moAttr.reset(oCurrentAttr);
            this.mnRunStart = oRenderInfo.mpoGlyphLoc.getMapIndex();
            this.moX = oX;
            this.moY = oY;
            this.mbIsRTL = bIsRTL;
            this.moCharSpacing = 0.0f;
            this.moWordSpacing = 0.0f;
            TextAttr poAttr = this.moAttr.getAttr();
            if (poAttr != null) {
                if (poAttr.charSpacingEnable()) {
                    this.moCharSpacing = Units.toFloat(poAttr.charSpacing().getLength());
                }
                if (poAttr.wordSpacingEnable()) {
                    this.moWordSpacing = Units.toFloat(poAttr.wordSpacing().getLength());
                }
            }
            if (oRenderInfo.mbAttrChange) {
                this.mbAttrChange = true;
                oRenderInfo.mbAttrChange = false;
            }
        }
    }

    private boolean flushCommon(StringBuilder debugMsg) {
        boolean attrChange = this.mbAttrChange;
        this.mbAttrChange = false;
        if (attrChange && !this.moAttr.assertAttrs(this.moClipRect)) {
            return false;
        }
        GFXDriver poDriver = this.moParm.driver();
        CoordPair oOffset = new CoordPair(Units.toUnitSpan(this.moX), Units.toUnitSpan(this.moY));
        oOffset = ABXY.toXY(this.mpoLine.getXYOrigin(), oOffset, this.mpoLine.frame().getLayoutOrientation());
        poDriver.relPosition(oOffset);
        if (debugMsg != null) {
            debugMsg.append("At Y=");
            debugMsg.append(oOffset.y().toString());
            debugMsg.append(", X=");
            debugMsg.append(oOffset.x().toString());
            debugMsg.append(", ");
        }
        this.flushMultiple();
        switch (this.meMappingType) {
            case 2: {
                poDriver.mapChars(this.mnRunStart, this.mnRunLength);
                break;
            }
            case 1: {
                poDriver.mapGlyphs(this.moMappingList, this.mbIsRTL);
                this.moMappingList.reset();
            }
        }
        return true;
    }

    private void updatePosition(GlyphLoc poGlyphLoc, float oX, float oY, int nGlyph, boolean bIsGlyph) {
        float oOffset;
        boolean bHorizontal;
        FontInstance oFontInstance = this.moAttr.getWorkingFont();
        this.mbUnknownWidth = true;
        this.moPrevX = oX;
        this.moPrevY = oY;
        if (oFontInstance != null && (oOffset = oFontInstance.getGlyphWidth(nGlyph, bHorizontal = !this.mpoLine.verticalOrientation())) >= 0.0f) {
            this.mbUnknownWidth = false;
            if (this.mbCharSpacingSupported) {
                oOffset += this.moCharSpacing;
            }
            if (this.mbWordSpacingSupported && this.mpoLine.getBreakClass(poGlyphLoc.getMapIndex()) == 31) {
                oOffset += this.moWordSpacing;
            }
            this.moPrevX += oOffset;
        }
    }

    private void accumulateMapping(int nCharIndex, int nGlyphIndex, int nCharLength) {
        if (this.meMappingType != 1) {
            return;
        }
        if (nCharLength != 1) {
            this.flushMultiple();
            this.moMappingList.addMapping(nCharIndex, nGlyphIndex, nCharLength);
            return;
        }
        if (!this.moMultiple.canAccumulate(nCharIndex, nGlyphIndex)) {
            this.flushMultiple();
        }
        this.moMultiple.accumulate(nCharIndex, nGlyphIndex);
    }

    private void accumulateMapping(int nCharIndex, int nGlyphIndex) {
        this.accumulateMapping(nCharIndex, nGlyphIndex, 1);
    }

    private void flushMultiple() {
        this.moMultiple.flush(this.moMappingList);
    }
}