Example #1
0
        /// <summary>
        /// Calculates / Renders the Main Geometry object
        /// </summary>
        /// <returns></returns>
        private void BuildGeometry()
        {
            Uri           ttfPathUri    = new Uri(TtfPath);
            GlyphTypeface glyphTypeface = new GlyphTypeface(ttfPathUri);

            ushort[] glyphIndexes  = new ushort[Text.Length];
            double[] advanceWidths = new double[Text.Length];

            for (int n = 0; n < Text.Length; n++)
            {
                ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[Text[n]];
                glyphIndexes[n] = glyphIndex;

                double width = glyphTypeface.AdvanceWidths[glyphIndex] * HintingEmSize;
                advanceWidths[n] = width;
            }

            GlyphRun wholeString = new GlyphRun(
                glyphTypeface, //glyphTypeface
                0,             //bidiLevel Specifies the bidirectional layout level. Even-numbered and zero values imply left-to-right layout; odd-numbered values imply right-to-left layout.
                false,         //isSideways
                HintingEmSize, //renderingEmSize
                glyphIndexes,  //glyphIndices (IList<ushort>)
                Offset,        //Point baselineOrigin
                advanceWidths, //IList<double> advancedWiths
                null,          //IList<Point> glyphOffsets
                null,          //IList<char> characters
                null,          //string deviceFontName
                null,          //IList<ushort> clustermap
                null,          //IList<bool>caretStops
                null           //System.Windows.MarkupLanguage
                );

            TextAsGeometry = wholeString.BuildGeometry();
        }
        public override PathGeometry Build(SvgTextContentElement element, string text, double x, double y)
        {
            ComputeMeasurement(text, x, y);

            _textWidth = 0;

            if (_glyphRun == null)
            {
                return(new PathGeometry());
            }

            // Approximate the width of the text...
            Rect designRect = _glyphRun.ComputeAlignmentBox();

            designRect.Offset(_glyphRunOrigin.X, _glyphRunOrigin.Y);

            _textWidth = Math.Max(0, designRect.Right);

            PathGeometry pathGeometry = null;

            var geometry = _glyphRun.BuildGeometry();

            if (geometry is PathGeometry)
            {
                pathGeometry = (PathGeometry)geometry;
            }
            else
            {
                pathGeometry = new PathGeometry();
                pathGeometry.AddGeometry(geometry);
            }

            return(pathGeometry);
        }
        public override void Render(DrawingContext context)
        {
            var c = (char)_rand.Next(65, 90);

            if (_fontSize + _direction > 200)
            {
                _direction = -10;
            }

            if (_fontSize + _direction < 20)
            {
                _direction = 10;
            }

            _fontSize += _direction;

            _glyphIndices[0] = _glyphTypeface.GetGlyph(c);

            _characters[0] = c;

            var glyphRun = new GlyphRun(_glyphTypeface, _fontSize, _characters, _glyphIndices);

            var geometry = glyphRun.BuildGeometry();

            context.DrawGeometry(Brushes.Green, null, geometry);
        }
        private bool CheckGlyphRun()
        {
            if (glyphRun == null)
            {
                if (string.IsNullOrEmpty(Text))
                {
                    return(false);
                }

                var           typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
                GlyphTypeface glyphTypeface;

                if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                {
                    return(false);
                }

                var glyphIndices  = new ushort[Text.Length];
                var advanceWidths = new double[Text.Length];

                for (int i = 0; i < Text.Length; i++)
                {
                    var glyphIndex = glyphTypeface.CharacterToGlyphMap[Text[i]];
                    glyphIndices[i]  = glyphIndex;
                    advanceWidths[i] = glyphTypeface.AdvanceWidths[glyphIndex] * FontSize;
                }

                glyphRun = new GlyphRun(glyphTypeface, 0, false, FontSize, glyphIndices, new Point(), advanceWidths, null, null, null, null, null, null);

                outline = glyphRun.BuildGeometry().GetWidenedPathGeometry(new Pen(null, OutlineThickness * 2d));
            }

            return(true);
        }
