public GlyphMetrics[] GetGlyphMetrics(MyScript.IInk.Text.Text text, TextSpan[] spans)
        {
            var glyphMetrics = new List <GlyphMetrics>();

            GetGlyphMetrics(text, spans, glyphMetrics);
            return(glyphMetrics.ToArray());
        }
        public Rectangle[] GetCharacterBoundingBoxes(MyScript.IInk.Text.Text text, TextSpan[] spans)
        {
            var glyphMetrics = GetGlyphMetrics(text, spans);

            Rectangle[] rectangles = new Rectangle[glyphMetrics.Length];
            for (int i = 0; i < glyphMetrics.Length; ++i)
            {
                rectangles[i] = glyphMetrics[i].BoundingBox;
            }

            return(rectangles);
        }
Ejemplo n.º 3
0
        public Rectangle[] GetCharacterBoundingBoxes(MyScript.IInk.Text.Text text, TextSpan[] spans)
        {
            List <Rectangle> rectangles = new List <Rectangle>();

            if (Thread.CurrentThread == Application.Current.Dispatcher.Thread)
            {
                GetCharacterBoundingBoxes_(text, spans, rectangles, dpiX, dpiY);
            }
            else
            {
                Application.Current.Dispatcher.BeginInvoke(new Action(() => { GetCharacterBoundingBoxes_(text, spans, rectangles, dpiX, dpiY); })).Wait();
            }
            return(rectangles.ToArray());
        }
        public Rectangle[] GetCharacterBoundingBoxes(MyScript.IInk.Text.Text text, TextSpan[] spans)
        {
            var glyphMetrics = new List <GlyphMetrics>();
            var rectangles   = new List <Rectangle>();

            GetGlyphMetrics(text, spans, glyphMetrics);

            foreach (var metrics in glyphMetrics)
            {
                rectangles.Add(metrics.BoundingBox);
            }

            return(rectangles.ToArray());
        }
