⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 teepdfcanvas.pas

📁 TeeChart7Source 控件
💻 PAS
📖 第 1 页 / 共 4 页
字号:
  FChartObject.Free;
  OffsetList.Clear;
  inherited;
end;

procedure TTeePDFPage.SaveToStream(AStream: TStream);
begin
  WriteHeader(AStream);
  WriteInfo(AStream);

  // write chart canvas code
  Inc(IObjCount);
  AddToOffset(AStream.Size);
  WriteStringToStream(AStream,IntToStr(IObjCount)+ ' 0 obj'+CRLF);
  FChartObject.SaveToStream(AStream);
  WriteStringToStream(AStream,'endobj'+CRLF);

  // TT fonts
  WriteTTFonts(AStream);
  // Additional images, if they exist
  WriteImages(AStream);
  // Resources
  WriteResources(AStream);
  // Pages and page
  WritePages(AStream);
  WritePage(AStream);
  WriteCatalog(AStream);
  WriteXRef(AStream);
  WriteStringToStream(AStream,'%%EOF'+CRLF);
end;

procedure TTeePDFPage.SetPageHeight(const Value: Integer);
begin
  FPageHeight := Value;
end;

procedure TTeePDFPage.SetPageWidth(const Value: Integer);
begin
  FPageWidth := Value;
end;

procedure TTeePDFPage.WriteCatalog(AStream: TStream);
begin
  Inc(IObjCount);
  CatalogNum := IObjCount;
  AddToOffset(AStream.Size);
  WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
  WriteStringToStream(AStream,'<< /Type /Catalog' + CRLF);
  WriteStringToStream(AStream,'/Pages ' + IntToStr(ParentNum) + ' 0 R'+ CRLF);
  WriteStringToStream(AStream,'>>'+CRLF);
  WriteStringToStream(AStream,'endobj'+CRLF);
end;

procedure TTeePDFPage.WriteHeader(AStream: TStream);
begin
  WriteStringToStream(AStream,'%PDF-1.4'+CRLF);
end;

procedure TTeePDFPage.WriteImages(AStream: TStream);
var i: Integer;
begin
  with FChartObject.ImageArray do
  begin
    for i := 0 to ItemsCount -1 do
    begin
      Inc(IObjCount);
      AddToOffset(AStream.Size);
      Items[i].ObjectNumber := IObjCount;
      WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
      WriteStringToStream(AStream,'<< /Type /XObject'+CRLF);
      WriteStringToStream(AStream,'/Subtype /Image'+CRLF);
      WriteStringToStream(AStream,'/Name /Im'+IntToStr(i)+CRLF);
      WriteStringToStream(AStream,'/Length '+IntToStr(Items[i].DataLength)+CRLF);
      WriteStringToStream(AStream,'/Width '+IntToStr(Items[i].Width)+CRLF);
      WriteStringToStream(AStream,'/Height '+IntToStr(Items[i].Height)+CRLF);
      WriteStringToStream(AStream,'/ColorSpace /DeviceRGB'+CRLF);
      WriteStringToStream(AStream,'/BitsPerComponent 8'+CRLF);
      if Items[i].ImageType = itJPEG then WriteStringToStream(AStream,'/Filter [/DCTDecode]'+CRLF);
      WriteStringToStream(AStream,'>>'+CRLF);
      WriteStringToStream(AStream,'stream'+CRLF);
      Items[i].WriteDataToStream(AStream);
      WriteStringToStream(AStream,'endstream'+CRLF);
      WriteStringToStream(AStream,'endobj'+CRLF);
    end;
  end;
end;

procedure TTeePDFPage.WriteInfo(AStream: TStream);
begin
  Inc(IObjCount);
  AddToOffset(AStream.Size);
  WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
  tmpSt := '<<'+CRLF+'/Creator (' + TeeMsg_Version +')'+CRLF+'/Producer (' + TeeMsg_Version+')'+CRLF+
    '/CreationDate (D:'+FormatDateTime('YYYYMMDDHHmmSS',Now)+')'+CRLF+'/ModDate ()' + CRLF +
    '/Keywords ()'+CRLF+'/Title (TChart Export)' + CRLF+'>>'+CRLF;
  WriteStringToStream(AStream, tmpSt);
  WriteStringToStream(AStream,'endobj'+CRLF);
