示例#1
0
        PdfTilingPattern BuildPattern(ImageBrush brush, XMatrix transform)
        {
            // Bounding box repects viewbox
            //XRect bbox = new XRect(brush.Viewbox.X, brush.Viewbox.Y, brush.Viewbox.Width, brush.Viewbox.Height);
            // double scalex = brush.Viewport.Width / brush.Viewbox.Width * 96 / pdfForm.DpiX;
            //BitmapImage src = new BitmapImage();
            //BitmapSource cropbrush = BitmapSource.Create()
            //CroppedBitmap cropbrush = new CroppedBitmap((BitmapSource)brush.ImageSource, new System.Windows.Int32Rect((int)brush.Viewbox.X, (int)brush.Viewbox.Y, (int)brush.Viewbox.Width, (int)brush.Viewbox.Height));
            //using (var fileStream = new System.IO.FileStream("c:\\fullimage.png", System.IO.FileMode.Create))
            //{
            //    BitmapEncoder encoder = new PngBitmapEncoder();
            //    encoder.Frames.Add(BitmapFrame.Create((BitmapSource)brush.ImageSource));
            //    encoder.Save(fileStream);
            //}
            double scaledpix = ((BitmapSource)brush.ImageSource).DpiX;
            double scaledpiy = ((BitmapSource)brush.ImageSource).DpiY;

            if (brush.Viewbox.X > 0 || brush.Viewbox.Y > 0)
            {
                CroppedBitmap cropbrush = new CroppedBitmap((BitmapSource)brush.ImageSource, new System.Windows.Int32Rect((int)Math.Round((brush.Viewbox.X / 96) * scaledpix), (int)Math.Round((brush.Viewbox.Y / 96) * scaledpiy), (int)Math.Round((brush.Viewbox.Width / 96) * scaledpiy), (int)Math.Round((brush.Viewbox.Height / 96) * scaledpiy)));
                //cropbrush.DpiX = scaledpix;
                //cropbrush.DpiY = scaledpiy;
                brush.ImageSource = cropbrush;
                //brush.Viewport = new System.Windows.Rect(0, 0, brush.Viewport.Width, brush.Viewport.Height);
                //brush.Viewbox = new System.Windows.Rect(0, 0, ((Math.Round((brush.Viewbox.Width / 96) * scaledpiy)) / scaledpiy * 96) , brush.Viewbox.Height);
                brush.Viewbox = new System.Windows.Rect(0, 0, brush.Viewbox.Width, brush.Viewbox.Height);
            }

            //brush = new ImageBrush(cropbrush);

            //BitmapSource
            //BitmapSource. cropbrushbitmap = new BitmapSource(cropbrush);


            //using (var fileStream = new System.IO.FileStream("c:\\cropimage.png", System.IO.FileMode.Create))
            //{
            //   BitmapEncoder encoder = new PngBitmapEncoder();
            //   encoder.Frames.Add(BitmapFrame.Create(cropbrush));
            //   encoder.Save(fileStream);
            //}

            //XRect bbox = new XRect(brush.Viewport.X - brush.Viewbox.X, brush.Viewport.Y - brush.Viewbox.Y, brush.Viewbox.Width, brush.Viewbox.Height);
            //XRect bbox = new XRect((brush.Viewbox.X / 96) * scaledpix, (brush.Viewbox.Y / 96) * scaledpiy, (brush.Viewbox.Width / 96) * scaledpix, (brush.Viewbox.Height / 96) * scaledpiy);
            //XRect bbox = new XRect(0, 0, (brush.Viewport.Width / 96) * scaledpix, (brush.Viewport.Height / 96) * scaledpiy);
            XRect bbox = new XRect(0, 0, brush.Viewport.Width, brush.Viewport.Height);

#if true
            XMatrix matrix = transform;
//this only needs to be a translate and to offset the viewbox viewport difference
            matrix.TranslatePrepend(brush.Viewport.X, brush.Viewport.Y);
            //matrix.TranslatePrepend((brush.Viewport.X - brush.Viewbox.X)+2, (brush.Viewport.Y - brush.Viewbox.Y)+2);

            if (brush.Transform != null)
            {
                matrix.Prepend(new XMatrix(brush.Transform.Value.M11, brush.Transform.Value.M12, brush.Transform.Value.M21,
                                           brush.Transform.Value.M22, brush.Transform.Value.OffsetX,
                                           brush.Transform.Value.OffsetY));
            }
#else
            double  c      = 1;
            XMatrix matrix = new XMatrix(1 * c, 0, 0, 1 * c, brush.Viewport.X * c, brush.Viewport.Y * c); // HACK: 480
            XMatrix t      = transform;
            //t.Invert();
            t.Prepend(matrix);
            //t.TranslateAppend(brush.Viewport.X , brush.Viewport.Y);
            //matrix.Append(t);
            matrix = t;
#endif
            double xStep = brush.Viewport.Width + 1;  // (brush.Viewbox.Width / 96) * scaledpix; //* (brush.TileMode == TileMode.None ? 2 : 1);
            double yStep = brush.Viewport.Height + 1; // (brush.Viewbox.Height / 96) * scaledpiy; //* (brush.TileMode == TileMode.None ? 2 : 1);


            // PdfTilingPattern
            //<<
            //  /BBox [0 0 240 120]
            //  /Length 74
            //  /Matrix [0.75 0 0 -0.75 0 480]
            //  /PaintType 1
            //  /PatternType 1
            //  /Resources
            //  <<
            //    /ExtGState
            //    <<
            //      /GS0 10 0 R
            //    >>
            //    /XObject
            //    <<
            //      /Fm0 17 0 R
            //    >>
            //  >>
            //  /TilingType 3
            //  /Type /Pattern
            //  /XStep 480
            //  /YStep 640
            //>>
            //stream
            //  q
            //  0 0 240 120 re
            //  W n
            //  q
            //    2.3999939 0 0 1.1999969 0 0 cm
            //    /GS0 gs
            //    /Fm0 Do
            //  Q
            //Q
            //endstream
            PdfTilingPattern pattern = Context.PdfDocument.Internals.CreateIndirectObject <PdfTilingPattern>();
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.PatternType, 1); // Tiling
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.PaintType, 1);   // Color
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.TilingType, 3);  // Constant spacing and faster tiling
            pattern.Elements.SetMatrix(PdfTilingPattern.Keys.Matrix, matrix);
            pattern.Elements.SetRectangle(PdfTilingPattern.Keys.BBox, new PdfRectangle(bbox));
            pattern.Elements.SetReal(PdfTilingPattern.Keys.XStep, xStep);
            pattern.Elements.SetReal(PdfTilingPattern.Keys.YStep, yStep);

            // Set extended graphic state like Acrobat do
            PdfExtGState pdfExtGState = Context.PdfDocument.Internals.CreateIndirectObject <PdfExtGState>();
            pdfExtGState.SetDefault1();

            PdfFormXObject pdfForm = BuildForm(brush);
            //XRect viewBoxForm = new XRect(0, 0, 640, 480);

            PdfContentWriter writer = new PdfContentWriter(Context, pattern);
            writer.BeginContentRaw();

            // Acrobat 8 clips to bounding box, so do we
            //writer.WriteClip(bbox);

            XMatrix transformation = new XMatrix();
            //double dx = brush.Viewport.Width / brush.Viewbox.Width * 96 / pdfForm.DpiX;
            //double dy = brush.Viewport.Height / brush.Viewbox.Height * 96 / pdfForm.DpiY;

            double dx = brush.Viewport.Width / brush.Viewbox.Width * 96 / pdfForm.DpiX;
            double dy = brush.Viewport.Height / brush.Viewbox.Height * 96 / pdfForm.DpiY;
            transformation = new XMatrix(dx, 0, 0, dy, 0, 0);
            writer.WriteMatrix(transformation);
            writer.WriteGraphicsState(pdfExtGState);

            string name = writer.Resources.AddForm(pdfForm);
            writer.WriteLiteral(name + " Do\n");

            writer.EndContent();

            return(pattern);
        }
示例#2
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 public void Multiply(XMatrix matrix)
 {
     Append(matrix);
 }
示例#3
0
    // --------------------------------------------------------------------------------------------

    #region Append to PDF stream

    /// <summary>
    /// Appends one or up to five Bézier curves that interpolate the arc.
    /// </summary>
    void AppendPartialArc(double x, double y, double width, double height, double startAngle, double sweepAngle, PathStart pathStart, XMatrix matrix)
    {
      // Normalize the angles
      double α = startAngle;
      if (α < 0)
        α = α + (1 + Math.Floor((Math.Abs(α) / 360))) * 360;
      else if (α > 360)
        α = α - Math.Floor(α / 360) * 360;
      Debug.Assert(α >= 0 && α <= 360);

      double β = sweepAngle;
      if (β < -360)
        β = -360;
      else if (β > 360)
        β = 360;

      if (α == 0 && β < 0)
        α = 360;
      else if (α == 360 && β > 0)
        α = 0;

      // Is it possible that the arc is small starts and ends in same quadrant?
      bool smallAngle = Math.Abs(β) <= 90;

      β = α + β;
      if (β < 0)
        β = β + (1 + Math.Floor((Math.Abs(β) / 360))) * 360;

      bool clockwise = sweepAngle > 0;
      int startQuadrant = Quatrant(α, true, clockwise);
      int endQuadrant = Quatrant(β, false, clockwise);

      if (startQuadrant == endQuadrant && smallAngle)
        AppendPartialArcQuadrant(x, y, width, height, α, β, pathStart, matrix);
      else
      {
        int currentQuadrant = startQuadrant;
        bool firstLoop = true;
        do
        {
          if (currentQuadrant == startQuadrant && firstLoop)
          {
            double ξ = currentQuadrant * 90 + (clockwise ? 90 : 0);
            AppendPartialArcQuadrant(x, y, width, height, α, ξ, pathStart, matrix);
          }
          else if (currentQuadrant == endQuadrant)
          {
            double ξ = currentQuadrant * 90 + (clockwise ? 0 : 90);
            AppendPartialArcQuadrant(x, y, width, height, ξ, β, PathStart.Ignore1st, matrix);
          }
          else
          {
            double ξ1 = currentQuadrant * 90 + (clockwise ? 0 : 90);
            double ξ2 = currentQuadrant * 90 + (clockwise ? 90 : 0);
            AppendPartialArcQuadrant(x, y, width, height, ξ1, ξ2, PathStart.Ignore1st, matrix);
          }

          // Don't stop immediately if arc is greater than 270 degrees
          if (currentQuadrant == endQuadrant && smallAngle)
            break;
          else
            smallAngle = true;

          if (clockwise)
            currentQuadrant = currentQuadrant == 3 ? 0 : currentQuadrant + 1;
          else
            currentQuadrant = currentQuadrant == 0 ? 3 : currentQuadrant - 1;

          firstLoop = false;
        } while (true);
      }
    }
示例#4
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static XMatrix CreateSkewRadians(double skewX, double skewY)
 {
     XMatrix matrix = new XMatrix();
     matrix.SetMatrix(1, Math.Tan(skewY), Math.Tan(skewX), 1, 0, 0, XMatrixTypes.Unknown);
     return matrix;
 }
示例#5
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static void TransformRect(ref XRect rect, ref XMatrix matrix)
 {
     if (!rect.IsEmpty)
     {
         XMatrixTypes type = matrix._type;
         if (type != XMatrixTypes.Identity)
         {
             if ((type & XMatrixTypes.Scaling) != XMatrixTypes.Identity)
             {
                 rect.X *= matrix._m11;
                 rect.Y *= matrix._m22;
                 rect.Width *= matrix._m11;
                 rect.Height *= matrix._m22;
                 if (rect.Width < 0)
                 {
                     rect.X += rect.Width;
                     rect.Width = -rect.Width;
                 }
                 if (rect.Height < 0)
                 {
                     rect.Y += rect.Height;
                     rect.Height = -rect.Height;
                 }
             }
             if ((type & XMatrixTypes.Translation) != XMatrixTypes.Identity)
             {
                 rect.X += matrix._offsetX;
                 rect.Y += matrix._offsetY;
             }
             if (type == XMatrixTypes.Unknown)
             {
                 XPoint point1 = matrix.Transform(rect.TopLeft);
                 XPoint point2 = matrix.Transform(rect.TopRight);
                 XPoint point3 = matrix.Transform(rect.BottomRight);
                 XPoint point4 = matrix.Transform(rect.BottomLeft);
                 rect.X = Math.Min(Math.Min(point1.X, point2.X), Math.Min(point3.X, point4.X));
                 rect.Y = Math.Min(Math.Min(point1.Y, point2.Y), Math.Min(point3.Y, point4.Y));
                 rect.Width = Math.Max(Math.Max(point1.X, point2.X), Math.Max(point3.X, point4.X)) - rect.X;
                 rect.Height = Math.Max(Math.Max(point1.Y, point2.Y), Math.Max(point3.Y, point4.Y)) - rect.Y;
             }
         }
     }
 }
示例#6
0
 public void AddTransform(XMatrix value, XMatrixOrder matrixOrder)
 {
     _gfxState.AddTransform(value, matrixOrder);
 }
