コード例 #1
0
        protected WpfTextStringFormat GetTextStringFormat(SvgTextContentElement element)
        {
            WpfTextStringFormat sf = WpfTextStringFormat.Default;

            bool doAlign  = true;
            var  elemName = element.LocalName;

//            if (element is SvgTSpanElement || element is SvgTRefElement)
            if (string.Equals(elemName, "tspan", StringComparison.Ordinal) ||
                string.Equals(elemName, "tref", StringComparison.Ordinal))
            {
                var posElement = (SvgTextPositioningElement)element;
                if (posElement.X.AnimVal.NumberOfItems == 0)
                {
                    doAlign = false;
                }
            }

            var comparer = StringComparison.OrdinalIgnoreCase;

            string dir           = element.GetPropertyValue("direction");
            bool   isRightToLeft = string.Equals(dir, "rtl", comparer);

            sf.Direction = isRightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;

            if (doAlign)
            {
                string anchor = element.GetPropertyValue("text-anchor");

                if (isRightToLeft)
                {
                    if (string.Equals(anchor, "middle", comparer))
                    {
                        sf.Anchor = WpfTextAnchor.Middle;
                    }
                    else if (string.Equals(anchor, "end", comparer))
                    {
                        sf.Anchor = WpfTextAnchor.Start;
                    }
                    else
                    {
                        sf.Anchor = WpfTextAnchor.End;
                    }
                }
                else
                {
                    if (string.Equals(anchor, "middle", comparer))
                    {
                        sf.Anchor = WpfTextAnchor.Middle;
                    }
                    else if (string.Equals(anchor, "end", comparer))
                    {
                        sf.Anchor = WpfTextAnchor.End;
                    }
                }
            }
            else
            {
                SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement;
                if (textElement != null)
                {
                    string anchor = textElement.GetPropertyValue("text-anchor");
                    if (isRightToLeft)
                    {
                        if (string.Equals(anchor, "middle", comparer))
                        {
                            sf.Anchor = WpfTextAnchor.Middle;
                        }
                        else if (string.Equals(anchor, "end", comparer))
                        {
                            sf.Anchor = WpfTextAnchor.Start;
                        }
                        else
                        {
                            sf.Anchor = WpfTextAnchor.End;
                        }
                    }
                    else
                    {
                        if (string.Equals(anchor, "middle", comparer))
                        {
                            sf.Anchor = WpfTextAnchor.Middle;
                        }
                        else if (string.Equals(anchor, "end", comparer))
                        {
                            sf.Anchor = WpfTextAnchor.End;
                        }
                    }
                }
            }

            //if (isRightToLeft)
            //{
            //    if (sf.Alignment == TextAlignment.Right)
            //        sf.Alignment = TextAlignment.Left;
            //    else if (sf.Alignment == TextAlignment.Left)
            //        sf.Alignment = TextAlignment.Right;

            //    //sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
            //}

            //dir = element.GetPropertyValue("writing-mode");
            //if (dir == "tb")
            //{
            //    sf.FormatFlags = sf.FormatFlags | StringFormatFlags.DirectionVertical;
            //}

            //sf.FormatFlags = sf.FormatFlags | StringFormatFlags.MeasureTrailingSpaces;

            return(sf);
        }
コード例 #2
0
 public abstract void RenderTextRun(SvgTextContentElement element,
                                    ref Point ctp, string text, double rotate, WpfTextPlacement placement);
コード例 #3
0
        public override void RenderText(SvgTextContentElement element,
                                        ref Point ctp, string text, double rotate, WpfTextPlacement placement)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return;
            }

            int    vertOrientation = -1;
            int    horzOrientation = -1;
            string orientationText = element.GetPropertyValue("glyph-orientation-vertical");

            if (!string.IsNullOrWhiteSpace(orientationText))
            {
                double orientationValue = 0;
                if (double.TryParse(orientationText, out orientationValue))
                {
                    vertOrientation = (int)orientationValue;
                }
            }
            orientationText = element.GetPropertyValue("glyph-orientation-horizontal");
            if (!string.IsNullOrWhiteSpace(orientationText))
            {
                double orientationValue = 0;
                if (double.TryParse(orientationText, out orientationValue))
                {
                    horzOrientation = (int)orientationValue;
                }
            }

            Point startPoint = ctp;
            IList <WpfTextRun> textRunList = WpfTextRun.BreakWords(text,
                                                                   vertOrientation, horzOrientation);

            for (int tr = 0; tr < textRunList.Count; tr++)
            {
                // For unknown reasons, FormattedText will split a text like "-70%" into two parts "-"
                // and "70%". We provide a shift to account for the split...
                double baselineShiftX = 0;
                double baselineShiftY = 0;

                WpfTextRun textRun = textRunList[tr];

                DrawingGroup verticalGroup = new DrawingGroup();

                DrawingContext verticalContext = verticalGroup.Open();
                DrawingContext currentContext  = _drawContext;

                _drawContext = verticalContext;

                this.DrawSingleLineText(element, ref ctp, textRun, rotate, placement);

                verticalContext.Close();

                _drawContext = currentContext;

                if (verticalGroup.Children.Count == 1)
                {
                    DrawingGroup textGroup = verticalGroup.Children[0] as DrawingGroup;
                    if (textGroup != null)
                    {
                        verticalGroup = textGroup;
                    }
                }

                string runText   = textRun.Text;
                int    charCount = runText.Length;

                double            totalHeight = 0;
                DrawingCollection drawings    = verticalGroup.Children;
                int itemCount = drawings != null ? drawings.Count : 0;
                for (int i = 0; i < itemCount; i++)
                {
                    Drawing      textDrawing = drawings[i];
                    DrawingGroup textGroup   = textDrawing as DrawingGroup;

                    if (vertOrientation == -1)
                    {
                        if (textGroup != null)
                        {
                            for (int j = 0; j < textGroup.Children.Count; j++)
                            {
                                GlyphRunDrawing glyphDrawing = textGroup.Children[j] as GlyphRunDrawing;
                                if (glyphDrawing != null)
                                {
                                    if (textRun.IsLatin)
                                    {
                                        GlyphRun glyphRun = glyphDrawing.GlyphRun;

                                        IList <ushort> glyphIndices = glyphRun.GlyphIndices;
                                        IDictionary <ushort, double> allGlyphWeights = glyphRun.GlyphTypeface.AdvanceWidths;
                                        double lastAdvanceWeight =
                                            allGlyphWeights[glyphIndices[glyphIndices.Count - 1]] * glyphRun.FontRenderingEmSize;

                                        totalHeight += glyphRun.ComputeAlignmentBox().Width + lastAdvanceWeight / 2d;
                                    }
                                    else
                                    {
                                        totalHeight += ChangeGlyphOrientation(glyphDrawing,
                                                                              baselineShiftX, baselineShiftY, false);
                                    }
                                }
                            }
                        }
                        else
                        {
                            GlyphRunDrawing glyphDrawing = textDrawing as GlyphRunDrawing;
                            if (glyphDrawing != null)
                            {
                                if (textRun.IsLatin)
                                {
                                    GlyphRun glyphRun = glyphDrawing.GlyphRun;

                                    IList <UInt16> glyphIndices = glyphRun.GlyphIndices;
                                    IDictionary <ushort, double> allGlyphWeights = glyphRun.GlyphTypeface.AdvanceWidths;
                                    double lastAdvanceWeight =
                                        allGlyphWeights[glyphIndices[glyphIndices.Count - 1]] * glyphRun.FontRenderingEmSize;

                                    totalHeight += glyphRun.ComputeAlignmentBox().Width + lastAdvanceWeight / 2d;
                                }
                                else
                                {
                                    totalHeight += ChangeGlyphOrientation(glyphDrawing,
                                                                          baselineShiftX, baselineShiftY, false);
                                }
                            }
                        }
                    }
                    else if (vertOrientation == 0)
                    {
                        if (textGroup != null)
                        {
                            for (int j = 0; j < textGroup.Children.Count; j++)
                            {
                                GlyphRunDrawing glyphDrawing = textGroup.Children[j] as GlyphRunDrawing;
                                if (glyphDrawing != null)
                                {
                                    baselineShiftX = ChangeGlyphOrientation(glyphDrawing,
                                                                            baselineShiftX, baselineShiftY, textRun.IsLatin);
                                    totalHeight += baselineShiftX;
                                }
                            }
                        }
                        else
                        {
                            GlyphRunDrawing glyphDrawing = textDrawing as GlyphRunDrawing;
                            if (textDrawing != null)
                            {
                                totalHeight += ChangeGlyphOrientation(glyphDrawing,
                                                                      baselineShiftX, baselineShiftY, textRun.IsLatin);
                            }
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }

                if (!this.IsMeasuring)
                {
                    _drawContext.DrawDrawing(verticalGroup);
                }

                if (tr < textRunList.Count)
                {
                    ctp.X         = startPoint.X;
                    ctp.Y         = startPoint.Y + totalHeight;
                    startPoint.Y += totalHeight;
                }
            }
        }
コード例 #4
0
        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);
            var    fontFamilyInfo = GetTextFontFamilyInfo(element);

            FontFamily  fontFamily  = fontFamilyInfo.Family;
            FontStyle   fontStyle   = fontFamilyInfo.Style;
            FontWeight  fontWeight  = fontFamilyInfo.Weight;
            FontStretch fontStretch = fontFamilyInfo.Stretch;

            WpfTextStringFormat stringFormat = GetTextStringFormat(element);

            // Fix the use of Postscript fonts...
            WpfFontFamilyVisitor fontFamilyVisitor = _context.FontFamilyVisitor;

            if (!string.IsNullOrWhiteSpace(_actualFontName) && fontFamilyVisitor != null)
            {
                //WpfFontFamilyInfo currentFamily = new WpfFontFamilyInfo(fontFamily, fontWeight,
                //    fontStyle, fontStretch);
                WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName,
                                                                       fontFamilyInfo, _context);
                if (familyInfo != null && !familyInfo.IsEmpty)
                {
                    fontFamily  = familyInfo.Family;
                    fontWeight  = familyInfo.Weight;
                    fontStyle   = familyInfo.Style;
                    fontStretch = familyInfo.Stretch;
                }
            }

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

            WpfSvgPaint strokePaint = new WpfSvgPaint(_context, 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.IsNullOrWhiteSpace(letterSpacing))
            {
                FormattedText formattedText = new FormattedText(text,
                                                                textRun.IsLatin ? _context.EnglishCultureInfo : _context.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);
                _drawContext.PushTransform(rotateAt);

                _drawContext.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)
                {
                    _drawContext.Pop();
                }
            }
            else
            {
                RotateTransform rotateAt = new RotateTransform(90, ctp.X, ctp.Y);
                _drawContext.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 ? _context.EnglishCultureInfo : _context.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);

                    _drawContext.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)
                {
                    _drawContext.Pop();
                }
            }
        }