Example #5
0
        private PathGeometry BuildStyledFontGeometry()
        {
            var typeface = new Typeface(Font,
                                        FontStyles.Normal,
                                        FontWeights.Normal,
                                        FontStretches.Normal);

            GlyphTypeface glyphTypeface;

            if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
            {
                return(null);
            }

            var glyphIndexes  = new ushort[Font.Source.Length];
            var advanceWidths = new double[Font.Source.Length];

            for (int n = 0; n < Font.Source.Length; n++)
            {
                if (glyphTypeface.CharacterToGlyphMap.ContainsKey(Font.Source[n]))
                {
                    ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[Font.Source[n]];
                    glyphIndexes[n] = glyphIndex;

                    double width = glyphTypeface.AdvanceWidths[glyphIndex] * 12;
                    advanceWidths[n] = width;
                }
            }

            var          run = new GlyphRun(glyphTypeface, 0, false, 12, glyphIndexes, new Point(0, 12), advanceWidths, null, null, null, null, null, null);
            PathGeometry ret = PathGeometry.CreateFromGeometry(run.BuildGeometry());

            ret.Freeze();
            return(ret);
        }
Example #6
0
        public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
        {
            GlyphRun glyphRun = GetGlyphRun(scale, x, y);

            GeometryGroup geoGroup = glyphRun.BuildGeometry() as GeometryGroup;

            geometry.Children.Add(geoGroup);
        }
Example #7
0
        public override void RenderGeometry(GeometryGroup geometry, double scale, double x, double y)
        {
            GlyphRun glyphRun = GetGlyphRun(scale, x, y);

            GeometryGroup geoGroup = glyphRun.BuildGeometry() as GeometryGroup;
            PathGeometry  pg       = geoGroup.GetFlattenedPathGeometry();

            geometry.Children.Add(pg);
        }
Example #8
0
        /// <summary>
        /// Returns a rough outline of a glyph run.  useful for calculating a convex hull
        /// </summary>
        /// <param name="glyphRun">Glyph run to outline</param>
        /// <returns>List<Point> of geometry tracing the GlyphRun</Point></returns>
        public static List <Point> GetOutline(this GlyphRun glyphRun)
        {
            if (glyphRun != null)
            {
                var geo = glyphRun.BuildGeometry();
                return(GetGeoPoints(geo));
            }

            return(null);
        }
Example #9
0
        public void DrawGlyphRun(PenF pen, Color?fillColor, GlyphRun glyphRun, float?tolerance = null)
        {
            pen.Color = _transform.Transform(pen.Color);
            if (fillColor.HasValue)
            {
                fillColor = _transform.Transform(fillColor.Value);
            }

            _DrawGeometry(pen, fillColor, glyphRun.BuildGeometry(), tolerance);
        }
Example #10
0
            public GlyphRunGeometryControl()
            {
                var glyphTypeface = new Typeface(TestFontFamily).GlyphTypeface;

                var glyphIndices = new[] { glyphTypeface.GetGlyph('A'), glyphTypeface.GetGlyph('B'), glyphTypeface.GetGlyph('C') };

                var characters = new[] { 'A', 'B', 'C' };

                var glyphRun = new GlyphRun(glyphTypeface, 100, characters, glyphIndices);

                Geometry = glyphRun.BuildGeometry();
            }
        // External API
        public bool DrawGlyphs(GlyphRun glyphrun, Rect bounds, Matrix trans, string desp)
        {
            if (glyphrun == null)
            {
                return(true);
            }

            int start = 0;

            PrimitiveInfo topPI;
            Geometry      topBounds;
            Geometry      inter;

            // If glyph has intersection with something on the top, change to geometry fill
            // Use bounding rectangle to test for overlapping first, avoinding expensive BuildGeometry call
            if ((_overlapping != null) && FindIntersection(new RectangleGeometry(bounds), ref start, out topPI, out topBounds, out inter))
            {
                start = 0;

                Geometry cur = glyphrun.BuildGeometry();

                cur = Utility.TransformGeometry(cur, trans);

                if (FindIntersection(cur, ref start, out topPI, out topBounds, out inter))
                {
                    // FillGeometry expects brush in world space. Apply trans to brush.
                    if (_brush != null)
                    {
                        _brush = _brush.ApplyTransformCopy(trans);
                    }

                    FillGeometry(topPI, cur, desp, null, null, start, inter, topBounds);

                    return(true);
                }
            }

            _dc.Comment(desp);

            return(_dc.DrawGlyphs(glyphrun, _clip, trans, _brush));
        }
