public void DrawGlyphRun(
                Vector2 position,
                CanvasFontFace fontFace,
                float fontSize,
                CanvasGlyph[] glyphs,
                bool isSideways,
                uint bidiLevel,
                object brush,
                CanvasTextMeasuringMode measuringMode,
                string locale,
                string textString,
                int[] clusterMapIndices,
                uint startingTextPosition,
                CanvasGlyphOrientation glyphOrientation)
            {
                if (glyphs == null || glyphs.Length == 0)
                {
                    return;
                }

                float scaledFontAscent               = fontFace.Ascent * fontSize;
                float subscriptBaselineDropAmount    = scaledFontAscent * subscriptBaselineScale;
                float superscriptBaselineRaiseAmount = scaledFontAscent * superscriptBaselineScale;

                // Draw glyph-by-glyph.
                for (int i = 0; i < glyphs.Length; ++i)
                {
                    CanvasGlyph[] singleGlyph = new CanvasGlyph[1];
                    singleGlyph[0] = glyphs[i];

                    Vector2 positionForThisGlyph = position;

                    CustomBrushData brushData = (CustomBrushData)brush;
                    if (brushData != null)
                    {
                        if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Lower)
                        {
                            positionForThisGlyph.Y += subscriptBaselineDropAmount;
                        }
                        else if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Raise)
                        {
                            positionForThisGlyph.Y -= superscriptBaselineRaiseAmount;
                        }
                    }

                    DrawingSession.DrawGlyphRun(
                        positionForThisGlyph,
                        fontFace,
                        fontSize,
                        singleGlyph,
                        isSideways,
                        bidiLevel,
                        TextBrush);

                    position.X += glyphs[i].Advance;
                }
            }
Exemple #2
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;
            }
        }
 public void LoadPage(Page page)
 {
     MainGlyph = new CanvasGlyph(WordConfig)
     {
         Redactor = _redactor, ParentVectorRedactor = this
     };
     foreach (var line in page.Lines)
     {
         var lineGlyph = MainGlyph.InsertNewLineGlyph(line);
         foreach (var word in line.Words)
         {
             lineGlyph.InsertNewWordGlyph(word);
         }
     }
 }
        public VectorRedactorRepository(Graphics canvas, Redactor redactor, VectorRedactorConfig config)
        {
            Canvas               = canvas;
            _redactor            = redactor;
            canvas.SmoothingMode = SmoothingMode.HighQuality;

            Layout = new Layout(canvas);

            WordConfig = new GlyphConfig(config.WordBrush, config.WordPen);
            LineConfig = new GlyphConfig(config.LineBrush, config.LinePen);

            RedactorState = RedactorStates.Default;

            MainGlyph = new CanvasGlyph(WordConfig)
            {
                Redactor = _redactor, ParentVectorRedactor = this
            };
            MainGlyph.MainGlyph = MainGlyph;

            ActiveGlyph = MainGlyph;
        }
Exemple #5
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);
        }
