private void DrawTextRun(SvgTextContentElement element, ref Point ctp,
            WpfTextRun textRun, double rotate, WpfTextPlacement placement)
        {
            if (textRun == null || textRun.IsEmpty)
                return;

            string text           = textRun.Text;
            double emSize         = GetComputedFontSize(element);
            FontFamily fontFamily = GetTextFontFamily(element, emSize);

            FontStyle fontStyle   = GetTextFontStyle(element);
            FontWeight fontWeight = GetTextFontWeight(element);

            FontStretch fontStretch = GetTextFontStretch(element);

            WpfTextStringFormat stringFormat = GetTextStringFormat(element);

            // Fix the use of Postscript fonts...
            WpfFontFamilyVisitor fontFamilyVisitor = _drawContext.FontFamilyVisitor;
            if (!String.IsNullOrEmpty(_actualFontName) && fontFamilyVisitor != null)
            {
                WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight,
                    fontStyle, fontStretch);
                WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName,
                    currentFamily, _drawContext);
                if (familyInfo != null && !familyInfo.IsEmpty)
                {
                    fontFamily  = familyInfo.Family;
                    fontWeight  = familyInfo.Weight;
                    fontStyle   = familyInfo.Style;
                    fontStretch = familyInfo.Stretch;
                }
            }

            WpfSvgPaint fillPaint = new WpfSvgPaint(_drawContext, element, "fill");
            Brush textBrush       = fillPaint.GetBrush();

            WpfSvgPaint strokePaint = new WpfSvgPaint(_drawContext, element, "stroke");
            Pen textPen = strokePaint.GetPen();

            if (textBrush == null && textPen == null)
            {
                return;
            }
            else if (textBrush == null)
            {
                // If here, then the pen is not null, and so the fill cannot be null.
                // We set this to transparent for stroke only text path...
                textBrush = Brushes.Transparent;
            }

            TextDecorationCollection textDecors = GetTextDecoration(element);
            TextAlignment alignment = stringFormat.Alignment;

            string letterSpacing = element.GetAttribute("letter-spacing");
            if (String.IsNullOrEmpty(letterSpacing))
            {
                FormattedText formattedText = new FormattedText(text,
                    textRun.IsLatin ? _drawContext.EnglishCultureInfo : _drawContext.CultureInfo,
                    stringFormat.Direction, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
                    emSize, textBrush);

                formattedText.TextAlignment = stringFormat.Alignment;
                formattedText.Trimming      = stringFormat.Trimming;

                if (textDecors != null && textDecors.Count != 0)
                {
                    formattedText.SetTextDecorations(textDecors);
                }

                //float xCorrection = 0;
                //if (alignment == TextAlignment.Left)
                //    xCorrection = emSize * 1f / 6f;
                //else if (alignment == TextAlignment.Right)
                //    xCorrection = -emSize * 1f / 6f;

                double yCorrection = formattedText.Baseline;

                Point textPoint = new Point(ctp.X, ctp.Y - yCorrection);

                RotateTransform rotateAt = new RotateTransform(90, ctp.X, ctp.Y);
                _textContext.PushTransform(rotateAt);

                _textContext.DrawText(formattedText, textPoint);

                //float bboxWidth = (float)formattedText.Width;
                double bboxWidth = formattedText.WidthIncludingTrailingWhitespace;
                if (alignment == TextAlignment.Center)
                    bboxWidth /= 2f;
                else if (alignment == TextAlignment.Right)
                    bboxWidth = 0;

                //ctp.X += bboxWidth + emSize / 4;
                ctp.X += bboxWidth;

                if (rotateAt != null)
                {
                    _textContext.Pop();
                }
            }
            else
            {
                RotateTransform rotateAt = new RotateTransform(90, ctp.X, ctp.Y);
                _textContext.PushTransform(rotateAt);

                float spacing = Convert.ToSingle(letterSpacing);
                for (int i = 0; i < text.Length; i++)
                {
                    FormattedText formattedText = new FormattedText(new string(text[i], 1),
                        textRun.IsLatin ? _drawContext.EnglishCultureInfo : _drawContext.CultureInfo,
                        stringFormat.Direction,
                        new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
                        emSize, textBrush);

                    formattedText.Trimming      = stringFormat.Trimming;
                    formattedText.TextAlignment = stringFormat.Alignment;

                    if (textDecors != null && textDecors.Count != 0)
                    {
                        formattedText.SetTextDecorations(textDecors);
                    }

                    //float xCorrection = 0;
                    //if (alignment == TextAlignment.Left)
                    //    xCorrection = emSize * 1f / 6f;
                    //else if (alignment == TextAlignment.Right)
                    //    xCorrection = -emSize * 1f / 6f;

                    double yCorrection = formattedText.Baseline;

                    Point textPoint = new Point(ctp.X, ctp.Y - yCorrection);

                    _textContext.DrawText(formattedText, textPoint);

                    //float bboxWidth = (float)formattedText.Width;
                    double bboxWidth = formattedText.WidthIncludingTrailingWhitespace;
                    if (alignment == TextAlignment.Center)
                        bboxWidth /= 2f;
                    else if (alignment == TextAlignment.Right)
                        bboxWidth = 0;

                    //ctp.X += bboxWidth + emSize / 4 + spacing;
                    ctp.X += bboxWidth + spacing;
                }

                if (rotateAt != null)
                {
                    _textContext.Pop();
                }
            }
        }
 public abstract WpfFontFamilyInfo Visit(string fontName, WpfFontFamilyInfo familyInfo,
     WpfDrawingContext context);
        public override void RenderTextRun(SvgTextContentElement element, ref Point ctp,
            string text, double rotate, WpfTextPlacement placement)
        {
            if (String.IsNullOrEmpty(text))
                return;

            double emSize         = GetComputedFontSize(element);
            FontFamily fontFamily = GetTextFontFamily(element, emSize);

            FontStyle fontStyle   = GetTextFontStyle(element);
            FontWeight fontWeight = GetTextFontWeight(element);

            FontStretch fontStretch = GetTextFontStretch(element);

            WpfTextStringFormat stringFormat = GetTextStringFormat(element);

            // Fix the use of Postscript fonts...
            WpfFontFamilyVisitor fontFamilyVisitor = _drawContext.FontFamilyVisitor;
            if (!String.IsNullOrEmpty(_actualFontName) && fontFamilyVisitor != null)
            {
                WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight,
                    fontStyle, fontStretch);
                WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName,
                    currentFamily,_drawContext);
                if (familyInfo != null && !familyInfo.IsEmpty)
                {
                    fontFamily  = familyInfo.Family;
                    fontWeight  = familyInfo.Weight;
                    fontStyle   = familyInfo.Style;
                    fontStretch = familyInfo.Stretch;
                }
            }

            WpfSvgPaint fillPaint = new WpfSvgPaint(_drawContext, element, "fill");
            Brush textBrush = fillPaint.GetBrush();

            WpfSvgPaint strokePaint = new WpfSvgPaint(_drawContext, element, "stroke");
            Pen textPen = strokePaint.GetPen();

            if (textBrush == null && textPen == null)
            {
                return;
            }
            else if (textBrush == null)
            {
                // If here, then the pen is not null, and so the fill cannot be null.
                // We set this to transparent for stroke only text path...
                textBrush = Brushes.Transparent;
            }

            TextDecorationCollection textDecors = GetTextDecoration(element);
            if (textDecors == null)
            {
                SvgTextElement textElement = element.ParentNode as SvgTextElement;

                if (textElement != null)
                {
                    textDecors = GetTextDecoration(textElement);
                }
            }

            TextAlignment alignment = stringFormat.Alignment;

            bool hasWordSpacing  = false;
            string wordSpaceText = element.GetAttribute("word-spacing");
            double wordSpacing = 0;
            if (!String.IsNullOrEmpty(wordSpaceText) &&
                Double.TryParse(wordSpaceText, out wordSpacing) && (float)wordSpacing != 0)
            {
                hasWordSpacing = true;
            }

            bool hasLetterSpacing = false;
            string letterSpaceText = element.GetAttribute("letter-spacing");
            double letterSpacing = 0;
            if (!String.IsNullOrEmpty(letterSpaceText) &&
                Double.TryParse(letterSpaceText, out letterSpacing) && (float)letterSpacing != 0)
            {
                hasLetterSpacing = true;
            }

            bool isRotatePosOnly = false;

            IList<WpfTextPosition> textPositions = null;
            int textPosCount = 0;
            if ((placement != null && placement.HasPositions))
            {
                textPositions   = placement.Positions;
                textPosCount    = textPositions.Count;
                isRotatePosOnly = placement.IsRotateOnly;
            }

            if (hasLetterSpacing || hasWordSpacing || textPositions != null)
            {
                double spacing = Convert.ToDouble(letterSpacing);
                for (int i = 0; i < text.Length; i++)
                {
                    FormattedText formattedText = new FormattedText(new string(text[i], 1),
                        _drawContext.CultureInfo, stringFormat.Direction,
                        new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
                        emSize, textBrush);

                    if (this.IsMeasuring)
                    {
                        this.AddTextWidth(formattedText.WidthIncludingTrailingWhitespace);
                        continue;
                    }

                    formattedText.Trimming      = stringFormat.Trimming;
                    formattedText.TextAlignment = stringFormat.Alignment;

                    if (textDecors != null && textDecors.Count != 0)
                    {
                        formattedText.SetTextDecorations(textDecors);
                    }

                    WpfTextPosition? textPosition = null;
                    if (textPositions != null && i < textPosCount)
                    {
                        textPosition = textPositions[i];
                    }

                    //float xCorrection = 0;
                    //if (alignment == TextAlignment.Left)
                    //    xCorrection = emSize * 1f / 6f;
                    //else if (alignment == TextAlignment.Right)
                    //    xCorrection = -emSize * 1f / 6f;

                    double yCorrection = formattedText.Baseline;

                    float rotateAngle = (float)rotate;
                    if (textPosition != null)
                    {
                        if (!isRotatePosOnly)
                        {
                            Point pt = textPosition.Value.Location;
                            ctp.X = pt.X;
                            ctp.Y = pt.Y;
                        }
                        rotateAngle = (float)textPosition.Value.Rotation;
                    }
                    Point textStart = ctp;

                    RotateTransform rotateAt = null;
                    if (rotateAngle != 0)
                    {
                        rotateAt = new RotateTransform(rotateAngle, textStart.X, textStart.Y);
                        _textContext.PushTransform(rotateAt);
                    }

                    Point textPoint = new Point(ctp.X, ctp.Y - yCorrection);

                    if (textPen != null || _drawContext.TextAsGeometry)
                    {
                        Geometry textGeometry = formattedText.BuildGeometry(textPoint);
                        if (textGeometry != null && !textGeometry.IsEmpty())
                        {
                            _textContext.DrawGeometry(textBrush, textPen,
                                ExtractTextPathGeometry(textGeometry));

                            this.IsTextPath = true;
                        }
                        else
                        {
                            _textContext.DrawText(formattedText, textPoint);
                        }
                    }
                    else
                    {
                        _textContext.DrawText(formattedText, textPoint);
                    }

                    //float bboxWidth = (float)formattedText.Width;
                    double bboxWidth = formattedText.WidthIncludingTrailingWhitespace;
                    if (alignment == TextAlignment.Center)
                        bboxWidth /= 2f;
                    else if (alignment == TextAlignment.Right)
                        bboxWidth = 0;

                    //ctp.X += bboxWidth + emSize / 4 + spacing;
                    if (hasLetterSpacing)
                    {
                        ctp.X += bboxWidth + letterSpacing;
                    }
                    if (hasWordSpacing && Char.IsWhiteSpace(text[i]))
                    {
                        if (hasLetterSpacing)
                        {
                            ctp.X += wordSpacing;
                        }
                        else
                        {
                            ctp.X += bboxWidth + wordSpacing;
                        }
                    }
                    else
                    {
                        if (!hasLetterSpacing)
                        {
                            ctp.X += bboxWidth;
                        }
                    }

                    if (rotateAt != null)
                    {
                        _textContext.Pop();
                    }
                }
            }
            else
            {
                FormattedText formattedText = new FormattedText(text, _drawContext.CultureInfo,
                    stringFormat.Direction, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
                    emSize, textBrush);

                if (this.IsMeasuring)
                {
                    this.AddTextWidth(formattedText.WidthIncludingTrailingWhitespace);
                    return;
                }

                if (alignment == TextAlignment.Center && this.TextWidth > 0)
                {
                    alignment = TextAlignment.Left;
                }

                formattedText.TextAlignment = alignment;
                formattedText.Trimming      = stringFormat.Trimming;

                if (textDecors != null && textDecors.Count != 0)
                {
                    formattedText.SetTextDecorations(textDecors);
                }

                //float xCorrection = 0;
                //if (alignment == TextAlignment.Left)
                //    xCorrection = emSize * 1f / 6f;
                //else if (alignment == TextAlignment.Right)
                //    xCorrection = -emSize * 1f / 6f;

                double yCorrection = formattedText.Baseline;

                float rotateAngle  = (float)rotate;
                Point textPoint    = new Point(ctp.X, ctp.Y - yCorrection);

                RotateTransform rotateAt = null;
                if (rotateAngle != 0)
                {
                    rotateAt = new RotateTransform(rotateAngle, ctp.X, ctp.Y);
                    _textContext.PushTransform(rotateAt);
                }

                if (textPen != null || _drawContext.TextAsGeometry)
                {
                    Geometry textGeometry = formattedText.BuildGeometry(textPoint);
                    if (textGeometry != null && !textGeometry.IsEmpty())
                    {
                        _textContext.DrawGeometry(textBrush, textPen,
                            ExtractTextPathGeometry(textGeometry));

                        this.IsTextPath = true;
                    }
                    else
                    {
                        _textContext.DrawText(formattedText, textPoint);
                    }
                }
                else
                {
                    _textContext.DrawText(formattedText, textPoint);
                }

                //float bboxWidth = (float)formattedText.Width;
                double bboxWidth = formattedText.WidthIncludingTrailingWhitespace;
                if (alignment == TextAlignment.Center)
                    bboxWidth /= 2f;
                else if (alignment == TextAlignment.Right)
                    bboxWidth = 0;

                //ctp.X += bboxWidth + emSize / 4;
                ctp.X += bboxWidth;

                if (rotateAt != null)
                {
                    _textContext.Pop();
                }
            }
        }