Example #12
0
 /// <summary>
 /// Enumerates through the drawing group of a visual to extract the geometries.
 /// </summary>
 /// <param name="dg"></param>
 /// <param name="currentParent"></param>
 private static void EnumerateDrawingGroup(DrawingGroup dg, GeometryGroup currentParent)
 {
     for (int i = 0; i < dg.Children.Count; i++)
     {
         if (dg.Children[i] is GeometryDrawing)
         {
             GeometryDrawing geometryDrawing = dg.Children[i] as GeometryDrawing;
             if (geometryDrawing != null)
             {
                 Geometry geometry = geometryDrawing.Geometry;
                 currentParent.Children.Add(geometry);
             }
         }
         else if (dg.Children[i] is DrawingGroup)
         {
             EnumerateDrawingGroup((DrawingGroup)dg.Children[i], currentParent);
         }
         else if (dg.Children[i] is GlyphRunDrawing)
         {
             GlyphRunDrawing glyphrunDrawing = dg.Children[i] as GlyphRunDrawing;
             GlyphRun        glyphrun        = glyphrunDrawing.GlyphRun;
             if (glyphrun != null)
             {
                 Geometry geometry = glyphrun.BuildGeometry();
                 currentParent.Children.Add(geometry);
             }
         }
         else if (dg.Children[i] is ImageDrawing)
         {
             ImageDrawing      imagedrawing = dg.Children[i] as ImageDrawing;
             RectangleGeometry rg           = new RectangleGeometry(imagedrawing.Rect);
             currentParent.Children.Add(rg);
         }
         else if (dg.Children[i] is VideoDrawing)
         {
             VideoDrawing      videodrawing = dg.Children[i] as VideoDrawing;
             RectangleGeometry rg           = new RectangleGeometry(videodrawing.Rect);
             currentParent.Children.Add(rg);
         }
     }
 }
