Качество печати, чтобы соответствовать Adobe Reader - PullRequest
0 голосов
/ 26 апреля 2018

Я использую C # и библиотеку PDFium для печати PDF на конкретном принтере этикеток. Когда я печатаю этот PDF через Chrome, Edge или мое приложение, качество сомнительно. Когда я печатаю через Adobe Reader или Foxit Reader, качество именно то, что я хочу.

Вот изображение на изображении различий: https://i.imgur.com/gSnYcEE.jpg

Мое приложение называется «Сетевая печать». Как вы можете видеть на изображении, его качество соответствует тому, что делают браузеры. В частности, небольшой текст справа - моя забота.

Так что же отличают настольные программы чтения PDF при печати с них?

Вот фрагмент кода, который фактически печатает PDF в C #:

public static Boolean Print(PrintQueue printer, byte[] content, Boolean landscape)
{
    using (MemoryStream stream = new MemoryStream(content))
    {
        PdfDocument doc = PdfDocument.Load(stream);
        PrintDocument pd = GetPrintDocumentAsPDF(printer.Name, doc, landscape);
        pd.Print();
        return true;
    }
}

private static PrintDocument GetPrintDocumentAsPDF(String printerName, PdfDocument doc, Boolean landscape)
{
    PdfPrintMultiplePages multiPages = new PdfPrintMultiplePages(1, 1, landscape ? System.Windows.Forms.Orientation.Horizontal : System.Windows.Forms.Orientation.Vertical, 0);
    PdfPrintSettings settings = new PdfPrintSettings(PdfPrintMode.CutMargin, multiPages);

    PrintDocument pd = doc.CreatePrintDocument(settings);
    pd.PrinterSettings.PrinterName = printerName;

    Rectangle firstPage = GetSizeForDoc(doc, 0);

    pd.DefaultPageSettings.Landscape = landscape;

    // Find the closest matching media profile based on the size of the first page
    PaperSize bestFit = GetBestFitMediaProfile(firstPage.Width, firstPage.Height, landscape, pd.PrinterSettings.PaperSizes);

    if (bestFit != null)
    {
        pd.DefaultPageSettings.PaperSize = bestFit;
    }
    else
    {
        Util.RestLog("!!! No matching media profile. Using default !!!");
    }

    return pd;
}

/// <summary>
/// Calculates the size of a page from a document
/// </summary>
/// <param name="doc">the document to get the page from</param>
/// <param name="page">the page number to get the size for</param>
/// <returns>a rectangle with the width and height of the page</returns>
private static Rectangle GetSizeForDoc(PdfDocument doc, int page)
{
    // Calculate the actual size of the document
    SizeF docSize = doc.PageSizes[page];
    Rectangle docBounds = new Rectangle(0, 0, (int)Math.Floor(docSize.Width / DOT_PER_INCH * 100),
        (int)Math.Floor(docSize.Height / DOT_PER_INCH * 100));

    return docBounds;
}

/// <summary>
/// For a given width and height (of a document page), determines the smallest available media profile
/// that can be printed to while still encompassing the entire page
/// </summary>
/// <param name="width">width of the page to print</param>
/// <param name="height">height of the page to print</param>
/// <param name="mediaProfiles">the media profiles available on the print being printed to</param>
/// <returns></returns>
private static PaperSize GetBestFitMediaProfile(int width, int height, bool landscape, PrinterSettings.PaperSizeCollection mediaProfiles)
{
    PaperSize mediaProfile = null;
    double docLong = Math.Round((landscape ? width : height) * 1f, 2);
    double docShort = Math.Round((landscape ? height : width) * 1f, 2);

    double profileLong;
    double profileShort;

    foreach (PaperSize profile in mediaProfiles)
    {
        Util.RestLog("Found media profile: " + profile.Width + " x " + profile.Height);

        double profileWidth = Math.Round(profile.Width * 1f, 2);
        double profileHeight = Math.Round(profile.Height * 1f, 2);

        profileLong = landscape ? profileWidth : profileHeight;
        profileShort = landscape ? profileHeight : profileWidth;

        if (mediaProfile == null)
        {
            // Grab the first media profile that is larger than the document in both width and height
            if (profileLong >= docLong && profileShort >= docShort)
            {
                mediaProfile = profile;
            }
        }
        else
        {
            // If this profile is closer to the document size than the current one
            if (profileLong >= docLong && profileShort >= docShort &&
                GetArea(profileWidth, profileHeight) < GetArea(mediaProfile.Width, mediaProfile.Height))
            {
                mediaProfile = profile;
            }
        }
    }

    return mediaProfile;
}

/// <summary>
/// Calculates an area give a width and a height
/// </summary>
/// <param name="width">the width</param>
/// <param name="height">the height</param>
/// <returns>the area of the width and height</returns>
private static double GetArea(double width, double height)
{
    return width * height;
}

По сути, главное, что он делает, - это выбирает правильный профиль носителя для размера печатаемого документа PDF. Я не верю, что кому-то понадобится видеть методы, связанные с поиском правильного размера (GetSizeForDoc и GetBestFitMediaProfile), но я могу опубликовать их, если кому-то понадобится.

...