Example #4
0
        public override WpfFontFamilyInfo Visit(string fontName, WpfFontFamilyInfo familyInfo, 
            WpfDrawingContext context)
        {
            if (String.IsNullOrEmpty(fontName))
            {
                return null;
            }

            if (fontName.StartsWith("Arial", StringComparison.OrdinalIgnoreCase) &&
                fontName.Length > 5)
            {
                if (String.Equals(fontName, "ArialMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "Arial-BoldMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "Arial-ItalicMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        FontStyles.Italic, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "Arial-BoldItalicMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        FontStyles.Italic, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "Arial Unicode MS",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return null;
                }

                return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                    familyInfo.Style, familyInfo.Stretch);
            }
            else if (fontName.StartsWith("Helvetica", StringComparison.OrdinalIgnoreCase))
            {
                if (String.Equals(fontName, "Helvetica", StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "Helvetica-Bold",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "Helvetica-Oblique",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        FontStyles.Italic, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "Helvetica-BoldOblique",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        FontStyles.Italic, familyInfo.Stretch);
                }

                return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                    familyInfo.Style, familyInfo.Stretch);
            }
            else if (fontName.StartsWith("TimesNewRomanPS", StringComparison.OrdinalIgnoreCase))
            {
                if (String.Equals(fontName, "TimesNewRomanPSMT", StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "TimesNewRomanPS-BoldMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "TimesNewRomanPS-ItalicMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        FontStyles.Italic, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "TimesNewRomanPS-BoldItalicMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        FontStyles.Italic, familyInfo.Stretch);
                }

                return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                    familyInfo.Style, familyInfo.Stretch);
            }
            else if (fontName.StartsWith("CourierNewPS", StringComparison.OrdinalIgnoreCase))
            {
                if (String.Equals(fontName, "CourierNewPSMT", StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "CourierNewPS-BoldMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        familyInfo.Style, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "CourierNewPS-ItalicMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                        FontStyles.Italic, familyInfo.Stretch);
                }
                else if (String.Equals(fontName, "CourierNewPS-BoldItalicMT",
                    StringComparison.OrdinalIgnoreCase))
                {
                    return new WpfFontFamilyInfo(_arialFamily, FontWeights.Bold,
                        FontStyles.Italic, familyInfo.Stretch);
                }

                return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                    familyInfo.Style, familyInfo.Stretch);
            }
            else if (fontName.Equals("MS-Gothic", StringComparison.OrdinalIgnoreCase))
            {
                return new WpfFontFamilyInfo(new FontFamily("MS Gothic"), familyInfo.Weight,
                    familyInfo.Style, familyInfo.Stretch);
                //return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
                //    familyInfo.Style, familyInfo.Stretch);
            }
            else if (fontName.Equals("MS-PGothic", StringComparison.OrdinalIgnoreCase))
            {
                return new WpfFontFamilyInfo(new FontFamily("MS PGothic"), familyInfo.Weight,
                    familyInfo.Style, familyInfo.Stretch);
            }
            else if (fontName.Equals("MS Pゴシック", StringComparison.OrdinalIgnoreCase))
            {
                return new WpfFontFamilyInfo(new FontFamily("MS PGothic"), familyInfo.Weight,
                    familyInfo.Style, familyInfo.Stretch);
            }

            return null;
            //return new WpfFontFamilyInfo(_arialFamily, familyInfo.Weight,
            //    familyInfo.Style, familyInfo.Stretch);
        }
 public abstract WpfFontFamilyInfo Visit(string fontName, WpfFontFamilyInfo familyInfo,
                                         WpfDrawingContext context);
        private void RenderTextPath(SvgTextContentElement element, WpfTextOnPathDrawing pathDrawing,
            string text, Point origin, double rotate, WpfTextPlacement placement)
        {
            if (String.IsNullOrEmpty(text))
            {
                return;
            }

            double emSize         = GetComputedFontSize(element);
            FontFamily fontFamily = GetTextFontFamily(element, emSize);

            FontStyle fontStyle = GetTextFontStyle(element);
            FontWeight fontWeight = GetTextFontWeight(element);

            FontStretch fontStretch = GetTextFontStretch(element);

            WpfTextStringFormat stringFormat = GetTextStringFormat(element);

            // Fix the use of Postscript fonts...
            WpfFontFamilyVisitor fontFamilyVisitor = _drawContext.FontFamilyVisitor;
            if (!String.IsNullOrEmpty(_actualFontName) && fontFamilyVisitor != null)
            {
                WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight,
                    fontStyle, fontStretch);
                WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName,
                    currentFamily, _drawContext);
                if (familyInfo != null && !familyInfo.IsEmpty)
                {
                    fontFamily  = familyInfo.Family;
                    fontWeight  = familyInfo.Weight;
                    fontStyle   = familyInfo.Style;
                    fontStretch = familyInfo.Stretch;
                }
            }

            WpfSvgPaint fillPaint = new WpfSvgPaint(_drawContext, element, "fill");
            Brush textBrush = fillPaint.GetBrush();

            WpfSvgPaint strokePaint = new WpfSvgPaint(_drawContext, element, "stroke");
            Pen pen = strokePaint.GetPen();

            TextDecorationCollection textDecors = GetTextDecoration(element);
            TextAlignment alignment = stringFormat.Alignment;

            pathDrawing.FontSize = emSize;

            pathDrawing.FontFamily  = fontFamily;
            pathDrawing.FontWeight  = fontWeight;
            pathDrawing.FontStretch = fontStretch;

            pathDrawing.Foreground = textBrush;

            pathDrawing.AddTextPath(text, origin);
        }