Ejemplo n.º 5
0
        private static void GetCharacterBoundingBoxes_(MyScript.IInk.Text.Text text, TextSpan[] spans, List <Rectangle> rectangles, float dpiX, float dpiY)
        {
            var firstStyle = spans.First().Style;
            var textBlock  = new TextBlock();

            textBlock.FontFamily          = new FontFamily(firstStyle.FontFamily);
            textBlock.Padding             = new Thickness(0.0);
            textBlock.Margin              = new Thickness(0.0);
            textBlock.TextWrapping        = TextWrapping.NoWrap;
            textBlock.HorizontalAlignment = HorizontalAlignment.Left;
            textBlock.VerticalAlignment   = VerticalAlignment.Top;

            foreach (var textSpan in spans)
            {
                var fontFamily  = new FontFamily(textSpan.Style.FontFamily);
                var fontSize    = mm2px(textSpan.Style.FontSize, dpiY);
                var fontWeight  = FontWeight.FromOpenTypeWeight(textSpan.Style.FontWeight);
                var fontStretch = FontStretches.Normal;
                var fontStyle   = FontStyles.Normal;

                if (textSpan.Style.FontStyle.Equals("italic"))
                {
                    fontStyle = FontStyles.Italic;
                }
                else if (textSpan.Style.FontStyle.Equals("oblique"))
                {
                    fontStyle = FontStyles.Oblique;
                }

                if (textSpan.Style.FontWeight >= 700)
                {
                    fontWeight = FontWeights.Bold;
                }
                else if (textSpan.Style.FontWeight >= 400)
                {
                    fontWeight = FontWeights.Normal;
                }
                else
                {
                    fontWeight = FontWeights.Light;
                }

                // Process glyph one by one to generate one box per glyph
                for (int j = textSpan.BeginPosition; j < textSpan.EndPosition; ++j)
                {
                    var textRun = new Run(text.GetGlyphLabelAt(j));

                    textRun.FontFamily  = fontFamily;
                    textRun.FontSize    = fontSize;
                    textRun.FontWeight  = fontWeight;
                    textRun.FontStyle   = fontStyle;
                    textRun.FontStretch = fontStretch;

                    textBlock.Inlines.Add(textRun);
                }
            }

            textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
            textBlock.Arrange(new Rect(textBlock.DesiredSize));

            var baseline = (float)textBlock.BaselineOffset;
            var d        = VisualTreeHelper.GetDrawing(textBlock);

            WalkDrawingForText(d, rectangles, baseline, dpiX, dpiY);
        }
        private void GetGlyphMetrics(MyScript.IInk.Text.Text text, TextSpan[] spans, List <GlyphMetrics> glyphMetrics)
        {
            // Process glyph one by one to generate one box per glyph
            for (int s = 0; s < spans.Length; ++s)
            {
                var textSpan = spans[s];
                var fontKey  = FontKeyFromStyle(textSpan.Style);

                for (int j = textSpan.BeginPosition; j < textSpan.EndPosition; ++j)
                {
                    var glyphLabel    = text.GetGlyphLabelAt(j);
                    var glyphMetrics_ = GetGlyphMetrics(fontKey, glyphLabel);

                    glyphMetrics.Add(glyphMetrics_);
                }
            }

            if (glyphMetrics.Count == 0)
            {
                return;
            }

            // Draw text to get data for glyphs
            FormattedText formattedText;
            {
                var firstStyle        = spans[0].Style;
                var firstFontKey      = FontKeyFromStyle(firstStyle);
                var firstFontTypeFace = new Typeface(firstFontKey.FontFamily, firstFontKey.FontStyle, firstFontKey.FontWeight, firstFontKey.FontStretch);

                formattedText = new FormattedText
                                (
                    text.Label, System.Globalization.CultureInfo.CurrentCulture,
                    FlowDirection.LeftToRight, firstFontTypeFace, firstFontKey.FontSize,
                    Brushes.Black
                                );

                formattedText.TextAlignment = TextAlignment.Left;

                for (int s = 0; s < spans.Length; ++s)
                {
                    var textSpan     = spans[s];
                    var charIndex    = textSpan.BeginPosition;
                    var charCount    = textSpan.EndPosition - textSpan.BeginPosition;
                    var fontKey      = FontKeyFromStyle(textSpan.Style);
                    var fontTypeFace = new Typeface(fontKey.FontFamily, fontKey.FontStyle, fontKey.FontWeight, fontKey.FontStretch);

                    formattedText.SetFontFamily(fontKey.FontFamily, charIndex, charCount);
                    formattedText.SetFontSize(fontKey.FontSize, charIndex, charCount);
                    formattedText.SetFontWeight(fontKey.FontWeight, charIndex, charCount);
                    formattedText.SetFontStretch(fontKey.FontStretch, charIndex, charCount);
                    formattedText.SetFontStyle(fontKey.FontStyle, charIndex, charCount);
                    formattedText.SetFontTypeface(fontTypeFace, charIndex, charCount);
                }
            }

            var drawing = new DrawingGroup();
            {
                var ctx = drawing.Open();
                ctx.DrawText(formattedText, new System.Windows.Point(0.0, 0.0));
                ctx.Close();
            }

            // Apply baseline and offsets of glyphs to bounding boxes
            float baseline = (float)formattedText.Baseline;

            WalkDrawingForText(drawing, glyphMetrics, baseline);
        }
        public GlyphMetrics[] GetGlyphMetrics(MyScript.IInk.Text.Text text, TextSpan[] spans)
        {
            CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();

            GlyphMetrics[] glyphMetrics = new GlyphMetrics[text.GlyphCount];

            var firstStyle   = spans[0].Style;
            var firstFontKey = FontKeyFromStyle(firstStyle);

            if (text.GlyphCount == 1)
            {
                glyphMetrics[0] = GetGlyphMetrics(firstFontKey, text.Label, canvasDevice);
            }
            else
            {
                var textFormat = new CanvasTextFormat()
                {
                    FontSize   = mm2px(firstStyle.FontSize, dpiY),
                    FontFamily = firstStyle.FontFamily,
                    FontStyle  = firstFontKey.FontStyle,
                    FontWeight = firstFontKey.FontWeight
                };

                using (var canvasTextLayout = new CanvasTextLayout(canvasDevice, text.Label, textFormat, 10000, 10000))
                {
                    for (int i = 0; i < spans.Length; ++i)
                    {
                        var charIndex = spans[i].BeginPosition;
                        var charCount = spans[i].EndPosition - spans[i].BeginPosition;

                        var style   = spans[i].Style;
                        var fontKey = FontKeyFromStyle(style);

                        canvasTextLayout.SetFontFamily(charIndex, charCount, fontKey.FontFamily);
                        canvasTextLayout.SetFontSize(charIndex, charCount, fontKey.FontSize);
                        canvasTextLayout.SetFontWeight(charIndex, charCount, fontKey.FontWeight);
                        canvasTextLayout.SetFontStyle(charIndex, charCount, fontKey.FontStyle);
                    }

                    // Use of TextElementEnumerator to get character indices as in the CanvasTextLayout
                    var tee = StringInfo.GetTextElementEnumerator(text.Label);

                    // Use of ClusterMetrics to identify ligatures in the CanvasTextLayout
                    int cluster          = 0;
                    int clusterStartChar = 0;
                    var clusterCharCount = canvasTextLayout.ClusterMetrics[cluster].CharacterCount;

                    for (int i = 0, g = 0; i < text.GlyphCount; ++i)
                    {
                        var fontKey = new FontKey(canvasTextLayout.GetFontFamily(i)
                                                  , canvasTextLayout.GetFontSize(i)
                                                  , canvasTextLayout.GetFontWeight(i)
                                                  , canvasTextLayout.GetFontStyle(i));
                        var glyphLabel    = text.GetGlyphLabelAt(i);
                        var glyphMetrics_ = GetGlyphMetrics(fontKey, glyphLabel, canvasDevice);

                        // Find cluster associated to element
                        if (tee.MoveNext())
                        {
                            g = tee.ElementIndex;
                        }

                        while ((g < clusterStartChar) || (g >= (clusterStartChar + clusterCharCount)))
                        {
                            ++cluster;
                            clusterStartChar += clusterCharCount;
                            clusterCharCount  = canvasTextLayout.ClusterMetrics[cluster].CharacterCount;
                        }

                        if (g > clusterStartChar)
                        {
                            // Ligature with the previous glyph
                            // The position is not accurate because of glyphs substitution at rendering
                            // but it makes the illusion.
                            var prevGlyphMetrics = glyphMetrics[i - 1];
                            glyphMetrics_.BoundingBox.X = prevGlyphMetrics.BoundingBox.X
                                                          + prevGlyphMetrics.BoundingBox.Width
                                                          + prevGlyphMetrics.RightSideBearing
                                                          + glyphMetrics_.LeftSideBearing;
                        }
                        else
                        {
                            var charPos = canvasTextLayout.GetCaretPosition(g, false);
                            glyphMetrics_.BoundingBox.X += px2mm(charPos.X, dpiX);
                        }

                        glyphMetrics[i] = glyphMetrics_;
                    }
                }
            }

            return(glyphMetrics);
        }
