示例#1
0
        void SplitJustifiedGlyphsIntoRuns(CanvasTextAnalyzer textAnalyzer, LayoutBox layoutBox, CanvasGlyph[] justifiedGlyphs, bool needsAdditionalJustificationCharacters)
        {
            int glyphIndex = 0;

            float xPosition = (float)layoutBox.Rectangle.Right;

            for (int i = 0; i < layoutBox.GlyphRuns.Count; i++)
            {
                if (layoutBox.GlyphRuns[i].Glyphs.Count == 0)
                {
                    continue;
                }

                int originalGlyphCountForThisRun = layoutBox.GlyphRuns[i].Glyphs.Count;

                if (needsAdditionalJustificationCharacters)
                {
                    // Replace the glyph data, since justification can modify glyphs
                    CanvasGlyph[] justifiedGlyphsForThisGlyphRun = new CanvasGlyph[layoutBox.GlyphRuns[i].Glyphs.Count];
                    for (int j = 0; j < layoutBox.GlyphRuns[i].Glyphs.Count; j++)
                    {
                        justifiedGlyphsForThisGlyphRun[j] = justifiedGlyphs[glyphIndex + j];
                    }

                    CanvasCharacterRange range = layoutBox.GlyphRuns[i].GetRange();

                    var glyphRunClusterMap = layoutBox.GlyphRuns[i].GetClusterMap(range);
                    var glyphRunShaping    = layoutBox.GlyphRuns[i].GetShaping();

                    CanvasGlyph[] newSetOfGlyphs = textAnalyzer.AddGlyphsAfterJustification(
                        layoutBox.GlyphRuns[i].FormattingSpan.FontFace,
                        layoutBox.GlyphRuns[i].FormattingSpan.FontSize,
                        layoutBox.GlyphRuns[i].FormattingSpan.Script,
                        glyphRunClusterMap,
                        layoutBox.GlyphRuns[i].Glyphs.ToArray(),
                        justifiedGlyphsForThisGlyphRun,
                        glyphRunShaping);

                    layoutBox.GlyphRuns[i].Glyphs = new List <CanvasGlyph>(newSetOfGlyphs);
                }
                else
                {
                    for (int j = 0; j < layoutBox.GlyphRuns[i].Glyphs.Count; j++)
                    {
                        layoutBox.GlyphRuns[i].Glyphs[j] = justifiedGlyphs[glyphIndex + j];
                    }
                }

                glyphIndex += originalGlyphCountForThisRun;
            }
        }
示例#2
0
            public int[] GetClusterMap(CanvasCharacterRange range)
            {
                //
                // Create a cluster map for this character range. Because the cluster map
                // should reflect only the text positions in the range, we need to re-normalize
                // it (so that it starts at 0).
                //
                int[] clusterMap = new int[range.CharacterCount];

                int formattingSpanStartIndex = FormattingSpan.Range.CharacterIndex;

                int firstClusterMapValue = FormattingSpan.ClusterMap[range.CharacterIndex - formattingSpanStartIndex];

                for (int i = 0; i < range.CharacterCount; ++i)
                {
                    int indexWithinFormattingSpan = range.CharacterIndex - formattingSpanStartIndex + i; // Cluster maps are per formatting span.

                    clusterMap[i] = FormattingSpan.ClusterMap[indexWithinFormattingSpan] - firstClusterMapValue;
                }
                return(clusterMap);
            }
示例#3
0
        CanvasJustificationOpportunity[] GetJustificationOpportunities(CanvasTextAnalyzer textAnalyzer, LayoutBox layoutBox, out CanvasGlyph[] allGlyphs)
        {
            int layoutBoxGlyphCount = layoutBox.GetGlyphCount();

            CanvasJustificationOpportunity[] justificationOpportunities = new CanvasJustificationOpportunity[layoutBoxGlyphCount];
            allGlyphs = new CanvasGlyph[layoutBoxGlyphCount];

            int glyphIndex = 0;

            for (int i = 0; i < layoutBox.GlyphRuns.Count; i++)
            {
                if (layoutBox.GlyphRuns[i].Glyphs.Count == 0)
                {
                    continue;
                }

                CanvasCharacterRange range = layoutBox.GlyphRuns[i].GetRange();

                var glyphRunClusterMap = layoutBox.GlyphRuns[i].GetClusterMap(range);
                var glyphRunShaping    = layoutBox.GlyphRuns[i].GetShaping();

                var justificationOpportunitiesThisGlyphRun = textAnalyzer.GetJustificationOpportunities(
                    range,
                    layoutBox.GlyphRuns[i].FormattingSpan.FontFace,
                    layoutBox.GlyphRuns[i].FormattingSpan.FontSize,
                    layoutBox.GlyphRuns[i].FormattingSpan.Script,
                    glyphRunClusterMap,
                    glyphRunShaping);

                for (int j = 0; j < layoutBox.GlyphRuns[i].Glyphs.Count; ++j)
                {
                    justificationOpportunities[glyphIndex + j] = justificationOpportunitiesThisGlyphRun[j];
                    allGlyphs[glyphIndex + j] = layoutBox.GlyphRuns[i].Glyphs[j];
                }
                glyphIndex += layoutBox.GlyphRuns[i].Glyphs.Count;
            }

            return(justificationOpportunities);
        }
