Hello
Hello,
I use a component that do some nice things on the Printer's Canvas...but I would like to adapt the code to print two A5 on a single A4 paper.
Instead of changing all the logic of the component, I've tried something that work very well but not on all printers :(
I've replaced de Printer.NewPage call by a code that apply a SetWorldTransform() like this
if (PageNo > 1) and (PageNo and 1 = 1) then
Printer.NewPage;
with Printer.Canvas do
begin
// x' = x * eM11 + y * eM21 + eDx
// y' = x * eM12 + y * eM22 + eDy
XFORM.eM11 := 0;
XFORM.em12 := -(210/297); // A4 (210x297) -> A5 (148x210)
XFORM.em21 := +(210/297);
XFORM.em22 := 0;
if Printer.Orientation = poPortrait then
begin
XFORM.eDx := 0;
XFORM.eDy := Printer.PageHeight;
if PageNo and 1 = 0 then
begin
XFORM.eDy := XFORM.eDy / 2;
end;
end else begin
XFORM.eDx := 0;
XFORM.eDy := Printer.PageHeight;
if PageNo and 1 = 0 then
begin
XFORM.eDx := Printer.PageWidth / 2;
end;
end;
SetGraphicsMode(Handle, GM_ADVANCED);
SetWorldTransform(Handle, XFORM);
end;
Is there a known bug or something I've forgot ?
Thanks
I use a component that do some nice things on the Printer's Canvas...but I would like to adapt the code to print two A5 on a single A4 paper.
Instead of changing all the logic of the component, I've tried something that work very well but not on all printers :(
I've replaced de Printer.NewPage call by a code that apply a SetWorldTransform() like this
if (PageNo > 1) and (PageNo and 1 = 1) then
Printer.NewPage;
with Printer.Canvas do
begin
// x' = x * eM11 + y * eM21 + eDx
// y' = x * eM12 + y * eM22 + eDy
XFORM.eM11 := 0;
XFORM.em12 := -(210/297); // A4 (210x297) -> A5 (148x210)
XFORM.em21 := +(210/297);
XFORM.em22 := 0;
if Printer.Orientation = poPortrait then
begin
XFORM.eDx := 0;
XFORM.eDy := Printer.PageHeight;
if PageNo and 1 = 0 then
begin
XFORM.eDy := XFORM.eDy / 2;
end;
end else begin
XFORM.eDx := 0;
XFORM.eDy := Printer.PageHeight;
if PageNo and 1 = 0 then
begin
XFORM.eDx := Printer.PageWidth / 2;
end;
end;
SetGraphicsMode(Handle, GM_ADVANCED);
SetWorldTransform(Handle, XFORM);
end;
Is there a known bug or something I've forgot ?
Thanks
Read the Documentation about WorldTransform etc. again. Your Matrix is wrong. Sorry i have now not enough time. If tomorrow there is no answer, i will comment again
ReplyDeleteFriedrich Westermann wrong ?! it works fine on the XPS printer at least...
ReplyDeleteim in the Train now, so from Memory you need to combine three transformations. Translate, rotate and scale. Your Matrix is wrong because em11 and em22 is 0.
ReplyDeletewell it's a 90° rotation, Cos = 0, sin = 1
ReplyDeletex' = 0 * x - 1 * y
y' = 1 * x + 0 *y
:)
You have only the Rotation in your matrix combine it with the default etc... Trust me, Not all drivers are tolerant. Im doing thinks like these a lot.
ReplyDelete/sub
ReplyDeleteAttila Kovacs thanks, but in fact, I do know what a Matrix is :)
ReplyDeletehttp://lookinside.free.fr/delphi.php?FlashPascal+3D
with your code tr = (0, -0,707070708274841, 0,707070708274841, 0, 0, 296) and 210/297 = 0,70707070707067
so my code is just fine for the matrix ;) the problem is why the printer driver do not take it into account :/
Paul TOTH i was total wrong yesterday :-( Sorry for that. Your Matrix is ok. After looking in our Sources for printing i have found these comment:
ReplyDelete// Don't use setworldTransform on Printer.
// Some drivers don't handle it correct
// We will only use ModifyWorldTransform
// Let Windows and Driver do the Job
With these rules there are no problems for us.
more then 6000 Installations and we use it more or less on all output
Our flow is
setidenty
move to our base point
Scale
rotate
move to position
Friedrich Westermann Thanks Friedrich, that is completely insane
ReplyDeleteI've changed this and it works perfectly !
// SetWorldTransform(Handle, XFORM);
ModifyWorldTransform(Handle, XFORM, MWT_IDENTITY); // Reset
ModifyWorldTransform(Handle, XFORM, MWT_LEFTMULTIPLY); // Apply change
/subbbbb
ReplyDeleteSo, maybe I'm slow, but I have to write something like
ReplyDeletefunction MySetWorldTransform(DC: HDC; const XFORM: TXForm): BOOL;
begin
Result := ModifyWorldTransform(DC, XFORM, MWT_IDENTITY); // Reset
if Result then
Result := ModifyWorldTransform(DC, XFORM, MWT_LEFTMULTIPLY); // Apply change
end;
and call that instead of SetWorldTransform and that's it? And MS/the driver manufacturer got that wrong?
Yes don't calculate the transform yourself, use ModifyWorldTransform.
ReplyDeleteSome Drivers are a really pain.......
Ok, thanks!
ReplyDeleteHi there,
ReplyDeleteI can hep to get to the bottom of the issue. I have been writing Windows print drivers since Windows 0.8 beta (1987?).
Drivers do not get calls for SetWorldTransform". It cannot be the driver's fault for mishandling the call.
SetWorldTransform, Modify Transform et all), all do the same thing... produce one single transform (way ahead of the driver).
Done right, the result will always be exactly the same: the coordinates and transform that (may) arrive at the driver.
Take (0,0) and (Device.PixelWidth, Device.PixelHeight) and transform them in reverse.
Do you get the expected results?
Take PointIWantToPrint() and transform it to the printer's device space.
Did the transformed point end up within the bounds of Device.PixelWidth, Device.PixelHeight?
If so, OK, blame the driver subsystem and write a nasty letter to someone (hopefully it will end up on my desk, I need some work right now).
If not, it is a math or order issue with your calls.
It is worth noting that the vast majority of drivers are Unidrivers, and do not even receive these sort of transforms (they mostly only get pixels to print). Only Monolithic drivers are really affected by needing to interpret (some) transforms, and they are very rare to come by.
You can easily test the driver subsystem by using a simple, "easy to get right" transform. Print a rotated line. If that works, the driver is fine (be sure to use a line width and color you can see - a one pixel line can be hard to see at 600+ dpi).
Hope that helps!
Joe [did I mention I am looking for work? I specialize in Windows GDI, graphic engines, print drivers, PDF, and PostScirpt]
Joe C. Hecht Thanks for the insights!
ReplyDeleteUli Gerhardt You are very welcome. I hope it to be helpful.
ReplyDelete