Ejemplo n.º 8
0
        private static void GetGlyphMetrics_(MyScript.IInk.Text.Text text, TextSpan[] spans, List <GlyphMetrics> glyphMetrics, float dpiX, float dpiY)
        {
            var drawing = new DrawingGroup();
            var ctx     = drawing.Open();

            float baseline  = 0.0f;
            int   spanCount = 0;

            foreach (var textSpan in spans)
            {
                var fontFamily  = new FontFamily(textSpan.Style.FontFamily);
                var fontSize    = mm2px(textSpan.Style.FontSize, dpiY);
                var fontWeight  = FontWeight.FromOpenTypeWeight(textSpan.Style.FontWeight);
                var fontStretch = FontStretches.Normal;
                var fontStyle   = FontStyles.Normal;

                if (textSpan.Style.FontStyle.Equals("italic"))
                {
                    fontStyle = FontStyles.Italic;
                }
                else if (textSpan.Style.FontStyle.Equals("oblique"))
                {
                    fontStyle = FontStyles.Oblique;
                }

                if (textSpan.Style.FontWeight >= 700)
                {
                    fontWeight = FontWeights.Bold;
                }
                else if (textSpan.Style.FontWeight >= 400)
                {
                    fontWeight = FontWeights.Normal;
                }
                else
                {
                    fontWeight = FontWeights.Light;
                }

                var typeFace = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);

                // Process glyph one by one to generate one box per glyph
                var label = "";

                for (int j = textSpan.BeginPosition; j < textSpan.EndPosition; ++j)
                {
                    var glyphLabel = text.GetGlyphLabelAt(j);

                    var formattedText = new FormattedText
                                        (
                        glyphLabel, System.Globalization.CultureInfo.CurrentCulture,
                        FlowDirection.LeftToRight, typeFace, fontSize, Brushes.Black
                                        );

                    formattedText.TextAlignment = TextAlignment.Left;

                    var geometry = formattedText.BuildGeometry(new System.Windows.Point(0.0f, 0.0f));
                    var rect     = geometry.Bounds;

                    // For glyph without geometry (space)
                    if (rect.IsEmpty)
                    {
                        rect = new Rect(0.0, 0.0, formattedText.Width, formattedText.Height);
                    }

                    var rectX = (float)rect.X;
                    var rectY = (float)rect.Y;
                    var rectW = (float)rect.Width;
                    var rectH = (float)rect.Height;

                    var leftBearing  = -(float)(rect.X);
                    var rightBearing = 0.0f;

                    var glyphX            = px2mm(rectX, dpiX);
                    var glyphY            = px2mm(rectY, dpiY);
                    var glyphW            = px2mm(rectW, dpiX);
                    var glyphH            = px2mm(rectH, dpiY);
                    var glyphRect         = new Rectangle(glyphX, glyphY, glyphW, glyphH);
                    var glyphLeftBearing  = px2mm(leftBearing, dpiX);
                    var glyphRightBearing = px2mm(rightBearing, dpiX);

                    glyphMetrics.Add(new GlyphMetrics(glyphRect, glyphLeftBearing, glyphRightBearing));

                    label += glyphLabel;
                }

                // Draw current span
                {
                    var formattedText = new FormattedText
                                        (
                        label, System.Globalization.CultureInfo.CurrentCulture,
                        FlowDirection.LeftToRight, typeFace, fontSize, Brushes.Black
                                        );

                    formattedText.TextAlignment = TextAlignment.Left;

                    if (spanCount == 0)
                    {
                        baseline = (float)formattedText.Baseline;
                    }

                    ctx.DrawText(formattedText, new System.Windows.Point(0.0, 0.0));
                }

                ++spanCount;
            }

            ctx.Close();

            // Apply baseline and offsets of glyphs to bounding boxes
            if (glyphMetrics.Count > 0)
            {
                WalkDrawingForText(drawing, glyphMetrics, baseline, dpiX, dpiY);
            }
        }
        public GlyphMetrics[] GetGlyphMetrics(MyScript.IInk.Text.Text text, TextSpan[] spans)
        {
            CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();

            GlyphMetrics[] glyphMetrics = new GlyphMetrics[text.GlyphCount];

            var firstStyle   = spans[0].Style;
            var firstFontKey = FontKeyFromStyle(firstStyle);

            if (text.GlyphCount == 1)
            {
                glyphMetrics[0] = GetGlyphMetrics(firstFontKey, text.Label, canvasDevice);
            }
            else
            {
                var textFormat = new CanvasTextFormat()
                {
                    FontSize     = firstFontKey.FontSize,
                    FontFamily   = firstFontKey.FontFamily,
                    FontStyle    = firstFontKey.FontStyle,
                    FontWeight   = firstFontKey.FontWeight,
                    WordWrapping = CanvasWordWrapping.NoWrap,
                    Options      = UseColorFont ? CanvasDrawTextOptions.EnableColorFont : CanvasDrawTextOptions.Default
                };

                using (var canvasTextLayout = new CanvasTextLayout(canvasDevice, text.Label, textFormat, 0.0f, 0.0f))
                {
                    for (int i = 0; i < spans.Length; ++i)
                    {
                        var charIndex = text.GetGlyphBeginAt(spans[i].BeginPosition);
                        var charCount = text.GetGlyphEndAt(spans[i].EndPosition - 1) - charIndex;

                        var style   = spans[i].Style;
                        var fontKey = FontKeyFromStyle(style);

                        canvasTextLayout.SetFontFamily(charIndex, charCount, fontKey.FontFamily);
                        canvasTextLayout.SetFontSize(charIndex, charCount, fontKey.FontSize);
                        canvasTextLayout.SetFontWeight(charIndex, charCount, fontKey.FontWeight);
                        canvasTextLayout.SetFontStyle(charIndex, charCount, fontKey.FontStyle);
                    }

                    for (int i = 0; i < text.GlyphCount; ++i)
                    {
                        var glyphLabel     = text.GetGlyphLabelAt(i);
                        var glyphCharStart = text.GetGlyphBeginAt(i);
                        var glyphCharEnd   = text.GetGlyphEndAt(i);

                        var glyphFontKey = new FontKey(canvasTextLayout.GetFontFamily(glyphCharStart)
                                                       , canvasTextLayout.GetFontSize(glyphCharStart)
                                                       , canvasTextLayout.GetFontWeight(glyphCharStart)
                                                       , canvasTextLayout.GetFontStyle(glyphCharStart));

                        var glyphMetrics_ = GetGlyphMetrics(glyphFontKey, glyphLabel, canvasDevice);

                        // Find cluster associated to element
                        // (Use of ClusterMetrics to identify ligatures in the CanvasTextLayout)
                        int cluster          = -1;
                        int clusterCharStart = 0;

                        if (canvasTextLayout.ClusterMetrics != null)
                        {
                            for (int c = 0; c < canvasTextLayout.ClusterMetrics.Length; ++c)
                            {
                                var clusterCharCount = canvasTextLayout.ClusterMetrics[c].CharacterCount;
                                if ((glyphCharStart >= clusterCharStart) && (glyphCharStart < (clusterCharStart + clusterCharCount)))
                                {
                                    cluster = c;
                                    break;
                                }

                                clusterCharStart += clusterCharCount;
                            }
                        }

                        if ((i > 0) && (cluster >= 0) && (glyphCharStart > clusterCharStart))
                        {
                            // Ligature with the previous glyph
                            // The position is not accurate because of glyphs substitution at rendering
                            // but it makes the illusion.
                            var prevGlyphMetrics = glyphMetrics[i - 1];
                            glyphMetrics_.BoundingBox.X = prevGlyphMetrics.BoundingBox.X
                                                          + prevGlyphMetrics.BoundingBox.Width
                                                          + prevGlyphMetrics.RightSideBearing
                                                          + glyphMetrics_.LeftSideBearing;
                        }
                        else
                        {
                            float glyphX      = 0.0f;
                            var   charRegions = canvasTextLayout.GetCharacterRegions(glyphCharStart, glyphCharEnd - glyphCharStart);

                            if ((charRegions != null) && (charRegions.Length > 0))
                            {
                                glyphX = (float)charRegions[0].LayoutBounds.X;
                            }
                            else
                            {
                                var glyphPos = canvasTextLayout.GetCaretPosition(glyphCharStart, false);
                                glyphX = (float)glyphPos.X;
                            }

                            glyphMetrics_.BoundingBox.X += px2mm(glyphX, dpiX);
                        }

                        glyphMetrics[i] = glyphMetrics_;
                    }
                }
            }

            return(glyphMetrics);
        }