#1 2011-12-16 08:19:32

macaos
Member
Registered: 2011-12-15
Posts: 3

Scaling with CTM

Hi
First off, thank you for making this excellent tool available.
It is far more functional and flexible than the quick and dirty attempt that I made a couple of years ago.

We are using the PDF engine to generate technical drawings.
Our working unit for our objects is 0.0001mm and our coordinates are integer values.
Our object space has a bottom left origin, and we have objects embedded within objects, so we make extensive use of the Current Transformation Matrix in PDF space to handle scaling, origin translation and rotation. For this reason, it is much more practical for us to draw to the PDF canvas rather than to the VCL canvas.

However we have run into a couple of limitations, and I wonder if these are necessary.

1) TPdfCanvas.ConcatToCTM makes use of the TPdfWrite.AddWithSpace function, which rounds output values to 2 decimal points. While I understand the value of this function for most coordinates passed to the PDFWriter, I question whether it is an appropriate limitation on CTM transformations, since it can have serious effects on the precision of scaling and rotation when concatenating to the CTM (especially in cases where one wants to do the inverse of the previous transformation). Would it be possible to support 6 or 8 decimal precision when concatenating to the CTM?

2) TPdfCanvas.SetDash uses an array of Byte as an input to the dashed line array. This limits the dash values to 255, which is more than enough when working in points, but far to little when working at our desired scale. Is there any reason why this could not be changed to an array of integer?

3) TPdfPage.SetFontSize limits the font size to PDF_MAX_FONTSIZE (300), which again is fine when working in points. It is, however, an artificial limitation if the CTM scale has been changed. I haven't tried overriding this limitation because I don't have a lot of experience working with fonts in PDF and I am unsure what might happen to character spacing, kerning, leading or other font related parameters. Is it possible to take away this limitation? I understand that removing the font size limit may increase the risk of problems if the CTM scale has not been changed. So perhaps it might be an idea to use a compiler directive to disable the font size limitation.

For the time being, we are drawing graphics directly to the PDF canvas and drawing text to the VCL canvas. But this means a lot of extra work to do the conversion between the two geometric spaces in order to properly place texts.

Bruce

Offline

#2 2011-12-16 09:29:58

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,243
Website

Re: Scaling with CTM

Thanks a lot for your interest in your work, and for your very good proposals.

1) Added a "Decimals: cardinal=6" parameter to TPdfCanvas.ConcatToCTM.

2) TPdfCanvas.SetDash parameter is now an array of integer.

3) Set PDF_MAX_FONTSIZE limit to 2000 - should be big enough in practice.

See http://synopse.info/fossil/info/f7ef6f72d3

All your points does definitively make sense!

Thanks for the feedback.

Offline

#3 2011-12-16 11:02:35

macaos
Member
Registered: 2011-12-15
Posts: 3

Re: Scaling with CTM

Thanks so much for your quick response
Bruce

Offline

#4 2011-12-27 10:35:56

macaos
Member
Registered: 2011-12-15
Posts: 3

Re: Scaling with CTM

Hi
We've gotten things working in a satisfactory manner for our purposes, and would therefore like to propose the following two changes to the SynPDF unit:

1) In order to more flexibly manage CTM scaling together with max font size, etc...

const
  PDF_MAX_FONTSIZE = 300;  // return this to it's original value, scaling is managed below

type
  TPdfCanvas = class(TObject)
  protected
    // CTM scaling factors -- used in conjunction with min/max text sizes
    FCTMScaleX, FCTMScaleY: single;

constructor TPdfCanvas.Create(APdfDoc: TPdfDocument);
  FCTMScaleX := 1.0;
  FCTMScaleY := 1.0;

procedure TPdfCanvas.ConcatToCTM(a, b, c, d, e, f: Single; Decimals: Cardinal);
  // if concatenating a scaling operation, then adjust the FCTMScale factors
  if (not IsZero(a)) and (not IsZero(d)) and IsZero(b) and IsZero(c) then
    begin
      FCTMScaleX:=FCTMScaleX*a;
      FCTMScaleY:=FCTMScaleY*d;
    end;

procedure TPdfPage.SetCharSpace(Value: Single);
  if (Value < Abs(PDF_MIN_CHARSPACE/fDoc.Canvas.FCTMScaleX)) or (VALUE > Abs(PDF_MAX_CHARSPACE/fDoc.Canvas.FCTMScaleX)) then                  

procedure TPdfPage.SetFontSize(Value: Single);
  if (Value < 0) or (Value > Abs(PDF_MAX_FONTSIZE/fDoc.Canvas.FCTMScaleY)) then

procedure TPdfPage.SetHorizontalScaling(Value: Single);
  if (Value < Abs(PDF_MIN_HORIZONTALSCALING/fDoc.Canvas.FCTMScaleX)) or (Value > Abs(PDF_MAX_HORIZONTALSCALING/fDoc.Canvas.FCTMScaleX)) then

procedure TPdfPage.SetLeading(Value: Single);
  if (Value < 0) or (Value > Abs(PDF_MAX_LEADING/fDoc.Canvas.FCTMScaleY)) then

There are a couple of weaknesses with this approach, but it is more flexible than hardcoding the PDF_MAX_xxx values.
a) our proposed modification to ConcatToCTM assumes that a scaling operation will never be combined with a rotate or skew operation.
b) if the horizontal and vertical scales are not identical, then undesired limitations may arise for rotated text.
    This is because we propose using X scale for min/max charspace and horizontal scaling and Y scale for max fontsize and leading.
c) The constant PDF_MAX_WORDSPACE does not appear to be used in SynPDF, so we have ignored it in our proposal.




2) In order to support user defined keys in the Document Information Dictionary...

type
  TPdfInfo = class(TPdfDictionaryWrapper)
  private
    function GetUserKey(Key: PDFString): string;
    procedure SetUserKey(Key: PDFString; Value: string);
  public
    property UserKey[Key: PDFString]: string read GetUserKey write SetUserKey;

function TPdfInfo.GetUserKey(Key: PDFString): string;
begin
  result := FData.PdfTextStringValueByName(Key);
end;

procedure TPdfInfo.SetUserKey(Key: PDFString; Value: string);
begin
  FData.AddItemTextString(Key, Value);
end;

Last edited by macaos (2012-02-13 09:06:48)

Offline

Board footer

Powered by FluxBB