Exemple #6
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);
        }
            public void DrawGlyphRun(
                Vector2 position,
                CanvasFontFace fontFace,
                float fontSize,
                CanvasGlyph[] glyphs,
                bool isSideways,
                uint bidiLevel,
                object brush,
                CanvasTextMeasuringMode measuringMode,
                string locale,
                string textString,
                int[] clusterMapIndices,
                uint textPosition,
                CanvasGlyphOrientation glyphOrientation)
            {
                var script = GetScript(textPosition);

                if (CurrentMode == Mode.BuildTypographyList)
                {
                    CanvasTypographyFeatureName[] features = fontFace.GetSupportedTypographicFeatureNames(script);

                    foreach (var featureName in features)
                    {
                        TypographyFeatureInfo featureInfo = new TypographyFeatureInfo(featureName);

                        if (!TypographyOptions.Contains(featureInfo))
                        {
                            TypographyOptions.Add(featureInfo);
                        }
                    }
                }
                else
                {
                    if (glyphs == null || glyphs.Length == 0)
                    {
                        return;
                    }
                    //
                    // This demo handles only simple Latin text with no diacritical
                    // markers or ligatures, so we can make assumptions about the
                    // mapping of text positions to glyph indices. This works fine for
                    // the sake of this example.
                    //
                    // In general, apps should use the cluster map to map text
                    // positions to glyphs while knowing that glyph substitution can happen
                    // for reasons besides typography.
                    //
                    uint[] codePoints = new uint[glyphs.Length];
                    for (int i = 0; i < glyphs.Length; i++)
                    {
                        int glyphTextPosition = 0;
                        for (int j = 0; j < clusterMapIndices.Length; j++)
                        {
                            if (clusterMapIndices[j] == i)
                            {
                                glyphTextPosition = j;
                                break;
                            }
                        }
                        codePoints[i] = textString[glyphTextPosition];
                    }
                    int[] nominalGlyphIndices = fontFace.GetGlyphIndices(codePoints);

                    CanvasGlyph[] unsubstitutedGlyphs = new CanvasGlyph[glyphs.Length];
                    for (int i = 0; i < glyphs.Length; i++)
                    {
                        unsubstitutedGlyphs[i]       = glyphs[i];
                        unsubstitutedGlyphs[i].Index = nominalGlyphIndices[i];
                    }

                    bool[] eligible = fontFace.GetTypographicFeatureGlyphSupport(script, FeatureToHighlight, unsubstitutedGlyphs);

                    var highlightBrush = new CanvasSolidColorBrush(currentDrawingSession, Colors.Yellow);

                    for (int i = 0; i < glyphs.Length; ++i)
                    {
                        if (eligible[i])
                        {
                            CanvasGlyph[] singleGlyph = new CanvasGlyph[1];
                            singleGlyph[0] = glyphs[i];

                            currentDrawingSession.DrawGlyphRun(
                                position,
                                fontFace,
                                fontSize,
                                singleGlyph,
                                isSideways,
                                bidiLevel,
                                highlightBrush);
                        }

                        position.X += glyphs[i].Advance;
                    }
                }
            }
            public void DrawGlyphRun(
                Vector2 position,
                CanvasFontFace fontFace, 
                float fontSize, 
                CanvasGlyph[] glyphs, 
                bool isSideways,
                uint bidiLevel,
                object brush,
                CanvasTextMeasuringMode measuringMode, 
                string locale, 
                string textString, 
                int[] custerMapIndices, 
                uint textPosition, 
                CanvasGlyphOrientation glyphOrientation)
            {
                Metrics m = new Metrics();
                m.Ascent = fontFace.Ascent;
                m.LineGap = fontFace.LineGap;
                m.Descent = fontFace.Descent;
                m.CapHeight = fontFace.CapHeight;
                m.LowercaseLetterHeight = fontFace.LowercaseLetterHeight;
                m.Bounds = fontFace.GetGlyphRunBounds(
                    drawingSession,
                    position,
                    fontSize,
                    glyphs,
                    isSideways,
                    bidiLevel);

                GlyphRunMetrics.Add(m);
            }
            public void DrawGlyphRun(
                Vector2 position,
                CanvasFontFace fontFace,
                float fontSize,
                CanvasGlyph[] glyphs,
                bool isSideways,
                uint bidiLevel,
                object brush,
                CanvasTextMeasuringMode measuringMode,
                string locale,
                string textString,
                int[] custerMapIndices,
                uint textPosition,
                CanvasGlyphOrientation glyphOrientation)
            {
                if (glyphs == null)
                    return;

                var previousTransform = drawingSession.Transform;

                drawingSession.Transform = CanvasTextLayout.GetGlyphOrientationTransform(glyphOrientation, isSideways, position);

                drawingSession.DrawGlyphRun(
                    position,
                    fontFace,
                    fontSize,
                    glyphs,
                    isSideways,
                    bidiLevel,
                    textBrush);

                drawingSession.Transform = previousTransform;
            }
            public void DrawGlyphRun(
                Vector2 position,
                CanvasFontFace fontFace,
                float fontSize,
                CanvasGlyph[] glyphs,
                bool isSideways,
                uint bidiLevel,
                object brush,
                CanvasTextMeasuringMode measuringMode,
                string locale,
                string textString,
                int[] clusterMapIndices,
                uint startingTextPosition,
                CanvasGlyphOrientation glyphOrientation)
            {
                if (glyphs == null || glyphs.Length == 0)
                    return;

                float scaledFontAscent = fontFace.Ascent * fontSize;
                float subscriptBaselineDropAmount = scaledFontAscent * subscriptBaselineScale;
                float superscriptBaselineRaiseAmount = scaledFontAscent * superscriptBaselineScale;

                // Draw glyph-by-glyph.
                for (int i = 0; i < glyphs.Length; ++i)
                {
                    CanvasGlyph[] singleGlyph = new CanvasGlyph[1];
                    singleGlyph[0] = glyphs[i];

                    Vector2 positionForThisGlyph = position;

                    CustomBrushData brushData = (CustomBrushData)brush;
                    if (brushData != null)
                    {
                        if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Lower)
                        {
                            positionForThisGlyph.Y += subscriptBaselineDropAmount;
                        }
                        else if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Raise)
                        {
                            positionForThisGlyph.Y -= superscriptBaselineRaiseAmount;
                        }
                    }

                    DrawingSession.DrawGlyphRun(
                        positionForThisGlyph,
                        fontFace,
                        fontSize,
                        singleGlyph,
                        isSideways,
                        bidiLevel,
                        TextBrush);

                    position.X += glyphs[i].Advance;
                }
            }