示例#4
0
        CanvasJustificationOpportunity[] GetJustificationOpportunities(CanvasTextAnalyzer textAnalyzer, int startingGlyphRunIndex, int endingGlyphRunIndex, int glyphCount, out CanvasGlyph[] allGlyphs)
        {
            CanvasJustificationOpportunity[] justificationOpportunities = new CanvasJustificationOpportunity[glyphCount];
            allGlyphs = new CanvasGlyph[glyphCount];

            int glyphIndex = 0;

            for (int i = startingGlyphRunIndex; i < endingGlyphRunIndex; ++i)
            {
                if (glyphRuns[i].Glyphs.Count == 0)
                {
                    continue;
                }

                CanvasCharacterRange range = glyphRuns[i].GetRange();

                var glyphRunClusterMap = glyphRuns[i].GetClusterMap(range);
                var glyphRunShaping    = glyphRuns[i].GetShaping();

                var justificationOpportunitiesThisGlyphRun = textAnalyzer.GetJustificationOpportunities(
                    range,
                    glyphRuns[i].FormattingSpan.FontFace,
                    glyphRuns[i].FormattingSpan.FontSize,
                    glyphRuns[i].FormattingSpan.Script,
                    glyphRunClusterMap,
                    glyphRunShaping);

                for (int j = 0; j < glyphRuns[i].Glyphs.Count; ++j)
                {
                    justificationOpportunities[glyphIndex + j] = justificationOpportunitiesThisGlyphRun[j];
                    allGlyphs[glyphIndex + j] = glyphRuns[i].Glyphs[j];
                }
                glyphIndex += glyphRuns[i].Glyphs.Count;
            }

            return(justificationOpportunities);
        }
示例#5
0
 int GetBoundary(CanvasCharacterRange range)
 {
     return(range.CharacterIndex + range.CharacterCount);
 }
示例#6
0
        void SplitJustifiedGlyphsIntoRuns(CanvasTextAnalyzer textAnalyzer, int startingGlyphRunIndex, int endingGlyphRunIndex, CanvasGlyph[] justifiedGlyphs, bool needsAdditionalJustificationCharacters)
        {
            int glyphIndex = 0;

            float xPosition = glyphRuns[startingGlyphRunIndex].Position.X;

            for (int i = startingGlyphRunIndex; i < endingGlyphRunIndex; ++i)
            {
                if (glyphRuns[i].Glyphs.Count == 0)
                {
                    continue;
                }

                // Adjust glyph run positioning based on justification
                glyphRuns[i].Position = new Vector2()
                {
                    X = xPosition, Y = glyphRuns[i].Position.Y
                };

                // Update running total glyph run advance
                for (int j = 0; j < glyphRuns[i].Glyphs.Count; j++)
                {
                    xPosition += glyphRuns[i].Glyphs[j].Advance;
                }

                if (needsAdditionalJustificationCharacters)
                {
                    // Replace the glyph data, since justification can modify glyphs
                    CanvasGlyph[] justifiedGlyphsForThisGlyphRun = new CanvasGlyph[glyphRuns[i].Glyphs.Count];
                    for (int j = 0; j < glyphRuns[i].Glyphs.Count; j++)
                    {
                        justifiedGlyphsForThisGlyphRun[j] = justifiedGlyphs[glyphIndex + j];
                    }

                    CanvasCharacterRange range = glyphRuns[i].GetRange();

                    var glyphRunClusterMap = glyphRuns[i].GetClusterMap(range);
                    var glyphRunShaping    = glyphRuns[i].GetShaping();

                    CanvasGlyph[] newSetOfGlyphs = textAnalyzer.AddGlyphsAfterJustification(
                        glyphRuns[i].FormattingSpan.FontFace,
                        glyphRuns[i].FormattingSpan.FontSize,
                        glyphRuns[i].FormattingSpan.Script,
                        glyphRunClusterMap,
                        glyphRuns[i].Glyphs.ToArray(),
                        justifiedGlyphsForThisGlyphRun,
                        glyphRunShaping);

                    glyphRuns[i].Glyphs = new List <CanvasGlyph>(newSetOfGlyphs);
                }
                else
                {
                    for (int j = 0; j < glyphRuns[i].Glyphs.Count; j++)
                    {
                        glyphRuns[i].Glyphs[j] = justifiedGlyphs[glyphIndex + j];
                    }
                }

                glyphIndex += glyphRuns[i].Glyphs.Count;
            }
        }
