HTMPrintMeasure or basics of HTML/CSS printing

PrintEx API of htmlayout has HTMPrintMeasure function with the following signature:

HPRESULT HTMPrintMeasure(HTMPRINT hPrint, HDC hdc,
            int scaledWidth,
            int viewportWidth,
            int viewportHeight,
            int* pOutNumberOfPages);

I would like to explain here meanings of its parameters as I am getting questions about printing and scaling pretty frequently.

First fact that we need to know: pixels in HTML and CSS are logical units and have nothing common with device pixels our HTML/CSS is rendered on.

By accident 1px in HTML normally mapped to one physical pixel on screen (but not always, sic!) and one "HTML pixel" on printer can be mapped to some rectangular area that covers multiple printer "pixels". Strictly speaking printers have no pixels.

Showing that more device pixels (dots)
are needed to cover a 1px by 1px area on a high-resolution device than
on a low-res one   [D]
(illustration taken from W3C CSS specification)

According to the specification, HTML pixels are logical units that are just fractions of real length units:

   1px (html,css) = 1in / 96

Thus pixel in HTML is very close by its nature to "point" – 1pt is 1/72nd of an inch.

And this is it about theory, back to our business – HTMPrintMeasure function and its parameters:

  • int scaledWidth

    – is a number of "HTML pixels" between left and right border of the page.

  • int viewportWidth

    – is a number of "printer physical pixels" or dots between left and right border of the page (a.k.a. physical page width).

  • int viewportHeight

    – is a number of "printer physical pixels" or dots between top and bottom border of the page (a.k.a. physical page height).

At this point of our "printing saga" we can ask the question "what are the correct values for these parameters?"

Let’s assume that we have given:

  1. printer that has 600 dpi (dots per inch) resolution.

  2. paper of the format "legal" – 8.5 by 11 inches.

Calculation then is pretty straightforward:

viewportWidth = 600 dpi * 8.5in = 5100 dots (or printer pixels if you wish)
viewportHeight = 600 dpi * 11in = 6600 dots.
scaledWidth = 8.5in * 96 (html px per inch) = 816

Therefore we have 816 "HTML pixels" on printing page of the legal/portrait format in horizontal direction.
This means that if you have <table width=800> or <img width=800> then they shall fit on such page in full (if printing margins were set to zero).

In reality things are a bit more complex – you need to take in account printing margins in calculations to get precise results. But this I hope will not be so difficult for people who knows, let’s say, C# programming language .