示例#7
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static XMatrix CreateRotationRadians(double angle, double centerX, double centerY)
 {
     XMatrix matrix = new XMatrix();
     double sin = Math.Sin(angle);
     double cos = Math.Cos(angle);
     double offsetX = (centerX * (1.0 - cos)) + (centerY * sin);
     double offsetY = (centerY * (1.0 - cos)) - (centerX * sin);
     matrix.SetMatrix(cos, sin, -sin, cos, offsetX, offsetY, XMatrixTypes.Unknown);
     return matrix;
 }
        /// <summary>
        /// Builds a PdfTilingPattern pattern from a visual brush.
        /// </summary>
        public static PdfTilingPattern BuildFromVisualBrush(DocumentRenderingContext context, VisualBrush brush, XMatrix transform)
        {
            TilingPatternBuilder builder    = new TilingPatternBuilder(context);
            PdfTilingPattern     pdfPattern = builder.BuildPattern(brush, transform);

            return(pdfPattern);
        }
        PdfTilingPattern BuildPattern(ImageBrush brush, XMatrix transform)
        {
            // Bounding box lays always at (0,0)
            XRect bbox = new XRect(0, 0, brush.Viewport.Width, brush.Viewport.Height);

#if true
            XMatrix matrix = transform;
            matrix.Prepend(new XMatrix(1, 0, 0, 1, brush.Viewport.X, brush.Viewport.Y));
#else
            double  c      = 1;
            XMatrix matrix = new XMatrix(1 * c, 0, 0, 1 * c, brush.Viewport.X * c, brush.Viewport.Y * c); // HACK: 480
            XMatrix t      = transform;
            //t.Invert();
            t.Prepend(matrix);
            //t.TranslateAppend(brush.Viewport.X , brush.Viewport.Y);
            //matrix.Append(t);
            matrix = t;
#endif
            double xStep = brush.Viewport.Width;
            double yStep = brush.Viewport.Height;

            // PdfTilingPattern
            //<<
            //  /BBox [0 0 240 120]
            //  /Length 74
            //  /Matrix [0.75 0 0 -0.75 0 480]
            //  /PaintType 1
            //  /PatternType 1
            //  /Resources
            //  <<
            //    /ExtGState
            //    <<
            //      /GS0 10 0 R
            //    >>
            //    /XObject
            //    <<
            //      /Fm0 17 0 R
            //    >>
            //  >>
            //  /TilingType 3
            //  /Type /Pattern
            //  /XStep 480
            //  /YStep 640
            //>>
            //stream
            //  q
            //  0 0 240 120 re
            //  W n
            //  q
            //    2.3999939 0 0 1.1999969 0 0 cm
            //    /GS0 gs
            //    /Fm0 Do
            //  Q
            //Q
            //endstream
            PdfTilingPattern pattern = Context.PdfDocument.Internals.CreateIndirectObject <PdfTilingPattern>();
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.PatternType, 1); // Tiling
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.PaintType, 1);   // Color
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.TilingType, 3);  // Constant spacing and faster tiling
            pattern.Elements.SetMatrix(PdfTilingPattern.Keys.Matrix, matrix);
            pattern.Elements.SetRectangle(PdfTilingPattern.Keys.BBox, new PdfRectangle(bbox));
            pattern.Elements.SetReal(PdfTilingPattern.Keys.XStep, xStep);
            pattern.Elements.SetReal(PdfTilingPattern.Keys.YStep, yStep);

            // Set extended graphic state like Acrobat do
            PdfExtGState pdfExtGState = Context.PdfDocument.Internals.CreateIndirectObject <PdfExtGState>();
            pdfExtGState.SetDefault1();

            PdfFormXObject pdfForm = BuildForm(brush);
            //XRect viewBoxForm = new XRect(0, 0, 640, 480);

            PdfContentWriter writer = new PdfContentWriter(Context, pattern);
            writer.BeginContentRaw();

            // Acrobat 8 clips to bounding box, so do we
            //writer.WriteClip(bbox);

            XMatrix transformation = new XMatrix();
            double  dx             = brush.Viewport.Width / brush.Viewbox.Width * 96 / pdfForm.DpiX;
            double  dy             = brush.Viewport.Height / brush.Viewbox.Height * 96 / pdfForm.DpiY;
            transformation = new XMatrix(dx, 0, 0, dy, 0, 0);
            writer.WriteMatrix(transformation);
            writer.WriteGraphicsState(pdfExtGState);

            string name = writer.Resources.AddForm(pdfForm);
            writer.WriteLiteral(name + " Do\n");

            writer.EndContent();

            return(pattern);
        }
        /// <summary>
        /// Builds a PdfFormXObject from the specified brush.
        /// </summary>
        PdfFormXObject BuildForm(ImageBrush brush)
        {
            //<<
            //  /BBox [0 100 100 0]
            //  /Length 65
            //  /Matrix [1 0 0 1 0 0]
            //  /Resources
            //  <<
            //    /ColorSpace
            //    <<
            //      /CS0 15 0 R
            //    >>
            //    /ExtGState
            //    <<
            //      /GS0 10 0 R
            //    >>
            //    /ProcSet [/PDF /ImageC /ImageI]
            //    /XObject
            //    <<
            //      /Im0 16 0 R
            //    >>
            //  >>
            //  /Subtype /Form
            //>>
            //stream
            //  q
            //  0 0 100 100 re
            //  W n
            //  q
            //    /GS0 gs
            //    100 0 0 -100 0 100 cm
            //    /Im0 Do
            //  Q
            //Q
            //endstream
            PdfFormXObject pdfForm = Context.PdfDocument.Internals.CreateIndirectObject <PdfFormXObject>();
            XPImage        xpImage = ImageBuilder.FromImageBrush(Context, brush);
            XImage         ximage  = xpImage.XImage;

            ximage.Interpolate = false;
            double width  = ximage.PixelWidth;
            double height = ximage.PixelHeight;

            pdfForm.DpiX = ximage.HorizontalResolution;
            pdfForm.DpiY = ximage.VerticalResolution;

            // view box in point
            // XRect box = new XRect(brush.Viewbox.X * 0.75, brush.Viewbox.Y * 0.75, brush.Viewbox.Width * 0.75, brush.Viewbox.Height * 0.75);
            XRect box = new XRect(0, 0, width, height);

            pdfForm.Elements.SetRectangle(PdfFormXObject.Keys.BBox, new PdfRectangle(0, height, width, 0));
            pdfForm.Elements.SetMatrix(PdfFormXObject.Keys.Matrix, new XMatrix());

            PdfContentWriter writer = new PdfContentWriter(Context, pdfForm);

            Debug.Assert(ximage != null);

            //PdfFormXObject pdfForm = xform.PdfForm;
            pdfForm.Elements.SetMatrix(PdfFormXObject.Keys.Matrix, new XMatrix());

            //formWriter.Size = brush.Viewport.Size;
            writer.BeginContentRaw();

            string  imageID = writer.Resources.AddImage(new PdfImage(Context.PdfDocument, ximage));
            XMatrix matrix  = new XMatrix();

            //double scaleX = brush.Viewport.Width / brush.Viewbox.Width * 4 / 3 * ximage.PointWidth;
            //double scaleY = brush.Viewport.Height / brush.Viewbox.Height * 4 / 3 * ximage.PointHeight;
            //matrix.TranslatePrepend(-brush.Viewbox.X, -brush.Viewbox.Y);
            //matrix.ScalePrepend(scaleX, scaleY);
            //matrix.TranslatePrepend(brush.Viewport.X / scaleX, brush.Viewport.Y / scaleY);

            //double scaleX = 96 / ximage.HorizontalResolution;
            //double scaleY = 96 / ximage.VerticalResolution;
            //width *= scaleX;
            //height *= scaleY;
            matrix = new XMatrix(width, 0, 0, -height, 0, height);
            writer.WriteLiteral("q\n");
            // TODO:WriteClip(path.Data);
            //formWriter.WriteLiteral("{0:0.###} 0 0 -{1:0.###} {2:0.###} {3:0.###} cm 100 Tz {4} Do Q\n",
            //  matrix.M11, matrix.M22, matrix.OffsetX, matrix.OffsetY + brush.Viewport.Height, imageID);
            writer.WriteMatrix(matrix);
            writer.WriteLiteral(imageID + " Do Q\n");

#if DEBUG
            if (DevHelper.BorderPatterns)
            {
                writer.WriteLiteral("1 1 1 rg 0 0 m {0:0.###} 0 l {0:0.###} {1:0.###} l 0 {1:0.###} l h s\n", width, height);
            }
#endif

            writer.EndContent();

            return(pdfForm);
        }
        /// <summary>
        /// Builds a PdfFormXObject from the specified brush.
        /// </summary>
        PdfFormXObject BuildForm(VisualBrush brush)
        {
            //<<
            //  /BBox [0 100 100 0]
            //  /Length 65
            //  /Matrix [1 0 0 1 0 0]
            //  /Resources
            //  <<
            //    /ColorSpace
            //    <<
            //      /CS0 15 0 R
            //    >>
            //    /ExtGState
            //    <<
            //      /GS0 10 0 R
            //    >>
            //    /ProcSet [/PDF /ImageC /ImageI]
            //    /XObject
            //    <<
            //      /Im0 16 0 R
            //    >>
            //  >>
            //  /Subtype /Form
            //>>
            //stream
            //  q
            //  0 0 100 100 re
            //  W n
            //  q
            //    /GS0 gs
            //    100 0 0 -100 0 100 cm
            //    /Im0 Do
            //  Q
            //Q
            //endstream
            PdfFormXObject pdfForm = Context.PdfDocument.Internals.CreateIndirectObject <PdfFormXObject>();

            double width  = brush.Viewport.Width;
            double height = brush.Viewport.Height;

            pdfForm.DpiX = 96;
            pdfForm.DpiY = 96;

            // view box
            XRect box = new XRect(0, 0, width, height);

            pdfForm.Elements.SetRectangle(PdfFormXObject.Keys.BBox, new PdfRectangle(0, height, width, 0));
            pdfForm.Elements.SetMatrix(PdfFormXObject.Keys.Matrix, new XMatrix());

            PdfContentWriter writer = new PdfContentWriter(Context, pdfForm);

            pdfForm.Elements.SetMatrix(PdfFormXObject.Keys.Matrix, new XMatrix());

            writer.BeginContentRaw();
            writer.WriteLiteral("-100 Tz\n");
            XMatrix matrix = new XMatrix(width, 0, 0, -height, 0, height);

            writer.WriteLiteral("q\n");
            //writer.WriteMatrix(matrix);
            writer.WriteVisual(brush.Visual);
            writer.WriteLiteral("Q\n");

#if DEBUG
            if (DevHelper.BorderPatterns)
            {
                writer.WriteLiteral("1 1 1 rg 0 0 m {0:0.###} 0 l {0:0.###} {1:0.###} l 0 {1:0.###} l h s\n", width, height);
            }
#endif

            writer.EndContent();

            return(pdfForm);
        }
示例#12
0
        /// <summary>
        /// Builds a pattern from a linear gradient brush.
        /// </summary>
        public static PdfShadingPattern BuildPatternFromLinearGradientBrush(DocumentRenderingContext context, LinearGradientBrush brush, XMatrix transform)
        {
            LinearShadingBuilder builder = new LinearShadingBuilder(context);
            PdfShadingPattern    pattern = builder.BuildShadingPattern(brush, transform);

            return(pattern);
        }
示例#13
0
        /// <summary>
        /// Builds the soft mask.
        /// </summary>
        PdfSoftMask BuildSoftMask(RadialGradientBrush brush)
        {
            Debug.Assert(brush.GradientStops.HasTransparency);

            XRect viewBox = new XRect(0, 0, 360, 480); // HACK
            //XForm xform = new XForm(Context.PdfDocument, viewBox);

            PdfFormXObject form = Context.PdfDocument.Internals.CreateIndirectObject <PdfFormXObject>();

#if DEBUG
            if (DevHelper.RenderComments)
            {
                form.Elements.SetString("/@comment", "This is the Form XObject of the soft mask");
            }
#endif
            form.Elements.SetRectangle(PdfFormXObject.Keys.BBox, new PdfRectangle(viewBox));


            // Transparency group of mask form
            //<<
            //  /CS /DeviceGray
            //  /I false
            //  /K false
            //  /S /Transparency
            //  /Type /Group
            //>>
            PdfTransparencyGroupAttributes tgAttributes = Context.PdfDocument.Internals.CreateIndirectObject <PdfTransparencyGroupAttributes>();
            tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceGray");
            tgAttributes.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.I, false);
            tgAttributes.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.K, false);

            // ExtGState of mask form
            //<<
            //  /AIS false
            //  /BM /Normal
            //  /ca 1
            //  /CA 1
            //  /op false
            //  /OP false
            //  /OPM 1
            //  /SA true
            //  /SMask /None
            //  /Type /ExtGState
            //>>
            PdfExtGState pdfStateMaskFrom = Context.PdfDocument.Internals.CreateIndirectObject <PdfExtGState>();
            pdfStateMaskFrom.SetDefault1();

            // Shading of mask form
            PdfShading shadingFrom = BuildShadingForSoftMask(brush);

            ////// Set reference to transparency group attributes
            ////pdfForm.Elements.SetObject(PdfFormXObject.Keys.Group, tgAttributes);
            ////pdfForm.Elements[PdfFormXObject.Keys.Matrix] = new PdfLiteral("[1.001 0 0 1.001 0.001 0.001]");

            // Soft mask
            //<<
            //  /G 21 0 R   % form
            //  /S /Luminosity
            //  /Type /Mask
            //>>
            PdfSoftMask softmask = Context.PdfDocument.Internals.CreateIndirectObject <PdfSoftMask>(); // new PdfSoftMask(this.writer.Owner);
            //extGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask);
            //this.writer.Owner.Internals.AddObject(softmask);
#if DEBUG
            if (DevHelper.RenderComments)
            {
                softmask.Elements.SetString("/@comment", "This is the soft mask");
            }
#endif
            softmask.Elements.SetName(PdfSoftMask.Keys.S, "/Luminosity");
            softmask.Elements.SetReference(PdfSoftMask.Keys.G, form);

            // Create content of mask form
            //<<
            //  /BBox [200.118 369.142 582.795 -141.094]
            //  /Group 16 0 R
            //  /Length 121
            //  /Matrix [1 0 0 1 0 0]
            //  /Resources
            //  <<
            //    /ExtGState
            //    <<
            //      /GS0 20 0 R
            //    >>
            //    /Shading
            //    <<
            //      /Sh0 19 0 R
            //    >>
            //  >>
            //  /Subtype /Form
            //>>
            //stream
            //  q
            //    200.118 369.142 382.677 -510.236 re
            //    W n
            //  q
            //    0 g
            //    1 i
            //    GS0 gs
            //    0.75 0 0 -0.75 200.1181183 369.1417236 cm
            //   BX /Sh0 sh EX Q
            //  Q
            //endstream
            form.Elements.SetReference(PdfFormXObject.Keys.Group, tgAttributes);
            PdfContentWriter writer = new PdfContentWriter(Context, form);
            writer.BeginContentRaw();
            // Acrobat 8 clips to bounding box, so we should do
            // why   0 480 360 -480 re ??
            //writer.WriteClip(bbox);
            //writer.WriteGraphicsState(extGState);
            writer.WriteLiteral("1 i 0 g\n");
            writer.WriteLiteral(writer.Resources.AddExtGState(pdfStateMaskFrom) + " gs\n");

            XMatrix transform = new XMatrix(); //(brush.Viewport.Width / viewBoxForm.width, 0, 0, brush.Viewport.Height / viewBoxForm.height, 0, 0);
            writer.WriteMatrix(transform);
            writer.WriteLiteral("BX " + writer.Resources.AddShading(shadingFrom) + " sh EX\n");
            writer.EndContent();

            return(softmask);
        }