示例#7
0
        List <FormattingSpan> EvaluateFormattingSpans(
            CanvasTextAnalyzer textAnalyzer,
            IReadOnlyList <KeyValuePair <CanvasCharacterRange, CanvasScaledFont> > fontRuns,
            IReadOnlyList <KeyValuePair <CanvasCharacterRange, CanvasAnalyzedScript> > scriptRuns,
            out float maxLineSpacing)
        {
            maxLineSpacing = 0;

            List <FormattingSpan> formattingSpans = new List <FormattingSpan>();

            //
            // Divide up our text space into spans of uniform font face and uniform script.
            //
            foreach (var scriptRun in scriptRuns)
            {
                var scriptProperties = textAnalyzer.GetScriptProperties(scriptRun.Value);

                bool isRightToLeft = IsRightToLeft(scriptProperties.IsoScriptNumber);

                foreach (var fontRun in fontRuns)
                {
                    int fontMatchEnd = fontRun.Key.CharacterIndex + fontRun.Key.CharacterCount;
                    int scriptEnd    = scriptRun.Key.CharacterIndex + scriptRun.Key.CharacterCount;

                    if (fontRun.Key.CharacterIndex > scriptEnd)
                    {
                        continue;
                    }

                    if (fontMatchEnd < scriptRun.Key.CharacterIndex)
                    {
                        continue;
                    }

                    int rangeStart = System.Math.Max(fontRun.Key.CharacterIndex, scriptRun.Key.CharacterIndex);
                    int rangeEnd   = System.Math.Min(fontMatchEnd, scriptEnd);
                    int length     = rangeEnd - rangeStart;

                    float fontSize = desiredFontSize * fontRun.Value.ScaleFactor;

                    FormattingSpan formattingSpan = new FormattingSpan();
                    formattingSpan.IsRightToLeft = isRightToLeft;

                    int[]  clusterMap;
                    bool[] isShapedAlone;
                    CanvasGlyphShaping[] glyphShaping;

                    CanvasCharacterRange range = new CanvasCharacterRange {
                        CharacterIndex = rangeStart, CharacterCount = length
                    };

                    // Evaluate which glyphs comprise the text.
                    formattingSpan.Glyphs = textAnalyzer.GetGlyphs(
                        range,
                        fontRun.Value.FontFace,
                        fontSize,
                        false, // isSideways
                        formattingSpan.IsRightToLeft,
                        scriptRun.Value,
                        "",
                        null,
                        null,
                        out clusterMap,
                        out isShapedAlone,
                        out glyphShaping);

                    formattingSpan.FontFace     = fontRun.Value.FontFace;
                    formattingSpan.FontSize     = fontSize;
                    formattingSpan.Script       = scriptRun.Value;
                    formattingSpan.ClusterMap   = clusterMap;
                    formattingSpan.GlyphShaping = glyphShaping;
                    formattingSpan.Range        = range;
                    formattingSpan.NeedsAdditionalJustificationCharacters = scriptProperties.JustificationCharacter != null;

                    formattingSpans.Add(formattingSpan);

                    //
                    // For text which contains non-uniform font faces, CanvasTextLayout takes the maximum of
                    // all of line spacings and applies it as the overall line spacing. We do the same thing, here.
                    //
                    maxLineSpacing = System.Math.Max(maxLineSpacing, GetLineSpacing(formattingSpan.FontFace, fontSize));
                }
            }

            return(formattingSpans);
        }