Ejemplo n.º 1
0
        //            Shaper.applyKerning(fontProgram, text);
        internal static byte[] GetBidiLevels(BaseDirection?baseDirection, int[] unicodeIds)
        {
            if (!TYPOGRAPHY_MODULE_INITIALIZED)
            {
                logger.Warn(typographyNotFoundException);
            }
            else
            {
                byte direction;
                switch (baseDirection)
                {
                case BaseDirection.LEFT_TO_RIGHT: {
                    direction = 0;
                    break;
                }

                case BaseDirection.RIGHT_TO_LEFT: {
                    direction = 1;
                    break;
                }

                case BaseDirection.DEFAULT_BIDI:
                default: {
                    direction = 2;
                    break;
                }
                }
                int    len   = unicodeIds.Length;
                byte[] types = (byte[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_CHARACTER_MAP, GET_CHARACTER_TYPES, new Type[]
                                                  { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len);
                //            byte[] types = BidiCharacterMap.getCharacterTypes(unicodeIds, 0, len);
                byte[] pairTypes = (byte[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_BRACKET_MAP, GET_BRACKET_TYPES, new Type[]
                                                      { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len);
                //            byte[] pairTypes = BidiBracketMap.getBracketTypes(unicodeIds, 0, len);
                int[] pairValues = (int[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_BRACKET_MAP, GET_BRACKET_VALUES, new Type[]
                                                     { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len);
                //            int[] pairValues = BidiBracketMap.getBracketValues(unicodeIds, 0, len);
                Object bidiReorder = CallConstructor(TYPOGRAPHY_PACKAGE + BIDI_ALGORITHM, new Type[] { typeof(byte[]), typeof(
                                                                                                           byte[]), typeof(int[]), typeof(byte) }, types, pairTypes, pairValues, direction);
                //            BidiAlgorithm bidiReorder = new BidiAlgorithm(types, pairTypes, pairValues, direction);
                return((byte[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_ALGORITHM, GET_LEVELS, bidiReorder, new Type[] { typeof(
                                                                                                                         int[]) }, new int[] { len }));
            }
            //            return bidiReorder.getLevels(new int[]{len});
            return(null);
        }
 /// <summary>
 /// This attribute specifies the base direction of directionally neutral text
 /// (i.e., text that doesn't have inherent directionality as defined in Unicode)
 /// in an element's content and attribute values.
 /// </summary>
 /// <param name="baseDirection">base direction</param>
 /// <returns>this element</returns>
 public virtual T SetBaseDirection(BaseDirection?baseDirection)
 {
     SetProperty(Property.BASE_DIRECTION, baseDirection);
     return((T)(Object)this);
 }
Ejemplo n.º 3
0
        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            Rectangle layoutBox = layoutContext.GetArea().GetBBox().Clone();

            occupiedArea = new LayoutArea(layoutContext.GetArea().GetPageNumber(), layoutBox.
                                          Clone().MoveDown(-layoutBox.GetHeight()).SetHeight(0));
            float curWidth = 0;

            maxAscent  = 0;
            maxDescent = 0;
            int           childPos      = 0;
            BaseDirection?baseDirection = this.GetProperty <BaseDirection?>(Property.BASE_DIRECTION, BaseDirection.NO_BIDI);

            foreach (IRenderer renderer in childRenderers)
            {
                if (renderer is TextRenderer)
                {
                    renderer.SetParent(this);
                    ((TextRenderer)renderer).ApplyOtf();
                    renderer.SetParent(null);
                    if (baseDirection == null || baseDirection == BaseDirection.NO_BIDI)
                    {
                        baseDirection = renderer.GetOwnProperty <BaseDirection?>(Property.BASE_DIRECTION);
                    }
                }
            }
            IList <int> unicodeIdsReorderingList = null;

            if (levels == null && baseDirection != null && baseDirection != BaseDirection.NO_BIDI)
            {
                unicodeIdsReorderingList = new List <int>();
                bool newLineFound = false;

                foreach (IRenderer child in childRenderers)
                {
                    if (newLineFound)
                    {
                        break;
                    }
                    if (child is TextRenderer)
                    {
                        GlyphLine text = ((TextRenderer)child).GetText();
                        for (int i = text.start; i < text.end; i++)
                        {
                            if (TextRenderer.IsNewLine(text, i))
                            {
                                newLineFound = true;
                                break;
                            }
                            // we assume all the chars will have the same bidi group
                            // we also assume pairing symbols won't get merged with other ones
                            unicodeIdsReorderingList.Add(text.Get(i).GetUnicode());
                        }
                    }
                }
                levels = unicodeIdsReorderingList.Count > 0 ? TypographyUtils.GetBidiLevels((BaseDirection)baseDirection, ArrayUtil.ToArray(unicodeIdsReorderingList)) : null;
            }
            bool             anythingPlaced = false;
            TabStop          nextTabStop    = null;
            LineLayoutResult result         = null;

            while (childPos < childRenderers.Count)
            {
                IRenderer    childRenderer = childRenderers[childPos];
                LayoutResult childResult;
                Rectangle    bbox = new Rectangle(layoutBox.GetX() + curWidth, layoutBox.GetY(), layoutBox
                                                  .GetWidth() - curWidth, layoutBox.GetHeight());
                if (childRenderer is TextRenderer)
                {
                    // Delete these properties in case of relayout. We might have applied them during justify().
                    childRenderer.DeleteOwnProperty(Property.CHARACTER_SPACING);
                    childRenderer.DeleteOwnProperty(Property.WORD_SPACING);
                }
                else
                {
                    if (childRenderer is TabRenderer)
                    {
                        if (nextTabStop != null)
                        {
                            IRenderer tabRenderer = childRenderers[childPos - 1];
                            tabRenderer.Layout(new LayoutContext(new LayoutArea(layoutContext.GetArea().GetPageNumber
                                                                                    (), bbox)));
                            curWidth += tabRenderer.GetOccupiedArea().GetBBox().GetWidth();
                        }
                        nextTabStop = CalculateTab(childRenderer, curWidth, layoutBox.GetWidth());
                        if (childPos == childRenderers.Count - 1)
                        {
                            nextTabStop = null;
                        }
                        if (nextTabStop != null)
                        {
                            ++childPos;
                            continue;
                        }
                    }
                }
                if (!anythingPlaced && childRenderer is TextRenderer)
                {
                    ((TextRenderer)childRenderer).TrimFirst();
                }
                if (nextTabStop != null && nextTabStop.GetTabAlignment() == TabAlignment.ANCHOR &&
                    childRenderer is TextRenderer)
                {
                    childRenderer.SetProperty(Property.TAB_ANCHOR, nextTabStop
                                              .GetTabAnchor());
                }
                childResult = childRenderer.SetParent(this).Layout(new LayoutContext(new LayoutArea
                                                                                         (layoutContext.GetArea().GetPageNumber(), bbox)));
                float childAscent  = 0;
                float childDescent = 0;
                if (childRenderer is TextRenderer)
                {
                    childAscent  = ((TextRenderer)childRenderer).GetAscent();
                    childDescent = ((TextRenderer)childRenderer).GetDescent();
                }
                else
                {
                    if (childRenderer is ImageRenderer)
                    {
                        childAscent = childRenderer.GetOccupiedArea().GetBBox().GetHeight();
                    }
                }
                maxAscent  = Math.Max(maxAscent, childAscent);
                maxDescent = Math.Min(maxDescent, childDescent);
                float maxHeight = maxAscent - maxDescent;
                if (nextTabStop != null)
                {
                    IRenderer tabRenderer = childRenderers[childPos - 1];
                    float     tabWidth    = CalculateTab(layoutBox, curWidth, nextTabStop, childRenderer, childResult
                                                         , tabRenderer);
                    tabRenderer.Layout(new LayoutContext(new LayoutArea(layoutContext.GetArea().GetPageNumber
                                                                            (), bbox)));
                    childResult.GetOccupiedArea().GetBBox().MoveRight(tabWidth);
                    if (childResult.GetSplitRenderer() != null)
                    {
                        childResult.GetSplitRenderer().GetOccupiedArea().GetBBox().MoveRight(tabWidth);
                    }
                    float tabAndNextElemWidth = tabWidth + childResult.GetOccupiedArea().GetBBox().GetWidth();
                    if (nextTabStop.GetTabAlignment() == TabAlignment.RIGHT && curWidth + tabAndNextElemWidth < nextTabStop.GetTabPosition())
                    {
                        curWidth = nextTabStop.GetTabPosition();
                    }
                    else
                    {
                        curWidth += tabAndNextElemWidth;
                    }
                    nextTabStop = null;
                }
                else
                {
                    curWidth += childResult.GetOccupiedArea().GetBBox().GetWidth();
                }
                occupiedArea.SetBBox(new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox
                                                   .GetHeight() - maxHeight, curWidth, maxHeight));
                if (childResult.GetStatus() != LayoutResult.FULL)
                {
                    LineRenderer[] split = Split();
                    split[0].childRenderers = new List <IRenderer>(childRenderers.SubList(0, childPos)
                                                                   );
                    bool wordWasSplitAndItWillFitOntoNextLine = false;
                    if (childResult is TextLayoutResult && ((TextLayoutResult)childResult).IsWordHasBeenSplit
                            ())
                    {
                        LayoutResult newLayoutResult = childRenderer.Layout(layoutContext);
                        if (newLayoutResult is TextLayoutResult && !((TextLayoutResult)newLayoutResult).IsWordHasBeenSplit
                                ())
                        {
                            wordWasSplitAndItWillFitOntoNextLine = true;
                        }
                    }
                    if (wordWasSplitAndItWillFitOntoNextLine)
                    {
                        split[1].childRenderers.Add(childRenderer);
                        split[1].childRenderers.AddAll(childRenderers.SubList(childPos + 1, childRenderers
                                                                              .Count));
                    }
                    else
                    {
                        if (childResult.GetStatus() == LayoutResult.PARTIAL)
                        {
                            split[0].AddChild(childResult.GetSplitRenderer());
                            anythingPlaced = true;
                        }
                        if (childResult.GetStatus() == LayoutResult.PARTIAL && childResult.GetOverflowRenderer
                                () is ImageRenderer)
                        {
                            ((ImageRenderer)childResult.GetOverflowRenderer()).AutoScale(layoutContext.GetArea
                                                                                             ());
                        }
                        if (null != childResult.GetOverflowRenderer())
                        {
                            split[1].childRenderers.Add(childResult.GetOverflowRenderer());
                        }
                        split[1].childRenderers.AddAll(childRenderers.SubList(childPos + 1, childRenderers
                                                                              .Count));
                        // no sense to process empty renderer
                        if (split[1].childRenderers.Count == 0)
                        {
                            split[1] = null;
                        }
                    }
                    result = new LineLayoutResult(anythingPlaced ? LayoutResult.PARTIAL : LayoutResult.NOTHING, occupiedArea, split[0], split[1],
                                                  childResult.GetStatus() == LayoutResult.NOTHING ? childResult.GetCauseOfNothing() : this);

                    if (childResult.GetStatus() == LayoutResult.PARTIAL && childResult is TextLayoutResult && ((TextLayoutResult)childResult).IsSplitForcedByNewline())
                    {
                        result.SetSplitForcedByNewline(true);
                    }
                    break;
                }
                else
                {
                    anythingPlaced = true;
                    childPos++;
                }
            }
            if (result == null)
            {
                if (anythingPlaced)
                {
                    result = new LineLayoutResult(LayoutResult.FULL, occupiedArea, null, null);
                }
                else
                {
                    result = new LineLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this);
                }
            }
            // Consider for now that all the children have the same font, and that after reordering text pieces
            // can be reordered, but cannot be split.
            if (baseDirection != null && baseDirection != BaseDirection.NO_BIDI)
            {
                IList <IRenderer> children = null;
                if (result.GetStatus() == LayoutResult.PARTIAL)
                {
                    children = result.GetSplitRenderer().GetChildRenderers();
                }
                else
                {
                    if (result.GetStatus() == LayoutResult.FULL)
                    {
                        children = GetChildRenderers();
                    }
                }
                if (children != null)
                {
                    IList <LineRenderer.RendererGlyph> lineGlyphs = new List <LineRenderer.RendererGlyph
                                                                              >();
                    foreach (IRenderer child in children)
                    {
                        if (child is TextRenderer)
                        {
                            GlyphLine childLine = ((TextRenderer)child).line;
                            for (int i = childLine.start; i < childLine.end; i++)
                            {
                                lineGlyphs.Add(new LineRenderer.RendererGlyph(childLine.Get(i), (TextRenderer)child
                                                                              ));
                            }
                        }
                    }
                    byte[] lineLevels = new byte[lineGlyphs.Count];
                    if (levels != null)
                    {
                        System.Array.Copy(levels, 0, lineLevels, 0, lineGlyphs.Count);
                    }
                    int[] reorder = TypographyUtils.ReorderLine(lineGlyphs, lineLevels, levels);
                    if (reorder != null)
                    {
                        children.Clear();
                        int           pos            = 0;
                        IList <int[]> reversedRanges = new List <int[]>();
                        int           initialPos     = 0;
                        bool          reversed       = false;
                        int           offset         = 0;
                        while (pos < lineGlyphs.Count)
                        {
                            IRenderer    renderer_1  = lineGlyphs[pos].renderer;
                            TextRenderer newRenderer = new TextRenderer((TextRenderer)renderer_1);
                            newRenderer.DeleteOwnProperty(Property.REVERSED);
                            children.Add(newRenderer);
                            ((TextRenderer)children[children.Count - 1]).line = new GlyphLine(((TextRenderer)
                                                                                               children[children.Count - 1]).line);
                            GlyphLine     gl = ((TextRenderer)children[children.Count - 1]).line;
                            IList <Glyph> replacementGlyphs = new List <Glyph>();
                            while (pos < lineGlyphs.Count && lineGlyphs[pos].renderer == renderer_1)
                            {
                                if (pos < lineGlyphs.Count - 1)
                                {
                                    if (reorder[pos] == reorder[pos + 1] + 1)
                                    {
                                        reversed = true;
                                    }
                                    else
                                    {
                                        if (reversed)
                                        {
                                            IList <int[]> reversedRange = new List <int[]>();
                                            reversedRange.Add(new int[] { initialPos - offset, pos - offset });
                                            newRenderer.SetProperty(Property.REVERSED, reversedRange);
                                            reversedRanges.Add(new int[] { initialPos - offset, pos - offset });
                                            reversed = false;
                                        }
                                        initialPos = pos + 1;
                                    }
                                }
                                replacementGlyphs.Add(lineGlyphs[pos].glyph);
                                pos++;
                            }
                            if (reversed)
                            {
                                IList <int[]> reversedRange = new List <int[]>();
                                reversedRange.Add(new int[] { initialPos - offset, pos - 1 - offset });
                                newRenderer.SetProperty(Property.REVERSED, reversedRange
                                                        );
                                reversedRanges.Add(new int[] { initialPos - offset, pos - 1 - offset });
                                reversed   = false;
                                initialPos = pos;
                            }
                            offset = initialPos;
                            gl.SetGlyphs(replacementGlyphs);
                        }
                        if (reversed)
                        {
                            if (children.Count == 1)
                            {
                                offset = 0;
                            }
                            IList <int[]> reversedRange = new List <int[]>();
                            reversedRange.Add(new int[] { initialPos - offset, pos - offset - 1 });
                            lineGlyphs[pos - 1].renderer.SetProperty(Property.REVERSED
                                                                     , reversedRange);
                            reversedRanges.Add(new int[] { initialPos - offset, pos - 1 - offset });
                        }
                        if (!reversedRanges.IsEmpty())
                        {
                            if (children.Count == 1)
                            {
                                lineGlyphs[0].renderer.SetProperty(Property.REVERSED, reversedRanges);
                            }
                        }
                        float currentXPos = layoutContext.GetArea().GetBBox().GetLeft();
                        foreach (IRenderer child_1 in children)
                        {
                            float currentWidth = ((TextRenderer)child_1).CalculateLineWidth();
                            ((TextRenderer)child_1).occupiedArea.GetBBox().SetX(currentXPos).SetWidth(currentWidth
                                                                                                      );
                            currentXPos += currentWidth;
                        }
                    }
                    if (result.GetStatus() == LayoutResult.PARTIAL)
                    {
                        LineRenderer overflow = (LineRenderer)result.GetOverflowRenderer();
                        if (levels != null)
                        {
                            overflow.levels = new byte[levels.Length - lineLevels.Length];
                            System.Array.Copy(levels, lineLevels.Length, overflow.levels, 0, overflow.levels.
                                              Length);
                            if (overflow.levels.Length == 0)
                            {
                                overflow.levels = null;
                            }
                        }
                    }
                    else if (result.GetStatus() == LayoutResult.NOTHING)
                    {
                        if (levels != null)
                        {
                            ((LineRenderer)result.GetOverflowRenderer()).levels = levels;
                        }
                    }
                }
            }
            if (anythingPlaced)
            {
                LineRenderer processed = result.GetStatus() == LayoutResult.FULL ? this : (LineRenderer
                                                                                           )result.GetSplitRenderer();
                processed.AdjustChildrenYLine().TrimLast();
            }
            return(result);
        }