Example #13
0
        private void Test2()
        {
            //Glyph系クラス
            GlyphRun        glyphRun;
            GlyphRunDrawing glyphRunDrawing;
            Glyphs          glyphs;
            GlyphTypeface   glyphTypeface;

            FontFamily fontFamily = new FontFamily("Meiryo UI");
            var        typefaces  = fontFamily.GetTypefaces();
            Uri        myFontUri  = null;

            foreach (var face in typefaces)
            {
                face.TryGetGlyphTypeface(out GlyphTypeface gType);
                myFontUri = gType.FontUri;
                break;
            }

            glyphs                     = new();
            glyphs.FontUri             = myFontUri;
            glyphs.FontRenderingEmSize = 100;
            //glyphs.StyleSimulations = StyleSimulations.BoldItalicSimulation;
            glyphs.UnicodeString = "(ゆっくり)";
            glyphs.Fill          = Brushes.MediumOrchid;
            //glyphs.BidiLevel = 1;
            //glyphs.IsSideways = true;
            GlyphRun gRun      = glyphs.ToGlyphRun();
            var      chars     = gRun.Characters;
            var      clustre   = gRun.ClusterMap;
            var      box       = gRun.ComputeAlignmentBox();
            var      inkBox    = gRun.ComputeInkBoundingBox();
            var      dfName    = gRun.DeviceFontName;
            var      inside    = gRun.GetCaretCharacterHitFromDistance(100, out bool isindside);
            var      hit       = gRun.GetNextCaretCharacterHit(new System.Windows.Media.TextFormatting.CharacterHit());
            var      gInd      = gRun.GlyphIndices;
            var      gOffset   = gRun.GlyphOffsets;
            var      gTypeface = gRun.GlyphTypeface;

            MyGrid.Children.Add(glyphs);

            DrawingVisual dv = new();

            //dv.Offset = new Vector(0, -100);

            using (var dc = dv.RenderOpen())
            {
                //dc.DrawRectangle(Brushes.MediumBlue, null, new Rect(0, 0, 500, 500));
                //dc.DrawRectangle(Brushes.MediumBlue, null, new Rect(0, 0, box.Width, box.Height));
                dc.DrawGlyphRun(Brushes.MediumAquamarine, gRun);
            }
            Rect r3                   = dv.Drawing.Bounds;
            Rect r                    = dv.ContentBounds;
            Rect r2                   = dv.DescendantBounds;
            var  geo                  = gRun.BuildGeometry();
            Rect rectGeo1             = geo.Bounds;
            Rect rectGeo2             = geo.GetRenderBounds(null);
            RenderTargetBitmap bitmap = new((int)box.Width, (int)box.Height, 96, 96, PixelFormats.Pbgra32);

            bitmap.Render(dv);

            glyphRunDrawing   = new(Brushes.MediumAquamarine, gRun);
            MyGrid.Background = new DrawingBrush(glyphRunDrawing);
            //Glyphs
            //FontUri               フォント
            //FontRenderingEmSize   フォントサイズみたいなもの
            //StyleSimulations      太字と斜体の指定
            //BidiLevel             文字を並べる向きの指定、0or偶数で左から、奇数で右からになる
            //ToGlyphRun()          GlyphRun作成

            //GlyphRun クラス (System.Windows.Media) | Microsoft Docs
            //https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.media.glyphrun?view=net-6.0
            //  同じ描画スタイルが設定され、サイズ、フォント、およびフォントの書体が同じである一連のグリフを表します。
            //GlyphRunDrawingと組み合わせて使う

            //プロパティ
            //AdvanceWidths
            //グリフ インデックスに対応するアドバンス幅を表す Double 値の一覧を取得または設定します。

            //BaselineOrigin    Point
            //GlyphRun のベースライン原点を取得または設定します。

            //BidiLevel     Int32
            //GlyphRun の双方向の入れ子レベルを取得または設定します。

            //CaretStops    bool
            //GlyphRun を表す Unicode で UTF16 コード ポイント毎にキャレット ストップがあるかどうかを決定する Boolean 値の一覧を取得または設定します。

            //Characters    List<Char>
            //GlyphRun の Unicode を表す UTF16 コード ポイントの一覧を取得または設定します。

            //ClusterMap    List<Uint16>
            //GlyphRun の文字をグリフ インデックスにマップする UInt16 値の一覧を取得または設定します。

            //DeviceFontName    string
            //GlyphRun が最適化される対象の、デバイス固有のフォントを取得または設定します。

            //FontRenderingEmSize   double
            //GlyphRun のレンダリングに使用する全角サイズを取得または設定します。

            //GlyphIndices      list<Uint16>
            //描画物理フォントのグリフ インデックスを表す UInt16 値の配列を取得または設定します。

            //GlyphOffsets      List<point>
            //GlyphRun のグリフのオフセットを表す Point 値の配列を取得または設定します。

            //GlyphTypeface     GlyphTypeface
            //GlyphTypeface の GlyphRun を取得または設定します。

            //IsHitTestable     bool
            //GlyphRun 内に有効なキャレット文字ヒットがあるかどうかを示す値を取得します。

            //IsSideways        bool
            //グリフを回転するかどうかを示す値を取得または設定します。

            //Language          XmlLanguage
            //XmlLanguage の GlyphRun を取得または設定します。

            //PixelsPerDip      Single
            //テキストを表示する PixelsPerDip を取得または設定します。


            //メソッド
            //BuildGeometry
            //  GlyphRunのジオメトリを取得します。
            //ComputeAlignmentBox   Rect
            //  GlyphRunの配置ボックスを取得します。
            //ComputeInkBoundingBox Rect
            //  GlyphRunのインク境界ボックスを取得します。
            //GetCaretCharacterHitFromDistance(Double, Boolean) CharacterHitグリフラン内でヒットした文字に関する情報を表します。
            //  GlyphRunのキャレットの文字ヒットを表すCharacterHit値を取得します。
            //GetDistanceFromCaretCharacterHit(CharacterHit) double
            //  GlyphRunの前縁から、指定された文字ヒットを含むキャレットストップの前縁または後縁までのオフセットを取得します。
            //GetNextCaretCharacterHit(CharacterHit) CharacterHit
            //  GlyphRunで論理方向にヒットした次の有効なキャレット文字を取得します。
            //GetPreviousCaretCharacterHit(CharacterHit) CharacterHit
            //  GlyphRunで論理方向にヒットした前の有効なキャレット文字を取得します。
        }
