fpvectorial: Improves the pen width and the EPS reader

git-svn-id: trunk@17694 -
This commit is contained in:
sekelsenmat 2011-06-08 13:54:52 +00:00
parent 8f90fce6f2
commit 949a2d1c3a
5 changed files with 143 additions and 66 deletions

View File

@ -30,12 +30,9 @@ interface
uses
Classes, SysUtils, Math,
fpvectorial, fpimage;
fpvectorial, fpimage, fpvutils;
type
{ Used by tcutils.SeparateString }
T10Strings = array[0..9] of shortstring;
TDXFToken = class;
TDXFTokens = TFPList;// TDXFToken;
@ -90,7 +87,6 @@ type
IsReadingPolyline: Boolean;
Polyline: array of TPolylineElement;
//
function SeparateString(AString: string; ASeparator: Char): T10Strings;
procedure ReadHEADER(ATokens: TDXFTokens; AData: TvVectorialDocument);
procedure ReadENTITIES(ATokens: TDXFTokens; AData: TvVectorialDocument);
procedure ReadENTITIES_LINE(ATokens: TDXFTokens; AData: TvVectorialDocument);
@ -347,39 +343,6 @@ end;
{ TvDXFVectorialReader }
{@@
Reads a string and separates it in substring
using ASeparator to delimite them.
Limits:
Number of substrings: 10 (indexed 0 to 9)
Length of each substring: 255 (they are shortstrings)
}
function TvDXFVectorialReader.SeparateString(AString: string; ASeparator: Char): T10Strings;
var
i, CurrentPart: Integer;
begin
CurrentPart := 0;
{ Clears the result }
for i := 0 to 9 do Result[i] := '';
{ Iterates througth the string, filling strings }
for i := 1 to Length(AString) do
begin
if Copy(AString, i, 1) = ASeparator then
begin
Inc(CurrentPart);
{ Verifies if the string capacity wasn't exceeded }
if CurrentPart > 9 then Exit;
end
else
Result[CurrentPart] := Result[CurrentPart] + Copy(AString, i, 1);
end;
end;
procedure TvDXFVectorialReader.ReadHEADER(ATokens: TDXFTokens;
AData: TvVectorialDocument);
var

View File

@ -15,7 +15,7 @@ interface
uses
Classes, SysUtils, Math,
fpvectorial, fpimage;
fpvectorial, fpimage, fpvutils;
type
TPSTokenType = (ttComment, ttFloat);
@ -32,7 +32,13 @@ type
TCommentToken = class(TPSToken)
end;
TPostScriptScannerState = (ssSearchingToken, ssInComment);
TDefinitionToken = class(TPSToken)
end;
TExpressionToken = class(TPSToken)
end;
TPostScriptScannerState = (ssSearchingToken, ssInComment, ssInDefinition, ssInExpressionElement);
{ TPSTokenizer }
@ -44,10 +50,10 @@ type
procedure ReadFromStream(AStream: TStream);
procedure DebugOut();
function IsValidPostScriptChar(AChar: Byte): Boolean;
function IsPostScriptSpace(AChar: Byte): Boolean;
function IsEndOfLine(ACurChar: Byte; AStream: TStream): Boolean;
end;
{ TvEPSFVectorialReader }
{ TvEPSVectorialReader }
TvEPSVectorialReader = class(TvCustomVectorialReader)
@ -87,8 +93,13 @@ procedure TPSTokenizer.ReadFromStream(AStream: TStream);
var
i: Integer;
CurChar: Char;
CurLine: Integer = 1;
State: TPostScriptScannerState = ssSearchingToken;
CommentToken: TCommentToken;
DefinitionToken: TDefinitionToken;
ExpressionToken: TExpressionToken;
Len: Integer;
lIsEndOfLine: Boolean;
begin
while AStream.Position < AStream.Size do
begin
@ -96,42 +107,72 @@ begin
if not IsValidPostScriptChar(Byte(CurChar)) then
raise Exception.Create('[TPSTokenizer.ReadFromStream] Invalid char: ' + IntToHex(Byte(CurChar), 2));
lIsEndOfLine := IsEndOfLine(Byte(CurChar), AStream);
if lIsEndOfLine then Inc(CurLine);
case State of
{ Searching for a token }
ssSearchingToken:
begin
case CurChar of
'%':
begin
CommentToken := TCommentToken.Create;
State := ssInComment;
end;
end;
if CurChar = '%' then
begin
CommentToken := TCommentToken.Create;
State := ssInComment;
end
else if CurChar = '/' then
begin
DefinitionToken := TDefinitionToken.Create;
State := ssInDefinition;
end
else if CurChar in ['a'..'z'] + ['A'..'Z'] + ['0'..'9'] then
begin
ExpressionToken := TExpressionToken.Create;
State := ssInExpressionElement;
end
else if lIsEndOfLine then Continue
else
raise Exception.Create(Format('[TPSTokenizer.ReadFromStream] Unexpected char while searching for token: $%s in Line %d',
[IntToHex(Byte(CurChar), 2), CurLine]));
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
if lIsEndOfLine then
begin
Tokens.Add(CommentToken);
State := ssSearchingToken;
end;
end; // ssInComment
// Dictionary definitions end in "def"
ssInDefinition:
begin
DefinitionToken.StrValue := DefinitionToken.StrValue + CurChar;
Len := Length(DefinitionToken.StrValue);
if Len >= 3 then
begin
if (DefinitionToken.StrValue[Len-2] = 'd') and (DefinitionToken.StrValue[Len-1] = 'e') and (DefinitionToken.StrValue[Len] = 'f') then
begin
Tokens.Add(DefinitionToken);
State := ssSearchingToken;
end;
end;
end;
// Goes until a space comes
ssInExpressionElement:
begin
if IsPostScriptSpace(Byte(CurChar)) then
begin
Tokens.Add(ExpressionToken);
State := ssSearchingToken;
end
else
ExpressionToken.StrValue := ExpressionToken.StrValue + CurChar;
end;
end; // case
end; // while
end;
@ -148,6 +189,14 @@ begin
if Token is TCommentToken then
begin
WriteLn(Format('TCommentToken StrValue=%s', [Token.StrValue]));
end
else if Token is TDefinitionToken then
begin
WriteLn(Format('TDefinitionToken StrValue=%s', [Token.StrValue]));
end
else if Token is TExpressionToken then
begin
WriteLn(Format('TExpressionToken StrValue=%s', [Token.StrValue]));
end;
end;
end;
@ -169,6 +218,32 @@ begin
Result := ((AChar > 32) and (AChar < 127)) or (AChar in [0, 9, 10, 12, 13, 32]);
end;
function TPSTokenizer.IsPostScriptSpace(AChar: Byte): Boolean;
begin
Result := AChar in [0, 9, 10, 12, 13, 32];
end;
function TPSTokenizer.IsEndOfLine(ACurChar: Byte; AStream: TStream): Boolean;
var
HasNextChar: Boolean = False;
NextChar: Byte;
begin
Result := False;
if ACurChar = 13 then
begin
if AStream.Position < AStream.Size then
begin
HasNextChar := True;
NextChar := AStream.ReadByte();
if NextChar <> 10 then AStream.Seek(-1, soFromCurrent); // Go back if it wasnt a #13#10
Exit(True);
end;
end;
if ACurChar = 10 then Result := True;
end;
{$ifndef Windows}
{$define FPVECTORIALDEBUG}
{$endif}

View File

@ -884,6 +884,7 @@ begin
FTmpPath.Brush.Style := bsClear;
FTmpPath.Pen.Color := clvBlack;
FTmpPath.Pen.Style := psSolid;
FTmpPath.Pen.Width := 1;
end;
procedure TvVectorialDocument.AppendSegmentToTmpPath(ASegment: TPathSegment);

View File

@ -171,6 +171,7 @@ begin
// Set the path Pen and Brush options
ADest.Pen.Style := CurPath.Pen.Style;
ADest.Pen.Width := CurPath.Pen.Width;
ADest.Brush.Style := CurPath.Brush.Style;
{$ifdef USE_LCL_CANVAS}
ADest.Pen.Color := VColorToTColor(CurPath.Pen.Color);

View File

@ -21,10 +21,14 @@ uses
Classes, SysUtils, Math,
fpvectorial, fpimage;
type
T10Strings = array[0..9] of shortstring;
// Color Conversion routines
function VColorToFPColor(AVColor: TvColor): TFPColor; inline;
function VColorToRGBHexString(AVColor: TvColor): string;
function RGBToVColor(AR, AG, AB: Byte): TvColor; inline;
function SeparateString(AString: string; ASeparator: Char): T10Strings;
implementation
@ -49,5 +53,38 @@ begin
Result.Alpha := 255;
end;
{@@
Reads a string and separates it in substring
using ASeparator to delimite them.
Limits:
Number of substrings: 10 (indexed 0 to 9)
Length of each substring: 255 (they are shortstrings)
}
function SeparateString(AString: string; ASeparator: Char): T10Strings;
var
i, CurrentPart: Integer;
begin
CurrentPart := 0;
{ Clears the result }
for i := 0 to 9 do Result[i] := '';
{ Iterates througth the string, filling strings }
for i := 1 to Length(AString) do
begin
if Copy(AString, i, 1) = ASeparator then
begin
Inc(CurrentPart);
{ Verifies if the string capacity wasn't exceeded }
if CurrentPart > 9 then Exit;
end
else
Result[CurrentPart] := Result[CurrentPart] + Copy(AString, i, 1);
end;
end;
end.