end;

procedure TTeePDFPage.WritePage(AStream: TStream);
begin
  Inc(IObjCount);
  AddToOffset(AStream.Size);
  WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
  WriteStringToStream(AStream,'<< /Type /Page' + CRLF + '/Parent '+IntToStr(ParentNum)+ ' 0 R'+CRLF);
  WriteStringToStream(AStream,'/MediaBox [ 0 0 ' + IntToStr(FPageWidth) + ' ' + IntToStr(FPageHeight) + ' ]'+CRLF);
  WriteStringToStream(AStream,'/Contents 2 0 R'+CRLF);
  WriteStringToStream(AStream,'/Resources ' + IntToStr(ResourceNum)+' 0 R'+CRLF);
  WriteStringToStream(AStream,'>>'+CRLF);
  WriteStringToStream(AStream,'endobj'+CRLF);
end;

procedure TTeePDFPage.WritePages(AStream: TStream);
begin
  Inc(IObjCount);
  AddToOffset(AStream.Size);
  ParentNum := IObjCount;
  WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
  // Must be followed by WritePage call, otherwise object reference will not be correct
  tmpSt := '<< /Type /Pages' + CRLF + '/Kids [' + IntToStr(IObjCount+1)+' 0 R]'+CRLF+
    '/Count 1'+CRLF+'>>'+CRLF;
  WriteStringToStream(AStream,tmpSt);
  WriteStringToStream(AStream,'endobj'+CRLF);
end;

procedure TTeePDFPage.WriteResources(AStream: TStream);
var i: Integer;
begin
  Inc(IObjCount);
  ResourceNum := IObjCount;
  AddToOffset(AStream.Size);
  WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
  WriteStringToStream(AStream,'<< /ProcSet [/PDF /Text /ImageC]'+CRLF);
  With FChartObject do
  begin
    WriteStringToStream(AStream,'/Font << '+CRLF);
    for i := 0 to FontArray.ItemsCount -1 do
      WriteStringToStream(AStream,'/F'+IntToStr(i) + ' ' + IntToStr(FontArray.Items[i].ObjectNumber)+' 0 R'+CRLF);
    WriteStringToStream(AStream,'>>'+CRLF);
    WriteStringToStream(AStream,'/XObject << '+CRLF);
    for i := 0 to ImageArray.ItemsCount -1 do
      WriteStringToStream(AStream,'/Im'+IntToStr(i) + ' ' + IntToStr(ImageArray.Items[i].ObjectNumber)+' 0 R'+CRLF);
    WriteStringToStream(AStream,'>>'+CRLF);
  end;

  WriteStringToStream(AStream,'>>'+CRLF);
  WriteStringToStream(AStream,'endobj'+CRLF);
end;

procedure TTeePDFFontListEntry.SetObjectNumber(const Value: Integer);
begin
  FObjectNumber := Value;
end;

procedure TTeePDFPage.WriteTrailer(AStream: TStream);
begin
  WriteStringToStream(AStream,'trailer'+CRLF);
  WriteStringToStream(AStream,'<< /Size '+ IntToStr(IObjCount)+CRLF);
  WriteStringToStream(AStream,'/Root '+ IntToStr(CatalogNum)+ ' 0 R'+CRLF);
  WriteStringToStream(AStream,'/Info 1 0 R'+CRLF);
  WriteStringToStream(AStream,'>>'+CRLF);
  WriteStringToStream(AStream,'startxref'+CRLF);
  WriteStringToStream(AStream,IntToStr(XRefPos)+CRLF);
end;

