Recent

Author Topic: Printer.XDPI and Printer.YDPI under OSX 10.9  (Read 10962 times)

lelebass

  • New Member
  • *
  • Posts: 20
Printer.XDPI and Printer.YDPI under OSX 10.9
« on: March 25, 2015, 02:35:47 pm »
Seems that the Printer.XDPI and Printer.YDPI are always returning 72 under OSX. I am using Lazarus 1.2.6.
I wrote a small piece of code, and tested on Win 7 and OSX 10.9 on the same machine and the same printer.

Code: [Select]
begin
  PrintDialog1.Execute;
  with Printer do
  try
    BeginDoc;   
    Memo1.Lines.Add('XDPI='+IntToStr(XDPI));
    Memo1.Lines.Add('YDPI='+IntToStr(YDPI));
  finally
    EndDoc;
  end;
end;

Here are the results.
Windows 7 (HP C4700):

Printer.XDPI=600
Printer.YDPI=600

OSX 10.9 (HP C4700):

Printer.XDPI=72
Printer.YDPI=72

Found an old thread on the forum:

http://forum.lazarus.freepascal.org/index.php/topic,14641.msg77612.html#msg77612

But checking the code in components/printers/carbon/carbonprinters.inc it seems that the XDPI and YDPI are not hardcoded anymore.

Is anyone running in the same issue?

Thanks,
Dan

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #1 on: March 25, 2015, 02:46:10 pm »
is there a bug report for that? if not, please file one and it will be fixed tonight!
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

jwdietrich

  • Hero Member
  • *****
  • Posts: 1028
    • formatio reticularis
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #2 on: March 25, 2015, 03:20:44 pm »
This is an old and annoying issue on Mac OS X.