示例#14
0
        /// <summary>
        /// Builds a PdfFormXObject from the specified brush.
        /// // If a gradient contains transparency, a soft mask is created an added to the specified graphic state.
        /// </summary>
        PdfFormXObject BuildForm(LinearGradientBrush brush, PathGeometry geometry)
        {
            PdfFormXObject pdfForm = Context.PdfDocument.Internals.CreateIndirectObject <PdfFormXObject>();

            // HACK
            pdfForm.Elements.SetRectangle(PdfFormXObject.Keys.BBox, new PdfRectangle(0, 640, 480, 0));

            // Transparency group of the form
            //<<
            //  /I true
            //  /K false
            //  /S /Transparency
            //  /Type /Group
            //>>
            PdfTransparencyGroupAttributes tgPrimaryForm = Context.PdfDocument.Internals.CreateIndirectObject <PdfTransparencyGroupAttributes>();

            // not set by Acrobat: tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceRGB");
            tgPrimaryForm.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.I, true);
            tgPrimaryForm.Elements.SetBoolean(PdfTransparencyGroupAttributes.Keys.K, false);
            pdfForm.Elements.SetReference(PdfFormXObject.Keys.Group, tgPrimaryForm);

            // Shading
            PdfShading shading = BuildShading(brush);

            // ExtGState
            //<<
            //  /AIS false
            //  /BM /Normal
            //  /ca 1
            //  /CA 1
            //  /op false
            //  /OP false
            //  /OPM 1
            //  /SA true
            //  /SMask 22 0 R
            //  /Type /ExtGState
            //>>
            PdfExtGState pdfExtGState = Context.PdfDocument.Internals.CreateIndirectObject <PdfExtGState>();

            pdfExtGState.SetDefault1();

            // Soft mask
            PdfSoftMask softmask = BuildSoftMask(brush);

            pdfExtGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask);

            // PdfFormXObject
            //<<
            //  /BBox [200.118 369.142 582.795 -141.094]
            //  /Group 11 0 R
            //  /Length 117
            //  /Matrix [1 0 0 1 0 0]
            //  /Resources
            //  <<
            //    /ColorSpace
            //    <<
            //      /CS0 8 0 R
            //    >>
            //    /ExtGState
            //    <<
            //      /GS0 23 0 R
            //    >>
            //    /Shading
            //    <<
            //      /Sh0 14 0 R
            //    >>
            //  >>
            //  /Subtype /Form
            //>>
            //stream
            //q
            //203.868 365.392 157.5 -97.5 re
            //W* n
            //q
            //0 g
            //1 i
            ///GS0 gs
            //0.75 0 0 -0.75 200.1181183 369.1417236 cm
            //BX /Sh0 sh EX Q
            //Q
            //endstream
            PdfContentWriter writer = new PdfContentWriter(Context, pdfForm);

            writer.BeginContentRaw();
            // Acrobat 8 clips to bounding box, so we should do
            writer.WriteClip(geometry);
            //writer.WriteGraphicsState(extGState);
            //writer.WriteLiteral("0 g\n");
            writer.WriteLiteral(writer.Resources.AddExtGState(pdfExtGState) + " gs\n");

            XMatrix transform = new XMatrix(); //(brush.Viewport.Width / viewBoxForm.width, 0, 0, brush.Viewport.Height / viewBoxForm.height, 0, 0);

            writer.WriteMatrix(transform);
            writer.WriteLiteral("BX " + writer.Resources.AddShading(shading) + " sh EX\n");
            writer.EndContent();

            return(pdfForm);
        }
示例#15
0
        /// <summary>
        /// Realizes the CTM.
        /// </summary>
        public void RealizeCtm()
        {
            //if (MustRealizeCtm)
            if (!UnrealizedCtm.IsIdentity)
            {
                Debug.Assert(!UnrealizedCtm.IsIdentity, "mrCtm is unnecessarily set.");

                const string format = Config.SignificantFigures7;

                double[] matrix = UnrealizedCtm.GetElements();
                // Use up to six decimal digits to prevent round up problems.
                _renderer.AppendFormatArgs("{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "} {4:" + format + "} {5:" + format + "} cm\n",
                    matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);

                RealizedCtm.Prepend(UnrealizedCtm);
                UnrealizedCtm = new XMatrix();
                EffectiveCtm = RealizedCtm;
                InverseEffectiveCtm = EffectiveCtm;
                InverseEffectiveCtm.Invert();
            }
        }
示例#16
0
        void RealizeLinearGradientBrush(LinearGradientBrush brush, XForm xform)
        {
            XMatrix           matrix  = this.currentTransform;
            PdfShadingPattern pattern = new PdfShadingPattern(this.writer.Owner);

            pattern.Elements[PdfShadingPattern.Keys.PatternType] = new PdfInteger(2); // shading pattern

            // Setup shading
            PdfShading   shading   = new PdfShading(this.writer.Owner);
            PdfColorMode colorMode = PdfColorMode.Rgb; //this.document.Options.ColorMode;

            PdfDictionary function = BuildShadingFunction(brush.GradientStops, colorMode);

            function.Elements.SetString("/@", "This is the shading function of a LinearGradientBrush");
            shading.Elements[PdfShading.Keys.Function] = function;

            shading.Elements[PdfShading.Keys.ShadingType] = new PdfInteger(2); // Axial shading
            //if (colorMode != PdfColorMode.Cmyk)
            shading.Elements[PdfShading.Keys.ColorSpace] = new PdfName("/DeviceRGB");
            //else
            //shading.Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK");

            //double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
            double x1 = brush.StartPoint.X;
            double y1 = brush.StartPoint.Y;
            double x2 = brush.EndPoint.X;
            double y2 = brush.EndPoint.Y;

            shading.Elements[PdfShading.Keys.Coords] = new PdfLiteral("[{0:0.###} {1:0.###} {2:0.###} {3:0.###}]", x1, y1, x2, y2);

            // old: Elements[Keys.Background] = new PdfRawItem("[0 1 1]");
            // old: Elements[Keys.Domain] =
            shading.Elements[PdfShading.Keys.Extend] = new PdfLiteral("[true true]");

            // Setup pattern
            pattern.Elements[PdfShadingPattern.Keys.Shading] = shading;
            pattern.Elements[PdfShadingPattern.Keys.Matrix]  = PdfLiteral.FromMatrix(matrix); // new PdfLiteral("[" + PdfEncoders.ToString(matrix) + "]");

            string name = this.writer.Resources.AddPattern(pattern);

            this.writer.WriteLiteral("/Pattern cs\n", name);
            this.writer.WriteLiteral("{0} scn\n", name);

            double alpha = brush.Opacity * brush.GradientStops.GetAverageAlpha();

            if (alpha < 1 && this.writer.renderMode == RenderMode.Default)
            {
#if true
                PdfExtGState extGState = this.writer.Owner.ExtGStateTable.GetExtGStateNonStroke(alpha);
                string       gs        = this.writer.Resources.AddExtGState(extGState);
                this.writer.WriteLiteral("{0} gs\n", gs);
#else
#if true
                if (xform == null)
                {
                    PdfExtGState extGState = this.writer.Owner.ExtGStateTable.GetExtGStateNonStroke(alpha);
                    string       gs        = this.writer.Resources.AddExtGState(extGState);
                    this.writer.WriteGraphicState(extGState);
                }
                else
                {
                    //PdfFormXObject pdfForm = this.writer.Owner.FormTable.GetForm(form);
                    PdfFormXObject pdfForm = xform.pdfForm;
                    pdfForm.Elements.SetString("/@", "This is the Form XObject of the soft mask");

                    string formName = this.writer.Resources.AddForm(pdfForm);

                    PdfTransparencyGroupAttributes tgAttributes = new PdfTransparencyGroupAttributes(this.writer.Owner);
                    //this.writer.Owner.Internals.AddObject(tgAttributes);
                    tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceRGB");

                    // Set reference to transparency group attributes
                    pdfForm.Elements.SetObject(PdfFormXObject.Keys.Group, tgAttributes);
                    pdfForm.Elements[PdfFormXObject.Keys.Matrix] = new PdfLiteral("[1.001 0 0 1.001 0.001 0.001]");


                    PdfSoftMask softmask = new PdfSoftMask(this.writer.Owner);
                    this.writer.Owner.Internals.AddObject(softmask);
                    softmask.Elements.SetString("/@", "This is the soft mask");
                    softmask.Elements.SetName(PdfSoftMask.Keys.S, "/Luminosity");
                    softmask.Elements.SetReference(PdfSoftMask.Keys.G, pdfForm);
                    //pdfForm.Elements.SetName(PdfFormXObject.Keys.Type, "Group");
                    //pdfForm.Elements.SetName(PdfFormXObject.Keys.ss.Ss.Type, "Group");

                    PdfExtGState extGState = new PdfExtGState(this.writer.Owner);
                    this.writer.Owner.Internals.AddObject(extGState);
                    extGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask);
                    this.writer.WriteGraphicState(extGState);
                }
#else
                XForm     form    = new XForm(this.writer.Owner, 220, 140);
                XGraphics formGfx = XGraphics.FromForm(form);

                // draw something
                //XSolidBrush xbrush = new XSolidBrush(XColor.FromArgb(128, 128, 128));
                XLinearGradientBrush xbrush = new XLinearGradientBrush(new XPoint(0, 0), new XPoint(220, 0), XColors.White, XColors.Black);
                formGfx.DrawRectangle(xbrush, -10000, -10000, 20000, 20000);
                //formGfx.DrawString("Text, Graphics, Images, and Forms", new XFont("Verdana", 10, XFontStyle.Regular), XBrushes.Navy, 3, 0, XStringFormat.TopLeft);
                formGfx.Dispose();

                // Close form
                form.Finish();
                PdfFormXObject pdfForm  = this.writer.Owner.FormTable.GetForm(form);
                string         formName = this.writer.Resources.AddForm(pdfForm);

                //double x = 20, y = 20;
                //double cx = 1;
                //double cy = 1;

                //this.writer.AppendFormat("q {2:0.###} 0 0 -{3:0.###} {0:0.###} {4:0.###} cm 100 Tz {5} Do Q\n",
                //  x, y, cx, cy, y + 0, formName);

                //this.writer.AppendFormat("q {2:0.###} 0 0 -{3:0.###} {0:0.###} {4:0.###} cm 100 Tz {5} Do Q\n",
                //  x, y, cx, cy, y + 220/1.5, formName);

                PdfTransparencyGroupAttributes tgAttributes = new PdfTransparencyGroupAttributes(this.writer.Owner);
                this.writer.Owner.Internals.AddObject(tgAttributes);

                tgAttributes.Elements.SetName(PdfTransparencyGroupAttributes.Keys.CS, "/DeviceRGB");


                // Set reference to transparency group attributes
                pdfForm.Elements.SetReference(PdfFormXObject.Keys.Group, tgAttributes);


                PdfSoftMask softmask = new PdfSoftMask(this.writer.Owner);
                this.writer.Owner.Internals.AddObject(softmask);
                softmask.Elements.SetName(PdfSoftMask.Keys.S, "/Luminosity");
                softmask.Elements.SetReference(PdfSoftMask.Keys.G, pdfForm);
                //pdfForm.Elements.SetName(PdfFormXObject.Keys.Type, "Group");
                //pdfForm.Elements.SetName(PdfFormXObject.Keys.ss.Ss.Type, "Group");

                PdfExtGState extGState = new PdfExtGState(this.writer.Owner);
                this.writer.Owner.Internals.AddObject(extGState);
                extGState.Elements.SetReference(PdfExtGState.Keys.SMask, softmask);
                this.writer.WriteGraphicState(extGState);
#endif
#endif
            }
        }
示例#17
0
        // --------------------------------------------------------------------------------------------

        #region Realizing graphical state

        /// <summary>
        /// Initializes the default view transformation, i.e. the transformation from the user page
        /// space to the PDF page space.
        /// </summary>
        void BeginPage()
        {
            if (_gfxState.Level == GraphicsStackLevelInitial)
            {
                // TODO: Is PageOriging and PageScale (== Viewport) useful? Or just public DefaultViewMatrix (like Presentation Manager has had)
                // May be a BeginContainer(windows, viewport) is useful for userer that are not familar with maxtrix transformations.

                // Flip page horizontally and mirror text.

                // PDF uses a standard right-handed Cartesian coordinate system with the y axis directed up
                // and the rotation counterclockwise. Windows uses the opposite convertion with y axis
                // directed down and rotation clockwise. When I started with PDFsharp I flipped pages horizontally
                // and then mirrored text to compensate the effect that the fipping turns text upside down.
                // I found this technique during analysis of PDF documents generated with PDFlib. Unfortunately
                // this technique leads to several problems with programms that compose or view PDF documents
                // generated with PDFsharp.
                // In PDFsharp 1.4 I implement a revised technique that does not need text mirroring any more.

                DefaultViewMatrix = new XMatrix();
                if (_gfx.PageDirection == XPageDirection.Downwards)
                {
                    // Take TrimBox into account.
                    PageHeightPt = Size.Height;
                    XPoint trimOffset = new XPoint();
                    if (_page != null && _page.TrimMargins.AreSet)
                    {
                        PageHeightPt += _page.TrimMargins.Top.Point + _page.TrimMargins.Bottom.Point;
                        trimOffset = new XPoint(_page.TrimMargins.Left.Point, _page.TrimMargins.Top.Point);
                    }

                    // Scale with page units.
                    switch (_gfx.PageUnit)
                    {
                        case XGraphicsUnit.Point:
                            // Factor is 1.
                            // DefaultViewMatrix.ScalePrepend(XUnit.PointFactor);
                            break;

                        case XGraphicsUnit.Presentation:
                            DefaultViewMatrix.ScalePrepend(XUnit.PresentationFactor);
                            break;

                        case XGraphicsUnit.Inch:
                            DefaultViewMatrix.ScalePrepend(XUnit.InchFactor);
                            break;

                        case XGraphicsUnit.Millimeter:
                            DefaultViewMatrix.ScalePrepend(XUnit.MillimeterFactor);
                            break;

                        case XGraphicsUnit.Centimeter:
                            DefaultViewMatrix.ScalePrepend(XUnit.CentimeterFactor);
                            break;
                    }

                    if (trimOffset != new XPoint())
                    {
                        Debug.Assert(_gfx.PageUnit == XGraphicsUnit.Point, "With TrimMargins set the page units must be Point. Ohter cases nyi.");
                        DefaultViewMatrix.TranslatePrepend(trimOffset.X, -trimOffset.Y);
                    }

                    // Save initial graphic state.
                    SaveState();

                    // Set default page transformation, if any.
                    if (!DefaultViewMatrix.IsIdentity)
                    {
                        Debug.Assert(_gfxState.RealizedCtm.IsIdentity);
                        //_gfxState.RealizedCtm = DefaultViewMatrix;
                        const string format = Config.SignificantFigures7;
                        double[] cm = DefaultViewMatrix.GetElements();
                        AppendFormatArgs("{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "} {4:" + format + "} {5:" + format + "} cm ",
                                     cm[0], cm[1], cm[2], cm[3], cm[4], cm[5]);
                    }

                    // Set page transformation
                    //double[] cm = DefaultViewMatrix.GetElements();
                    //AppendFormat("{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "} {4:" + format + "} {5:" + format + "} cm ",
                    //  cm[0], cm[1], cm[2], cm[3], cm[4], cm[5]);
                }
                else
                {
                    // Scale with page units.
                    switch (_gfx.PageUnit)
                    {
                        case XGraphicsUnit.Point:
                            // Factor is 1.
                            // DefaultViewMatrix.ScalePrepend(XUnit.PointFactor);
                            break;

                        case XGraphicsUnit.Presentation:
                            DefaultViewMatrix.ScalePrepend(XUnit.PresentationFactor);
                            break;

                        case XGraphicsUnit.Inch:
                            DefaultViewMatrix.ScalePrepend(XUnit.InchFactor);
                            break;

                        case XGraphicsUnit.Millimeter:
                            DefaultViewMatrix.ScalePrepend(XUnit.MillimeterFactor);
                            break;

                        case XGraphicsUnit.Centimeter:
                            DefaultViewMatrix.ScalePrepend(XUnit.CentimeterFactor);
                            break;
                    }

                    // Save initial graphic state.
                    SaveState();
                    // Set page transformation.
                    const string format = Config.SignificantFigures7;
                    double[] cm = DefaultViewMatrix.GetElements();
                    AppendFormat3Points("{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "} {4:" + format + "} {5:" + format + "} cm ",
                        cm[0], cm[1], cm[2], cm[3], cm[4], cm[5]);
                }
            }
        }
        /// <summary>
        /// Appends a Bézier curve for an arc within a full quadrant.
        /// </summary>
        static void AppendPartialArcQuadrant(List <XPoint> points, double x, double y, double width, double height, double α, double β, PathStart pathStart, XMatrix matrix)
        {
            Debug.Assert(α >= 0 && α <= 360);
            Debug.Assert(β >= 0);
            if (β > 360)
            {
                β = β - Math.Floor(β / 360) * 360;
            }
            Debug.Assert(Math.Abs(α - β) <= 90);

            // Scanling factor
            double δx = width / 2;
            double δy = height / 2;

            // Center of ellipse
            double x0 = x + δx;
            double y0 = y + δy;

            // We have the following quarters:
            //     |
            //   2 | 3
            // ----+-----
            //   1 | 0
            //     |
            // If the angles lie in quarter 2 or 3, their values are subtracted by 180 and the
            // resulting curve is reflected at the center. This algorithm works as expected (simply tried out).
            // There may be a mathematically more elegant solution...
            bool reflect = false;

            if (α >= 180 && β >= 180)
            {
                α      -= 180;
                β      -= 180;
                reflect = true;
            }

            double cosα, cosβ, sinα, sinβ;

            if (width == height)
            {
                // Circular arc needs no correction.
                α = α * Calc.Deg2Rad;
                β = β * Calc.Deg2Rad;
            }
            else
            {
                // Elliptic arc needs the angles to be adjusted such that the scaling transformation is compensated.
                α    = α * Calc.Deg2Rad;
                sinα = Math.Sin(α);
                if (Math.Abs(sinα) > 1E-10)
                {
                    α = Calc.πHalf - Math.Atan(δy * Math.Cos(α) / (δx * sinα));
                }
                β    = β * Calc.Deg2Rad;
                sinβ = Math.Sin(β);
                if (Math.Abs(sinβ) > 1E-10)
                {
                    β = Calc.πHalf - Math.Atan(δy * Math.Cos(β) / (δx * sinβ));
                }
            }

            double κ = 4 * (1 - Math.Cos((α - β) / 2)) / (3 * Math.Sin((β - α) / 2));

            sinα = Math.Sin(α);
            cosα = Math.Cos(α);
            sinβ = Math.Sin(β);
            cosβ = Math.Cos(β);

            //XPoint pt1, pt2, pt3;
            if (!reflect)
            {
                // Calculation for quarter 0 and 1
                switch (pathStart)
                {
                case PathStart.MoveTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα)));
                    break;

                case PathStart.LineTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα)));
                    break;

                case PathStart.Ignore1st:
                    break;
                }
                points.Add(matrix.Transform(new XPoint(x0 + δx * (cosα - κ * sinα), y0 + δy * (sinα + κ * cosα))));
                points.Add(matrix.Transform(new XPoint(x0 + δx * (cosβ + κ * sinβ), y0 + δy * (sinβ - κ * cosβ))));
                points.Add(matrix.Transform(new XPoint(x0 + δx * cosβ, y0 + δy * sinβ)));
            }
            else
            {
                // Calculation for quarter 2 and 3
                switch (pathStart)
                {
                case PathStart.MoveTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα)));
                    break;

                case PathStart.LineTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα)));
                    break;

                case PathStart.Ignore1st:
                    break;
                }
                points.Add(matrix.Transform(new XPoint(x0 - δx * (cosα - κ * sinα), y0 - δy * (sinα + κ * cosα))));
                points.Add(matrix.Transform(new XPoint(x0 - δx * (cosβ + κ * sinβ), y0 - δy * (sinβ - κ * cosβ))));
                points.Add(matrix.Transform(new XPoint(x0 - δx * cosβ, y0 - δy * sinβ)));
            }
        }
