empira / PDFsharp-1.5

A .NET library for processing PDF
MIT License
1.28k stars 588 forks source link

Relative coordinates are drawn in invalid way #61

Closed drweb86-work closed 6 years ago

drweb86-work commented 6 years ago

Reporting an Issue Here

Expected Behavior

Relative coordinates are drawn normally image

Actual Behavior

Relative coordinates are drawn with increasing of actual coordinate values. image

Steps to Reproduce the Behavior

using System;
using System.Diagnostics;
using System.IO;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace DrawRectangle
{
    class Program
    {
        static void Main()
        {
            var srcPdf = @"C:\Users\Sergey Kuchuk\Desktop\TEST.pdf";
            var tmpPdf = @"C:\Users\Sergey Kuchuk\Desktop\TEST-REZ.pdf";

            if (File.Exists(tmpPdf))
                File.Delete(tmpPdf);
            File.Copy(srcPdf, tmpPdf);

            var inputPdfDocument = PdfReader.Open(tmpPdf, PdfDocumentOpenMode.Import);
            var pdfDocument = new PdfDocument();
            foreach (var page in inputPdfDocument.Pages)
                pdfDocument.AddPage(page);
            inputPdfDocument.Close();

            double x = 0.18900810339655708;
            double y = 0.0638677225513861;
            double w = 0.21725069355926102;
            double h = 0.028283526804211694;

            using (var pageGraphics = XGraphics.FromPdfPage(pdfDocument.Pages[0]))
            {
                Console.WriteLine("Width (points) {0}; Height: {1}", pdfDocument.Pages[0].Width.Point, pdfDocument.Pages[0].Height.Point);
                DrawRectangle(pageGraphics, XColors.Green, 1,
                    x * pdfDocument.Pages[0].Width, y * pdfDocument.Pages[0].Height,
                    w * pdfDocument.Pages[0].Width, h * pdfDocument.Pages[0].Height);
            }

            pdfDocument.Save(tmpPdf);
            Process.Start(tmpPdf);
        }

        public static void DrawRectangle(XGraphics pageGraphics, XColor color, double penWidth, double x, double y, double width, double height)
        {
            var pen = new XPen(color, penWidth)
            {
                LineCap = XLineCap.Round,
                LineJoin = XLineJoin.Bevel
            };
            Console.WriteLine(pageGraphics.PageUnit);
            pageGraphics.DrawRectangle(pen, new XRect(x, y, width, height));
        }
    }
}
drweb86-work commented 6 years ago

Original document TEST.pdf

drweb86-work commented 6 years ago

It also draws lines not from the exact corners. That code produces next look.

using System;
using System.Diagnostics;
using System.IO;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace DrawRectangle
{
    class Program
    {
        static void Main()
        {
            var srcPdf = @"C:\Users\Sergey Kuchuk\Desktop\TEST.pdf";
            var tmpPdf = @"C:\Users\Sergey Kuchuk\Desktop\TEST-REZ.pdf";

            if (File.Exists(tmpPdf))
                File.Delete(tmpPdf);
            File.Copy(srcPdf, tmpPdf);

            var inputPdfDocument = PdfReader.Open(tmpPdf, PdfDocumentOpenMode.Import);
            var pdfDocument = new PdfDocument();
            foreach (var page in inputPdfDocument.Pages)
                pdfDocument.AddPage(page);
            inputPdfDocument.Close();

            using (var pageGraphics = XGraphics.FromPdfPage(pdfDocument.Pages[0]))
            {
                Console.WriteLine(pageGraphics.PageUnit);
                Console.WriteLine("Width (points) {0}; Height: {1}", pdfDocument.Pages[0].Width.Point, pdfDocument.Pages[0].Height.Point);

                // line starts not from the exact corner of document,
                // line ends not in exact corner of document
                pageGraphics.DrawLine(new XPen(XColors.Red), 0, 0, pdfDocument.Pages[0].Width, pdfDocument.Pages[0].Height);
            }

            pdfDocument.Save(tmpPdf);
            Process.Start(tmpPdf);
        }

        public static void DrawRectangle(XGraphics pageGraphics, XColor color, double penWidth, double x, double y, double width, double height)
        {
            var pen = new XPen(color, penWidth)
            {
                LineCap = XLineCap.Round,
                LineJoin = XLineJoin.Bevel
            };

            pageGraphics.DrawRectangle(pen, new XRect(x, y, width, height));
        }
    }
}

image

ThomasHoevel commented 6 years ago

Two issues in one thread may not be a good idea. Pages can be larger than the visible area (MediaBox, CropBox, BleedBox &c.). This could explain the second issue. For the first issue you provide undocumented code and I cannot easily understand whether the expected result is the correct result. This could also be related to visible/invisible areas of the page.

drweb86-work commented 6 years ago

Thank you for your fast response. I've spent a day already trying to figure this out. Can you please point out where to read about how to properly draw line from one corner to another?

drweb86-work commented 6 years ago

Issue with drawing is reproduced on this particular document only, BTW

ThomasHoevel commented 6 years ago

Search for MediaBox, CropBox, BleedBox, TrimBox, ArtBox. MediaBox should be the page size reported by PDFsharp, but CropBox should be the area visible in Adobe Reader. So try using CropBox for your calculations. Pages created with PDFsharp always start at (0, 0), but this can be different for pages from other tools - there can also be negative numbers. The visible area of the page can be smaller than the page - professional printers may print on large pages, fold them, and cut off the edges - it's a feature to have content extend beyond the area that will finally be visible.

drweb86-work commented 6 years ago

Thank you soooo much!

drweb86-work commented 6 years ago

I solved the issue.

Correct code would be for relative coordinates

x = xpage.CropBox.Width + page.cropBox.X1 y = ypage.CropBox.Height + page.cropBox.Y1 width = page.CropBox.Width; height = page.CropBox.Height;

Correct code for absolute coordinates

x += page.cropBox.X1 y += page.cropBox.Y1

Correct way of getting width and height is using page.CropBox.Width + page.CropBox.Height