Exemple #11
0
 public void DrawGlyphRun(
     Vector2 position,
     CanvasFontFace fontFace,
     float fontSize,
     CanvasGlyph[] glyphs,
     bool isSideways,
     uint bidiLevel,
     object brush,
     CanvasTextMeasuringMode measuringMode,
     string locale,
     string textString,
     int[] custerMapIndices,
     uint textPosition,
     CanvasGlyphOrientation glyphOrientation)
 {
     CanvasGeometry geometry = CanvasGeometry.CreateGlyphRun(
         resourceCreator,
         position,
         fontFace,
         fontSize,
         glyphs,
         isSideways,
         bidiLevel,
         measuringMode,
         glyphOrientation);
     geometries.Add(geometry);
 }
Exemple #12
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;
            }
        }
            public void DrawGlyphRun(
                Vector2 position,
                CanvasFontFace fontFace,
                float fontSize,
                CanvasGlyph[] glyphs,
                bool isSideways,
                uint bidiLevel,
                object brush,
                CanvasTextMeasuringMode measuringMode,
                string locale,
                string textString,
                int[] clusterMapIndices,
                uint textPosition,
                CanvasGlyphOrientation glyphOrientation)
            {
                var script = GetScript(textPosition);

                if (CurrentMode == Mode.BuildTypographyList)
                {
                    CanvasTypographyFeatureName[] features = fontFace.GetSupportedTypographicFeatureNames(script);

                    foreach (var featureName in features)
                    {
                        TypographyFeatureInfo featureInfo = new TypographyFeatureInfo(featureName);

                        if (!TypographyOptions.Contains(featureInfo))
                        {
                            TypographyOptions.Add(featureInfo);
                        }
                    }
                }
                else
                {
                    if (glyphs == null || glyphs.Length == 0)
                        return;
                    //
                    // This demo handles only simple Latin text with no diacritical
                    // markers or ligatures, so we can make assumptions about the 
                    // mapping of text positions to glyph indices. This works fine for
                    // the sake of this example.
                    //
                    // In general, apps should use the cluster map to map text 
                    // positions to glyphs while knowing that glyph substitution can happen 
                    // for reasons besides typography.
                    //
                    uint[] codePoints = new uint[glyphs.Length];
                    for (int i = 0; i < glyphs.Length; i++)
                    {
                        int glyphTextPosition = 0;
                        for (int j=0; j<clusterMapIndices.Length; j++)
                        {
                            if (clusterMapIndices[j] == i)
                            {
                                glyphTextPosition = j;
                                break;
                            }
                        }
                        codePoints[i] = textString[glyphTextPosition];
                    }
                    int[] nominalGlyphIndices = fontFace.GetGlyphIndices(codePoints);

                    CanvasGlyph[] unsubstitutedGlyphs = new CanvasGlyph[glyphs.Length];
                    for (int i = 0; i < glyphs.Length; i++)
                    {
                        unsubstitutedGlyphs[i] = glyphs[i];
                        unsubstitutedGlyphs[i].Index = nominalGlyphIndices[i];
                    }

                    bool[] eligible = fontFace.GetTypographicFeatureGlyphSupport(script, FeatureToHighlight, unsubstitutedGlyphs);

                    var highlightBrush = new CanvasSolidColorBrush(currentDrawingSession, Colors.Yellow);

                    for (int i = 0; i < glyphs.Length; ++i)
                    {
                        if (eligible[i])
                        {
                            CanvasGlyph[] singleGlyph = new CanvasGlyph[1];
                            singleGlyph[0] = glyphs[i];

                            currentDrawingSession.DrawGlyphRun(
                                position,
                                fontFace,
                                fontSize,
                                singleGlyph,
                                isSideways,
                                bidiLevel,
                                highlightBrush);
                        }

                        position.X += glyphs[i].Advance;
                    }
                }
            }