示例#19
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 /// <summary>
 /// Determines whether this matrix is equal to the specified matrix.
 /// </summary>
 public bool Equals(XMatrix value)
 {
     return Equals(this, value);
 }
        /// <summary>
        /// Creates between 1 and 5 Béziers curves from parameters specified like in WPF.
        /// </summary>
        public static List <XPoint> BezierCurveFromArc(XPoint point1, XPoint point2, double rotationAngle,
                                                       XSize size, bool isLargeArc, bool clockwise, PathStart pathStart)
        {
#if DEBUG_
            if (size == new XSize(115, 115))
            {
                Debugger.Break();
            }
#endif
            // See also http://www.charlespetzold.com/blog/blog.xml from January 2, 2008
            double δx = size.Width;
            double δy = size.Height;
            Debug.Assert(δx * δy > 0);
            double factor             = δy / δx;
            bool   isCounterclockwise = !clockwise;

            // Adjust for different radii and rotation angle
            XMatrix matrix = new XMatrix();
            matrix.RotateAppend(-rotationAngle);
            matrix.ScaleAppend(δy / δx, 1);
            XPoint pt1 = matrix.Transform(point1);
            XPoint pt2 = matrix.Transform(point2);

            // Get info about chord that connects both points
            XPoint  midPoint  = new XPoint((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);
            XVector vect      = pt2 - pt1;
            double  halfChord = vect.Length / 2;

            // Get vector from chord to center
            XVector vectRotated;

            // (comparing two Booleans here!)
            if (isLargeArc == isCounterclockwise)
            {
                vectRotated = new XVector(-vect.Y, vect.X);
            }
            else
            {
                vectRotated = new XVector(vect.Y, -vect.X);
            }

            vectRotated.Normalize();

            // Distance from chord to center
            double centerDistance = Math.Sqrt(δy * δy - halfChord * halfChord);
            if (double.IsNaN(centerDistance))
            {
                centerDistance = 0;
            }

            // Calculate center point
            XPoint center = midPoint + centerDistance * vectRotated;

            // Get angles from center to the two points
            double α = Math.Atan2(pt1.Y - center.Y, pt1.X - center.X);
            double β = Math.Atan2(pt2.Y - center.Y, pt2.X - center.X);

            // (another comparison of two Booleans!)
            if (isLargeArc == (Math.Abs(β - α) < Math.PI))
            {
                if (α < β)
                {
                    α += 2 * Math.PI;
                }
                else
                {
                    β += 2 * Math.PI;
                }
            }

            // Invert matrix for final point calculation
            matrix.Invert();
            double sweepAngle = β - α;

            // Let the algorithm of GDI+ DrawArc to Bézier curves do the rest of the job
            return(BezierCurveFromArc(center.X - δx * factor, center.Y - δy, 2 * δx * factor, 2 * δy,
                                      α / Calc.Deg2Rad, sweepAngle / Calc.Deg2Rad, pathStart, ref matrix));
        }
示例#21
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static XMatrix CreateScaling(double scaleX, double scaleY, double centerX, double centerY)
 {
     XMatrix matrix = new XMatrix();
     matrix.SetMatrix(scaleX, 0, 0, scaleY, centerX - scaleX * centerX, centerY - scaleY * centerY, XMatrixTypes.Scaling | XMatrixTypes.Translation);
     return matrix;
 }
        //+-------------------------------------------------------------------------------------------------
        //
        //  Function: ArcToBezier
        //
        //  Synopsis: Compute the Bezier approximation of an arc
        //
        //  Notes:    This utilitycomputes the Bezier approximation for an elliptical arc as it is defined
        //            in the SVG arc spec. The ellipse from which the arc is carved is axis-aligned in its
        //            own coordinates, and defined there by its x and y radii. The rotation angle defines
        //            how the ellipse's axes are rotated relative to our x axis. The start and end points
        //            define one of 4 possible arcs; the sweep and large-arc flags determine which one of
        //            these arcs will be chosen. See SVG spec for details.
        //
        //            Returning pieces = 0 indicates a line instead of an arc
        //                      pieces = -1 indicates that the arc degenerates to a point
        //
        //--------------------------------------------------------------------------------------------------
        public static PointCollection ArcToBezier(double xStart, double yStart, double xRadius, double yRadius, double rotationAngle,
                                                  bool isLargeArc, bool isClockwise, double xEnd, double yEnd, out int pieces)
        {
            double  cosArcAngle, sinArcAngle, xCenter, yCenter, r, bezDist;
            XVector vecToBez1, vecToBez2;
            XMatrix matToEllipse;

            double fuzz2        = FUZZ * FUZZ;
            bool   isZeroCenter = false;

            pieces = -1;

            // In the following, the line segment between between the arc's start and
            // end points is referred to as "the chord".

            // Transform 1: Shift the origin to the chord's midpoint
            double x = (xEnd - xStart) / 2;
            double y = (yEnd - yStart) / 2;

            double halfChord2 = x * x + y * y;     // (half chord length)^2

            // Degenerate case: single point
            if (halfChord2 < fuzz2)
            {
                // The chord degeneartes to a point, the arc will be ignored
                return(null);
            }

            // Degenerate case: straight line
            if (!AcceptRadius(halfChord2, fuzz2, ref xRadius) || !AcceptRadius(halfChord2, fuzz2, ref yRadius))
            {
                // We have a zero radius, add a straight line segment instead of an arc
                pieces = 0;
                return(null);
            }

            if (xRadius == 0 || yRadius == 0)
            {
                // We have a zero radius, add a straight line segment instead of an arc
                pieces = 0;
                return(null);
            }

            // Transform 2: Rotate to the ellipse's coordinate system
            rotationAngle = -rotationAngle * Calc.Deg2Rad;

            double cos = Math.Cos(rotationAngle);
            double sin = Math.Sin(rotationAngle);

            r = x * cos - y * sin;
            y = x * sin + y * cos;
            x = r;

            // Transform 3: Scale so that the ellipse will become a unit circle
            x /= xRadius;
            y /= yRadius;

            // We get to the center of that circle along a verctor perpendicular to the chord
            // from the origin, which is the chord's midpoint. By Pythagoras, the length of that
            // vector is sqrt(1 - (half chord)^2).

            halfChord2 = x * x + y * y;   // now in the circle coordinates

            if (halfChord2 > 1)
            {
                // The chord is longer than the circle's diameter; we scale the radii uniformly so
                // that the chord will be a diameter. The center will then be the chord's midpoint,
                // which is now the origin.
                r            = Math.Sqrt(halfChord2);
                xRadius     *= r;
                yRadius     *= r;
                xCenter      = yCenter = 0;
                isZeroCenter = true;

                // Adjust the unit-circle coordinates x and y
                x /= r;
                y /= r;
            }
            else
            {
                // The length of (-y,x) or (x,-y) is sqrt(rHalfChord2), and we want a vector
                // of length sqrt(1 - rHalfChord2), so we'll multiply it by:
                r = Math.Sqrt((1 - halfChord2) / halfChord2);
                //if (isLargeArc != (eSweepDirection == SweepDirection.Clockwise))
                if (isLargeArc != isClockwise)
                // Going to the center from the origin=chord-midpoint
                {
                    // in the direction of (-y, x)
                    xCenter = -r * y;
                    yCenter = r * x;
                }
                else
                {
                    // in the direction of (y, -x)
                    xCenter = r * y;
                    yCenter = -r * x;
                }
            }

            // Transformation 4: shift the origin to the center of the circle, which then becomes
            // the unit circle. Since the chord's midpoint is the origin, the start point is (-x, -y)
            // and the endpoint is (x, y).
            XPoint ptStart = new XPoint(-x - xCenter, -y - yCenter);
            XPoint ptEnd   = new XPoint(x - xCenter, y - yCenter);

            // Set up the matrix that will take us back to our coordinate system.  This matrix is
            // the inverse of the combination of transformation 1 thru 4.
            matToEllipse = new XMatrix(cos * xRadius, -sin * xRadius,
                                       sin * yRadius, cos * yRadius,
                                       (xEnd + xStart) / 2, (yEnd + yStart) / 2);

            if (!isZeroCenter)
            {
                // Prepend the translation that will take the origin to the circle's center
                matToEllipse.OffsetX += (matToEllipse.M11 * xCenter + matToEllipse.M21 * yCenter);
                matToEllipse.OffsetY += (matToEllipse.M12 * xCenter + matToEllipse.M22 * yCenter);
            }

            // Get the sine & cosine of the angle that will generate the arc pieces
            GetArcAngle(ptStart, ptEnd, isLargeArc, isClockwise, out cosArcAngle, out sinArcAngle, out pieces);

            // Get the vector to the first Bezier control point
            bezDist = GetBezierDistance(cosArcAngle, 1);

            //if (eSweepDirection == SweepDirection.Counterclockwise)
            if (!isClockwise)
            {
                bezDist = -bezDist;
            }

            vecToBez1 = new XVector(-bezDist * ptStart.Y, bezDist * ptStart.X);

            PointCollection result = new PointCollection();

            // Add the arc pieces, except for the last
            for (int idx = 1; idx < pieces; idx++)
            {
                // Get the arc piece's endpoint
                XPoint ptPieceEnd = new XPoint(ptStart.X * cosArcAngle - ptStart.Y * sinArcAngle, ptStart.X * sinArcAngle + ptStart.Y * cosArcAngle);
                vecToBez2 = new XVector(-bezDist * ptPieceEnd.Y, bezDist * ptPieceEnd.X);

                result.Add(matToEllipse.Transform(ptStart + vecToBez1));
                result.Add(matToEllipse.Transform(ptPieceEnd - vecToBez2));
                result.Add(matToEllipse.Transform(ptPieceEnd));

                // Move on to the next arc
                ptStart   = ptPieceEnd;
                vecToBez1 = vecToBez2;
            }

            // Last arc - we know the endpoint
            vecToBez2 = new XVector(-bezDist * ptEnd.Y, bezDist * ptEnd.X);

            result.Add(matToEllipse.Transform(ptStart + vecToBez1));
            result.Add(matToEllipse.Transform(ptEnd - vecToBez2));
            result.Add(new XPoint(xEnd, yEnd));

            return(result);
        }
示例#23
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
            // Fast mutiplication taking matrix type into account. Reflectored from WPF.
            internal static void MultiplyMatrix(ref XMatrix matrix1, ref XMatrix matrix2)
            {
                XMatrixTypes type1 = matrix1._type;
                XMatrixTypes type2 = matrix2._type;
                if (type2 != XMatrixTypes.Identity)
                {
                    if (type1 == XMatrixTypes.Identity)
                        matrix1 = matrix2;
                    else if (type2 == XMatrixTypes.Translation)
                    {
                        matrix1._offsetX += matrix2._offsetX;
                        matrix1._offsetY += matrix2._offsetY;
                        if (type1 != XMatrixTypes.Unknown)
                            matrix1._type |= XMatrixTypes.Translation;
                    }
                    else if (type1 == XMatrixTypes.Translation)
                    {
                        double num = matrix1._offsetX;
                        double num2 = matrix1._offsetY;
                        matrix1 = matrix2;
                        matrix1._offsetX = num * matrix2._m11 + num2 * matrix2._m21 + matrix2._offsetX;
                        matrix1._offsetY = num * matrix2._m12 + num2 * matrix2._m22 + matrix2._offsetY;
                        if (type2 == XMatrixTypes.Unknown)
                            matrix1._type = XMatrixTypes.Unknown;
                        else
                            matrix1._type = XMatrixTypes.Scaling | XMatrixTypes.Translation;
                    }
                    else
                    {
                        switch ((((int)type1) << 4) | (int)type2)
                        {
                            case 0x22:
                                matrix1._m11 *= matrix2._m11;
                                matrix1._m22 *= matrix2._m22;
                                return;

                            case 0x23:
                                matrix1._m11 *= matrix2._m11;
                                matrix1._m22 *= matrix2._m22;
                                matrix1._offsetX = matrix2._offsetX;
                                matrix1._offsetY = matrix2._offsetY;
                                matrix1._type = XMatrixTypes.Scaling | XMatrixTypes.Translation;
                                return;

                            case 0x24:
                            case 0x34:
                            case 0x42:
                            case 0x43:
                            case 0x44:
                                matrix1 = new XMatrix(
                                  matrix1._m11 * matrix2._m11 + matrix1._m12 * matrix2._m21,
                                  matrix1._m11 * matrix2._m12 + matrix1._m12 * matrix2._m22,
                                  matrix1._m21 * matrix2._m11 + matrix1._m22 * matrix2._m21,
                                  matrix1._m21 * matrix2._m12 + matrix1._m22 * matrix2._m22,
                                  matrix1._offsetX * matrix2._m11 + matrix1._offsetY * matrix2._m21 + matrix2._offsetX,
                                  matrix1._offsetX * matrix2._m12 + matrix1._offsetY * matrix2._m22 + matrix2._offsetY);
                                return;

                            case 50:
                                matrix1._m11 *= matrix2._m11;
                                matrix1._m22 *= matrix2._m22;
                                matrix1._offsetX *= matrix2._m11;
                                matrix1._offsetY *= matrix2._m22;
                                return;

                            case 0x33:
                                matrix1._m11 *= matrix2._m11;
                                matrix1._m22 *= matrix2._m22;
                                matrix1._offsetX = matrix2._m11 * matrix1._offsetX + matrix2._offsetX;
                                matrix1._offsetY = matrix2._m22 * matrix1._offsetY + matrix2._offsetY;
                                return;
                        }
                    }
                }
            }
示例#24
0
 /// <summary>
 /// Multiply the brush transformation matrix with the specified matrix.
 /// </summary>
 public void MultiplyTransform(XMatrix matrix)
 {
     _matrix.Prepend(matrix);
 }
示例#25
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 /// <summary>
 /// Appends the specified matrix to this matrix. 
 /// </summary>
 public void Append(XMatrix matrix)
 {
     this *= matrix;
 }
示例#26
0
 /// <summary>
 /// Multiply the brush transformation matrix with the specified matrix.
 /// </summary>
 public void MultiplyTransform(XMatrix matrix, XMatrixOrder order)
 {
     _matrix.Multiply(matrix, order);
 }
示例#27
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
        /// <summary>
        /// Multiplies this matrix with the specified matrix.
        /// </summary>
        public void Multiply(XMatrix matrix, XMatrixOrder order)
        {
            if (_type == XMatrixTypes.Identity)
                this = CreateIdentity();

            // Must use properties, the fields can be invalid if the matrix is identity matrix.
            double t11 = M11;
            double t12 = M12;
            double t21 = M21;
            double t22 = M22;
            double tdx = OffsetX;
            double tdy = OffsetY;

            if (order == XMatrixOrder.Append)
            {
                _m11 = t11 * matrix.M11 + t12 * matrix.M21;
                _m12 = t11 * matrix.M12 + t12 * matrix.M22;
                _m21 = t21 * matrix.M11 + t22 * matrix.M21;
                _m22 = t21 * matrix.M12 + t22 * matrix.M22;
                _offsetX = tdx * matrix.M11 + tdy * matrix.M21 + matrix.OffsetX;
                _offsetY = tdx * matrix.M12 + tdy * matrix.M22 + matrix.OffsetY;
            }
            else
            {
                _m11 = t11 * matrix.M11 + t21 * matrix.M12;
                _m12 = t12 * matrix.M11 + t22 * matrix.M12;
                _m21 = t11 * matrix.M21 + t21 * matrix.M22;
                _m22 = t12 * matrix.M21 + t22 * matrix.M22;
                _offsetX = t11 * matrix.OffsetX + t21 * matrix.OffsetY + tdx;
                _offsetY = t12 * matrix.OffsetX + t22 * matrix.OffsetY + tdy;
            }
            DeriveMatrixType();
        }
示例#28
0
 /// <summary>
 /// Resets the brush transformation matrix with identity matrix.
 /// </summary>
 public void ResetTransform()
 {
     _matrix = new XMatrix();
 }
 /// <summary>
 /// Modifies the current transformation matrix.
 /// </summary>
 public void MultiplyTransform(XMatrix matrix, XMatrixOrder order)
 {
   if (!matrix.IsIdentity)
   {
     this.MustRealizeCtm = true;
     this.unrealizedCtm.Multiply(matrix, order);
   }
 }
        /// <summary>
        /// Draws the vertical Y axis.
        /// </summary>
        internal override void Draw()
        {
            AxisRendererInfo yari = ((ChartRendererInfo)this.rendererParms.RendererInfo).yAxisRendererInfo;

            double yMin       = yari.MinimumScale;
            double yMax       = yari.MaximumScale;
            double yMajorTick = yari.MajorTick;
            double yMinorTick = yari.MinorTick;

            XMatrix matrix = new XMatrix(); //XMatrix.Identity;

            matrix.TranslatePrepend(-yMin, -yari.Y);
            matrix.Scale(yari.InnerRect.Width / (yMax - yMin), 1, XMatrixOrder.Append);
            matrix.Translate(yari.X, yari.Y, XMatrixOrder.Append);

            // Draw axis.
            // First draw tick marks, second draw axis.
            double majorTickMarkStart = 0, majorTickMarkEnd = 0,
                   minorTickMarkStart = 0, minorTickMarkEnd = 0;

            GetTickMarkPos(yari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd);

            XGraphics          gfx                = this.rendererParms.Graphics;
            LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, yari.LineFormat);

            XPoint[] points = new XPoint[2];
            if (yari.MinorTickMark != TickMarkType.None)
            {
                for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
                {
                    points[0].X = y;
                    points[0].Y = minorTickMarkStart;
                    points[1].X = y;
                    points[1].Y = minorTickMarkEnd;
                    matrix.TransformPoints(points);
                    lineFormatRenderer.DrawLine(points[0], points[1]);
                }
            }

            XStringFormat xsf = new XStringFormat();

            xsf.LineAlignment = XLineAlignment.Near;
            int countTickLabels = (int)((yMax - yMin) / yMajorTick) + 1;

            for (int i = 0; i < countTickLabels; ++i)
            {
                double y   = yMin + yMajorTick * i;
                string str = y.ToString(yari.TickLabelsFormat);

                XSize labelSize = gfx.MeasureString(str, yari.TickLabelsFont);
                if (yari.MajorTickMark != TickMarkType.None)
                {
                    labelSize.Height += 1.5f * yari.MajorTickMarkWidth;
                    points[0].X       = y;
                    points[0].Y       = majorTickMarkStart;
                    points[1].X       = y;
                    points[1].Y       = majorTickMarkEnd;
                    matrix.TransformPoints(points);
                    lineFormatRenderer.DrawLine(points[0], points[1]);
                }

                XPoint[] layoutText = new XPoint[1];
                layoutText[0].X = y;
                layoutText[0].Y = yari.Y + 1.5 * yari.MajorTickMarkWidth;
                matrix.TransformPoints(layoutText);
                layoutText[0].X -= labelSize.Width / 2; // Center text vertically.
                gfx.DrawString(str, yari.TickLabelsFont, yari.TickLabelsBrush, layoutText[0], xsf);
            }

            if (yari.LineFormat != null)
            {
                points[0].X = yMin;
                points[0].Y = yari.Y;
                points[1].X = yMax;
                points[1].Y = yari.Y;
                matrix.TransformPoints(points);
                if (yari.MajorTickMark != TickMarkType.None)
                {
                    // yMax is at the upper side of the axis
                    points[0].X -= yari.LineFormat.Width / 2;
                    points[1].X += yari.LineFormat.Width / 2;
                }
                lineFormatRenderer.DrawLine(points[0], points[1]);
            }

            // Draw axis title
            if (yari.axisTitleRendererInfo != null)
            {
                RendererParameters parms = new RendererParameters();
                parms.Graphics     = gfx;
                parms.RendererInfo = yari;
                XRect rcTitle = yari.Rect;
                rcTitle.Height = yari.axisTitleRendererInfo.Height;
                rcTitle.Y     += yari.Rect.Height - rcTitle.Height;
                yari.axisTitleRendererInfo.Rect = rcTitle;
                AxisTitleRenderer atr = new AxisTitleRenderer(parms);
                atr.Draw();
            }
        }