It was discussed years ago in this forum (http://forum.lazarus.freepascal.org/index.php?topic=14641.0). I tried to resolve it, but due to the very complex implementation of printing on OS X and lack in time I gave up, but I would be happy to see this issue resolved.

Edit: Since this issue wasn't recorded in the Mantis system I reported a bug. See http://bugs.freepascal.org/view.php?id=27728 for current status information.
« Last Edit: March 25, 2015, 03:30:01 pm by jwdietrich »
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.0.2 | FPC 3.0.4 | PPC, Intel, ARM | macOS, Windows, Linux

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #3 on: March 25, 2015, 03:34:50 pm »
having this correct is critical for both Carbon and Cocoa widgets (the later doesn't have printers implemented yet).

But, IIRC both are using Core Printing (formerly Printer Manager) APIs.

There's a function PMPrinterGetOutputResolution that returns

Quote
struct PMResolution { double hRes; double vRes; };
Fields
hRes    - The horizontal resolution in dots per inch (dpi).
vRes    - The vertical resolution in dots per inch (dpi).

It's hard to be more straight forward than that.

...patches, anyone?
« Last Edit: March 25, 2015, 03:37:58 pm by skalogryz »
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #4 on: March 25, 2015, 03:46:34 pm »
Hmm.  it's available in 10.5 or later. That's why it was not there originally (Carbon claims compatibility with OSX 10.4).
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

lelebass

  • New Member
  • *
  • Posts: 20
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #5 on: March 25, 2015, 03:53:01 pm »
Code in \lazarus\components\printers\carbon\carbonprinters.inc seems to already call that function:

Code: [Select]
function TCarbonPrinter.GetOutputResolution: PMResolution;
var
  res: OSStatus;
begin
  // PMPrinterGetOutputResolution is supported on OS X 10.5 and later
  // TODO: check version instead, because 10.5 may still support PowerPC
  {$if defined(PowerPC) or defined(__ppc__) or defined(ppc)}
  res := noErr+1;
  {$else}
  res := PMPrinterGetOutputResolution(GetCurrentPrinter, PrintSettings, Result{%H-});
  {$endif}
  if res<>noErr then
  begin
    Result.vRes:=72;
    Result.hRes:=72;
  end;
end;

but seems to always end up in the res<>noErr case.

Dan


skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #6 on: March 25, 2015, 04:14:53 pm »
cool. what's the value of res?
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

lelebass

  • New Member
  • *
  • Posts: 20
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #7 on: March 25, 2015, 04:46:07 pm »
Interesting question.
Unfortunately I was unable to trace the code, what I was able to do is change the hardcoded value for dpi, then clean up and rebuild. :-[
From the outcome I concluded that res<>noErr should be true.
Willing to learn how to debug the Lazarus code, but I am quite new to OSX and still learning how to properly use the debugger under OSX.

Dan

jwdietrich

  • Hero Member
  • *****
  • Posts: 1028
    • formatio reticularis
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #8 on: March 25, 2015, 05:16:50 pm »
Code in \lazarus\components\printers\carbon\carbonprinters.inc seems to already call that function:

Yes, this seems to be the critical location. In my installations it always returned res<>noErr.

Additionally, the current implementation seems to be sub-optimal. Instead of checking for PowerPC vs. Intel processors it should check the system version, since some PPC Macs also support Mac OS X Leopard (10.5) and some Intel machines run on Mac OS X Tiger (10.4). This is also mentioned in the comment of the original code.

Therefore, I would suggest to rewrite this code as:

Code: [Select]
function TCarbonPrinter.GetOutputResolution: PMResolution;
var
  res: OSStatus;
  Major, Minor: SInt32;
  theError: SInt16;
begin
  theError := Gestalt(gestaltSystemVersionMajor, Major);
  if theError <> 0 then
    Major := 0;
  theError := Gestalt(gestaltSystemVersionMinor, Minor);
  if theError <> 0 then
    Minor := 0;
  if (Major < 10) or (Minor < 5) then
    res := noErr+1;
  else
    res := PMPrinterGetOutputResolution(GetCurrentPrinter, PrintSettings, Result{%H-});
  if res<>noErr then
  begin
    Result.vRes:=72;
    Result.hRes:=72;
  end;
end;

However, although this rewrite is basically reasonable, it didn't resolve the problem in my experiments.

function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.0.2 | FPC 3.0.4 | PPC, Intel, ARM | macOS, Windows, Linux

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #9 on: March 25, 2015, 06:27:23 pm »
Unfortunately I was unable to trace the code, what I was able to do is change the hardcoded value for dpi, then clean up and rebuild. :-[
tracing is easy, just add "writeln" after the function call
Code: [Select]
function TCarbonPrinter.GetOutputResolution: PMResolution;
var
  res: OSStatus;
begin
  // PMPrinterGetOutputResolution is supported on OS X 10.5 and later
  // TODO: check version instead, because 10.5 may still support PowerPC
  {$if defined(PowerPC) or defined(__ppc__) or defined(ppc)}
  res := noErr+1;
  {$else}
  res := PMPrinterGetOutputResolution(GetCurrentPrinter, PrintSettings, Result{%H-});
  writeln('PMPrinterGetOutputResolution ', res);
  {$endif}
  if res<>noErr then
  begin
    Result.vRes:=72;
    Result.hRes:=72;
  end;
end;
now, compile the project (you should see lazprinters component to be recompiled as well).
open terminal
cd to your project directory
cd to you bundle (project1.app ? )
cd to Contents/MacOS
and launch binary (./project1)
now just get to the point where printers DPI is received and watch the output in your terminal window. It should print the value for you.
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

jwdietrich

  • Hero Member
  • *****
  • Posts: 1028
    • formatio reticularis
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #10 on: March 25, 2015, 07:08:13 pm »
tracing is easy, just add "writeln" after the function call

...

now, compile the project (you should see lazprinters component to be recompiled as well).
open terminal
cd to your project directory
cd to you bundle (project1.app ? )
cd to Contents/MacOS
and launch binary (./project1)
now just get to the point where printers DPI is received and watch the output in your terminal window. It should print the value for you.

Good idea. However, it will work with non-GUI applications only. Most applications on a Mac are GUI-based. They run when launched from Terminal, but they don't allow any interaction via Quartz.

Anyway, please change the code to:

Code: [Select]
function TCarbonPrinter.GetOutputResolution: PMResolution;
var
  res: OSStatus;
  Major, Minor: SInt32;
  theError: SInt16;
begin
  theError := Gestalt(gestaltSystemVersionMajor, Major);
  if theError <> 0 then
    Major := 0;
  theError := Gestalt(gestaltSystemVersionMinor, Minor);
  if theError <> 0 then
    Minor := 0;
  if (Major < 10) or (Minor < 5) then
    res := noErr+1;
  else
    res := PMPrinterGetOutputResolution(GetCurrentPrinter, PrintSettings, Result{%H-});
  writeln('PMPrinterGetOutputResolution ', res);
  if res<>noErr then
  begin
    Result.vRes:=72;
    Result.hRes:=72;
  end;
end;

This avoids the old bug, where the processor architecture, which is totally unimportant in this context, is confused with the OS version.

If your code depends on GUI-based interaction you might want to replace the writeln statement, so that it writes to a file rather than to the terminal. Alternatively, you could use DbgAppendToFile() from the LCLProc unit, which writes debug output to a specified file.
« Last Edit: March 25, 2015, 07:10:05 pm by jwdietrich »
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.0.2 | FPC 3.0.4 | PPC, Intel, ARM | macOS, Windows, Linux

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #11 on: March 25, 2015, 07:19:59 pm »
Good idea. However, it will work with non-GUI applications only. Most applications on a Mac are GUI-based. They run when launched from Terminal, but they don't allow any interaction via Quartz.
That's inaccurate statement. Non-gui applications work fine if launched from within bundle.
If launched outside of the bundle, then indeed - terminal gets all the input and the application look stalled.


Also, it's possible to use "CONSOLE" application to see the standard output of an application. It's just a bit trickier to find, since a lot of processes are being logged there.
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

jwdietrich

  • Hero Member
  • *****
  • Posts: 1028
    • formatio reticularis
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #12 on: March 25, 2015, 07:25:41 pm »
Good idea. However, it will work with non-GUI applications only. Most applications on a Mac are GUI-based. They run when launched from Terminal, but they don't allow any interaction via Quartz.
That's inaccurate statement. Non-gui applications work fine if launched from within bundle.
If launched outside of the bundle, then indeed - terminal gets all the input and the application look stalled.

Also, it's possible to use "CONSOLE" application to see the standard output of an application. It's just a bit trickier to find, since a lot of processes are being logged there.

Your statements are correct and they don't contradict mine.
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.0.2 | FPC 3.0.4 | PPC, Intel, ARM | macOS, Windows, Linux

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #13 on: March 25, 2015, 07:28:00 pm »
Your statements are correct and they don't contradict mine.
hmm, should I say then:
Gui applications work fine if launched from within a bundle via Terminal.

I've been using "writeln" for debugging since I moved to Lazarus for all OSes.
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2264
    • havefunsoft.com
Re: Printer.XDPI and Printer.YDPI under OSX 10.9
« Reply #14 on: March 25, 2015, 07:33:35 pm »
so I guess the only reason for the function to fail is that either: GetCurrentPrinter or PrintSettings returns faulty information.
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz