teepdfcanvas.pas
来自「Delphi TeeChartPro.6.01的源代码」· PAS 代码 · 共 1,268 行 · 第 1/3 页
PAS
1,268 行
if (Brush.Style<>bsClear) then
begin
if (Pen.Style<>psClear) then AddString(sStream,'B')
else AddString(sStream,'f');
end else AddString(sStream,'S');
end;
end;
procedure TPDFCanvas.SetPixel3D(X,Y,Z:Integer; Value: TColor);
begin
if Pen.Style<>psClear then
begin
Calc3DPos(x,y,z);
Pen.Color:=Value;
MoveTo(x,y);
LineTo(x,y);
end;
end;
procedure TPDFCanvas.SetPixel(X, Y: Integer; Value: TColor);
begin
if Pen.Style<>psClear then
begin
Pen.Color:=Value;
MoveTo(x,y);
LineTo(x,y);
end;
end;
procedure TPDFCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
begin
InternalDrawArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4, True,False);
end;
procedure TPDFCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
begin
InternalDrawArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4, False, True);
end;
procedure TPDFCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
begin
InternalRect(TeeRect(X1,Y1,X2,Y2),True,True);
end;
Procedure TPDFCanvas.TextOut3D(X,Y,Z:Integer; const Text:String);
begin
RotateLabel3D(X,Y,Z,Text,0);
end;
Procedure TPDFCanvas.TextOut(X,Y:Integer; const Text:String);
begin
TextOut3D(X,Y,0,Text);
end;
procedure TPDFCanvas.MoveTo3D(X,Y,Z:Integer);
begin
Calc3DPos(x,y,z);
MoveTo(x,y);
end;
procedure TPDFCanvas.LineTo3D(X,Y,Z:Integer);
begin
Calc3DPos(x,y,z);
LineTo(x,y);
end;
Procedure TPDFCanvas.DoHorizLine(X0,X1,Y:Integer);
begin
MoveTo(X0,Y);
LineTo(X1,Y);
end;
Procedure TPDFCanvas.DoVertLine(X,Y0,Y1:Integer);
begin
MoveTo(X,Y0);
LineTo(X,Y1);
end;
procedure TPDFCanvas.RotateLabel3D(x,y,z:Integer; Const St:String; RotDegree:Integer);
Procedure DoText(AX,AY: double; RotRad: double);
var tw,th: double;
vcos, vsin : double;
xc,yc: double;
FontIndex: Integer;
begin
AddString(sStream,PDFColor(Font.Color)+' rg');
AddString(sStream,'BT');
if Assigned(IFont) then AddString(sStream,FontProperties(IFont,FontIndex))
else AddString(sStream,FontProperties(TTeeFont(Font),FontIndex));
{ Get text width and height }
th := TextHeight(St);
if (TextAlign and TA_CENTER)=TA_CENTER then tw := TextWidth(St)*0.5
else if (TextAlign and TA_RIGHT)=TA_RIGHT then tw := TextWidth(St)
else tw := 0 ;
{$IFNDEF LINUX}
{ FIX :
the system uses 72 Pixelsperinch as a base line figure, most systems are
96 DPI or if your in large Font Mode then 120 DPI
So when using the TextWidth/TextHeight of the currently selected font, you get the wrong answer
}
tw := tw*72/PFontEntry(FontList.Items[FontIndex]).FontData.otmTextMetrics.tmDigitizedAspectX;
th := th*72/PFontEntry(FontList.Items[FontIndex]).FontData.otmTextMetrics.tmDigitizedAspectY;
{$ENDIF}
TranslateVertCoord(AY);
{ rotation elements }
vcos := Cos(RotRad);
vsin := Sin(RotRad);
{ rotated values }
xc := AX - (tw*vcos-th*vsin);
yc := AY - (tw*vsin+th*vcos);
tmpSt := FormatFloat('0.000',vcos)+ ' ' + FormatFloat('0.000',vsin)+ ' '+
FormatFloat('0.000',-vsin)+ ' ' + FormatFloat('0.000',vcos)+ ' '+
FormatFloat('0.000',xc)+ ' ' + FormatFloat('0.000',yc)+ ' Tm';
FixSeparator(tmpSt);
AddString(sStream,tmpSt);
AddString(sStream,'('+TextToPDFText(St)+') Tj');
AddString(sStream,'ET');
end;
var tmpX : Integer;
tmpY : Integer;
begin
Calc3DPos(X,Y,Z);
if Assigned(IFont) then
With IFont.Shadow do
if (HorizSize<>0) or (VertSize<>0) then
begin
if HorizSize<0 then
begin
tmpX:=X;
X:=X-HorizSize;
end
else tmpX:=X+HorizSize;
if VertSize<0 then
begin
tmpY:=Y;
Y:=Y-VertSize;
end
else tmpY:=Y+VertSize;
DoText(tmpX,tmpY, RotDegree*0.01745329);
end;
DoText(X,Y, RotDegree*0.01745329);
end;
procedure TPDFCanvas.RotateLabel(x,y:Integer; Const St:String; RotDegree:Integer);
begin
RotateLabel3D(x,y,0,St,RotDegree);
end;
Procedure TPDFCanvas.Line(X0,Y0,X1,Y1:Integer);
begin
MoveTo(X0,Y0);
LineTo(X1,Y1);
end;
Procedure TPDFCanvas.HorizLine3D(Left,Right,Y,Z:Integer);
begin
MoveTo3D(Left,Y,Z);
LineTo3D(Right,Y,Z);
end;
Procedure TPDFCanvas.VertLine3D(X,Top,Bottom,Z:Integer);
begin
MoveTo3D(X,Top,Z);
LineTo3D(X,Bottom,Z);
end;
Procedure TPDFCanvas.ZLine3D(X,Y,Z0,Z1:Integer);
begin
MoveTo3D(X,Y,Z0);
LineTo3D(X,Y,Z1);
end;
Procedure TPDFCanvas.LineWithZ(X0,Y0,X1,Y1,Z:Integer);
begin
MoveTo3D(X0,Y0,Z);
LineTo3D(X1,Y1,Z);
end;
Function TPDFCanvas.GetBackMode:TCanvasBackMode;
begin
result:=FBackMode;
end;
Procedure TPDFCanvas.PolygonFour;
begin
Polygon(IPoints);
end;
Procedure TPDFCanvas.Polygon(const Points: Array of TPoint);
var t: Integer;
begin
if (Brush.Style<>bsClear) or (Pen.Style<>psClear) then
begin
if (Pen.Style<>psClear) then
AddString(sStream,PenProperties(Pen));
AddString(sStream,PointToStr(Points[0].X,Points[0].Y)+' m');
for t:=1 to High(Points) do
AddString(sStream,PointToStr(Points[t].X,Points[t].Y)+' l');
AddString(sStream,'h');
if (Brush.Style<>bsClear) then
begin
AddString(sStream,BrushProperties(Brush));
if (Pen.Style<>psClear) then AddString(sStream,'B')
else AddString(sStream,'f');
end else AddString(sStream,'S');
end;
end;
function TPDFCanvas.InitWindow(DestCanvas: TCanvas;
A3DOptions: TView3DOptions; ABackColor: TColor; Is3D: Boolean;
const UserRect: TRect): TRect;
var i: Integer;
begin
result:=inherited InitWindow(DestCanvas,A3DOptions,ABackColor,Is3D,UserRect);
IClipCalled := False;
TheBounds;
IObjCount := 0;
ObjectOffset := 0;
ObjectOffsetList.Clear;
for i := 0 to FontList.Count -1 do
begin
FontEntry := FontList.Items[i];
Dispose(FontEntry);
end;
FontList.Clear;
{ clear all streams }
PDF.Clear;
tStream.Clear;
sStream.Clear;
DefineHeader;
StartStream;
end;
function TPDFCanvas.SelectFont(Font: TFont): Integer;
var i: Integer;
FName : String;
{$IFNDEF CLX}
FontInfo: ^TOutlineTextMetric;
{$ENDIF}
begin
{$IFDEF CLX}
result:=-1;
{$ENDIF}
FName := ConstructFontName(Font);
for i := 0 to FontList.Count -1 do
{ Font already in the font list ? }
if FName = PFontEntry(FontList.Items[i]).UniqueName then
begin
Result := i;
Exit;
end;
{$IFNDEF CLX}
{ New font ? Generate entry for it }
New(FontInfo);
try
GetOutlineTextMetrics(Handle,SizeOf(TOutlineTextMetric),FontInfo);
New(FontEntry);
FontEntry^.UniqueName := FName;
FontEntry^.FontData := FontInfo^;
FontEntry^.Font := Font;
FontEntry^.Name := 'F'+IntToStr(FontList.Count +1);
FontList.Add(FontEntry);
Result := FontList.Count-1;
finally
Dispose(FontInfo);
end;
{$ENDIF}
end;
procedure TPDFCanvas.WriteTrueTypeFonts;
var
First, Last: Integer;
Flags: Integer;
i,j: Integer;
MulFactor: double;
FData : TOutlineTextMetric;
CharWidths: Array[0..255] of Integer;
begin
fStream.Clear;
for i := 0 to FontList.Count -1 do
begin
FData := PFontEntry(FontList.Items[i]).FontData;
ReferenceCanvas.Font.Assign(PFontEntry(FontList.Items[i]).Font);
{$IFNDEF CLX}
{ TODO : Verify the MulFactor calculation with large/small fonts }
{ Especially why it seems 0.6 is correct factor in both cases ? }
MulFactor :=FData.otmEMSquare/FData.otmTextMetrics.tmHeight*0.6;
{$ELSE}
MulFactor := 1;
{$ENDIF}
{$IFNDEF CLX}
GetCharWidth32(Handle,0,255,CharWidths);
{$ENDIF}
{$IFDEF LINUX}
First := 0;
Last := 255;
{$ELSE}
First := Ord(FData.otmTextMetrics.tmFirstChar);
Last := Ord(FData.otmTextMetrics.tmLastChar);
{$ENDIF}
Flags := 32; { TODO : Missing correct flag calculation }
{ Font header }
Inc(IObjCount);
PFontEntry(FontList.Items[i]).ObjPos := IObjCount;
tStream.Clear;
AddString(tStream,IntToStr(IObjCount)+' 0 obj');
AddString(tStream,'<< /Type /Font');
AddString(tStream,'/Subtype /TrueType');
AddString(tStream,'/BaseFont /'+PFontEntry(FontList.Items[i]).UniqueName);
AddString(tStream,'/FirstChar '+IntToStr(First));
AddString(tStream,'/LastChar '+IntToStr(Last));
AddString(tStream,'/FontDescriptor '+IntToStr(IObjCount+1)+' 0 R');
AddString(tStream,'/Widths '+IntToStr(IObjCount+2)+' 0 R');
AddString(tStream,'/Encoding /WinAnsiEncoding');
AddString(tStream,'>>');
AddString(tStream,'endobj');
AddToOffset(tStream.Size);
fStream.Seek(0, soFromEnd);
tStream.SaveToStream(fStream);
{ add font descriptor }
Inc(IObjCount);
tStream.Clear;
AddString(tStream,IntToStr(IObjCount)+' 0 obj');
AddString(tStream,'<< /Type /FontDescriptor');
AddString(tStream,'/FontName /'+PFontEntry(FontList.Items[i]).UniqueName);
AddString(tStream,'/Flags '+IntToStr(Flags));
{$IFNDEF LINUX}
AddString(tStream,'/FontBBox ['+
IntToStr(Round(FData.otmrcFontBox.Left*MulFactor))+' ' +
IntToStr(Round(FData.otmrcFontBox.Bottom*MulFactor))+' ' +
IntToStr(Round((FData.otmrcFontBox.right - FData.otmrcFontBox.Left)*MulFactor))+' ' +
IntToStr(Round((FData.otmrcFontBox.Top - FData.otmrcFontBox.Bottom)*MulFactor))+']');
AddString(tStream,'/CapHeight '+IntToStr(Round(FData.otmTextMetrics.tmHeight*MulFactor)));
AddString(tStream,'/Ascent '+IntToStr(Round(FData.otmAscent*MulFactor)));
AddString(tStream,'/Descent '+IntToStr(-Round(FData.otmDescent*MulFactor)));
AddString(tStream,'/Leading '+IntToStr(Round(FData.otmTextMetrics.tmInternalLeading*MulFactor)));
AddString(tStream,'/MaxWidth '+IntToStr(Round(FData.otmTextMetrics.tmMaxCharWidth*MulFactor)));
AddString(tStream,'/AvgWidth '+IntToStr(Round(FData.otmTextMetrics.tmAveCharWidth*MulFactor)));
AddString(tStream,'/ItalicAngle '+IntToStr(FData.otmItalicAngle));
{$ENDIF}
AddString(tStream,'>>');
AddString(tStream,'endobj');
AddToOffset(tStream.Size);
fStream.Seek(0, soFromEnd);
tStream.SaveToStream(fStream);
{ write widths }
Inc(IObjCount);
tStream.Clear;
AddString(tStream,IntToStr(IObjCount)+' 0 obj');
AddString(tStream,'[');
tmpSt := '';
for j := First to Last do
if (j mod 15 = 14) then tmpSt := tmpSt + IntToStr(Round(CharWidths[j]*MulFactor))+' '+#13+#10
else tmpSt := tmpSt + IntToStr(Round(CharWidths[j]*MulFactor))+' ';
AddString(tStream,tmpSt);
AddString(tStream,']');
AddString(tStream,'endobj');
AddToOffset(tStream.Size);
fStream.Seek(0, soFromEnd);
tStream.SaveToStream(fStream);
end;
PDF.Seek(0, soFromEnd);
fStream.SaveToStream(PDF);
end;
function TPDFCanvas.ConstructFontName(Font: TFont): String;
begin
tmpSt := Font.Name;
if (fsBold in Font.Style) then tmpSt := tmpSt+',Bold';
if (fsItalic in Font.Style) then tmpSt := tmpSt+',Italic';
Result := StringReplace(tmpSt,' ','#20',[rfReplaceAll]);
end;
procedure TPDFCanvas.DefineCatalog;
begin
{ Catalog part }
Inc(IObjCount);
ICatalogNum := IObjCount;
tStream.Clear;
AddString(tStream,IntToStr(IObjCount)+' 0 obj');
AddString(tStream,'<< /Type /Catalog');
AddString(tStream,'/Pages '+IntToStr(IParentNum)+' 0 R');
AddString(tStream,'/Outlines '+IntToStr(IOutlineNum)+' 0 R');
AddString(tStream,'>>');
AddString(tStream,'endobj');
AddToOffset(tStream.Size);
PDF.Seek(0, soFromEnd);
tStream.SaveToStream(PDF);
end;
procedure TPDFCanvas.DefineOutline;
begin
{ Outline part }
Inc(IObjCount);
IOutLineNum := IObjCount;
tStream.Clear;
AddString(tStream,IntToStr(IObjCount)+' 0 obj');
AddString(tStream,'<< /Type /Outlines');
AddString(tStream,'/Count 0');
AddString(tStream,'>>');
AddString(tStream,'endobj');
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?