Example #14
0
        /// <summary>
        /// 构建文本形状
        /// </summary>
        /// <param name="text">文本内容</param>
        /// <param name="x">横坐标</param>
        /// <param name="y">纵坐标</param>
        /// <param name="totalwidth">总宽度</param>
        /// <returns>形状</returns>
        private Geometry BuildGlyphRun(string text, double x, double y, ref double totalwidth)
        {
            double baseline = y;

            SVGBaseLineShift  baseline_shift  = this.GetAttributeValue <SVGBaseLineShift>("baseline-shift", true, null);
            double            font_size       = this.GetAttributeValue <SVGDouble>("font-size", true, new SVGDouble(12)).GetValue(12);
            SVGFontFamily     font_family     = this.GetAttributeValue <SVGFontFamily>("font-family", true, SVGFontFamily.Default);
            SVGFontWeight     font_weight     = this.GetAttributeValue <SVGFontWeight>("font-weight", true, SVGFontWeight.Default);
            SVGFontStyle      font_style      = this.GetAttributeValue <SVGFontStyle>("font-style", true, SVGFontStyle.Default);
            SVGTextAnchor     text_anchor     = this.GetAttributeValue <SVGTextAnchor>("text-anchor", true, SVGTextAnchor.Default);
            SVGTextDecoration text_decoration = this.GetAttributeValue <SVGTextDecoration>("text-decoration", true, null);
            double            letter_spacing  = this.GetAttributeValue <SVGDouble>("letter-spacing", true, SVGDouble.Zero).GetValue(12);
            double            word_spacing    = this.GetAttributeValue <SVGDouble>("word-spacing", true, SVGDouble.Zero).GetValue(12);

            GlyphRun glyphs = null;

            Typeface      type_face = new Typeface(font_family.Value, font_style.Value, font_weight.Value, FontStretch.FromOpenTypeStretch(9), SVGFontFamily.Default.Value);
            GlyphTypeface glyph_type_face;

            if (!type_face.TryGetGlyphTypeface(out glyph_type_face))
            {
                return(null);
            }

            glyphs = new GlyphRun();

            ((System.ComponentModel.ISupportInitialize)glyphs).BeginInit();

            glyphs.GlyphTypeface       = glyph_type_face;
            glyphs.FontRenderingEmSize = font_size;
            List <char>   text_chars     = new List <char>();
            List <ushort> glyph_indices  = new List <ushort>();
            List <double> advance_widths = new List <double>();

            totalwidth = 0;
            for (int i = 0; i < text.Length; ++i)
            {
                char   c          = text[i];
                int    code_point = c;
                ushort glyph_index;
                if (!glyph_type_face.CharacterToGlyphMap.TryGetValue(code_point, out glyph_index))
                {
                    continue;
                }

                text_chars.Add(c);
                double glyph_width = glyph_type_face.AdvanceWidths[glyph_index];
                glyph_indices.Add(glyph_index);
                advance_widths.Add(glyph_width * font_size + letter_spacing);
                if (char.IsWhiteSpace(c))
                {
                    advance_widths[advance_widths.Count - 1] += word_spacing;
                }
                totalwidth += advance_widths[advance_widths.Count - 1];
            }
            glyphs.Characters    = text_chars.ToArray();
            glyphs.GlyphIndices  = glyph_indices.ToArray();
            glyphs.AdvanceWidths = advance_widths.ToArray();

            double alignmentoffset = 0;

            if (text_anchor.Value == TextAlignment.Center)
            {
                alignmentoffset = totalwidth / 2;
            }
            else if (text_anchor.Value == TextAlignment.Right)
            {
                alignmentoffset = totalwidth;
            }

            glyphs.BaselineOrigin = new Point(x - alignmentoffset, baseline);

            ((System.ComponentModel.ISupportInitialize)glyphs).EndInit();

            GeometryGroup result = new GeometryGroup();

            result.Children.Add(glyphs.BuildGeometry());

            if (text_decoration != null)
            {
                double decoration_pos      = 0;
                double decoration_thinkess = 0;

                if (text_decoration.Value == TextDecorationLocation.Strikethrough)
                {
                    decoration_pos      = baseline - (type_face.StrikethroughPosition * font_size);
                    decoration_thinkess = type_face.StrikethroughThickness * font_size;
                }
                else if (text_decoration.Value == TextDecorationLocation.Underline)
                {
                    decoration_pos      = baseline - (type_face.UnderlinePosition * font_size);
                    decoration_thinkess = type_face.UnderlineThickness * font_size;
                }
                else if (text_decoration.Value == TextDecorationLocation.OverLine)
                {
                    decoration_pos      = baseline - font_size;
                    decoration_thinkess = type_face.StrikethroughThickness * font_size;
                }

                System.Windows.Rect bounds = new System.Windows.Rect(result.Bounds.Left, decoration_pos, result.Bounds.Width, decoration_thinkess);

                result.Children.Add(new RectangleGeometry(bounds));
            }

            return(result);
        }
