You've already forked lazarus-ccr
fpvectorial: Fixes some bugs in the PostScript interpreter, previously it didnt run some procedures, and adds more commands to it
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1743 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -15,6 +15,7 @@ unit epsvectorialreader;
|
|||||||
{.$define FPVECTORIALDEBUG_PATHS}
|
{.$define FPVECTORIALDEBUG_PATHS}
|
||||||
{.$define FPVECTORIALDEBUG_COLORS}
|
{.$define FPVECTORIALDEBUG_COLORS}
|
||||||
{.$define FPVECTORIALDEBUG_ROLL}
|
{.$define FPVECTORIALDEBUG_ROLL}
|
||||||
|
{.$define FPVECTORIALDEBUG_CODEFLOW}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@ -96,6 +97,8 @@ type
|
|||||||
ExitCalled: Boolean;
|
ExitCalled: Boolean;
|
||||||
CurrentGraphicState: TGraphicState;
|
CurrentGraphicState: TGraphicState;
|
||||||
//
|
//
|
||||||
|
procedure DebugStack();
|
||||||
|
//
|
||||||
procedure RunPostScript(ATokens: TPsTokens; AData: TvVectorialDocument);
|
procedure RunPostScript(ATokens: TPsTokens; AData: TvVectorialDocument);
|
||||||
//
|
//
|
||||||
procedure ExecuteProcedureToken(AToken: TProcedureToken; AData: TvVectorialDocument);
|
procedure ExecuteProcedureToken(AToken: TProcedureToken; AData: TvVectorialDocument);
|
||||||
@ -114,7 +117,7 @@ type
|
|||||||
function ExecuteStringOperator(AToken: TExpressionToken; AData: TvVectorialDocument): Boolean;
|
function ExecuteStringOperator(AToken: TExpressionToken; AData: TvVectorialDocument): Boolean;
|
||||||
//
|
//
|
||||||
procedure PostScriptCoordsToFPVectorialCoords(AParam1, AParam2: TPSToken; var APosX, APosY: Double);
|
procedure PostScriptCoordsToFPVectorialCoords(AParam1, AParam2: TPSToken; var APosX, APosY: Double);
|
||||||
procedure DictionarySubstituteOperator(ADictionary: TStringList; var ACurToken: TPSToken);
|
function DictionarySubstituteOperator(ADictionary: TStringList; var ACurToken: TPSToken): Boolean;
|
||||||
public
|
public
|
||||||
{ General reading methods }
|
{ General reading methods }
|
||||||
Tokenizer: TPSTokenizer;
|
Tokenizer: TPSTokenizer;
|
||||||
@ -125,6 +128,10 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
type
|
||||||
|
TStackAccess = class(TObjectStack)
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
FPointSeparator: TFormatSettings;
|
FPointSeparator: TFormatSettings;
|
||||||
|
|
||||||
@ -257,6 +264,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
ExpressionToken := TExpressionToken.Create;
|
ExpressionToken := TExpressionToken.Create;
|
||||||
ExpressionToken.Line := CurLine;
|
ExpressionToken.Line := CurLine;
|
||||||
|
ExpressionToken.StrValue := '';
|
||||||
if CurChar = '/' then
|
if CurChar = '/' then
|
||||||
ExpressionToken.ETType := ettNamedElement
|
ExpressionToken.ETType := ettNamedElement
|
||||||
else
|
else
|
||||||
@ -302,7 +310,15 @@ begin
|
|||||||
State := ssSearchingToken;
|
State := ssSearchingToken;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
ProcedureToken.StrValue := ProcedureToken.StrValue + CurChar;
|
begin
|
||||||
|
// Don't add line ends, because they cause problems when outputing the debug info
|
||||||
|
// but in this case we need to add spaces to compensate, or else items separates only
|
||||||
|
// by line end might get glued together
|
||||||
|
if CurChar in [#10, #13] then
|
||||||
|
ProcedureToken.StrValue := ProcedureToken.StrValue + ' '
|
||||||
|
else
|
||||||
|
ProcedureToken.StrValue := ProcedureToken.StrValue + CurChar;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Goes until a space comes, or {
|
// Goes until a space comes, or {
|
||||||
@ -403,10 +419,26 @@ end;
|
|||||||
|
|
||||||
{ TvEPSVectorialReader }
|
{ TvEPSVectorialReader }
|
||||||
|
|
||||||
|
procedure TvEPSVectorialReader.DebugStack();
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
lToken: TPSToken;
|
||||||
|
begin
|
||||||
|
WriteLn('====================');
|
||||||
|
WriteLn('Stack dump');
|
||||||
|
WriteLn('====================');
|
||||||
|
for i := 0 to TStackAccess(Stack).List.Count - 1 do
|
||||||
|
begin
|
||||||
|
lToken := TPSToken(TStackAccess(Stack).List.Items[i]);
|
||||||
|
WriteLn(Format('Stack #%d : %s', [i, lToken.StrValue]));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TvEPSVectorialReader.RunPostScript(ATokens: TPsTokens;
|
procedure TvEPSVectorialReader.RunPostScript(ATokens: TPsTokens;
|
||||||
AData: TvVectorialDocument);
|
AData: TvVectorialDocument);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
lSubstituted: Boolean;
|
||||||
CurToken: TPSToken;
|
CurToken: TPSToken;
|
||||||
begin
|
begin
|
||||||
{$ifdef FPVECTORIALDEBUG_CODEFLOW}
|
{$ifdef FPVECTORIALDEBUG_CODEFLOW}
|
||||||
@ -423,6 +455,11 @@ begin
|
|||||||
begin
|
begin
|
||||||
CurToken := TPSToken(ATokens.Items[i]);
|
CurToken := TPSToken(ATokens.Items[i]);
|
||||||
|
|
||||||
|
{ if CurToken.StrValue = 'J' then
|
||||||
|
begin
|
||||||
|
DebugStack();
|
||||||
|
end;}
|
||||||
|
|
||||||
if CurToken is TCommentToken then
|
if CurToken is TCommentToken then
|
||||||
begin
|
begin
|
||||||
{$ifdef FPVECTORIALDEBUG_CODEFLOW}
|
{$ifdef FPVECTORIALDEBUG_CODEFLOW}
|
||||||
@ -447,14 +484,22 @@ begin
|
|||||||
WriteLn(Format('[TvEPSVectorialReader.RunPostScript] Type: TExpressionToken Token: %s', [CurToken.StrValue]));
|
WriteLn(Format('[TvEPSVectorialReader.RunPostScript] Type: TExpressionToken Token: %s', [CurToken.StrValue]));
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
if TExpressionToken(CurToken).ETType <> ettOperator then
|
if TExpressionToken(CurToken).ETType = ettOperand then
|
||||||
begin
|
begin
|
||||||
Stack.Push(CurToken);
|
Stack.Push(CurToken);
|
||||||
Continue;
|
Continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Now we need to verify if the operator should be substituted in the dictionary
|
// Now we need to verify if the operator should be substituted in the dictionary
|
||||||
DictionarySubstituteOperator(Dictionary, CurToken);
|
lSubstituted := DictionarySubstituteOperator(Dictionary, CurToken);
|
||||||
|
|
||||||
|
// Check if this is the first time that a named element appears, if yes, don't try to execute it
|
||||||
|
// just put it into the stack
|
||||||
|
if (not lSubstituted) and (TExpressionToken(CurToken).ETType = ettNamedElement) then
|
||||||
|
begin
|
||||||
|
Stack.Push(CurToken);
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
|
||||||
if CurToken is TProcedureToken then ExecuteProcedureToken(TProcedureToken(CurToken), AData)
|
if CurToken is TProcedureToken then ExecuteProcedureToken(TProcedureToken(CurToken), AData)
|
||||||
else ExecuteOperatorToken(TExpressionToken(CurToken), AData);
|
else ExecuteOperatorToken(TExpressionToken(CurToken), AData);
|
||||||
@ -1006,15 +1051,15 @@ end;
|
|||||||
– eofill – Fill using even-odd rule
|
– eofill – Fill using even-odd rule
|
||||||
x y width height rectstroke – Define rectangular path and stroke
|
x y width height rectstroke – Define rectangular path and stroke
|
||||||
x y width height matrix rectstroke – Define rectangular path, concatenate matrix,
|
x y width height matrix rectstroke – Define rectangular path, concatenate matrix,
|
||||||
and stroke
|
and stroke
|
||||||
numarray|numstring rectstroke – Define rectangular paths and stroke
|
numarray|numstring rectstroke – Define rectangular paths and stroke
|
||||||
numarray|numstring matrix rectstroke – Define rectangular paths, concatenate
|
numarray|numstring matrix rectstroke – Define rectangular paths, concatenate
|
||||||
matrix, and stroke
|
matrix, and stroke
|
||||||
x y width height rectfill – Fill rectangular path
|
x y width height rectfill – Fill rectangular path
|
||||||
numarray|numstring rectfill – Fill rectangular paths
|
numarray|numstring rectfill – Fill rectangular paths
|
||||||
userpath ustroke – Interpret and stroke userpath
|
userpath ustroke – Interpret and stroke userpath
|
||||||
userpath matrix ustroke – Interpret userpath, concatenate matrix, and
|
userpath matrix ustroke – Interpret userpath, concatenate matrix, and
|
||||||
stroke
|
stroke
|
||||||
userpath ufill – Interpret and fill userpath
|
userpath ufill – Interpret and fill userpath
|
||||||
userpath ueofill – Fill userpath using even-odd rule
|
userpath ueofill – Fill userpath using even-odd rule
|
||||||
dict shfill – Fill area defined by shading pattern
|
dict shfill – Fill area defined by shading pattern
|
||||||
@ -1069,7 +1114,7 @@ begin
|
|||||||
|
|
||||||
if AToken.StrValue = 'eofill' then
|
if AToken.StrValue = 'eofill' then
|
||||||
begin
|
begin
|
||||||
AData.SetBrushStyle(bsDiagCross);
|
AData.SetBrushStyle(bsSolid);
|
||||||
|
|
||||||
Exit(True);
|
Exit(True);
|
||||||
end;
|
end;
|
||||||
@ -1483,6 +1528,19 @@ begin
|
|||||||
AData.AddBezierToPath(BaseX + PosX, BaseY + PosY, BaseX + PosX2, BaseY + PosY2, BaseX + PosX3, BaseY + PosY3);
|
AData.AddBezierToPath(BaseX + PosX, BaseY + PosY, BaseX + PosX2, BaseY + PosY2, BaseX + PosX3, BaseY + PosY3);
|
||||||
Exit(True);
|
Exit(True);
|
||||||
end;
|
end;
|
||||||
|
//
|
||||||
|
if AToken.StrValue = 'closepath' then
|
||||||
|
begin
|
||||||
|
{$ifdef FPVECTORIALDEBUG_PATHS}
|
||||||
|
WriteLn('[TvEPSVectorialReader.ExecutePathConstructionOperator] closepath');
|
||||||
|
{$endif}
|
||||||
|
AData.EndPath();
|
||||||
|
AData.StartPath();
|
||||||
|
|
||||||
|
AData.SetPenColor(CurrentGraphicState.Color);
|
||||||
|
|
||||||
|
Exit(True);
|
||||||
|
end;
|
||||||
// x y r angle1 angle2 arc – Append counterclockwise arc
|
// x y r angle1 angle2 arc – Append counterclockwise arc
|
||||||
if AToken.StrValue = 'arc' then
|
if AToken.StrValue = 'arc' then
|
||||||
begin
|
begin
|
||||||
@ -1594,6 +1652,12 @@ begin
|
|||||||
Exit(True);
|
Exit(True);
|
||||||
end;
|
end;
|
||||||
//
|
//
|
||||||
|
if AToken.StrValue = 'setlinecap' then
|
||||||
|
begin
|
||||||
|
Param1 := TPSToken(Stack.Pop);
|
||||||
|
Exit(True);
|
||||||
|
end;
|
||||||
|
//
|
||||||
if AToken.StrValue = 'setlinejoin' then
|
if AToken.StrValue = 'setlinejoin' then
|
||||||
begin
|
begin
|
||||||
Param1 := TPSToken(Stack.Pop);
|
Param1 := TPSToken(Stack.Pop);
|
||||||
@ -1846,15 +1910,19 @@ begin
|
|||||||
APosY := AParam1.FloatValue;
|
APosY := AParam1.FloatValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TvEPSVectorialReader.DictionarySubstituteOperator(
|
// Returns true if a dictionary substitution was executed
|
||||||
ADictionary: TStringList; var ACurToken: TPSToken);
|
function TvEPSVectorialReader.DictionarySubstituteOperator(
|
||||||
|
ADictionary: TStringList; var ACurToken: TPSToken): Boolean;
|
||||||
var
|
var
|
||||||
lIndex: Integer;
|
lIndex: Integer;
|
||||||
SubstituteToken, NewToken: TPSToken;
|
SubstituteToken, NewToken: TPSToken;
|
||||||
begin
|
begin
|
||||||
|
Result := False;
|
||||||
lIndex := ADictionary.IndexOf(ACurToken.StrValue);
|
lIndex := ADictionary.IndexOf(ACurToken.StrValue);
|
||||||
if lIndex >= 0 then
|
if lIndex >= 0 then
|
||||||
begin
|
begin
|
||||||
|
Result := True;
|
||||||
|
|
||||||
SubstituteToken := TPSToken(ADictionary.Objects[lIndex]);
|
SubstituteToken := TPSToken(ADictionary.Objects[lIndex]);
|
||||||
|
|
||||||
if SubstituteToken is TExpressionToken then
|
if SubstituteToken is TExpressionToken then
|
||||||
@ -1882,6 +1950,7 @@ begin
|
|||||||
Stack := TObjectStack.Create;
|
Stack := TObjectStack.Create;
|
||||||
GraphicStateStack := TObjectStack.Create;
|
GraphicStateStack := TObjectStack.Create;
|
||||||
Dictionary := TStringList.Create;
|
Dictionary := TStringList.Create;
|
||||||
|
Dictionary.CaseSensitive := True;
|
||||||
CurrentGraphicState := TGraphicState.Create;
|
CurrentGraphicState := TGraphicState.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ unit fpvtocanvas;
|
|||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
{$define USE_LCL_CANVAS}
|
{.$define USE_LCL_CANVAS}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Math,
|
Classes, SysUtils, Math,
|
||||||
@ -153,6 +153,8 @@ var
|
|||||||
CurX, CurY: Integer; // Not modified by ADestX, etc
|
CurX, CurY: Integer; // Not modified by ADestX, etc
|
||||||
CurveLength: Integer;
|
CurveLength: Integer;
|
||||||
t: Double;
|
t: Double;
|
||||||
|
// For polygons
|
||||||
|
Points: array of TPoint;
|
||||||
begin
|
begin
|
||||||
PosX := 0;
|
PosX := 0;
|
||||||
PosY := 0;
|
PosY := 0;
|
||||||
@ -165,10 +167,38 @@ begin
|
|||||||
// Set the path Pen and Brush options
|
// Set the path Pen and Brush options
|
||||||
ADest.Pen.Style := CurPath.Pen.Style;
|
ADest.Pen.Style := CurPath.Pen.Style;
|
||||||
ADest.Pen.Width := CurPath.Pen.Width;
|
ADest.Pen.Width := CurPath.Pen.Width;
|
||||||
ADest.Brush.Style := CurPath.Brush.Style;
|
|
||||||
ADest.Pen.FPColor := CurPath.Pen.Color;
|
ADest.Pen.FPColor := CurPath.Pen.Color;
|
||||||
ADest.Brush.FPColor := CurPath.Brush.Color;
|
ADest.Brush.FPColor := CurPath.Brush.Color;
|
||||||
|
|
||||||
|
//
|
||||||
|
// For solid paths, draw a polygon instead
|
||||||
|
//
|
||||||
|
if CurPath.Brush.Style = bsSolid then
|
||||||
|
begin
|
||||||
|
ADest.Brush.Style := CurPath.Brush.Style;
|
||||||
|
|
||||||
|
SetLength(Points, CurPath.Len);
|
||||||
|
|
||||||
|
for j := 0 to CurPath.Len - 1 do
|
||||||
|
begin
|
||||||
|
//WriteLn('j = ', j);
|
||||||
|
CurSegment := TPathSegment(CurPath.Next());
|
||||||
|
|
||||||
|
CoordX := CoordToCanvasX(Cur2DSegment.X);
|
||||||
|
CoordY := CoordToCanvasY(Cur2DSegment.Y);
|
||||||
|
|
||||||
|
Points[j].X := CoordX;
|
||||||
|
Points[j].Y := CoordY;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ADest.Polygon(Points);
|
||||||
|
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//
|
||||||
|
// For other paths, draw more carefully
|
||||||
|
//
|
||||||
for j := 0 to CurPath.Len - 1 do
|
for j := 0 to CurPath.Len - 1 do
|
||||||
begin
|
begin
|
||||||
//WriteLn('j = ', j);
|
//WriteLn('j = ', j);
|
||||||
|
Reference in New Issue
Block a user