private void EnsureTypographyList(TypographyHandler typographyHandler)
        {
            if (!needRefreshTypographyList)
            {
                return;
            }

            textLayout.DrawToTextRenderer(typographyHandler, 0, 0);

            TypographyOptions = typographyHandler.TypographyOptions;

            TypographyFeatureInfo previousOption = CurrentTypographyOption;

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("TypographyOptions"));
            }

            if (TypographyOptions.Contains(previousOption))
            {
                CurrentTypographyOption = previousOption;
            }
            else
            {
                CurrentTypographyOption = new TypographyFeatureInfo(CanvasTypographyFeatureName.None);
            }

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("CurrentTypographyOption"));
            }

            needRefreshTypographyList = false;
        }
        public TypographyExample()
        {
            DataContext = this;

            this.InitializeComponent();

            TypographyOptions = new List <TypographyFeatureInfo>();

            if (ThumbnailGenerator.IsDrawingThumbnail)
            {
                fontPicker.SelectFont("Gabriola");
                CurrentTypographyOption = new TypographyFeatureInfo(CanvasTypographyFeatureName.StylisticSet2);
            }
            else
            {
                CurrentTypographyOption = new TypographyFeatureInfo(CanvasTypographyFeatureName.Kerning);
            }
            HighlightTypographyAffectedGlyphs = true;
        }
            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[] 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;
                    }
                }
            }
        private void EnsureTypographyList(TypographyHandler typographyHandler)
        {
            if (!needRefreshTypographyList)
                return;

            textLayout.DrawToTextRenderer(typographyHandler, 0, 0);

            TypographyOptions = typographyHandler.TypographyOptions;

            TypographyFeatureInfo previousOption = CurrentTypographyOption;

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("TypographyOptions"));

            if (TypographyOptions.Contains(previousOption))
                CurrentTypographyOption = previousOption;
            else
                CurrentTypographyOption = new TypographyFeatureInfo(CanvasTypographyFeatureName.None);

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("CurrentTypographyOption"));

            needRefreshTypographyList = false;
        }
        public TypographyExample()
        {
            DataContext = this;

            this.InitializeComponent();    

            TypographyOptions = new List<TypographyFeatureInfo>();

            if (ThumbnailGenerator.IsDrawingThumbnail)
            {
                fontPicker.SelectFont("Gabriola");
                CurrentTypographyOption = new TypographyFeatureInfo(CanvasTypographyFeatureName.StylisticSet2);
            }
            else
            {
                CurrentTypographyOption = new TypographyFeatureInfo(CanvasTypographyFeatureName.Kerning);
            }
            HighlightTypographyAffectedGlyphs = true;
        }