示例#31
0
        ///// <summary>
        ///// The world transform in PDF world space.
        ///// </summary>
        //public XMatrix EffectiveCtm
        //{
        //  get
        //  {
        //    //if (MustRealizeCtm)
        //    if (!UnrealizedCtm.IsIdentity)
        //    {
        //      XMatrix matrix = RealizedCtm;
        //      matrix.Prepend(UnrealizedCtm);
        //      return matrix;
        //    }
        //    return RealizedCtm;
        //  }
        //  //set
        //  //{
        //  //  XMatrix matrix = realizedCtm;
        //  //  matrix.Invert();
        //  //  matrix.Prepend(value);
        //  //  unrealizedCtm = matrix;
        //  //  MustRealizeCtm = !unrealizedCtm.IsIdentity;
        //  //}
        //}

        public void AddTransform(XMatrix value, XMatrixOrder matrixOrder)
        {
            // TODO: User matrixOrder
#if DEBUG
            if (matrixOrder == XMatrixOrder.Append)
                throw new NotImplementedException("XMatrixOrder.Append");
#endif
            XMatrix transform = value;
            if (_renderer.Gfx.PageDirection == XPageDirection.Downwards)
            {
                // Take chirality into account and
                // invert the direction of rotation.
                transform.M12 = -value.M12;
                transform.M21 = -value.M21;
            }
            UnrealizedCtm.Prepend(transform);

            WorldTransform.Prepend(value);
        }
        /// <summary>
        /// Writes a Glyphs to the content stream.
        /// </summary>
        private void WriteGlyphs(Glyphs glyphs)
        {
            WriteSaveState("begin Glyphs", glyphs.Name);

            // Transform also affects clipping and opacity mask
            bool transformed = glyphs.RenderTransform != null;

            if (transformed)
            {
                WriteRenderTransform(glyphs.RenderTransform);
            }

            bool clipped = glyphs.Clip != null;

            if (clipped)
            {
                WriteClip(glyphs.Clip);
            }

            if (glyphs.Opacity < 1)
            {
                MultiplyOpacity(glyphs.Opacity);
            }

            if (glyphs.OpacityMask != null)
            {
                WriteOpacityMask(glyphs.OpacityMask);
            }

            XMatrix textMatrix = new XMatrix();

            textMatrix.TranslatePrepend(glyphs.OriginX, glyphs.OriginY);
            glyphs.OriginX = glyphs.OriginY = 0; // HACK: do not change model

            double emSize = glyphs.FontRenderingEmSize;

            textMatrix.ScalePrepend(glyphs.FontRenderingEmSize);
            glyphs.FontRenderingEmSize = 1; // HACK: do not change model


            bool boldSimulation = (glyphs.StyleSimulations & StyleSimulations.BoldSimulation) == StyleSimulations.BoldSimulation;

            // just a draft...
            if (boldSimulation)
            {
                boldSimulation = true;

                // draw black stroke if it is not a solid color brush
                XColor color = XColor.FromArgb(0, 0, 0);
                if (glyphs.Fill is SolidColorBrush)
                {
                    SolidColorBrush brush = glyphs.Fill as SolidColorBrush;
                    color = brush.Color;
                }
                WriteLiteral(String.Format(CultureInfo.InvariantCulture, "{0:0.###} {1:0.###} {2:0.###}  RG\n", color.R / 255.0, color.G / 255.0, color.B / 255.0));
                WriteLiteral("{0:0.###} w\n", emSize / 50);
            }

            if ((glyphs.StyleSimulations & StyleSimulations.ItalicSimulation) == StyleSimulations.ItalicSimulation)
            {
                textMatrix.SkewPrepend(-20, 0);
            }

            XForm  xform  = null;
            XImage ximage = null;

            RealizeFill(glyphs.Fill, ref xform, ref ximage);
            RealizeFont(glyphs);

            if (boldSimulation)
            {
                WriteLiteral("2 Tr\n", 1);
            }

            double x = glyphs.OriginX;
            double y = glyphs.OriginY;


            //switch (format.Alignment)
            //{
            //  case XStringAlignment.Near:
            //    // nothing to do
            //    break;

            //  case XStringAlignment.Center:
            //    x += (rect.Width - width) / 2;
            //    break;

            //  case XStringAlignment.Far:
            //    x += rect.Width - width;
            //    break;
            //}

            PdfFont realizedFont = this.graphicsState.realizedFont;

            Debug.Assert(realizedFont != null);
            realizedFont.AddChars(glyphs.UnicodeString);

            OpenTypeDescriptor descriptor = realizedFont.FontDescriptor.descriptor;

            //if (bold && !descriptor.IsBoldFace)
            //{
            //  // TODO: emulate bold by thicker outline
            //}

            //if (italic && !descriptor.IsBoldFace)
            //{
            //  // TODO: emulate italic by shearing transformation
            //}

#if true
            string s2 = "";
            string s  = glyphs.UnicodeString;
            if (!String.IsNullOrEmpty(s))
            {
                int length = s.Length;
                for (int idx = 0; idx < length; idx++)
                {
                    char ch      = s[idx];
                    int  glyphID = 0;
                    if (descriptor.fontData.cmap.symbol)
                    {
                        glyphID = (int)ch + (descriptor.fontData.os2.usFirstCharIndex & 0xFF00);
                        glyphID = descriptor.CharCodeToGlyphIndex((char)glyphID);
                    }
                    else
                    {
                        glyphID = descriptor.CharCodeToGlyphIndex(ch);
                    }
                    s2 += (char)glyphID;
                }
            }
            s = s2;
#endif

            byte[] bytes = PdfEncoders.RawUnicodeEncoding.GetBytes(s);
            bytes = PdfEncoders.FormatStringLiteral(bytes, true, false, true, null);
            string text = PdfEncoders.RawEncoding.GetString(bytes);
            if (glyphs.IsSideways)
            {
                textMatrix.RotateAtPrepend(-90, new XPoint(x, y));
                XPoint pos = new XPoint(x, y);
                AdjustTextMatrix(ref pos);
                //WriteTextTransform(textMatrix);
                WriteLiteral("{0} Tj\n", text);
            }
            else
            {
#if true
                //if (glyphs.BidiLevel % 2 == 1)
                //  WriteLiteral("-1 Tc\n");

                if (!textMatrix.IsIdentity)
                {
                    WriteTextTransform(textMatrix);
                }

                WriteGlyphsInternal(glyphs, null);
#else
                XPoint pos = new XPoint(x, y);
                AdjustTextMatrix(ref pos);
                WriteLiteral("{0:0.###} {1:0.###} Td {2} Tj\n", pos.x, pos.y, text);
                //PdfEncoders.ToStringLiteral(s, PdfStringEncoding.RawEncoding, null));
#endif
            }
            WriteRestoreState("end Glyphs", glyphs.Name);
        }
示例#33
0
 public static XVector Multiply(XVector vector, XMatrix matrix)
 {
     return matrix.Transform(vector);
 }
示例#34
0
 /// <summary>
 /// Creates a literal from an XMatrix
 /// </summary>
 public static PdfLiteral FromMatrix(XMatrix matrix)
 {
     return(new PdfLiteral("[" + PdfEncoders.ToString(matrix) + "]"));
 }
示例#35
0
        // ----- DrawString ---------------------------------------------------------------------------

        public void DrawString(string s, XFont font, XBrush brush, XRect rect, XStringFormat format)
        {
            double x = rect.X;
            double y = rect.Y;

            double lineSpace = font.GetHeight();
            double cyAscent = lineSpace * font.CellAscent / font.CellSpace;
            double cyDescent = lineSpace * font.CellDescent / font.CellSpace;
            double width = _gfx.MeasureString(s, font).Width;

            //bool bold = (font.Style & XFontStyle.Bold) != 0;
            //bool italic = (font.Style & XFontStyle.Italic) != 0;
            bool italicSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.ItalicSimulation) != 0;
            bool boldSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.BoldSimulation) != 0;
            bool strikeout = (font.Style & XFontStyle.Strikeout) != 0;
            bool underline = (font.Style & XFontStyle.Underline) != 0;

            Realize(font, brush, boldSimulation ? 2 : 0);

            switch (format.Alignment)
            {
                case XStringAlignment.Near:
                    // nothing to do
                    break;

                case XStringAlignment.Center:
                    x += (rect.Width - width) / 2;
                    break;

                case XStringAlignment.Far:
                    x += rect.Width - width;
                    break;
            }
            if (Gfx.PageDirection == XPageDirection.Downwards)
            {
                switch (format.LineAlignment)
                {
                    case XLineAlignment.Near:
                        y += cyAscent;
                        break;

                    case XLineAlignment.Center:
                        // TODO: Use CapHeight. PDFlib also uses 3/4 of ascent
                        y += (cyAscent * 3 / 4) / 2 + rect.Height / 2;
                        break;

                    case XLineAlignment.Far:
                        y += -cyDescent + rect.Height;
                        break;

                    case XLineAlignment.BaseLine:
                        // Nothing to do.
                        break;
                }
            }
            else
            {
                switch (format.LineAlignment)
                {
                    case XLineAlignment.Near:
                        y += cyDescent;
                        break;

                    case XLineAlignment.Center:
                        // TODO: Use CapHeight. PDFlib also uses 3/4 of ascent
                        y += -(cyAscent * 3 / 4) / 2 + rect.Height / 2;
                        break;

                    case XLineAlignment.Far:
                        y += -cyAscent + rect.Height;
                        break;

                    case XLineAlignment.BaseLine:
                        // Nothing to do.
                        break;
                }
            }

            PdfFont realizedFont = _gfxState._realizedFont;
            Debug.Assert(realizedFont != null);
            realizedFont.AddChars(s);

            const string format2 = Config.SignificantFigures4;
            OpenTypeDescriptor descriptor = realizedFont.FontDescriptor._descriptor;

            string text = null;
            if (font.Unicode)
            {
                StringBuilder sb = new StringBuilder();
                bool isSymbolFont = descriptor.FontFace.cmap.symbol;
                for (int idx = 0; idx < s.Length; idx++)
                {
                    char ch = s[idx];
                    if (isSymbolFont)
                    {
                        // Remap ch for symbol fonts.
                        ch = (char)(ch | (descriptor.FontFace.os2.usFirstCharIndex & 0xFF00));  // @@@ refactor
                    }
                    int glyphID = descriptor.CharCodeToGlyphIndex(ch);
                    sb.Append((char)glyphID);
                }
                s = sb.ToString();

                byte[] bytes = PdfEncoders.RawUnicodeEncoding.GetBytes(s);
                bytes = PdfEncoders.FormatStringLiteral(bytes, true, false, true, null);
                text = PdfEncoders.RawEncoding.GetString(bytes, 0, bytes.Length);
            }
            else
            {
                byte[] bytes = PdfEncoders.WinAnsiEncoding.GetBytes(s);
                text = PdfEncoders.ToStringLiteral(bytes, false, null);
            }

            // Map absolute position to PDF world space.
            XPoint pos = new XPoint(x, y);
            pos = WorldToView(pos);

            double verticalOffset = 0;
            if (boldSimulation)
            {
                // Adjust baseline in case of bold simulation???
                // No, because this would change the center of the glyphs.
                //verticalOffset = font.Size * Const.BoldEmphasis / 2;
            }

#if ITALIC_SIMULATION
            if (italicSimulation)
            {
                if (_gfxState.ItalicSimulationOn)
                {
                    AdjustTdOffset(ref pos, verticalOffset, true);
                    AppendFormatArgs("{0:" + format2 + "} {1:" + format2 + "} Td\n{2} Tj\n", pos.X, pos.Y, text);
                }
                else
                {
                    // Italic simulation is done by skewing characters 20° to the right.
                    XMatrix m = new XMatrix(1, 0, Const.ItalicSkewAngleSinus, 1, pos.X, pos.Y);
                    AppendFormatArgs("{0:" + format2 + "} {1:" + format2 + "} {2:" + format2 + "} {3:" + format2 + "} {4:" + format2 + "} {5:" + format2 + "} Tm\n{6} Tj\n",
                        m.M11, m.M12, m.M21, m.M22, m.OffsetX, m.OffsetY, text);
                    _gfxState.ItalicSimulationOn = true;
                    AdjustTdOffset(ref pos, verticalOffset, false);
                }
            }
            else
            {
                if (_gfxState.ItalicSimulationOn)
                {
                    XMatrix m = new XMatrix(1, 0, 0, 1, pos.X, pos.Y);
                    AppendFormatArgs("{0:" + format2 + "} {1:" + format2 + "} {2:" + format2 + "} {3:" + format2 + "} {4:" + format2 + "} {5:" + format2 + "} Tm\n{6} Tj\n",
                        m.M11, m.M12, m.M21, m.M22, m.OffsetX, m.OffsetY, text);
                    _gfxState.ItalicSimulationOn = false;
                    AdjustTdOffset(ref pos, verticalOffset, false);
                }
                else
                {
                    AdjustTdOffset(ref pos, verticalOffset, false);
                    AppendFormatArgs("{0:" + format2 + "} {1:" + format2 + "} Td {2} Tj\n", pos.X, pos.Y, text);
                }
            }
#else
                AdjustTextMatrix(ref pos);
                AppendFormat2("{0:" + format2 + "} {1:" + format2 + "} Td {2} Tj\n", pos.X, pos.Y, text);
#endif
            if (underline)
            {
                double underlinePosition = lineSpace * realizedFont.FontDescriptor._descriptor.UnderlinePosition / font.CellSpace;
                double underlineThickness = lineSpace * realizedFont.FontDescriptor._descriptor.UnderlineThickness / font.CellSpace;
                //DrawRectangle(null, brush, x, y - underlinePosition, width, underlineThickness);
                double underlineRectY = Gfx.PageDirection == XPageDirection.Downwards
                    ? y - underlinePosition
                    : y + underlinePosition - underlineThickness;
                DrawRectangle(null, brush, x, underlineRectY, width, underlineThickness);
            }

            if (strikeout)
            {
                double strikeoutPosition = lineSpace * realizedFont.FontDescriptor._descriptor.StrikeoutPosition / font.CellSpace;
                double strikeoutSize = lineSpace * realizedFont.FontDescriptor._descriptor.StrikeoutSize / font.CellSpace;
                //DrawRectangle(null, brush, x, y - strikeoutPosition - strikeoutSize, width, strikeoutSize);
                double strikeoutRectY = Gfx.PageDirection == XPageDirection.Downwards
                    ? y - strikeoutPosition
                    : y + strikeoutPosition - strikeoutSize;
                DrawRectangle(null, brush, x, strikeoutRectY, width, strikeoutSize);
            }
        }
示例#36
0
 public static XVector Multiply(XVector vector, XMatrix matrix)
 {
     return(matrix.Transform(vector));
 }
示例#37
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
        /// <summary>
        /// Determines whether the two matrices are equal.
        /// </summary>
        public static bool Equals(XMatrix matrix1, XMatrix matrix2)
        {
            if (matrix1.IsDistinguishedIdentity || matrix2.IsDistinguishedIdentity)
                return matrix1.IsIdentity == matrix2.IsIdentity;

            return matrix1.M11.Equals(matrix2.M11) && matrix1.M12.Equals(matrix2.M12) &&
              matrix1.M21.Equals(matrix2.M21) && matrix1.M22.Equals(matrix2.M22) &&
              matrix1.OffsetX.Equals(matrix2.OffsetX) && matrix1.OffsetY.Equals(matrix2.OffsetY);
        }