Example #15
0
        public override Geometry Build(SvgTextContentElement element, string text, double x, double y)
        {
            var alignment = this.TextAlignment;

            if (alignment != TextAlignment.Left)
            {
                var textSize  = this.MeasureText(element, text, true);
                var textWidth = Math.Max(textSize.Width, this.Width);
                if (alignment == TextAlignment.Center)
                {
                    x -= textWidth / 2;
                }
                else
                {
                    x -= textWidth;
                }
            }

            ComputeMeasurement(text, x, y + this.Baseline);

            _textWidth = 0;

            if (_glyphRun == null)
            {
                return(new GeometryGroup());
            }

            // Approximate the width of the text...
            Rect designRect = _glyphRun.ComputeAlignmentBox();

            //designRect.Offset(_glyphRunOrigin.X, _glyphRunOrigin.Y);

            _textWidth = Math.Max(0, designRect.Right);

            var geometry = _glyphRun.BuildGeometry();

            if (geometry == null)
            {
                return(geometry);
            }

            if (_textDecorations == null || _textDecorations.Count == 0)
            {
                if (_buildPathGeometry)
                {
                    PathGeometry pathGeometry = geometry as PathGeometry;
                    if (pathGeometry == null)
                    {
                        pathGeometry = new PathGeometry();
                        pathGeometry.AddGeometry(geometry);
                    }
                    return(pathGeometry);
                }
                return(geometry);
            }

            var baseline = y + this.Baseline;

            GeometryGroup geomGroup = geometry as GeometryGroup;

            if (geomGroup == null)
            {
                geomGroup = new GeometryGroup();
                geomGroup.Children.Add(geometry);
            }

            foreach (var textDeDecoration in _textDecorations)
            {
                double decorationPos       = 0;
                double decorationThickness = 0;

                if (textDeDecoration.Location == TextDecorationLocation.Strikethrough)
                {
                    decorationPos       = baseline - (this.StrikethroughPosition * _fontSize);
                    decorationThickness = this.StrikethroughThickness * _fontSize;
                }
                else if (textDeDecoration.Location == TextDecorationLocation.Underline)
                {
                    decorationPos       = baseline - (this.UnderlinePosition * _fontSize);
                    decorationThickness = this.UnderlineThickness * _fontSize;
                }
                else if (textDeDecoration.Location == TextDecorationLocation.OverLine)
                {
                    decorationPos       = baseline - _fontSize;
                    decorationThickness = this.OverlineThickness * _fontSize;
                }
                Rect bounds = new Rect(geomGroup.Bounds.Left, decorationPos, geomGroup.Bounds.Width, decorationThickness + 0.5);

                var rectGeom = new RectangleGeometry(bounds);
                if (_buildPathGeometry)
                {
                    PathGeometry pathGeometry = new PathGeometry();
                    pathGeometry.AddGeometry(rectGeom);
                    geomGroup.Children.Add(pathGeometry);
                }
                else
                {
                    geomGroup.Children.Add(rectGeom);
                }
            }

            if (_buildPathGeometry)
            {
                PathGeometry pathGeometry = new PathGeometry();
                pathGeometry.AddGeometry(geomGroup);

                return(pathGeometry);
            }
            return(geomGroup);
        }
 public void DrawGlyphRun(Color?foreground, DrawingPen pen, GlyphRun glyphRun)
 {
     _needFilpCoordinate = false;
     _DrawPathGeometry(foreground, pen, glyphRun.BuildGeometry());
     _needFilpCoordinate = true;
 }
        public override Geometry Build(SvgTextContentElement element, string text, double x, double y)
        {
            if (_fontSize <= 0)
            {
                return(new GeometryGroup());
            }

//            bool isRightToLeft = false;
            var xmlLang = element.XmlLang;

            if (!string.IsNullOrWhiteSpace(xmlLang))
            {
                if (string.Equals(xmlLang, "ar", StringComparison.OrdinalIgnoreCase) ||   // Arabic language
                    string.Equals(xmlLang, "he", StringComparison.OrdinalIgnoreCase))     // Hebrew language
                {
//                    isRightToLeft = true;

                    //                    this.BidiLevel = 1;

                    if (text.Length > 0)
                    {
                        char[] charArray = text.ToCharArray();
                        Array.Reverse(charArray);
                        text = new string(charArray);
                    }
                }
            }

            var alignment = this.TextAlignment;

            if (alignment != TextAlignment.Left)
            {
                var textSize  = this.MeasureText(element, text, true);
                var textWidth = Math.Max(textSize.Width, this.Width);
                if (alignment == TextAlignment.Center)
                {
                    x -= textWidth / 2;
                }
                else
                {
                    x -= textWidth;
                }
            }
            //else if (isRightToLeft)
            //{
            //    var textSize  = this.MeasureText(element, text, true);
            //    var textWidth = Math.Max(textSize.Width, this.Width);

            //    x -= textWidth;
            //}

            ComputeMeasurement(text, x, y + this.Baseline);

            _textWidth = 0;

            if (_glyphRun == null)
            {
                return(new GeometryGroup());
            }

            // Approximate the width of the text...
            Rect designRect = _glyphRun.ComputeAlignmentBox();

            //designRect.Offset(_glyphRunOrigin.X, _glyphRunOrigin.Y);

            _textWidth = Math.Max(0, designRect.Right);

            var geometry = _glyphRun.BuildGeometry();

            if (geometry == null)
            {
                return(geometry);
            }

            if (_textDecorations == null || _textDecorations.Count == 0)
            {
                if (_buildPathGeometry)
                {
                    PathGeometry pathGeometry = geometry as PathGeometry;
                    if (pathGeometry == null)
                    {
                        pathGeometry = new PathGeometry();
                        pathGeometry.AddGeometry(geometry);
                    }
                    return(pathGeometry);
                }
                return(geometry);
            }

            var baseline = y + this.Baseline;

            GeometryGroup geomGroup = geometry as GeometryGroup;

            if (geomGroup == null)
            {
                geomGroup = new GeometryGroup();
                geomGroup.Children.Add(geometry);
            }

            foreach (var textDeDecoration in _textDecorations)
            {
                double decorationPos       = 0;
                double decorationThickness = 0;

                if (textDeDecoration.Location == TextDecorationLocation.Strikethrough)
                {
                    decorationPos       = baseline - (this.StrikethroughPosition * _fontSize);
                    decorationThickness = this.StrikethroughThickness * _fontSize;
                }
                else if (textDeDecoration.Location == TextDecorationLocation.Underline)
                {
                    decorationPos       = baseline - (this.UnderlinePosition * _fontSize);
                    decorationThickness = this.UnderlineThickness * _fontSize;
                }
                else if (textDeDecoration.Location == TextDecorationLocation.OverLine)
                {
                    decorationPos       = baseline - _fontSize;
                    decorationThickness = this.OverlineThickness * _fontSize;
                }
                Rect bounds = new Rect(geomGroup.Bounds.Left, decorationPos, geomGroup.Bounds.Width, decorationThickness + 0.5);

                var rectGeom = new RectangleGeometry(bounds);
                if (_buildPathGeometry)
                {
                    PathGeometry pathGeometry = new PathGeometry();
                    pathGeometry.AddGeometry(rectGeom);
                    geomGroup.Children.Add(pathGeometry);
                }
                else
                {
                    geomGroup.Children.Add(rectGeom);
                }
            }

            if (_buildPathGeometry)
            {
                PathGeometry pathGeometry = new PathGeometry();
                pathGeometry.AddGeometry(geomGroup);

                return(pathGeometry);
            }
            return(geomGroup);
        }
