diff --git a/applications/fpvviewer/fpvectorialsrc/epsvectorialreader.pas b/applications/fpvviewer/fpvectorialsrc/epsvectorialreader.pas new file mode 100644 index 000000000..6aad5abdb --- /dev/null +++ b/applications/fpvviewer/fpvectorialsrc/epsvectorialreader.pas @@ -0,0 +1,203 @@ +{ +Reads EPS files + +License: The same modified LGPL as the Free Pascal RTL + See the file COPYING.modifiedLGPL for more details + +AUTHORS: Felipe Monteiro de Carvalho + +} +unit epsvectorialreader; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Math, + fpvectorial, fpimage; + +type + TPSTokenType = (ttComment, ttFloat); + + TPSTokens = TFPList;// TPSToken; + + TPSToken = class + StrValue: string; + FloatValue: double; + IntValue: Integer; + Childs: TPSTokens; + end; + + TCommentToken = class(TPSToken) + end; + + TPostScriptScannerState = (ssSearchingToken, ssInComment); + + { TPSTokenizer } + + TPSTokenizer = class + public + Tokens: TPSTokens; + constructor Create; + destructor Destroy; override; + procedure ReadFromStream(AStream: TStream); + procedure DebugOut(); + function IsValidPostScriptChar(AChar: Byte): Boolean; + end; + + { TvEPSFVectorialReader } + + { TvEPSVectorialReader } + + TvEPSVectorialReader = class(TvCustomVectorialReader) + private + FPointSeparator: TFormatSettings; + public + { General reading methods } + Tokenizer: TPSTokenizer; + constructor Create; override; + Destructor Destroy; override; + procedure ReadFromStream(AStream: TStream; AData: TvVectorialDocument); override; + end; + +implementation + +{ TPSTokenizer } + +constructor TPSTokenizer.Create; +begin + inherited Create; + Tokens := TPSTokens.Create; +end; + +destructor TPSTokenizer.Destroy; +begin + Tokens.Free; + inherited Destroy; +end; + +{@@ Rules for parsing PostScript files: + +* Coments go from the first occurence of % outside a line to the next new line +* The only accepted characters are printable ASCII ones, plus spacing ASCII chars + See IsValidPostScriptChar about that +} +procedure TPSTokenizer.ReadFromStream(AStream: TStream); +var + i: Integer; + CurChar: Char; + State: TPostScriptScannerState = ssSearchingToken; + CommentToken: TCommentToken; +begin + while AStream.Position < AStream.Size do + begin + CurChar := Char(AStream.ReadByte()); + if not IsValidPostScriptChar(Byte(CurChar)) then + raise Exception.Create('[TPSTokenizer.ReadFromStream] Invalid char: ' + IntToHex(Byte(CurChar), 2)); + + case State of + { Searching for a token } + ssSearchingToken: + begin + case CurChar of + '%': + begin + CommentToken := TCommentToken.Create; + State := ssInComment; + end; + end; + + end; + + { Passing by comments } + ssInComment: + begin + CommentToken.StrValue := CommentToken.StrValue + CurChar; + + case CurChar of + #13: + begin + // Check if this is a Windows-style #13#10 line end marker by getting one more char + if AStream.ReadByte() <> 10 then AStream.Seek(-1, soFromCurrent); // Go back if it wasnt a #13#10 + + Tokens.Add(CommentToken); + State := ssSearchingToken; + end; + #10: + begin + Tokens.Add(CommentToken); + State := ssSearchingToken; + end; + end; // case + end; // ssInComment + + end; // case + end; // while +end; + +procedure TPSTokenizer.DebugOut(); +var + i: Integer; + Token: TPSToken; +begin + for i := 0 to Tokens.Count - 1 do + begin + Token := TPSToken(Tokens.Items[i]); + + if Token is TCommentToken then + begin + WriteLn(Format('TCommentToken StrValue=%s', [Token.StrValue])); + end; + end; +end; + +{@@ Valid PostScript Chars: + +All printable: a..zA..Z0..9 + +Plus the following white spaces +000 00 0 Null (nul) +011 09 9 Tab (tab) +012 0A 10 Line feed (LF) +014 0C 12 Form feed (FF) +015 0D 13 Carriage return (CR) +040 20 32 Space (SP) +} +function TPSTokenizer.IsValidPostScriptChar(AChar: Byte): Boolean; +begin + Result := ((AChar > 32) and (AChar < 127)) or (AChar in [0, 9, 10, 12, 13, 32]); +end; + +{$ifndef Windows} +{$define FPVECTORIALDEBUG} +{$endif} + +{ TvEPSVectorialReader } + +constructor TvEPSVectorialReader.Create; +begin + inherited Create; + + Tokenizer := TPSTokenizer.Create; +end; + +destructor TvEPSVectorialReader.Destroy; +begin + Tokenizer.Free; + inherited Destroy; +end; + +procedure TvEPSVectorialReader.ReadFromStream(AStream: TStream; + AData: TvVectorialDocument); +begin + Tokenizer.ReadFromStream(AStream); + Tokenizer.DebugOut(); +end; + +initialization + + RegisterVectorialReader(TvEPSVectorialReader, vfEncapsulatedPostScript); + +end. + diff --git a/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas b/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas index 43ab9ba97..d7d58542b 100644 --- a/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas +++ b/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas @@ -24,9 +24,11 @@ uses type TvVectorialFormat = ( { Multi-purpose document formats } - vfPDF, vfPostScript, vfSVG, vfCorelDrawCDR, vfWindowsMetafileWMF, + vfPDF, vfSVG, vfCorelDrawCDR, vfWindowsMetafileWMF, { CAD formats } vfDXF, + { Printing formats } + vfPostScript, vfEncapsulatedPostScript, { GCode formats } vfGCodeAvisoCNCPrototipoV5, vfGCodeAvisoCNCPrototipoV6); @@ -39,6 +41,7 @@ const STR_CORELDRAW_EXTENSION = '.cdr'; STR_WINMETAFILE_EXTENSION = '.wmf'; STR_AUTOCAD_EXCHANGE_EXTENSION = '.dxf'; + STR_ENCAPSULATEDPOSTSCRIPT_EXTENSION = '.eps'; type {@@ We need our own format because TFPColor is too big for our needs and TColor has no Alpha } @@ -1000,6 +1003,7 @@ begin else if AnsiCompareText(lExt, STR_CORELDRAW_EXTENSION) = 0 then Result := vfCorelDrawCDR else if AnsiCompareText(lExt, STR_WINMETAFILE_EXTENSION) = 0 then Result := vfWindowsMetafileWMF else if AnsiCompareText(lExt, STR_AUTOCAD_EXCHANGE_EXTENSION) = 0 then Result := vfDXF + else if AnsiCompareText(lExt, STR_ENCAPSULATEDPOSTSCRIPT_EXTENSION) = 0 then Result := vfEncapsulatedPostScript else raise Exception.Create('TvVectorialDocument.GetFormatFromExtension: The extension (' + lExt + ') doesn''t match any supported formats.'); end; diff --git a/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.lpk b/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.lpk index 1817e7d98..e19f8bd63 100644 --- a/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.lpk +++ b/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.lpk @@ -11,7 +11,7 @@ - + @@ -66,8 +66,12 @@ - + + + + + diff --git a/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.pas b/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.pas index cf589c426..281e53f97 100644 --- a/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.pas +++ b/applications/fpvviewer/fpvectorialsrc/fpvectorialpkg.pas @@ -10,7 +10,8 @@ uses svgvectorialwriter, pdfvrsintatico, pdfvrsemantico, pdfvrlexico, pdfvectorialreader, fpvtocanvas, fpvectorial, fpvectbuildunit, dxfvectorialreader, cdrvectorialreader, avisozlib, avisocncgcodewriter, - avisocncgcodereader, svgvectorialreader, LazarusPackageIntf; + avisocncgcodereader, svgvectorialreader, epsvectorialreader, + LazarusPackageIntf; implementation diff --git a/applications/fpvviewer/fpvv_mainform.lfm b/applications/fpvviewer/fpvv_mainform.lfm index 980ad1fd0..f8bbfc291 100644 --- a/applications/fpvviewer/fpvv_mainform.lfm +++ b/applications/fpvviewer/fpvv_mainform.lfm @@ -76,8 +76,8 @@ object frmFPVViewer: TfrmFPVViewer object pageViewer: TPage end object Page2: TPage - ClientWidth = 4224 - ClientHeight = 4992 + ClientWidth = 8448 + ClientHeight = 9984 object DXFTreeView: TTreeView Left = 8 Height = 313 diff --git a/applications/fpvviewer/fpvv_mainform.pas b/applications/fpvviewer/fpvv_mainform.pas index 0ed21704c..d286bfbea 100644 --- a/applications/fpvviewer/fpvv_mainform.pas +++ b/applications/fpvviewer/fpvv_mainform.pas @@ -41,7 +41,7 @@ implementation uses fpvectorial, cdrvectorialreader, svgvectorialwriter, pdfvectorialreader, - dxfvectorialreader, + dxfvectorialreader, epsvectorialreader, fpvtocanvas, dxftokentotree;