示例#38
0
        /// <summary>
        /// Draws the vertical Y axis.
        /// </summary>
        internal override void Draw()
        {
            AxisRendererInfo yari = ((ChartRendererInfo)_rendererParms.RendererInfo).yAxisRendererInfo;

            double yMin       = yari.MinimumScale;
            double yMax       = yari.MaximumScale;
            double yMajorTick = yari.MajorTick;
            double yMinorTick = yari.MinorTick;

            XMatrix matrix = new XMatrix();

            matrix.TranslatePrepend(-yari.InnerRect.X, yMax);
            matrix.Scale(1, yari.InnerRect.Height / (yMax - yMin), XMatrixOrder.Append);
            matrix.ScalePrepend(1, -1); // mirror horizontal
            matrix.Translate(yari.InnerRect.X, yari.InnerRect.Y, XMatrixOrder.Append);

            // Draw axis.
            // First draw tick marks, second draw axis.
            double majorTickMarkStart = 0, majorTickMarkEnd = 0,
                   minorTickMarkStart = 0, minorTickMarkEnd = 0;

            GetTickMarkPos(yari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd);

            XGraphics          gfx                     = _rendererParms.Graphics;
            LineFormatRenderer lineFormatRenderer      = new LineFormatRenderer(gfx, yari.LineFormat);
            LineFormatRenderer minorTickMarkLineFormat = new LineFormatRenderer(gfx, yari.MinorTickMarkLineFormat);
            LineFormatRenderer majorTickMarkLineFormat = new LineFormatRenderer(gfx, yari.MajorTickMarkLineFormat);

            XPoint[] points = new XPoint[2];

            // Draw minor tick marks.
            if (yari.MinorTickMark != TickMarkType.None)
            {
                for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
                {
                    points[0].X = minorTickMarkStart;
                    points[0].Y = y;
                    points[1].X = minorTickMarkEnd;
                    points[1].Y = y;
                    matrix.TransformPoints(points);
                    minorTickMarkLineFormat.DrawLine(points[0], points[1]);
                }
            }

            double lineSpace = yari.TickLabelsFont.GetHeight(); // old: yari.TickLabelsFont.GetHeight(gfx);
            int    cellSpace = yari.TickLabelsFont.FontFamily.GetLineSpacing(yari.TickLabelsFont.Style);
            double xHeight   = yari.TickLabelsFont.Metrics.XHeight;

            XSize labelSize = new XSize(0, 0);

            labelSize.Height = lineSpace * xHeight / cellSpace;

            int countTickLabels = (int)((yMax - yMin) / yMajorTick) + 1;

            for (int i = 0; i < countTickLabels; ++i)
            {
                double y   = yMin + yMajorTick * i;
                string str = y.ToString(yari.TickLabelsFormat);

                labelSize.Width = gfx.MeasureString(str, yari.TickLabelsFont).Width;

                // Draw major tick marks.
                if (yari.MajorTickMark != TickMarkType.None)
                {
                    labelSize.Width += yari.MajorTickMarkWidth * 1.5;
                    points[0].X      = majorTickMarkStart;
                    points[0].Y      = y;
                    points[1].X      = majorTickMarkEnd;
                    points[1].Y      = y;
                    matrix.TransformPoints(points);
                    majorTickMarkLineFormat.DrawLine(points[0], points[1]);
                }
                else
                {
                    labelSize.Width += SpaceBetweenLabelAndTickmark;
                }

                // Draw label text.
                XPoint[] layoutText = new XPoint[1];
                layoutText[0].X = yari.InnerRect.X + yari.InnerRect.Width - labelSize.Width;
                layoutText[0].Y = y;
                matrix.TransformPoints(layoutText);
                layoutText[0].Y += labelSize.Height / 2; // Center text vertically.
                gfx.DrawString(str, yari.TickLabelsFont, yari.TickLabelsBrush, layoutText[0]);
            }

            // Draw axis.
            if (yari.LineFormat != null && yari.LineFormat.Width > 0)
            {
                points[0].X = yari.InnerRect.X + yari.InnerRect.Width;
                points[0].Y = yMin;
                points[1].X = yari.InnerRect.X + yari.InnerRect.Width;
                points[1].Y = yMax;
                matrix.TransformPoints(points);
                if (yari.MajorTickMark != TickMarkType.None)
                {
                    // yMax is at the upper side of the axis
                    points[1].Y -= yari.LineFormat.Width / 2;
                    points[0].Y += yari.LineFormat.Width / 2;
                }
                lineFormatRenderer.DrawLine(points[0], points[1]);
            }

            // Draw axis title
            if (yari._axisTitleRendererInfo != null && yari._axisTitleRendererInfo.AxisTitleText != "")
            {
                RendererParameters parms = new RendererParameters();
                parms.Graphics     = gfx;
                parms.RendererInfo = yari;
                double width = yari._axisTitleRendererInfo.Width;
                yari._axisTitleRendererInfo.Rect  = yari.InnerRect;
                yari._axisTitleRendererInfo.Width = width;
                AxisTitleRenderer atr = new AxisTitleRenderer(parms);
                atr.Draw();
            }
        }
示例#39
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static XMatrix CreateTranslation(double offsetX, double offsetY)
 {
     XMatrix matrix = new XMatrix();
     matrix.SetMatrix(1, 0, 0, 1, offsetX, offsetY, XMatrixTypes.Translation);
     return matrix;
 }
示例#40
0
 public AbstractMatrix(float m11, float m12, float m21, float m22, float dx, float dy)
 {
     matrix = new XMatrix(m11, m12, m21, m22, dx, dy);
 }
示例#41
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static XMatrix CreateScaling(double scaleX, double scaleY)
 {
     XMatrix matrix = new XMatrix();
     matrix.SetMatrix(scaleX, 0, 0, scaleY, 0, 0, XMatrixTypes.Scaling);
     return matrix;
 }
        internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form)
            : base(thisDocument)
        {
            Elements.SetName(Keys.Type, "/XObject");
            Elements.SetName(Keys.Subtype, "/Form");

            if (form.IsTemplate)
            {
                Debug.Assert(importedObjectTable == null);
                // TODO more initialization here???
                return;
            }
            Debug.Assert(importedObjectTable != null);
            Debug.Assert(ReferenceEquals(thisDocument, importedObjectTable.Owner));

            XPdfForm pdfForm = form;
            // Get import page
            PdfPages importPages = importedObjectTable.ExternalDocument.Pages;

            if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count)
            {
                PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path);
            }
            PdfPage importPage = importPages[pdfForm.PageNumber - 1];

            // Import resources
            PdfItem res = importPage.Elements["/Resources"];

            if (res != null) // unlikely but possible
            {
#if true
                // Get root object
                PdfObject root;
                if (res is PdfReference)
                {
                    root = ((PdfReference)res).Value;
                }
                else
                {
                    root = (PdfDictionary)res;
                }

                root = ImportClosure(importedObjectTable, thisDocument, root);
                // If the root was a direct object, make it indirect.
                if (root.Reference == null)
                {
                    thisDocument._irefTable.Add(root);
                }

                Debug.Assert(root.Reference != null);
                Elements["/Resources"] = root.Reference;
#else
                // Get transitive closure
                PdfObject[] resources = importPage.Owner.Internals.GetClosure(resourcesRoot);
                int         count     = resources.Length;
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif
                // 1st step. Already imported objects are reused and new ones are cloned.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    if (importedObjectTable.Contains(obj.ObjectID))
                    {
                        // external object was already imported
                        PdfReference iref = importedObjectTable[obj.ObjectID];
                        Debug.Assert(iref != null);
                        Debug.Assert(iref.Value != null);
                        Debug.Assert(iref.Document == Owner);
                        // replace external object by the already clone counterpart
                        resources[idx] = iref.Value;
                    }
                    else
                    {
                        // External object was not imported ealier and must be cloned
                        PdfObject clone = obj.Clone();
                        Debug.Assert(clone.Reference == null);
                        clone.Document = Owner;
                        if (obj.Reference != null)
                        {
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                            // save old object identifier
                            importedObjectTable.Add(obj.ObjectID, clone.Reference);
                            //Debug.WriteLine("Cloned: " + obj.ObjectID.ToString());
                        }
                        else
                        {
                            // The root object (the /Resources value) is not an indirect object
                            Debug.Assert(idx == 0);
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                        }
                        // replace external object by its clone
                        resources[idx] = clone;
                    }
                }
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif

                // 2nd step. Fix up indirect references that still refers to the import document.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    Debug.Assert(obj.Owner != null);
                    FixUpObject(importedObjectTable, importedObjectTable.Owner, obj);
                }

                // Set resources key to the root of the clones
                Elements["/Resources"] = resources[0].Reference;
#endif
            }

            // Take /Rotate into account
            PdfRectangle rect   = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox);
            int          rotate = importPage.Elements.GetInteger(PdfPage.Keys.Rotate);
            //rotate = 0;
            if (rotate == 0)
            {
                // Set bounding box to media box
                Elements["/BBox"] = rect;
            }
            else
            {
                // TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem)
                Elements["/BBox"] = rect;

                // Rotate the image such that it is upright
                XMatrix matrix = new XMatrix();
                double  width  = rect.Width;
                double  height = rect.Height;
                matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2));

                // Translate the image such that its center lies on the center of the rotated bounding box
                double offset = (height - width) / 2;
                if (height > width)
                {
                    matrix.TranslatePrepend(offset, offset);
                }
                else
                {
                    matrix.TranslatePrepend(-offset, -offset);
                }

                //string item = "[" + PdfEncoders.ToString(matrix) + "]";
                //Elements[Keys.Matrix] = new PdfLiteral(item);
                Elements.SetMatrix(Keys.Matrix, matrix);
            }

            // Preserve filter because the content keeps unmodified
            PdfContent content = importPage.Contents.CreateSingleContent();
#if !DEBUG
            content.Compressed = true;
#endif
            PdfItem filter = content.Elements["/Filter"];
            if (filter != null)
            {
                Elements["/Filter"] = filter.Clone();
            }

            // (no cloning needed because the bytes keep untouched)
            Stream = content.Stream; // new PdfStream(bytes, this);
            Elements.SetInteger("/Length", content.Stream.Value.Length);
        }
示例#43
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static XMatrix CreateSkewRadians(double skewX, double skewY, double centerX, double centerY)
 {
     XMatrix matrix = new XMatrix();
     matrix.Append(CreateTranslation(-centerX, -centerY));
     matrix.Append(new XMatrix(1, Math.Tan(skewY), Math.Tan(skewX), 1, 0, 0));
     matrix.Append(CreateTranslation(centerX, centerY));
     return matrix;
 }
示例#44
0
 /// <summary>
 /// Muliplies the spcified transformation with the current transformation and returns the new value;
 /// </summary>
 public XMatrix MultiplyTransform(XMatrix matrix)
 {
     return(this.graphicsState.MultiplyTransform(matrix));
 }
示例#45
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 static XMatrix CreateIdentity()
 {
     XMatrix matrix = new XMatrix();
     matrix.SetMatrix(1, 0, 0, 1, 0, 0, XMatrixTypes.Identity);
     return matrix;
 }
示例#46
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;
            }
        }
示例#47
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 internal static void PrependOffset(ref XMatrix matrix, double offsetX, double offsetY)
 {
     if (matrix._type == XMatrixTypes.Identity)
     {
         matrix = new XMatrix(1, 0, 0, 1, offsetX, offsetY);
         matrix._type = XMatrixTypes.Translation;
     }
     else
     {
         matrix._offsetX += (matrix._m11 * offsetX) + (matrix._m21 * offsetY);
         matrix._offsetY += (matrix._m12 * offsetX) + (matrix._m22 * offsetY);
         if (matrix._type != XMatrixTypes.Unknown)
             matrix._type |= XMatrixTypes.Translation;
     }
 }
示例#48
0
 /// <summary>
 /// Writes the specified text transformation matrix to the content stream.
 /// </summary>
 public void WriteTextTransform(XMatrix matrix)
 {
     Debug.Assert(this.streamMode == StreamMode.Text, "Must be in text mode when setting text matrix.");
     WriteLiteral("{0:0.####} {1:0.####} {2:0.####} {3:0.####} {4:0.####} {5:0.####} Tm\n",
                  matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.OffsetX, matrix.OffsetY);
 }
示例#49
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 /// <summary>
 /// Multiplies two matrices.
 /// </summary>
 public static XMatrix Multiply(XMatrix trans1, XMatrix trans2)
 {
     MatrixHelper.MultiplyMatrix(ref trans1, ref trans2);
     return trans1;
 }
示例#50
0
 /// <summary>
 /// Multiplies a point with a matrix.
 /// </summary>
 public static XPoint Multiply(XPoint point, XMatrix matrix)
 {
     return(matrix.Transform(point));
 }
示例#51
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 /// <summary>
 /// Prepends the specified matrix to this matrix. 
 /// </summary>
 public void Prepend(XMatrix matrix)
 {
     this = matrix * this;
 }
        /// <summary>
        /// Draws the gridlines into the plot area.
        /// </summary>
        internal override void Draw()
        {
            ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo;

            XRect plotAreaRect = cri.plotAreaRendererInfo.Rect;

            if (plotAreaRect.IsEmpty)
            {
                return;
            }

            AxisRendererInfo xari = cri.xAxisRendererInfo;
            AxisRendererInfo yari = cri.yAxisRendererInfo;

            double xMin       = xari.MinimumScale;
            double xMax       = xari.MaximumScale;
            double yMin       = yari.MinimumScale;
            double yMax       = yari.MaximumScale;
            double xMajorTick = xari.MajorTick;
            double yMajorTick = yari.MajorTick;
            double xMinorTick = xari.MinorTick;
            double yMinorTick = yari.MinorTick;

            XMatrix matrix = cri.plotAreaRendererInfo._matrix;

            LineFormatRenderer lineFormatRenderer;
            XGraphics          gfx = _rendererParms.Graphics;

            XPoint[] points = new XPoint[2];
            if (xari.MinorGridlinesLineFormat != null)
            {
                lineFormatRenderer = new LineFormatRenderer(gfx, xari.MinorGridlinesLineFormat);
                for (double x = xMin + xMinorTick; x < xMax; x += xMinorTick)
                {
                    points[0].X = x;
                    points[0].Y = yMin;
                    points[1].X = x;
                    points[1].Y = yMax;
                    matrix.TransformPoints(points);
                    lineFormatRenderer.DrawLine(points[0], points[1]);
                }
            }

            if (xari.MajorGridlinesLineFormat != null)
            {
                lineFormatRenderer = new LineFormatRenderer(gfx, xari.MajorGridlinesLineFormat);
                for (double x = xMin; x <= xMax; x += xMajorTick)
                {
                    points[0].X = x;
                    points[0].Y = yMin;
                    points[1].X = x;
                    points[1].Y = yMax;
                    matrix.TransformPoints(points);
                    lineFormatRenderer.DrawLine(points[0], points[1]);
                }
            }

            if (yari.MinorGridlinesLineFormat != null)
            {
                lineFormatRenderer = new LineFormatRenderer(gfx, yari.MinorGridlinesLineFormat);
                for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick)
                {
                    points[0].X = xMin;
                    points[0].Y = y;
                    points[1].X = xMax;
                    points[1].Y = y;
                    matrix.TransformPoints(points);
                    lineFormatRenderer.DrawLine(points[0], points[1]);
                }
            }

            if (yari.MajorGridlinesLineFormat != null)
            {
                lineFormatRenderer = new LineFormatRenderer(gfx, yari.MajorGridlinesLineFormat);
                for (double y = yMin; y <= yMax; y += yMajorTick)
                {
                    points[0].X = xMin;
                    points[0].Y = y;
                    points[1].X = xMax;
                    points[1].Y = y;
                    matrix.TransformPoints(points);
                    lineFormatRenderer.DrawLine(points[0], points[1]);
                }
            }
        }
示例#53
0
文件: XMatrix.cs 项目: Sl0vi/PDFsharp
 public void MultiplyPrepend(XMatrix matrix)
 {
     Prepend(matrix);
 }
示例#54
0
 public void MultiplyTransform(XMatrix m)
 {
     g.MultiplyTransform(m);
 }
示例#55
0
    /// <summary>
    /// Sets the clip path empty. Only possible if graphic state level has the same value as it has when
    /// the first time SetClip was invoked.
    /// </summary>
    public void ResetClip()
    {
      // No clip level means no clipping occurs and nothing is to do.
      if (this.clipLevel == 0)
        return;

      // Only at the clipLevel the clipping can be reset.
      if (this.clipLevel != this.gfxState.Level)
        throw new NotImplementedException("Cannot reset clip region in an inner graphic state level.");

      // Must be in graphical mode before popping the graphics state.
      BeginGraphic();

      // Save InternalGraphicsState and transformation of the current graphical state.
      InternalGraphicsState state = this.gfxState.InternalState;
      XMatrix ctm = this.gfxState.Transform;
      // Empty clip path by switching back to the previous state.
      RestoreState();
      SaveState();
      // Save internal state
      this.gfxState.InternalState = state;
      // Restore CTM
      this.gfxState.Transform = ctm;
    }
示例#56
0
        /// <summary>
        /// Creates between 1 and 5 Béziers curves from parameters specified like in GDI+.
        /// </summary>
        public static List <XPoint> BezierCurveFromArc(double x, double y, double width, double height, double startAngle, double sweepAngle,
                                                       PathStart pathStart, ref XMatrix matrix)
        {
            List <XPoint> points = new List <XPoint>();

            // Normalize the angles.
            double α = startAngle;

            if (α < 0)
            {
                α = α + (1 + Math.Floor((Math.Abs(α) / 360))) * 360;
            }
            else if (α > 360)
            {
                α = α - Math.Floor(α / 360) * 360;
            }
            Debug.Assert(α >= 0 && α <= 360);

            double β = sweepAngle;

            if (β < -360)
            {
                β = -360;
            }
            else if (β > 360)
            {
                β = 360;
            }

            if (α == 0 && β < 0)
            {
                α = 360;
            }
            else if (α == 360 && β > 0)
            {
                α = 0;
            }

            // Is it possible that the arc is small starts and ends in same quadrant?
            bool smallAngle = Math.Abs(β) <= 90;

            β = α + β;
            if (β < 0)
            {
                β = β + (1 + Math.Floor((Math.Abs(β) / 360))) * 360;
            }

            bool clockwise     = sweepAngle > 0;
            int  startQuadrant = Quadrant(α, true, clockwise);
            int  endQuadrant   = Quadrant(β, false, clockwise);

            if (startQuadrant == endQuadrant && smallAngle)
            {
                AppendPartialArcQuadrant(points, x, y, width, height, α, β, pathStart, matrix);
            }
            else
            {
                int  currentQuadrant = startQuadrant;
                bool firstLoop       = true;
                do
                {
                    if (currentQuadrant == startQuadrant && firstLoop)
                    {
                        double ξ = currentQuadrant * 90 + (clockwise ? 90 : 0);
                        AppendPartialArcQuadrant(points, x, y, width, height, α, ξ, pathStart, matrix);
                    }
                    else if (currentQuadrant == endQuadrant)
                    {
                        double ξ = currentQuadrant * 90 + (clockwise ? 0 : 90);
                        AppendPartialArcQuadrant(points, x, y, width, height, ξ, β, PathStart.Ignore1st, matrix);
                    }
                    else
                    {
                        double ξ1 = currentQuadrant * 90 + (clockwise ? 0 : 90);
                        double ξ2 = currentQuadrant * 90 + (clockwise ? 90 : 0);
                        AppendPartialArcQuadrant(points, x, y, width, height, ξ1, ξ2, PathStart.Ignore1st, matrix);
                    }

                    // Don't stop immediately if arc is greater than 270 degrees.
                    if (currentQuadrant == endQuadrant && smallAngle)
                    {
                        break;
                    }
                    smallAngle = true;

                    if (clockwise)
                    {
                        currentQuadrant = currentQuadrant == 3 ? 0 : currentQuadrant + 1;
                    }
                    else
                    {
                        currentQuadrant = currentQuadrant == 0 ? 3 : currentQuadrant - 1;
                    }

                    firstLoop = false;
                } while (true);
            }
            return(points);
        }
示例#57
0
    /// <summary>
    /// Appends a Bézier curve for an arc within a quadrant.
    /// </summary>
    void AppendPartialArcQuadrant(double x, double y, double width, double height, double α, double β, PathStart pathStart, XMatrix matrix)
    {
      Debug.Assert(α >= 0 && α <= 360);
      Debug.Assert(β >= 0);
      if (β > 360)
        β = β - Math.Floor(β / 360) * 360;
      Debug.Assert(Math.Abs(α - β) <= 90);

      // Scanling factor
      double δx = width / 2;
      double δy = height / 2;

      // Center of ellipse
      double x0 = x + δx;
      double y0 = y + δy;

      // We have the following quarters:
      //     |
      //   2 | 3
      // ----+-----
      //   1 | 0
      //     |
      // If the angles lie in quarter 2 or 3, their values are subtracted by 180 and the
      // resulting curve is reflected at the center. This algorithm works as expected (simply tried out).
      // There may be a mathematically more elegant solution...
      bool reflect = false;
      if (α >= 180 && β >= 180)
      {
        α -= 180;
        β -= 180;
        reflect = true;
      }

      double cosα, cosβ, sinα, sinβ;
      if (width == height)
      {
        // Circular arc needs no correction.
        α = α * Calc.Deg2Rad;
        β = β * Calc.Deg2Rad;
      }
      else
      {
        // Elliptic arc needs the angles to be adjusted such that the scaling transformation is compensated.
        α = α * Calc.Deg2Rad;
        sinα = Math.Sin(α);
        if (Math.Abs(sinα) > 1E-10)
          α = Calc.πHalf - Math.Atan(δy * Math.Cos(α) / (δx * sinα));
        β = β * Calc.Deg2Rad;
        sinβ = Math.Sin(β);
        if (Math.Abs(sinβ) > 1E-10)
          β = Calc.πHalf - Math.Atan(δy * Math.Cos(β) / (δx * sinβ));
      }

      double κ = 4 * (1 - Math.Cos((α - β) / 2)) / (3 * Math.Sin((β - α) / 2));
      sinα = Math.Sin(α);
      cosα = Math.Cos(α);
      sinβ = Math.Sin(β);
      cosβ = Math.Cos(β);

      XPoint pt1, pt2, pt3;
      if (!reflect)
      {
        // Calculation for quarter 0 and 1
        switch (pathStart)
        {
          case PathStart.MoveTo1st:
            pt1 = matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα));
            AppendFormat("{0:0.###} {1:0.###} m\n", pt1.x, pt1.y);
            break;

          case PathStart.LineTo1st:
            pt1 = matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα));
            AppendFormat("{0:0.###} {1:0.###} l\n", pt1.x, pt1.y);
            break;

          case PathStart.Ignore1st:
            break;
        }
        pt1 = matrix.Transform(new XPoint(x0 + δx * (cosα - κ * sinα), y0 + δy * (sinα + κ * cosα)));
        pt2 = matrix.Transform(new XPoint(x0 + δx * (cosβ + κ * sinβ), y0 + δy * (sinβ - κ * cosβ)));
        pt3 = matrix.Transform(new XPoint(x0 + δx * cosβ, y0 + δy * sinβ));
        AppendFormat("{0:0.###} {1:0.###} {2:0.###} {3:0.###} {4:0.###} {5:0.###} c\n",
          pt1.x, pt1.y, pt2.x, pt2.y, pt3.x, pt3.y);
      }
      else
      {
        // Calculation for quarter 2 and 3
        switch (pathStart)
        {
          case PathStart.MoveTo1st:
            pt1 = matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα));
            AppendFormat("{0:0.###} {1:0.###} m\n", pt1.x, pt1.y);
            break;

          case PathStart.LineTo1st:
            pt1 = matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα));
            AppendFormat("{0:0.###} {1:0.###} l\n", pt1.x, pt1.y);
            break;

          case PathStart.Ignore1st:
            break;
        }
        pt1 = matrix.Transform(new XPoint(x0 - δx * (cosα - κ * sinα), y0 - δy * (sinα + κ * cosα)));
        pt2 = matrix.Transform(new XPoint(x0 - δx * (cosβ + κ * sinβ), y0 - δy * (sinβ - κ * cosβ)));
        pt3 = matrix.Transform(new XPoint(x0 - δx * cosβ, y0 - δy * sinβ));
        AppendFormat("{0:0.###} {1:0.###} {2:0.###} {3:0.###} {4:0.###} {5:0.###} c\n",
          pt1.x, pt1.y, pt2.x, pt2.y, pt3.x, pt3.y);
      }
    }
示例#58
0
文件: XPoint.cs 项目: Sl0vi/PDFsharp
 /// <summary>
 /// Multiplies a point with a matrix.
 /// </summary>
 public static XPoint Multiply(XPoint point, XMatrix matrix)
 {
     return matrix.Transform(point);
 }
    /// <summary>
    /// Realizes the CTM.
    /// </summary>
    public void RealizeCtm()
    {
      if (this.MustRealizeCtm)
      {
        Debug.Assert(!this.unrealizedCtm.IsIdentity, "mrCtm is unnecessarily set.");

        double[] matrix = this.unrealizedCtm.GetElements();
        // Up to six decimal digits to prevent round up problems
        this.renderer.AppendFormat("{0:0.######} {1:0.######} {2:0.######} {3:0.######} {4:0.######} {5:0.######} cm\n",
          matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);

        this.realizedCtm.Prepend(this.unrealizedCtm);
        this.unrealizedCtm = new XMatrix();  //XMatrix.Identity;
        this.MustRealizeCtm = false;
      }
    }
示例#60
0
        PdfTilingPattern BuildPattern(VisualBrush brush, XMatrix transform)
        {
            // Bounding box lays always at (0,0)
            XRect bbox = new XRect(0, 0, brush.Viewport.Width, brush.Viewport.Height);

            XMatrix matrix = transform;

            matrix.Prepend(new XMatrix(1, 0, 0, 1, brush.Viewport.X, brush.Viewport.Y));
            if (brush.Transform != null)
            {
                matrix.Prepend(new XMatrix(brush.Transform.Value.M11, brush.Transform.Value.M12,
                                           brush.Transform.Value.M21, brush.Transform.Value.M22,
                                           brush.Transform.Value.OffsetX, brush.Transform.Value.OffsetY));
            }

            // Set X Step beyond the viewport if tilemode is set to none since
            // there is no other easy way to turn off tiling - NPJ
            double xStep = brush.Viewport.Width * (brush.TileMode == TileMode.None ? 2 : 1);
            double yStep = brush.Viewport.Height * (brush.TileMode == TileMode.None ? 2 : 1);

            // PdfTilingPattern
            //<<
            //  /BBox [0 0 240 120]
            //  /Length 74
            //  /Matrix [0.75 0 0 -0.75 0 480]
            //  /PaintType 1
            //  /PatternType 1
            //  /Resources
            //  <<
            //    /ExtGState
            //    <<
            //      /GS0 10 0 R
            //    >>
            //    /XObject
            //    <<
            //      /Fm0 17 0 R
            //    >>
            //  >>
            //  /TilingType 3
            //  /Type /Pattern
            //  /XStep 480
            //  /YStep 640
            //>>
            //stream
            //  q
            //  0 0 240 120 re
            //  W n
            //  q
            //    2.3999939 0 0 1.1999969 0 0 cm
            //    /GS0 gs
            //    /Fm0 Do
            //  Q
            //Q
            //endstream
            var pattern = new PdfTilingPattern(Context.PdfDocument);

            Context.PdfDocument.Internals.AddObject(pattern);
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.PatternType, 1); // Tiling
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.PaintType, 1);   // Color
            pattern.Elements.SetInteger(PdfTilingPattern.Keys.TilingType, 3);  // Constant spacing and faster tiling
            pattern.Elements.SetMatrix(PdfTilingPattern.Keys.Matrix, matrix);
            pattern.Elements.SetRectangle(PdfTilingPattern.Keys.BBox, new PdfRectangle(bbox));
            pattern.Elements.SetReal(PdfTilingPattern.Keys.XStep, xStep);
            pattern.Elements.SetReal(PdfTilingPattern.Keys.YStep, yStep);

            // Set extended graphic state like Acrobat do
            var pdfExtGState = Context.PdfDocument.Internals.CreateIndirectObject <PdfExtGState>();

            pdfExtGState.SetDefault1();

            var pdfForm = BuildForm(brush);

            var writer = new PdfContentWriter(Context, pattern);

            writer.BeginContentRaw();

            // Acrobat 8 clips to bounding box, so do we
            //writer.WriteClip(bbox);

            XMatrix transformation = new XMatrix();
            double  dx             = brush.Viewport.Width / brush.Viewbox.Width * 96 / pdfForm.DpiX;
            double  dy             = brush.Viewport.Height / brush.Viewbox.Height * 96 / pdfForm.DpiY;

            transformation = new XMatrix(dx, 0, 0, dy, 0, 0);
            writer.WriteMatrix(transformation);
            writer.WriteGraphicsState(pdfExtGState);

            string name = writer.Resources.AddForm(pdfForm);

            writer.WriteLiteral(name + " Do\n");

            writer.EndContent();

            return(pattern);
        }