Example #18
0
        private void MakeBitmap()
        {
            while (true)
            {
                _newText.WaitOne();

                GlyphTypeface glyphTypeface = null;
                if (_glyphTypeface != null)
                {
                    lock (_glyphTypeface)
                    {
                        glyphTypeface = _glyphTypeface;
                    }
                }

                if (glyphTypeface != null)
                {
                    if (_lines == null || _lines.Length == 0)
                    {
                        _img = null;
                    }
                    else
                    {
                        if (_lines[0].VobSubMergedPack != null)
                        {
                            var          bitmaps = _lines.Select(l => l.GetImage()).ToArray();
                            int          bw      = bitmaps.Max(b => b.Width);
                            int          bh      = bitmaps.Sum(b => b.Height);
                            BitmapSource bimage  = CreateBitmap((int)bw, (int)bh, 96,
                                                                dc =>
                            {
                                double ypos = 0;
                                for (int lb = 0; lb < bitmaps.Count(); lb++)
                                {
                                    var bs     = bitmaps[lb].ToBitmapSource();
                                    Point bLoc = new Point((bw - bs.Width) / 2, ypos);
                                    Size bSize = new Size(bs.Width, bs.Height);
                                    ypos      += bs.Height;
                                    dc.DrawImage(bs, new Rect(bLoc, bSize));
                                }
                            });
                            bimage.Freeze();
                            _img = bimage;
                        }
                        else
                        {
                            var lines = new List <string>(_lines.Select(l => l.Text).SelectMany(t => t.Split(new string[] { Environment.NewLine }, 10000, StringSplitOptions.None))).ToArray();
                            {
                                ushort[][] glyphIndexes  = new ushort[lines.Length][];
                                double[][] advanceWidths = new double[lines.Length][];

                                double[] totalWidth = new double[lines.Length];

                                int l = 0;
                                foreach (var text in lines)
                                {
                                    glyphIndexes[l]  = new ushort[text.Length];
                                    advanceWidths[l] = new double[text.Length];
                                    for (int n = 0; n < text.Length; n++)
                                    {
                                        if (glyphTypeface.CharacterToGlyphMap.ContainsKey(text[n]))
                                        {
                                            ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];
                                            glyphIndexes[l][n] = glyphIndex;

                                            double width = glyphTypeface.AdvanceWidths[glyphIndex] * _fontSize;
                                            advanceWidths[l][n] = width;

                                            totalWidth[l] += width;
                                        }
                                    }
                                    l++;
                                }

                                double w = totalWidth.Max(lw => lw) + _marginLeft + _marginRight;
                                double h = (lines.Length * _fontSize) + _fontSize / 4 + _marginBottom;

                                BitmapSource image = CreateBitmap((int)w, (int)h, 96,
                                                                  dc =>
                                {
                                    int line = 1;
                                    if (_back != Brushes.Transparent)
                                    {
                                        dc.DrawRectangle(_back, null, new Rect(0d, 0d, w, h));
                                    }
                                    foreach (var text in lines)
                                    {
                                        if (string.IsNullOrEmpty(text))
                                        {
                                            line++;
                                            continue;
                                        }
                                        var origin      = new Point((w - totalWidth[line - 1]) / 2, line * _fontSize);
                                        var orig        = ((SolidColorBrush)_stroke.Clone()).Color;
                                        var strokeBrush = new SolidColorBrush
                                        {
                                            Color =
                                                new Color()
                                            {
                                                B = orig.B,
                                                R = orig.R,
                                                G = orig.G,
                                                A = _strokeGlow ? (byte)35 : orig.A
                                            }
                                        };

                                        var glyphRun = new GlyphRun(glyphTypeface, 0, false, _fontSize,
                                                                    glyphIndexes[line - 1], origin,
                                                                    advanceWidths[line - 1], null, null,
                                                                    null, null,
                                                                    null, null);

                                        if (_underline)
                                        {
                                            double y = origin.Y;
                                            y       -= (glyphTypeface.Baseline + _typeface.UnderlinePosition * _fontSize);
                                            for (double i = _strokeThickness; i > 0; i--)
                                            {
                                                dc.DrawLine(
                                                    new Pen(strokeBrush, (_typeface.UnderlineThickness * _fontSize) + i),
                                                    new Point(origin.X - _strokeThickness / 2, y),
                                                    new Point(origin.X + totalWidth[line - 1] + _strokeThickness / 2, y));
                                                if (!_strokeGlow)
                                                {
                                                    break;
                                                }
                                            }
                                        }

                                        var geo = glyphRun.BuildGeometry();
                                        for (double i = _strokeThickness; i > 0; i--)
                                        {
                                            dc.DrawGeometry(null, new Pen(strokeBrush, i), geo);
                                            if (!_strokeGlow)
                                            {
                                                break;
                                            }
                                        }

                                        dc.DrawGlyphRun(_fill, glyphRun);

                                        if (_underline)
                                        {
                                            double y = origin.Y;
                                            y       -= (glyphTypeface.Baseline + _typeface.UnderlinePosition * _fontSize);
                                            dc.DrawLine(new Pen(_fill, _typeface.UnderlineThickness * _fontSize),
                                                        new Point(origin.X, y),
                                                        new Point(origin.X + totalWidth[line - 1], y));
                                        }

                                        line++;
                                    }
                                });

                                image.Freeze();
                                _img = image;
                            }
                        }
                    }
                }
                try
                {
                    _newText.Release();
                }
                catch
                {
                }
                Dispatcher.Invoke(((Action)(() =>
                {
                    _newText.WaitOne(); InvalidateVisual();
                })), DispatcherPriority.Render, new object[] { });
            }
        }