procedure TTeePDFPage.WriteTTFonts(AStream: TStream);
var i,j: Integer;
begin
  With FChartObject.FontArray do
  begin
    for i := 0 to ItemsCount -1 do
    begin
      // font header
      Inc(IObjCount);
      AddToOffset(AStream.Size);
      Items[i].ObjectNumber := IObjCount;
      WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
      WriteStringToStream(AStream,'<< /Type /Font'+CRLF);
      WriteStringToStream(AStream,'/Subtype /TrueType'+CRLF);
      WriteStringToStream(AStream,'/BaseFont /'+ Items[i].PDFName+CRLF);
      WriteStringToStream(AStream,'/Name /F'+IntToStr(i)+CRLF);
      WriteStringToStream(AStream,'/FirstChar '+ IntToStr(Items[i].FontData.FirstChar)+CRLF);
      WriteStringToStream(AStream,'/LastChar '+ IntToStr(Items[i].FontData.LastChar)+CRLF);
      WriteStringToStream(AStream,'/Encoding /WinAnsiEncoding'+CRLF);
      WriteStringToStream(AStream,'/FontDescriptor '+ IntToStr(IObjCount+1)+ ' 0 R'+CRLF);
      WriteStringToStream(AStream,'/Widths '+ IntToStr(IObjCount+2)+' 0 R'+CRLF);
      WriteStringToStream(AStream,'>>'+CRLF);
      WriteStringToStream(AStream,'endobj'+CRLF);

      // Font descriptor
      Inc(IObjCount);
      AddToOffset(AStream.Size);
      WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
      WriteStringToStream(AStream,'<< /Type /FontDescriptor'+CRLF);
      WriteStringToStream(AStream,'/FontName /'+ Items[i].PDFName+CRLF);
      WriteStringToStream(AStream,'/Flags 32'+CRLF);
      With Items[i].FontData do
      begin
        WriteStringToStream(AStream,'/FontBBox ['+
          IntToStr(FontBBox.Left)+ ' ' +
          IntToStr(FontBBox.Bottom)+ ' ' +
          IntToStr(FontBBox.Right)+ ' ' +
          IntToStr(FontBBox.Top)+ ']' + CRLF);
        WriteStringToStream(AStream,'/CapHeight ' + IntToStr(CapHeight)+CRLF);
        WriteStringToStream(AStream,'/Ascent ' + IntToStr(Ascent)+CRLF);
        WriteStringToStream(AStream,'/Descent ' + IntToStr(Descent)+CRLF);
        WriteStringToStream(AStream,'/MaxWidth ' + IntToStr(MaxWidth)+CRLF);
        WriteStringToStream(AStream,'/AvgWidth ' + IntToStr(AvgWidth)+CRLF);
        WriteStringToStream(AStream,'/ItalicAngle ' + IntToStr(ItalicAngle)+CRLF);
        WriteStringToStream(AStream,'/StemV 0'+CRLF);
      end;
      WriteStringToStream(AStream,'>>'+CRLF);
      WriteStringToStream(AStream,'endobj'+CRLF);

      // Font widths
      Inc(IObjCount);
      AddToOffset(AStream.Size);
      WriteStringToStream(AStream,IntToStr(IObjCount)+' 0 obj'+CRLF);
      WriteStringToStream(AStream,'['+CRLF);
      tmpSt := '';
      for j := Items[i].FontData.FirstChar to Items[i].FontData.LastChar do
        if (j mod 15 = 14) then tmpSt := tmpSt + IntToStr(Items[i].FontData.CharWidths[j]) + ' '+CRLF
        else tmpSt := tmpSt + IntToStr(Items[i].FontData.CharWidths[j]) + ' ';
      WriteStringToStream(AStream,tmpSt+CRLF);
      WriteStringToStream(AStream,']'+CRLF);
      WriteStringToStream(AStream,'endobj'+CRLF);
    end;
  end;
end;

procedure TTeePDFPage.WriteXRef(AStream: TStream);
var i: Integer;
begin
  Inc(IObjCount);
  // no need to add xref to xref itself.
  XRefPos := AStream.Size;
  WriteStringToStream(AStream,'xref'+CRLF);
  WriteStringToStream(AStream,'0 '+IntToStr(IObjCount)+CRLF);
  WriteStringToStream(AStream,'0000000000 65535 f'+CRLF);
  for i := 0 to OffSetList.Count - 1  do
    WriteStringToStream(AStream,OffsetList.Strings[i]+' ' + FormatIntToString(0,5)+' n'+ CRLF);
  WriteTrailer(AStream);
end;


{ TTeePDFImageList }

function TTeePDFImageList.AddItem(AGraphic: TGraphic): Integer;
begin
  Result := IImageList.Add(TTeePDFImageListEntry.Create(AGraphic));
end;

constructor TTeePDFImageList.Create;
begin
  inherited;
  IImageList := TList.Create;
end;

