mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 14:21:31 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			266 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
| pdfvectorialreader.pas
 | |
| 
 | |
| Reads the vectorial information form a PDF file
 | |
| 
 | |
| PDF file format specification obtained from:
 | |
| 
 | |
| ADOBE SYSTEMS INCORPORATED. PDF Reference: Adobe®
 | |
| Portable Document Format. San Jose, 2006. (Sixth edition).
 | |
| 
 | |
| AUTHORS: Felipe Monteiro de Carvalho
 | |
|          Pedro Sol Pegorini L de Lima
 | |
| }
 | |
| unit pdfvectorialreader;
 | |
| 
 | |
| {$ifdef fpc}
 | |
|   {$mode delphi}
 | |
| {$endif}
 | |
| 
 | |
| interface
 | |
| 
 | |
| uses
 | |
|   Classes, SysUtils,
 | |
|   pdfvrlexico, pdfvrsintatico, pdfvrsemantico, avisozlib,
 | |
|   fpvectorial;
 | |
| 
 | |
| type
 | |
| 
 | |
|   { TvPDFVectorialReader }
 | |
| 
 | |
|   TvPDFVectorialReader = class(TvCustomVectorialReader)
 | |
|   private
 | |
|     procedure WriteStringToStream(AStream: TStream; AString: string);
 | |
|   public
 | |
|     { public to allow uncompressing PDFs independently }
 | |
|     function getFirstPage(AInput: TStream; AOutput: TStream):PageHeader;
 | |
|     procedure unzipPage(AInput: TStream; AOutput: TStream);
 | |
|     procedure translatePage(AInput: TStream; AData: TvVectorialDocument;
 | |
|               APageHeader: PageHeader);
 | |
|     { General reading methods }
 | |
|     procedure ReadFromStream(AStream: TStream; AData: TvVectorialDocument); override;
 | |
|   end;
 | |
| 
 | |
| implementation
 | |
| 
 | |
| { TvPDFVectorialReader }
 | |
| 
 | |
| procedure TvPDFVectorialReader.WriteStringToStream(AStream: TStream;
 | |
|   AString: string);
 | |
| begin
 | |
|   AStream.WriteBuffer(AString[1], Length(AString));
 | |
| end;
 | |
| 
 | |
| function TvPDFVectorialReader.getFirstPage(AInput: TStream; AOutput: TStream): PageHeader;
 | |
| var
 | |
|   mytoken: Token;
 | |
|   myAnLexicoPage: AnLexico;
 | |
|   myAnLexicoContents: AnLexico;
 | |
|   myAnSintaticoPage: AnSintaticoPage;
 | |
|   myAnSintaticoContents: AnSintaticoPageContents;
 | |
|   AInput2: TStream;
 | |
| begin
 | |
|   {$ifdef FPVECTORIALDEBUG}
 | |
|   WriteLn(':> TvPDFVectorialReader.getFirstPage');
 | |
|   {$endif}
 | |
|   AInput2 := TMemoryStream.Create;
 | |
|   AInput2.Size := AInput.Size;
 | |
|   AInput2.CopyFrom(AInput, AInput.Size);
 | |
|   AInput.Seek(0, soFromBeginning);
 | |
|   AInput2.Seek(0, soFromBeginning);
 | |
| 
 | |
|   myAnLexicoPage := AnLexico.Create;
 | |
|   myAnLexicoPage.Doc := AInput;
 | |
|   myAnLexicoPage.bytesRemaining:= myAnLexicoPage.Doc.Size;
 | |
|   myAnSintaticoPage := AnSintaticoPage.Create;
 | |
| 
 | |
|   // find first page
 | |
|   while ((myAnSintaticoPage.pageFound <> true) and
 | |
|                    (myAnLexicoPage.bytesRemaining > 0)) do
 | |
|   begin
 | |
|     mytoken := myAnLexicoPage.getToken();
 | |
|     myAnSintaticoPage.automata(mytoken);
 | |
|   end;
 | |
| 
 | |
|   if (myAnSintaticoPage.pageFound = false) then
 | |
|   begin
 | |
|     raise Exception.Create('ERROR: Arquivo corrompido.');
 | |
|     Halt(1);
 | |
|   end;
 | |
| 
 | |
|   AInput.Seek(0, soFromBeginning);
 | |
|   myAnLexicoContents := AnLexico.Create;
 | |
|   myAnLexicoContents.Doc := AInput;
 | |
|   myAnLexicoContents.bytesRemaining:= myAnLexicoContents.Doc.Size;
 | |
|   myAnSintaticoContents := AnSintaticoPageContents.Create;
 | |
| 
 | |
|   // gathering information of the first page
 | |
|   myAnSintaticoContents.obj1:=myAnSintaticoPage.obj1;
 | |
|   myAnSintaticoContents.obj2:=myAnSintaticoPage.obj2;
 | |
| 
 | |
|   //find first page contents
 | |
|   while ((myAnSintaticoContents.contentsFound <> true) and
 | |
|                    (myAnLexicoContents.bytesRemaining > 0)) do
 | |
|   begin
 | |
|     mytoken := myAnLexicoContents.getToken();
 | |
|     myAnSintaticoContents.automata(mytoken, AInput2);
 | |
|   end;
 | |
| 
 | |
|   if (myAnSintaticoContents.contentsFound = false) then
 | |
|   begin
 | |
|     raise Exception.Create('ERROR: Arquivo corrompido.');
 | |
|     Halt(1);
 | |
|   end;
 | |
| 
 | |
|   // gathering information of the first page
 | |
|   myAnLexicoContents.bytesRemaining:=myAnSintaticoContents.h.page_length;
 | |
| 
 | |
|   // write file with content just from the first page
 | |
|   while (myAnLexicoContents.bytesRemaining > 0) do
 | |
|   begin
 | |
|     mytoken := myAnLexicoContents.getPageToken();
 | |
|     WriteStringToStream(AOutput, mytoken.token_string);
 | |
|   end;
 | |
| 
 | |
|   Result:=myAnSintaticoContents.h;
 | |
| 
 | |
|   {$ifdef FPVECTORIALDEBUG}
 | |
|   WriteLn(':< TvPDFVectorialReader.getFirstPage');
 | |
|   {$endif}
 | |
| 
 | |
| //  AInput2.Free;
 | |
| end;
 | |
| 
 | |
| procedure TvPDFVectorialReader.unzipPage(AInput: TStream; AOutput: TStream);
 | |
| var
 | |
|   compr, uncompr: Pbyte;
 | |
|   comprLen, uncomprLen: LongInt;
 | |
|   myDecode: decode;
 | |
|   BufStr: string;
 | |
| begin
 | |
|   {$ifdef FPVECTORIALDEBUG}
 | |
|   WriteLn(':> TvPDFVectorialReader.unzipPage');
 | |
|   {$endif}
 | |
|   
 | |
|   myDecode := Decode.Create;
 | |
| 
 | |
|   comprLen := 10000 * SizeOf(Integer); // don't overflow
 | |
|   uncomprLen := comprLen;
 | |
|   GetMem(compr, comprLen);
 | |
|   GetMem(uncompr, uncomprLen);
 | |
| 
 | |
|   if (compr = NIL) or (uncompr = NIL) then
 | |
|      myDecode.EXIT_ERR('Out of memory');
 | |
| 
 | |
|   (* compr and uncompr are cleared to avoid reading uninitialized
 | |
|    * data and to ensure that uncompr compresses well.
 | |
|    *)
 | |
| 
 | |
|   FillChar(compr^, comprLen, 0);
 | |
|   FillChar(uncompr^, uncomprLen, 0);
 | |
| 
 | |
|   AInput.Read(compr^, comprLen);
 | |
| 
 | |
|   BufStr := string(myDecode.test_inflate(compr, comprLen, uncompr, uncomprLen));
 | |
| 
 | |
|   WriteStringToStream(AOutput, BufStr);
 | |
| 
 | |
|   FreeMem(compr, comprLen);
 | |
|   FreeMem(uncompr, uncomprLen);
 | |
| 
 | |
|   {$ifdef FPVECTORIALDEBUG}
 | |
|   WriteLn(':< TvPDFVectorialReader.unzipPage');
 | |
|   {$endif}
 | |
| end;
 | |
| 
 | |
| procedure TvPDFVectorialReader.translatePage(AInput: TStream;
 | |
|  AData: TvVectorialDocument; APageHeader: PageHeader);
 | |
| var
 | |
|   myAnLexico: AnLexico;
 | |
|   myAnSintaticoCommand: AnSintaticoCommand;
 | |
|   myAnSemantico: AnSemantico;
 | |
|   mytoken: Token;
 | |
|   c: Command;
 | |
| begin
 | |
|   {$ifdef FPVECTORIALDEBUG}
 | |
|   WriteLn(':> TvPDFVectorialReader.translatePage');
 | |
|   {$endif}
 | |
| 
 | |
|   // initialize data main
 | |
|   myAnLexico := AnLexico.Create;
 | |
|   myAnLexico.Doc := AInput;
 | |
|   myAnLexico.bytesRemaining:= myAnLexico.Doc.Size;
 | |
|   myAnSintaticoCommand := AnSintaticoCommand.Create;
 | |
|   myAnSemantico := AnSemantico.Create;
 | |
| 
 | |
|   // initialize machine
 | |
|   myAnSemantico.startMachine();
 | |
| 
 | |
|   while (myAnLexico.bytesRemaining > 0) do
 | |
|   begin
 | |
|     mytoken := myAnLexico.getToken();
 | |
|     c:=myAnSintaticoCommand.automata(mytoken);
 | |
|     if (myAnSintaticoCommand.Codigo = true) then
 | |
|       myAnSemantico.generate(c, AData);
 | |
|   end;
 | |
| 
 | |
|   // end machine
 | |
|   myAnSemantico.endMachine();
 | |
| end;
 | |
| 
 | |
| procedure TvPDFVectorialReader.ReadFromStream(AStream: TStream;
 | |
|   AData: TvVectorialDocument);
 | |
| var
 | |
|   APageHeader: PageHeader;
 | |
|   APageStream, AUnzipStream: TStream;
 | |
| begin
 | |
|   {$ifdef FPVECTORIALDEBUG}
 | |
|   WriteLn(':> TvPDFVectorialReader.ReadFromStream');
 | |
|   {$endif}
 | |
| 
 | |
|   APageStream := TMemoryStream.Create;
 | |
|   AUnzipStream := TMemoryStream.Create;
 | |
| 
 | |
|   // get first page
 | |
|   APageHeader := getFirstPage(AStream, APageStream);
 | |
| 
 | |
|   // unzip page
 | |
|   if (APageHeader.flate_decode = true) then
 | |
|   begin
 | |
|     APageStream.Seek(0, soFromBeginning);
 | |
|     unzipPage(APageStream, AUnzipStream);
 | |
| 
 | |
|     // translate page to doc data
 | |
|     AUnzipStream.Seek(0, soFromBeginning);
 | |
|     translatePage(AUnzipStream, AData, APageHeader);
 | |
|   end
 | |
|   else
 | |
|   begin
 | |
|     // translate page to doc data
 | |
|     APageStream.Seek(0, soFromBeginning);
 | |
|     translatePage(APageStream, AData, APageHeader);
 | |
|   end;
 | |
| 
 | |
|   APageStream.Free;
 | |
|   AUnzipStream.Free;
 | |
| 
 | |
|   //ShowMessage('Sucesso!');
 | |
|   {$ifdef FPVECTORIALDEBUG}
 | |
|   WriteLn(':< TvPDFVectorialReader.ReadFromStream');
 | |
|   WriteLn('Sucesso!');
 | |
|   {$endif}
 | |
| end;
 | |
| 
 | |
| {*******************************************************************
 | |
| *  Initialization section
 | |
| *
 | |
| *  Registers this reader / writer on fpVectorial
 | |
| *
 | |
| *******************************************************************}
 | |
| initialization
 | |
| 
 | |
|   RegisterVectorialReader(TvPDFVectorialReader, vfPDF);
 | |
| 
 | |
| end.
 | |
| 
 | 
