Scaling issues in old direct-printing code

I’m having to revisit some printing-framework code I wrote back in 2007 or so, when I was just getting started with wxPython. (In a thread a few months ago, I mentioned that I would never again willingly deal with direct printing… well, here I go!)

This code contains some horrible hacks, but it worked for years and I have forgotten why I did certain things. In any case, my chief customer recently had a hardware refresh, also moving from XP to Windows 8.1, and I’ve discovered that my perfectly-aligned forms… aren’t, anymore. Everything seems to have shrunk a bit (the top left is correct, but the right edge is about 2.5 characters short and the bottom line is about 3 lines too high), and I suspect that the issue is in my scaling logic… but why? What’s changed?

Here’s the relevant bit (please forgive the horrible hackishness!)

data = wx.PrintDialogData(Global.printData)
data.EnablePrintToFile(True)
data.EnablePageNumbers(True)
data.SetMinPage(1)
data.SetMaxPage(len(outForm))
data.SetAllPages(True)
dlg = wx.PrintDialog(self, data)
if dlg.ShowModal() == wx.ID_OK:
pdd = dlg.GetPrintDialogData()
data = pdd.GetPrintData()
dlg.Destroy()
dc = wx.PrinterDC(data)
scaleMM = dc.GetPPI()[0]/25.4
dc.SetDeviceOriginPoint(wx.Point(TopLeft[0]*scaleMM,TopLeft[1]*scaleMM))
wdth, hght = dc.GetSize()
dc.SetUserScale((wdth/lineLength),(hght/self.outLength))
font = wx.Font(1, wx.MODERN, wx.NORMAL, wx.NORMAL)
dc.SetFont(font)
dc.SetTextForeground(wx.BLACK)
dc.StartDoc(‘FSR1500’)
for num, form in enumerate(outForm):
if not (pdd.GetAllPages()):
if (num < (pdd.GetFromPage()-1)):
continue
if (num > (pdd.GetToPage()-1)):
continue
dc.StartPage()
for num, line in enumerate(form):
dc.DrawText(line, 0, num)
dc.EndPage()
dc.EndDoc()

  • When this was working, the only adjustment I needed was to set “TopLeft” (the top and left margins), from the Page Setup standard dialog. That dialog returns millimeters, while everything else is in inches or points…

  • dc.GetSize returns a width of 4800 and a height of 6400; those numbers don’t make any sense for letter-size paper, do they? If I were to switch to a hard-coded size, what would “sane” numbers be?

  • My “font = wx.Font()” line… the first parameter should be size, and most examples I find on the web have 8 or 10 there. But when I use any number but 1, the font size is gigantic - perhaps 120 points.

Python 2.7.10 32-bit, wxPython 3.0.2.0

Windows 8.1 Home Premium, 64-bit

attempting to print letter-size forms on a Brother HL-5370DW emulating an HP LaserJet 4

Any hints that would point me in a new direction of inquiry would be GREATLY appreciated.

As usual, writing (and sending!) the email helped me come up with a
solution. I just replaced "wdth, hght = dc.GetSize()" with "wdth, hght =
(4850, 6600)", and all is well.

I DO NOT like this solution; I hate magic numbers and I hate the fact that
I don't understand what's going on. But life is short.

- 6600 is completely logical: 11 inches by 600dpi.
- 4850, though? That makes sense if I assume a right and left margin of a
bit less than 1/4 inch - but then, why don't I need to account for the top
and bottom?
- And once again: where in the hell did the automatically-returned size of
(4800, 6400) come from?

- And what's going on with the "size" parameter in wx.Font()?

This is why I use ReportLab for all my new projects... this voodoo DC stuff
makes my head hurt.

···

On Mon, Sep 21, 2015 at 3:01 PM, Marc Tompkins <marc.tompkins@gmail.com> wrote:

- dc.GetSize returns a width of 4800 and a height of 6400; those numbers
don't make any sense for letter-size paper, do they? If I were to switch
to a hard-coded size, what would "sane" numbers be?

I feel your pain. I’ve had a Python envelope printing application
migrate through three different printers with three different
envelope trays, and extensive surgery was required each time.
Unfortunately, printing in Windows is much less an engineering
discipline than it is a black art. It’s unsatisfying, but if you
have achieved success, I suggest you hold your breath and back away
slowly.
You’re calling dc.SetUserScale, which changes the units for all
future API calls.

···

Marc Tompkins wrote:

        On Mon, Sep 21, 2015 at 3:01 PM, Marc

Tompkins marc.tompkins@gmail.com
wrote:

                      -  dc.GetSize returns a width of 4800 and a

height of 6400; those numbers don’t make any
sense for letter-size paper, do they? If I
were to switch to a hard-coded size, what
would “sane” numbers be?

      As usual, writing (and sending!) the email helped me come up

with a solution. I just replaced “wdth, hght = dc.GetSize()”
with “wdth, hght = (4850, 6600)”, and all is well.

      I DO NOT like this solution; I hate

magic numbers and I hate the fact that I don’t understand
what’s going on. But life is short.

      -  And what's going on with the "size"

parameter in wx.Font()?

-- Tim Roberts, Providenza & Boekelheide, Inc.

timr@probo.com

Yeah, that's my plan. Thanks for the moral support - it's good to know I'm
not the only one who's frustrated by this.

···

On Mon, Sep 21, 2015 at 4:41 PM, Tim Roberts <timr@probo.com> wrote:

I feel your pain. I've had a Python envelope printing application migrate
through three different printers with three different envelope trays, and
extensive surgery was required each time. Unfortunately, printing in
Windows is much less an engineering discipline than it is a black art.
It's unsatisfying, but if you have achieved success, I suggest you hold
your breath and back away slowly.