コード例 #5
0
 private string GetText(SvgTextContentElement element, XmlNode child)
 {
     return(TrimText(element, child.Value));
 }
コード例 #6
0
        private void AddGraphicsPath(SvgTextContentElement element, ref PointF ctp, string text)
        {
            if (text.Length == 0)
            {
                return;
            }

            float        emSize = GetComputedFontSize(element);
            FontFamily   family = GetGDIFontFamily(element, emSize);
            int          style  = GetGDIFontStyle(element);
            StringFormat sf     = GetGDIStringFormat(element);

            GraphicsPath textGeometry = new GraphicsPath();

            float xCorrection = 0;

            if (sf.Alignment == StringAlignment.Near)
            {
                xCorrection = emSize * 1 / 6;
            }
            else if (sf.Alignment == StringAlignment.Far)
            {
                xCorrection = -emSize * 1 / 6;
            }

            float yCorrection = (float)(family.GetCellAscent(FontStyle.Regular)) / (float)(family.GetEmHeight(FontStyle.Regular)) * emSize;

            // TODO: font property
            PointF p = new PointF(ctp.X - xCorrection, ctp.Y - yCorrection);

            textGeometry.AddString(text, family, style, emSize, p, sf);
            if (!textGeometry.GetBounds().IsEmpty)
            {
                float bboxWidth = textGeometry.GetBounds().Width;
                if (sf.Alignment == StringAlignment.Center)
                {
                    bboxWidth /= 2;
                }
                else if (sf.Alignment == StringAlignment.Far)
                {
                    bboxWidth = 0;
                }

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

            GdiSvgPaint fillPaint = new GdiSvgPaint(element, "fill");
            Brush       brush     = fillPaint.GetBrush(textGeometry);

            GdiSvgPaint strokePaint = new GdiSvgPaint(element, "stroke");
            Pen         pen         = strokePaint.GetPen(textGeometry);

            if (brush != null)
            {
                if (brush is PathGradientBrush)
                {
                    GdiGradientFill gps = fillPaint.PaintFill as GdiGradientFill;

                    _graphics.SetClip(gps.GetRadialGradientRegion(textGeometry.GetBounds()), CombineMode.Exclude);

                    SolidBrush tempBrush = new SolidBrush(((PathGradientBrush)brush).InterpolationColors.Colors[0]);
                    _graphics.FillPath(this, tempBrush, textGeometry);
                    tempBrush.Dispose();
                    _graphics.ResetClip();
                }

                _graphics.FillPath(this, brush, textGeometry);
                brush.Dispose();
            }

            if (pen != null)
            {
                if (pen.Brush is PathGradientBrush)
                {
                    GdiGradientFill      gps       = strokePaint.PaintFill as GdiGradientFill;
                    GdiGraphicsContainer container = _graphics.BeginContainer();

                    _graphics.SetClip(gps.GetRadialGradientRegion(textGeometry.GetBounds()), CombineMode.Exclude);

                    SolidBrush tempBrush = new SolidBrush(((PathGradientBrush)pen.Brush).InterpolationColors.Colors[0]);
                    Pen        tempPen   = new Pen(tempBrush, pen.Width);
                    _graphics.DrawPath(this, tempPen, textGeometry);
                    tempPen.Dispose();
                    tempBrush.Dispose();

                    _graphics.EndContainer(container);
                }

                _graphics.DrawPath(this, pen, textGeometry);
                pen.Dispose();
            }

            textGeometry.Dispose();
        }
コード例 #7
0
        private void RenderTextRun(WpfTextTuple textInfo, ref Point ctp,
                                   string text, double rotate, WpfTextPlacement placement)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return;
            }

            WpfFontFamilyInfo     familyInfo   = textInfo.Item1;
            double                emSize       = textInfo.Item2;
            WpfTextStringFormat   stringFormat = textInfo.Item3;
            SvgTextContentElement element      = textInfo.Item4;

            FontFamily  fontFamily  = familyInfo.Family;
            FontWeight  fontWeight  = familyInfo.Weight;
            FontStyle   fontStyle   = familyInfo.Style;
            FontStretch fontStretch = familyInfo.Stretch;

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

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

            if (textBrush == null && textPen == null)
            {
                return;
            }
            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;
            }
            if (textPen != null)
            {
                textPen.LineJoin   = PenLineJoin.Miter; // Better for text rendering
                textPen.MiterLimit = 1;
            }

            TextDecorationCollection textDecors = GetTextDecoration(element);

            if (textDecors == null)
            {
                SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement;

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

            TextAlignment alignment = stringFormat.Alignment;

            bool   hasWordSpacing = false;
            string wordSpaceText  = element.GetAttribute("word-spacing");
            double wordSpacing    = 0;

            if (!string.IsNullOrWhiteSpace(wordSpaceText) &&
                double.TryParse(wordSpaceText, out wordSpacing) && !wordSpacing.Equals(0))
            {
                hasWordSpacing = true;
            }

            bool   hasLetterSpacing = false;
            string letterSpaceText  = element.GetAttribute("letter-spacing");
            double letterSpacing    = 0;

            if (!string.IsNullOrWhiteSpace(letterSpaceText) &&
                double.TryParse(letterSpaceText, out letterSpacing) && !letterSpacing.Equals(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;
            }

            WpfTextBuilder textBuilder = WpfTextBuilder.Create(familyInfo, this.TextCulture, emSize);

            this.IsTextPath = true;

            if (textPositions != null && textPositions.Count != 0)
            {
                if (textPositions.Count == text.Trim().Length) //TODO: Best way to handle this...
                {
                    text = text.Trim();
                }
            }

            if (hasLetterSpacing || hasWordSpacing || textPositions != null)
            {
                double spacing = Convert.ToDouble(letterSpacing);

                int startSpaces = 0;
                for (int i = 0; i < text.Length; i++)
                {
                    if (char.IsWhiteSpace(text[i]))
                    {
                        startSpaces++;
                    }
                    else
                    {
                        break;
                    }
                }

                int j = 0;

                string inputText = string.Empty;
                for (int i = 0; i < text.Length; i++)
                {
                    // Avoid rendering only spaces at the start of text run...
                    if (i == 0 && startSpaces != 0)
                    {
                        inputText = text.Substring(0, startSpaces + 1);
                        i        += startSpaces;
                    }
                    else
                    {
                        inputText = new string(text[i], 1);
                    }

                    if (this.IsMeasuring)
                    {
                        var textSize = textBuilder.MeasureText(element, inputText);
                        this.AddTextWidth(ctp, textSize.Width);
                        continue;
                    }

                    textBuilder.Trimming      = stringFormat.Trimming;
                    textBuilder.TextAlignment = stringFormat.Alignment;

                    if (textDecors != null && textDecors.Count != 0)
                    {
                        textBuilder.TextDecorations = textDecors;
                    }

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

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

                    double yCorrection = textBuilder.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.Equals(0))
                    {
                        rotateAt = new RotateTransform(rotateAngle, textStart.X, textStart.Y);
                        _drawContext.PushTransform(rotateAt);
                    }

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

                    Geometry textGeometry = textBuilder.Build(element, inputText, textPoint.X, textPoint.Y);
                    if (textGeometry != null && !textGeometry.IsEmpty())
                    {
//                        _drawContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry));
                        _drawContext.DrawGeometry(textBrush, textPen, textGeometry);
                    }

                    //float bboxWidth = (float)formattedText.Width;
                    double bboxWidth = textGeometry.Bounds.Width;
                    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)
                    {
                        _drawContext.Pop();
                    }
                    j++;
                }
            }
            else
            {
                if (this.IsMeasuring)
                {
                    var textSize = textBuilder.MeasureText(element, text);
                    this.AddTextWidth(ctp, textSize.Width);
                    return;
                }

                var textContext = this.TextContext;
                if (textContext != null && textContext.IsPositionChanged(element) == false)
                {
                    if (alignment == TextAlignment.Center && this.TextWidth > 0)
                    {
                        alignment = TextAlignment.Left;
                    }
                }

                textBuilder.TextAlignment = alignment;
                textBuilder.Trimming      = stringFormat.Trimming;

                if (textDecors != null && textDecors.Count != 0)
                {
                    textBuilder.TextDecorations = textDecors;
                }

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

                double yCorrection = textBuilder.Baseline;

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

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

                Geometry textGeometry = textBuilder.Build(element, text, textPoint.X, textPoint.Y);
                if (textGeometry != null && !textGeometry.IsEmpty())
                {
//                    _drawContext.DrawGeometry(textBrush, textPen, ExtractTextPathGeometry(textGeometry));
                    _drawContext.DrawGeometry(textBrush, textPen, textGeometry);
                }

                //float bboxWidth = (float)formattedText.Width;
                //                double bboxWidth = textGeometry.Bounds.Width;
                double bboxWidth = textBuilder.Width;

                if (alignment == TextAlignment.Center)
                {
                    bboxWidth /= 2f;
                }
                else if (alignment == TextAlignment.Right)
                {
                    bboxWidth = 0;
                }

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

                if (rotateAt != null)
                {
                    _drawContext.Pop();
                }
            }
        }
コード例 #8
0
        public override void RenderTextRun(SvgTextContentElement element, ref Point ctp,
                                           string text, double rotate, WpfTextPlacement placement)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return;
            }

            double emSize         = GetComputedFontSize(element);
            var    fontFamilyInfo = GetTextFontFamilyInfo(element);

            WpfTextStringFormat stringFormat = GetTextStringFormat(element);

            if (fontFamilyInfo.FontFamilyType == WpfFontFamilyType.Svg)
            {
                WpfTextTuple textInfo = new WpfTextTuple(fontFamilyInfo, emSize, stringFormat, element);
                this.RenderTextRun(textInfo, ref ctp, text, rotate, placement);
                return;
            }

            FontFamily  fontFamily  = fontFamilyInfo.Family;
            FontStyle   fontStyle   = fontFamilyInfo.Style;
            FontWeight  fontWeight  = fontFamilyInfo.Weight;
            FontStretch fontStretch = fontFamilyInfo.Stretch;

            // Fix the use of Postscript fonts...
            WpfFontFamilyVisitor fontFamilyVisitor = _context.FontFamilyVisitor;

            if (!string.IsNullOrWhiteSpace(_actualFontName) && fontFamilyVisitor != null)
            {
                WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName,
                                                                       fontFamilyInfo, _context);
                if (familyInfo != null && !familyInfo.IsEmpty)
                {
                    fontFamily  = familyInfo.Family;
                    fontWeight  = familyInfo.Weight;
                    fontStyle   = familyInfo.Style;
                    fontStretch = familyInfo.Stretch;
                }
            }

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

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

            if (textBrush == null && textPen == null)
            {
                return;
            }
            bool isForcedPathMode = false;

            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;
            }
            else
            {
                // WPF gradient fill does not work well on text, use geometry to render it
                isForcedPathMode = (fillPaint.FillType == WpfFillType.Gradient);
            }
            if (textPen != null)
            {
                textPen.LineJoin = PenLineJoin.Round; // Better for text rendering
                isForcedPathMode = true;
            }

            TextDecorationCollection textDecors = GetTextDecoration(element);

            if (textDecors == null)
            {
                SvgTextBaseElement textElement = element.ParentNode as SvgTextBaseElement;

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

            TextAlignment alignment = stringFormat.Alignment;

            bool   hasWordSpacing = false;
            string wordSpaceText  = element.GetAttribute("word-spacing");
            double wordSpacing    = 0;

            if (!string.IsNullOrWhiteSpace(wordSpaceText) &&
                double.TryParse(wordSpaceText, out wordSpacing) && !wordSpacing.Equals(0))
            {
                hasWordSpacing = true;
            }

            bool   hasLetterSpacing = false;
            string letterSpaceText  = element.GetAttribute("letter-spacing");
            double letterSpacing    = 0;

            if (!string.IsNullOrWhiteSpace(letterSpaceText) &&
                double.TryParse(letterSpaceText, out letterSpacing) && !letterSpacing.Equals(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;
            }

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

            if (textPositions != null && textPositions.Count != 0)
            {
                if (textPositions.Count == text.Trim().Length) //TODO: Best way to handle this...
                {
                    text = text.Trim();
                }
            }

            if (hasLetterSpacing || hasWordSpacing || textPositions != null)
            {
                double spacing = Convert.ToDouble(letterSpacing);

                int startSpaces = 0;
                for (int i = 0; i < text.Length; i++)
                {
                    if (char.IsWhiteSpace(text[i]))
                    {
                        startSpaces++;
                    }
                    else
                    {
                        break;
                    }
                }

                int j = 0;

                string inputText = string.Empty;
                for (int i = 0; i < text.Length; i++)
                {
                    // Avoid rendering only spaces at the start of text run...
                    if (i == 0 && startSpaces != 0)
                    {
                        inputText = text.Substring(0, startSpaces + 1);
                        i        += startSpaces;
                    }
                    else
                    {
                        inputText = new string(text[i], 1);
                    }

                    FormattedText formattedText = new FormattedText(inputText, _context.CultureInfo,
                                                                    stringFormat.Direction, typeFace, emSize, textBrush);
//#if NET40
//                    FormattedText formattedText = new FormattedText(inputText,  _context.CultureInfo,
//                        stringFormat.Direction, typeFace, emSize, textBrush);
//#else
//                    FormattedText formattedText = new FormattedText(inputText, _context.CultureInfo,
//                        stringFormat.Direction, typeFace, emSize, textBrush, _context.PixelsPerDip);
//#endif

                    if (this.IsMeasuring)
                    {
                        this.AddTextWidth(ctp, 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 && j < textPosCount)
                    {
                        textPosition = textPositions[j];
                    }

                    //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.Equals(0))
                    {
                        rotateAt = new RotateTransform(rotateAngle, textStart.X, textStart.Y);
                        _drawContext.PushTransform(rotateAt);
                    }

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

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

                            this.IsTextPath = true;
                        }
                        else
                        {
                            _drawContext.DrawText(formattedText, textPoint);
                        }
                    }
                    else
                    {
                        _drawContext.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)
                    {
                        _drawContext.Pop();
                    }
                    j++;
                }
            }
            else
            {
                FormattedText formattedText = new FormattedText(text, _context.CultureInfo,
                                                                stringFormat.Direction, typeFace, emSize, textBrush);
//#if !NET40
//                FormattedText formattedText = new FormattedText(text, _context.CultureInfo,
//                    stringFormat.Direction, typeFace, emSize, textBrush, _context.PixelsPerDip);
//#else
//                FormattedText formattedText = new FormattedText(text, _context.CultureInfo,
//                    stringFormat.Direction, typeFace,  emSize, textBrush);
//#endif

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

                var textContext = this.TextContext;
                if (textContext != null && textContext.IsPositionChanged(element) == false)
                {
                    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.Equals(0))
                {
                    rotateAt = new RotateTransform(rotateAngle, ctp.X, ctp.Y);
                    _drawContext.PushTransform(rotateAt);
                }

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

                        this.IsTextPath = true;
                    }
                    else
                    {
                        _drawContext.DrawText(formattedText, textPoint);
                    }
                }
                else
                {
                    _drawContext.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)
                {
                    _drawContext.Pop();
                }
            }
        }
コード例 #9
0
        public override void RenderText(SvgTextContentElement element, ref Point ctp,
                                        string text, double rotate, WpfTextPlacement placement)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return;
            }

            double emSize         = GetComputedFontSize(element);
            var    fontFamilyInfo = GetTextFontFamilyInfo(element);

            WpfTextStringFormat stringFormat = GetTextStringFormat(element);

            if (fontFamilyInfo.FontFamilyType == WpfFontFamilyType.Svg ||
                fontFamilyInfo.FontFamilyType == WpfFontFamilyType.Private)
            {
                WpfTextTuple textInfo = new WpfTextTuple(fontFamilyInfo, emSize, stringFormat, element);
                this.RenderText(textInfo, ref ctp, text, rotate, placement);
                return;
            }

            FontFamily  fontFamily  = fontFamilyInfo.Family;
            FontStyle   fontStyle   = fontFamilyInfo.Style;
            FontWeight  fontWeight  = fontFamilyInfo.Weight;
            FontStretch fontStretch = fontFamilyInfo.Stretch;

            // Fix the use of Postscript fonts...
            WpfFontFamilyVisitor fontFamilyVisitor = _context.FontFamilyVisitor;

            if (!string.IsNullOrWhiteSpace(_actualFontName) && fontFamilyVisitor != null)
            {
                WpfFontFamilyInfo familyInfo = fontFamilyVisitor.Visit(_actualFontName,
                                                                       fontFamilyInfo, _context);
                if (familyInfo != null && !familyInfo.IsEmpty)
                {
                    fontFamily  = familyInfo.Family;
                    fontWeight  = familyInfo.Weight;
                    fontStyle   = familyInfo.Style;
                    fontStretch = familyInfo.Stretch;
                }
            }

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

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

            if (textBrush == null && textPen == null)
            {
                return;
            }
            bool isForcedPathMode = false;

            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;
            }
            else
            {
                // WPF gradient fill does not work well on text, use geometry to render it
                isForcedPathMode = (fillPaint.FillType == WpfFillType.Gradient);
            }
            if (textPen != null)
            {
                textPen.LineJoin = PenLineJoin.Round; // Better for text rendering
                isForcedPathMode = true;
            }

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

            bool   hasWordSpacing = false;
            string wordSpaceText  = element.GetAttribute("word-spacing");
            double wordSpacing    = 0;

            if (!string.IsNullOrWhiteSpace(wordSpaceText) &&
                double.TryParse(wordSpaceText, out wordSpacing) && !wordSpacing.Equals(0))
            {
                hasWordSpacing = true;
            }

            bool   hasLetterSpacing = false;
            string letterSpaceText  = element.GetAttribute("letter-spacing");
            double letterSpacing    = 0;

            if (!string.IsNullOrWhiteSpace(letterSpaceText) &&
                double.TryParse(letterSpaceText, out letterSpacing) && !letterSpacing.Equals(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;
            }

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

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

            if (hasLetterSpacing || hasWordSpacing || textPositions != null)
            {
                for (int i = 0; i < text.Length; i++)
                {
                    var nextText = new string(text[i], 1);

                    FormattedText formattedText = new FormattedText(nextText,
                                                                    _context.CultureInfo, stringFormat.Direction, typeFace, emSize, textBrush);
//#if NET40
//                    FormattedText formattedText = new FormattedText(nextText,
//                        _context.CultureInfo, stringFormat.Direction, typeFace, emSize, textBrush);
//#else
//                    FormattedText formattedText = new FormattedText(nextText, _context.CultureInfo,
//                        stringFormat.Direction, typeFace, emSize, textBrush, _context.PixelsPerDip);
//#endif
                    //                    formattedText.FlowDirection = isRightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
                    formattedText.TextAlignment = stringFormat.Alignment;
                    formattedText.Trimming      = stringFormat.Trimming;

                    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.Equals(0))
                    {
                        rotateAt = new RotateTransform(rotateAngle, textStart.X, textStart.Y);
                        _drawContext.PushTransform(rotateAt);
                    }

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

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

                            this.IsTextPath = true;
                        }
                        else
                        {
                            _drawContext.DrawText(formattedText, textPoint);
                        }
                    }
                    else
                    {
                        _drawContext.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)
                    {
                        _drawContext.Pop();
                    }
                }
            }
            else
            {
                FormattedText formattedText = new FormattedText(text, _context.CultureInfo,
                                                                stringFormat.Direction, typeFace, emSize, textBrush);
//#if NET40
//                FormattedText formattedText = new FormattedText(text, _context.CultureInfo,
//                    stringFormat.Direction, typeFace, emSize, textBrush);
//#else
//                FormattedText formattedText = new FormattedText(text, _context.CultureInfo,
//                    stringFormat.Direction, typeFace, emSize, textBrush, _context.PixelsPerDip);
//#endif

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

//                formattedText.FlowDirection = isRightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;

                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.Equals(0))
                {
                    rotateAt = new RotateTransform(rotateAngle, ctp.X, ctp.Y);
                    _drawContext.PushTransform(rotateAt);
                }

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

                        this.IsTextPath = true;
                    }
                    else
                    {
                        _drawContext.DrawText(formattedText, textPoint);
                    }
                }
                else
                {
                    _drawContext.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)
                {
                    _drawContext.Pop();
                }
            }
        }
コード例 #10
0
        public override void RenderTextRun(SvgTextContentElement element, ref Point ctp,
                                           string text, double rotate, WpfTextPlacement placement)
        {
            if (string.IsNullOrWhiteSpace(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.IsNullOrWhiteSpace(_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.IsNullOrWhiteSpace(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.IsNullOrWhiteSpace(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();
                }
            }
        }
コード例 #11
0
 public override void RenderSingleLineText(SvgTextContentElement element,
                                           ref Point ctp, string text, double rotate, WpfTextPlacement placement)
 {
     this.RenderTextPath((SvgTextPathElement)element, ref ctp, rotate, placement);
 }