/// <summary>
    /// Parses a Path element.
    /// </summary>
    Path ParsePath()
    {
      Debug.Assert(this.reader.Name == "Path");
      bool isEmptyElement = this.reader.IsEmptyElement;
      Path path = new Path();
      while (MoveToNextAttribute())
      {
        switch (this.reader.Name)
        {
          case "Data":
            path.Data = ParsePathGeometry(this.reader.Value);
            break;

          case "Fill":
            path.Fill = ParseBrush(this.reader.Value); 
            break;

          case "RenderTransform":
            path.RenderTransform = ParseMatrixTransform(this.reader.Value);
            break;

          case "Clip":
            path.Clip = ParsePathGeometry(this.reader.Value);
            break;

          case "Opacity":
            path.Opacity = ParseDouble(this.reader.Value);
            break;

          case "OpacityMask":
            path.OpacityMask = ParseBrush(this.reader.Value);
            break;

          case "Stroke":
            path.Stroke = ParseBrush(this.reader.Value);
            break;

          case "StrokeDashArray":
            path.StrokeDashArray = reader.Value;
            break;

          case "StrokeDashCap":
            path.StrokeDashCap = reader.Value;
            break;

          case "StrokeDashOffset":
            path.StrokeDashOffset = ParseDouble(reader.Value);
            break;

          case "StrokeEndLineCap":
            path.StrokeEndLineCap = ParseEnum<LineCap>(this.reader.Value);
            break;

          case "StrokeStartLineCap":
            path.StrokeStartLineCap = ParseEnum<LineCap>(this.reader.Value);
            break;

          case "StrokeLineJoin":
            path.StrokeLineJoin = ParseEnum<LineJoin>(this.reader.Value);
            break;

          case "StrokeMiterLimit":
            path.StrokeMiterLimit = ParseDouble(this.reader.Value);
            break;

          case "StrokeThickness":
            path.StrokeThickness = ParseDouble(this.reader.Value);
            break;

          case "Name":
            path.Name = this.reader.Value;
            break;

          case "FixedPage_NavigateUri":
          case "FixedPage.NavigateUri":
            path.FixedPage_NavigateUri = reader.Value;
            break;

          case "AutomationProperties_Name":
            path.AutomationProperties_Name = this.reader.Value;
            break;

          case "AutomationProperties.HelpText":
            path.AutomationProperties_HelpText = this.reader.Value;
            break;

          case "SnapsToDevicePixels":
            path.SnapsToDevicePixels = ParseBool(this.reader.Value);
            break;

          case "xml:lang":
            path.lang = this.reader.Value;
            break;

          case "x:Key":
            path.Key = this.reader.Value;
            break;

          case "xml:id":
            break;

          case "xml:space":
            break;

          default:
            UnexpectedAttribute(this.reader.Name);
            break;
        }
      }
      if (!isEmptyElement)
      {
        MoveToNextElement();
        while (this.reader.IsStartElement())
        {
          switch (this.reader.Name)
          {
            case "Path.RenderTransform":
              MoveToNextElement();
              path.RenderTransform = ParseMatrixTransform();
              break;

            case "Path.Clip":
              MoveToNextElement();
              path.Clip = ParsePathGeometry();
              MoveToNextElement();
              break;

            case "Path.OpacityMask":
              MoveToNextElement();
              path.OpacityMask = ParseBrush();
              path.OpacityMask.Parent = path;
              MoveToNextElement();
              break;

            case "Path.Fill":
              MoveToNextElement();
              path.Fill = ParseBrush();
              path.Fill.Parent = path;
              MoveToNextElement();
              break;

            case "Path.Stroke":
              MoveToNextElement();
              path.Fill = ParseBrush();
              path.Fill.Parent = path;
              MoveToNextElement();
              break;

            case "Path.Data":
              MoveToNextElement();
              path.Data = ParsePathGeometry();
              MoveToNextElement();
              break;

            default:
              Debugger.Break();
              break;
          }
        }
      }
      MoveToNextElement();
      return path;
    }
    /// <summary>
    /// Strokes the path geometry with the Stroke brush.
    /// </summary>
    private void WriteStrokeGeometry(Path path)
    {
      if (path.Stroke == null)
        return;

      SolidColorBrush sBrush;
      LinearGradientBrush lgBrush;
      RadialGradientBrush rgBrush;
      VisualBrush vBrush;
      ImageBrush iBrush;

      //if (path.Stroke != null && this.renderMode == RenderMode.Default) // HACK

      if ((sBrush = path.Stroke as SolidColorBrush) != null)
      {
        RealizeStroke(path);
        WriteGeometry(path.Data);
        WriteLiteral("S\n");
      }
      else if ((lgBrush = path.Stroke as LinearGradientBrush) != null)
      {
        PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
        xgState.SetDefault1();

        double opacity = Opacity * lgBrush.Opacity; ;
        if (opacity < 1)
        {
          xgState.StrokeAlpha = opacity;
          xgState.NonStrokeAlpha = opacity;
        }
        RealizeExtGState(xgState);

        // /CS1 CS /P0 SCN
        // 7.5 w 
        // q 1 0 0 1 15.5 462.9 cm
        // 0 0 m
        // 153 0 l
        // 153 -93 l
        // 0 -93 l
        // h
        // S
        // Q
        if (lgBrush.GradientStops.HasTransparency)
        {
          // TODO: Create Form
          PdfShadingPattern pattern = LinearShadingBuilder.BuildPatternFromLinearGradientBrush(Context, lgBrush, Transform);
          string paName = Resources.AddPattern(pattern);
          WriteLiteral("/Pattern CS " + paName + " SCN\n");
          WriteLiteral("q {0:0.###} w", path.StrokeThickness);
          WriteGeometry(path.Data);
          WriteLiteral("S Q\n");

          //// Create a FormXObject with a soft mask
          //PdfFormXObject form = LinearShadingBuilder.BuildFormFromLinearGradientBrush(Context, lgBrush, path.Data);
          //string foName = Resources.AddForm(form);
          //WriteLiteral(foName + " Do\n");
        }
        else
        {
          PdfShadingPattern pattern = LinearShadingBuilder.BuildPatternFromLinearGradientBrush(Context, lgBrush, Transform);
          string paName = Resources.AddPattern(pattern);
          WriteLiteral("/Pattern CS " + paName + " SCN\n");
          WriteLiteral("q {0:0.###} w", path.StrokeThickness);
          WriteGeometry(path.Data);
          WriteLiteral("S Q\n");
        }
      }
      else if ((rgBrush = path.Stroke as RadialGradientBrush) != null)
      {
        // HACK
        WriteLiteral("/DeviceRGB CS 0 1 0 RG\n");
        WriteLiteral("q {0:0.###} w", path.StrokeThickness);
        WriteGeometry(path.Data);
        WriteLiteral("S Q\n");
      }
      else if ((iBrush = path.Stroke as ImageBrush) != null)
      {
        // HACK
        WriteLiteral("/DeviceRGB CS 0 1 0 RG\n");
        WriteLiteral("q {0:0.###} w", path.StrokeThickness);
        WriteGeometry(path.Data);
        WriteLiteral("S Q\n");
      }
      else if ((vBrush = path.Stroke as VisualBrush) != null)
      {
        // HACK
        WriteLiteral("/DeviceRGB CS 0 1 0 RG\n");
        WriteLiteral("q {0:0.###} w", path.StrokeThickness);
        WriteGeometry(path.Data);
        WriteLiteral("S Q\n");
      }
      else
        Debug.Assert(false);
    }
 /// <summary>
 /// Writes the path fill and/or stroke operators to the content stream.
 /// </summary>
 internal void WritePathFillStroke(Path path)
 {
   if (path.Data.FillRule == FillRule.NonZero) // NonZero means Winding
   {
     if (path.Fill != null && path.Stroke != null)
       WriteLiteral("B\n");
     else if (path.Stroke != null)
       WriteLiteral("S\n");
     else
       WriteLiteral("f\n");
   }
   else
   {
     if (path.Fill != null && path.Stroke != null)
       WriteLiteral("B*\n");
     else if (path.Stroke != null)
       WriteLiteral("S\n");
     else
       WriteLiteral("f*\n");
   }
 }
    /// <summary>
    /// Writes a Path to the content stream.
    /// </summary>
    private void WritePath(Path path)
    {
      WriteSaveState("begin Path", path.Name);

      // Transform also affects clipping and opacity mask
      if (path.RenderTransform != null && this.renderMode == RenderMode.Default)
      {
        MultiplyTransform(path.RenderTransform);
        WriteRenderTransform(path.RenderTransform);
      }

      if (path.Clip != null && this.renderMode == RenderMode.Default)
        WriteClip(path.Clip);

      if (path.Opacity < 1)
        MultiplyOpacity(path.Opacity);

      if (path.OpacityMask != null)
        WriteOpacityMask(path.OpacityMask);

      if (path.Fill == null)
      {
        if (path.Stroke != null)
        {
#if true
          WriteStrokeGeometry(path);
#else
          // Just stroke the path
          RealizeStroke(path);
          WriteGeometry(path.Data);
          WritePathFillStroke(path);
#endif
        }
        else
          Debug.Assert(false, "??? Path with neither Stroke nor Fill encountered.");
      }
      else
      {
        SolidColorBrush sBrush;
        LinearGradientBrush lgBrush;
        RadialGradientBrush rgBrush;
        ImageBrush iBrush;
        VisualBrush vBrush;
        if ((sBrush = path.Fill as SolidColorBrush) != null)
        {
          Color color = sBrush.Color;
          double opacity = Opacity * color.ScA;
          if (opacity < 1)
            RealizeFillOpacity(opacity);

          WriteRgb(color, " rg\n");

          if (path.Stroke != null)
            RealizeStroke(path);

          WriteGeometry(path.Data);
          WritePathFillStroke(path);
        }
        else if ((lgBrush = path.Fill as LinearGradientBrush) != null)
        {
          // TODO: For better visual compatibility use a Shading Pattern if Opacity is not 1 and
          // the Stroke Style is not solid. Acrobat 8 ignores this case.

          PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
          xgState.SetDefault1();

          double opacity = Opacity * lgBrush.Opacity; ;
          if (opacity < 1)
          {
            xgState.StrokeAlpha = opacity;
            xgState.NonStrokeAlpha = opacity;
          }
          RealizeExtGState(xgState);

          // 1st draw fill
          if (lgBrush.GradientStops.HasTransparency)
          {
            // Create a FormXObject with a soft mask
            PdfFormXObject form = LinearShadingBuilder.BuildFormFromLinearGradientBrush(Context, lgBrush, path.Data);
            string foName = Resources.AddForm(form);
            WriteLiteral(foName + " Do\n");
          }
          else
          {
            // Create just a shading
            PdfShading shading = LinearShadingBuilder.BuildShadingFromLinearGradientBrush(Context, lgBrush);
            string shName = Resources.AddShading(shading);
            WriteLiteral("q\n");
            WriteClip(path.Data);
            WriteLiteral("BX " + shName + " sh EX Q\n");
          }

          // 2nd draw stroke
          if (path.Stroke != null)
            WriteStrokeGeometry(path);
        }
        else if ((rgBrush = path.Fill as RadialGradientBrush) != null)
        {
          PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
          xgState.SetDefault1();

          double avGradientOpacity = rgBrush.GradientStops.GetAverageAlpha(); // HACK
          double opacity = Opacity * rgBrush.Opacity * avGradientOpacity;
          if (opacity < 1)
          {
            xgState.StrokeAlpha = opacity;
            xgState.NonStrokeAlpha = opacity;
          }
          //RealizeExtGState(xgState);

#if true
          XRect boundingBox = path.Data.GetBoundingBox();
          // Always creates a pattern, because the background must be filled
          PdfShadingPattern pattern = RadialShadingBuilder.BuildFromRadialGradientBrush(Context, rgBrush, boundingBox, Transform);
          string paName = Resources.AddPattern(pattern);

          // stream
          // /CS0 cs /P0 scn
          // /GS0 gs
          // 0 480 180 -90 re
          // f*
          // endstream
          // endobj
          WriteLiteral("/Pattern cs " + paName + " scn\n");
          // move to here: RealizeExtGState(xgState);
          RealizeExtGState(xgState);
          WriteGeometry(path.Data);
          if (path.Data.FillRule == FillRule.NonZero) // NonZero means Winding
            WriteLiteral("f\n");
          else
            WriteLiteral("f*\n");
#else
#if true
          // 1st draw fill
          if (rgBrush.GradientStops.HasTransparentColors)
          {
            // Create a FormXObject with a soft mask
            PdfFormXObject form = ShadingBuilder.BuildFormFromRadialGradientBrush(Context, rgBrush, path.Data);
            string foName = Resources.AddForm(form);
            WriteLiteral(foName + " Do\n");
          }
          else
          {
            // Create just a shading
            PdfShading shading = ShadingBuilder.BuildShadingFromRadialGradientBrush(Context, rgBrush);
            string shName = Resources.AddShading(shading);
            WriteLiteral("q\n");
            WriteClip(path.Data);
            WriteLiteral("BX " + shName + " sh EX Q\n");
          }
#else
          // Establish graphic state dictionary
          PdfExtGState extGState = new PdfExtGState(Context.PdfDocument);
          Context.PdfDocument.Internals.AddObject(extGState);
          string gsName = Resources.AddExtGState(extGState);
          WriteLiteral(gsName + " gs\n");

          // 1st draw fill
          PdfShading shading = ShadingBuilder.BuildFormFromRadialGradientBrush(Context, rgBrush); //, extGState);
          string shName = Resources.AddShading(shading);

          WriteClip(path.Data);
          WriteLiteral("BX " + shName + " sh EX\n");
#endif
#endif

          // 2nd draw stroke
          if (path.Stroke != null)
            WriteStrokeGeometry(path);
        }
        else if ((iBrush = path.Fill as ImageBrush) != null)
        {
          PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
          xgState.SetDefault1();

          double opacity = Opacity * iBrush.Opacity;
          if (opacity < 1)
          {
            xgState.StrokeAlpha = opacity;
            xgState.NonStrokeAlpha = opacity;
          }
          RealizeExtGState(xgState);

          // 1st draw fill
          PdfTilingPattern pattern = TilingPatternBuilder.BuildFromImageBrush(Context, iBrush, Transform);
          string name = Resources.AddPattern(pattern);

          WriteLiteral("/Pattern cs " + name + " scn\n");
          WriteGeometry(path.Data);
          WritePathFillStroke(path);

          // 2nd draw stroke
          if (path.Stroke != null)
            WriteStrokeGeometry(path);
        }
        else if ((vBrush = path.Fill as VisualBrush) != null)
        {
          PdfExtGState xgState = Context.PdfDocument.Internals.CreateIndirectObject<PdfExtGState>();
          xgState.SetDefault1();

          double opacity = Opacity * vBrush.Opacity;
          if (opacity < 1)
          {
            xgState.StrokeAlpha = opacity;
            xgState.NonStrokeAlpha = opacity;
          }
          RealizeExtGState(xgState);

          // 1st draw fill
          PdfTilingPattern pattern = TilingPatternBuilder.BuildFromVisualBrush(Context, vBrush, Transform);
          string name = Resources.AddPattern(pattern);

          WriteLiteral("/Pattern cs " + name + " scn\n");
          WriteGeometry(path.Data);
          WritePathFillStroke(path);

          // 2nd draw stroke
          if (path.Stroke != null)
            WriteStrokeGeometry(path);
        }
        else
        {
          Debug.Assert(false, "Unknown brush type encountered.");
        }
      }
      WriteRestoreState("end Path", path.Name);
    }
 /// <summary>
 /// Makes the specified pen to the current graphics object.
 /// </summary>
 public void RealizeStroke(Path path)
 {
   this.graphicsState.RealizeStroke(path);
 }
Example #6
0
    void AddCapToPath(Path path, PathFigure figure, double length, double lineWidthHalf, LineCap lineCap, XMatrix matrix)
    {
      // sketch:
      // 1. create Transform that make a horizontal line with start in 0,0
      // 2. create a Polygon with the shape of the line including its caps
      // 3. render the shape with the brush of the pen
      //PolyLineSegment seg;
      switch (lineCap)
      {
        case LineCap.Flat:
          matrix.Transform(new XPoint(length + lineWidthHalf, -lineWidthHalf));
          break;

        case LineCap.Square:
          matrix.Transform(new XPoint(length + lineWidthHalf, -lineWidthHalf));
          break;

        case LineCap.Round:
          break;

        case LineCap.Triangle:
          break;
      }
    }
Example #7
0
    /// <summary>
    /// If the path is a single line with different start and end caps, convert the line into an area.
    /// </summary>
    private bool WriteSingleLineStrokeWithSpecialCaps(Path path)
    {
      if (path.StrokeStartLineCap == path.StrokeEndLineCap && path.StrokeStartLineCap != LineCap.Triangle)
        return false;
      if (path.Data.Figures.Count != 1)
        return false;
      PathFigure figure = path.Data.Figures[0];
      if (figure.Segments.Count != 1)
        return false;
      PolyLineSegment polyLineSegment = figure.Segments[0] as PolyLineSegment;
      if (polyLineSegment.Points.Count != 1)
        return false;

      // TODO: Create a new path that draws the line
      path.GetType();

      return false;
    }
Example #8
0
        /// <summary>
        /// Parses a Canvas element.
        /// </summary>
        Canvas ParseCanvas()
        {
            Debug.Assert(this.reader.Name == "Canvas");
            Canvas canvas = new Canvas();

            try
            {
                bool isEmptyElement = this.reader.IsEmptyElement;
                while (MoveToNextAttribute())
                {
                    switch (this.reader.Name)
                    {
                    case "Name":
                        canvas.Name = this.reader.Value;
                        break;

                    case "RenderTransform":
                        canvas.RenderTransform = ParseMatrixTransform(this.reader.Value);
                        break;

                    case "Clip":
                        canvas.Clip = ParsePathGeometry(this.reader.Value);
                        break;

                    case "Opacity":
                        canvas.Opacity = ParseDouble(this.reader.Value);
                        break;

                    case "OpacityMask":
                        canvas.OpacityMask = ParseBrush(this.reader.Value);
                        break;

                    case "RenderOptions.EdgeMode":
                        canvas.RenderOptions_EdgeMode = this.reader.Value;
                        break;

                    case "FixedPage.NavigateUri":
                        canvas.FixedPage_NavigateUri = this.reader.Value;
                        break;

                    case "AutomationProperties.HelpText":
                        canvas.AutomationProperties_HelpText = this.reader.Value;
                        break;

                    case "AutomationProperties.Name":
                        canvas.AutomationProperties_Name = this.reader.Value;
                        break;

                    case "xml:lang":
                        canvas.lang = this.reader.Value;
                        break;

                    case "xmlns:x":
                        break;

                    default:
                        UnexpectedAttribute(this.reader.Name);
                        break;
                    }
                }
                if (!isEmptyElement)
                {
                    MoveToNextElement();
                    while (this.reader.IsStartElement())
                    {
                        switch (this.reader.Name)
                        {
                        case "Canvas.Resources":
                            MoveToNextElement();
                            ResourceDictionary rd = new ResourceDictionary();
                            canvas.Resources  = rd;
                            rd.Parent         = canvas;
                            rd.ResourceParent = ResourceDictionaryStack.Current;
                            ResourceDictionaryStack.Push(rd);
                            ParseResourceDictionary(rd);
                            MoveToNextElement();
                            break;

                        case "Canvas.RenderTransform":
                            MoveToNextElement();
                            canvas.RenderTransform = ParseMatrixTransform();
                            MoveToNextElement();
                            break;

                        case "Canvas.Clip":
                            MoveToNextElement();
                            canvas.Clip = ParsePathGeometry();
                            break;

                        case "Canvas.OpacityMask":
                            MoveToNextElement();
                            canvas.OpacityMask        = ParseBrush();
                            canvas.OpacityMask.Parent = canvas;
                            break;

                        case "Path":
                        {
                            PdfSharp.Xps.XpsModel.Path path = ParsePath();
#if DEBUG
                            if (!String.IsNullOrEmpty(path.Name))
                            {
                                Debug.WriteLine("Path: " + path.Name);
                            }
#endif
                            canvas.Content.Add(path);
                            path.Parent = canvas;
                        }
                        break;

                        case "Glyphs":
                        {
                            PdfSharp.Xps.XpsModel.Glyphs glyphs = ParseGlyphs();
                            canvas.Content.Add(glyphs);
                            glyphs.Parent = canvas;
                        }
                        break;

                        case "Canvas":
                        {
                            PdfSharp.Xps.XpsModel.Canvas canvas2 = ParseCanvas();
                            canvas.Content.Add(canvas2);
                            canvas2.Parent = canvas;
                        }
                        break;

                        case "mc:AlternateContent":
                        case "mc:Choice":
                            MoveToNextElement();
                            //canvas.Content.Add(ParseCanvas());
                            break;

                        default:
                            Debugger.Break();
                            break;
                        }
                    }
                }
                MoveToNextElement();
            }
            finally
            {
                // If the current ResourceDictionary is from this Canvas, pop it.
                if (canvas != null && canvas.Resources != null)
                {
                    if (Object.ReferenceEquals(canvas.Resources, ResourceDictionaryStack.Current))
                    {
                        ResourceDictionaryStack.Pop();
                    }
                }
            }
            return(canvas);
        }