destructor TTeePDFImageList.Destroy;
var i: Integer;
begin
  for i := 0 to IImageList.Count - 1 do TTeePDFImageListEntry(IImageList.Items[i]).Free;
  IImageList.Free;
  inherited Destroy;
end;

function TTeePDFImageList.EqualImages(i1, i2: TGraphic): Boolean;
var ms: TMemoryStream;
    s1,s2: String;
    b:Boolean;
begin
  {$IFNDEF CLR}
  ms := TMemoryStream.Create;
  try
    i1.SaveToStream(ms);
    ms.Position := 0;
    SetLength(s1,ms.Size);
    ms.Read(S1[1],Length(s1));
    ms.Clear;
    i2.SaveToStream(ms);
    ms.Position := 0;
    SetLength(s2,ms.Size);
    ms.Read(S2[1],Length(s2));
  finally
    ms.Free;
  end;

  b:=s1=s2;
  result:=b;
  {$ELSE}
  result:=False;
  {$ENDIF}
end;


function TTeePDFImageList.Find(AGraphic: TGraphic): Integer;
var i: Integer;
begin
  Result := -1;
  for i := 0 to ItemsCount-1 do
    if EqualImages(AGraphic,Items[i].FGraphic) then
    begin
      Result := i;
      Break;
    end;
end;

function TTeePDFImageList.GetCount: Integer;
begin
  Result := IImageList.Count;  
end;

function TTeePDFImageList.GetImageEntry(
  Index: Integer): TTeePDFImageListEntry;
begin
  Result := TTeePDFImageListEntry(IImageList.Items[Index]);
end;

{ TTeePDFImageListEntry }

constructor TTeePDFImageListEntry.Create(AGraphic: TGraphic);
begin
  inherited Create;
  FGraphic := AGraphic;
  DefineImageData;
end;

procedure TTeePDFImageListEntry.DefineImageData;
begin
  FWidth := FGraphic.Width;
  FHeight := FGraphic.Height;
end;

function TTeePDFImageListEntry.GetDataLength: Integer;
var ms : TMemoryStream;
begin
  ms := TMemoryStream.Create;
  try
    FGraphic.SaveToStream(ms);
    Result := ms.Size;
  finally
    ms.Free;
  end;
end;

function TTeePDFImageListEntry.GetImageType: TImageType;
begin
  {$IFNDEF CLR}
  {$IFNDEF CLX}
  if (FGraphic is TJPEGImage) then Result := itJPEG
  else
  {$ENDIF}
  {$ENDIF}
  if (FGraphic is TBitmap) then Result := itBitmap
  else Result := itUnknown; 
end;

procedure TTeePDFImageListEntry.SetObjectNumber(const Value: Integer);
begin
  FObjectNumber := Value;
end;

function TPDFCanvas.SelectImage(Graphic: TGraphic): integer;
begin
  Result := FContents.ImageArray.Find(Graphic);
  if Result = -1 then Result := FContents.ImageArray.AddItem(Graphic);
end;

procedure TTeePDFImageListEntry.WriteDataToStream(AStream: TStream);
const BytesPerPixel={$IFDEF CLX}4{$ELSE}3{$ENDIF};
var x,y: Integer;
  pb: {$IFDEF CLR}IntPtr{$ELSE}PByteArray{$ENDIF};
  b: Byte;
begin
  {$IFNDEF CLR}
  {$IFNDEF CLX}
  if FGraphic is TJpegImage then
     (FGraphic as TJpegImage).SaveToStream(AStream)
  else
  {$ENDIF}
  {$ENDIF}
  if FGraphic is TBitmap then
  with (FGraphic as TBitmap) do
  begin
    if PixelFormat<>TeePixelFormat then PixelFormat:=TeePixelFormat;

    {$IFNDEF CLR}
    for y := 0 to Height -1 do
    begin
      pb := ScanLine[y];
      x := 0;
      while x < Width*BytesPerPixel do
      begin
        b := pb[x];
        pb[x] := pb[x+2];
        pb[x+2] := b;
        AStream.Write(pb[x],3);
        Inc(x,BytesPerPixel);
      end;
    end;
    {$ENDIF}
  end;

  WriteStringToStream(AStream,CRLF);
end;

initialization
  RegisterTeeExportFormat(TPDFExportFormat);
finalization
  UnRegisterTeeExportFormat(TPDFExportFormat);
end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -