Browse Source

fpvectorial: Fixes some bugs in the PostScript interpreter, previously it didnt run some procedures, and adds more commands to it

git-svn-id: trunk@17990 -
sekelsenmat 14 years ago
parent
commit
d37d0ae1a4

+ 79 - 10
packages/fpvectorial/src/epsvectorialreader.pas

@@ -15,6 +15,7 @@ unit epsvectorialreader;
 {.$define FPVECTORIALDEBUG_PATHS}
 {.$define FPVECTORIALDEBUG_COLORS}
 {.$define FPVECTORIALDEBUG_ROLL}
+{.$define FPVECTORIALDEBUG_CODEFLOW}
 
 interface
 
@@ -96,6 +97,8 @@ type
     ExitCalled: Boolean;
     CurrentGraphicState: TGraphicState;
     //
+    procedure DebugStack();
+    //
     procedure RunPostScript(ATokens: TPsTokens; AData: TvVectorialDocument);
     //
     procedure ExecuteProcedureToken(AToken: TProcedureToken; AData: TvVectorialDocument);
@@ -114,7 +117,7 @@ type
     function  ExecuteStringOperator(AToken: TExpressionToken; AData: TvVectorialDocument): Boolean;
     //
     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
     { General reading methods }
     Tokenizer: TPSTokenizer;
@@ -125,6 +128,10 @@ type
 
 implementation
 
+type
+  TStackAccess = class(TObjectStack)
+  end;
+
 var
   FPointSeparator: TFormatSettings;
 
@@ -257,6 +264,7 @@ begin
         begin
           ExpressionToken := TExpressionToken.Create;
           ExpressionToken.Line := CurLine;
+          ExpressionToken.StrValue := '';
           if CurChar = '/' then
             ExpressionToken.ETType := ettNamedElement
           else
@@ -302,7 +310,15 @@ begin
           State := ssSearchingToken;
         end
         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;
 
       // Goes until a space comes, or {
@@ -403,10 +419,26 @@ end;
 
 { 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;
   AData: TvVectorialDocument);
 var
   i: Integer;
+  lSubstituted: Boolean;
   CurToken: TPSToken;
 begin
   {$ifdef FPVECTORIALDEBUG_CODEFLOW}
@@ -423,6 +455,11 @@ begin
   begin
     CurToken := TPSToken(ATokens.Items[i]);
 
+{    if CurToken.StrValue = 'J' then
+    begin
+      DebugStack();
+    end;}
+
     if CurToken is TCommentToken then
     begin
       {$ifdef FPVECTORIALDEBUG_CODEFLOW}
@@ -447,14 +484,22 @@ begin
       WriteLn(Format('[TvEPSVectorialReader.RunPostScript] Type: TExpressionToken Token: %s', [CurToken.StrValue]));
       {$endif}
 
-      if TExpressionToken(CurToken).ETType <> ettOperator then
+      if TExpressionToken(CurToken).ETType = ettOperand then
       begin
         Stack.Push(CurToken);
         Continue;
       end;
 
       // 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)
       else ExecuteOperatorToken(TExpressionToken(CurToken), AData);
@@ -1006,15 +1051,15 @@ end;
   – eofill –      Fill using even-odd rule
   x y width height rectstroke – Define rectangular path and stroke
   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 matrix rectstroke – Define rectangular paths, concatenate
-  matrix, and stroke
+                                         matrix, and stroke
   x y width height rectfill – Fill rectangular path
   numarray|numstring rectfill – Fill rectangular paths
   userpath ustroke – Interpret and stroke userpath
   userpath matrix ustroke – Interpret userpath, concatenate matrix, and
-  stroke
+                            stroke
   userpath ufill – Interpret and fill userpath
   userpath ueofill – Fill userpath using even-odd rule
   dict shfill – Fill area defined by shading pattern
@@ -1069,7 +1114,7 @@ begin
 
   if AToken.StrValue = 'eofill' then
   begin
-    AData.SetBrushStyle(bsDiagCross);
+    AData.SetBrushStyle(bsSolid);
 
     Exit(True);
   end;
@@ -1483,6 +1528,19 @@ begin
     AData.AddBezierToPath(BaseX + PosX, BaseY + PosY, BaseX + PosX2, BaseY + PosY2, BaseX + PosX3, BaseY + PosY3);
     Exit(True);
   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
   if AToken.StrValue = 'arc' then
   begin
@@ -1594,6 +1652,12 @@ begin
     Exit(True);
   end;
   //
+  if AToken.StrValue = 'setlinecap' then
+  begin
+    Param1 := TPSToken(Stack.Pop);
+    Exit(True);
+  end;
+  //
   if AToken.StrValue = 'setlinejoin' then
   begin
     Param1 := TPSToken(Stack.Pop);
@@ -1846,15 +1910,19 @@ begin
   APosY := AParam1.FloatValue;
 end;
 
-procedure TvEPSVectorialReader.DictionarySubstituteOperator(
-  ADictionary: TStringList; var ACurToken: TPSToken);
+// Returns true if a dictionary substitution was executed
+function TvEPSVectorialReader.DictionarySubstituteOperator(
+  ADictionary: TStringList; var ACurToken: TPSToken): Boolean;
 var
   lIndex: Integer;
   SubstituteToken, NewToken: TPSToken;
 begin
+  Result := False;
   lIndex := ADictionary.IndexOf(ACurToken.StrValue);
   if lIndex >= 0 then
   begin
+    Result := True;
+
     SubstituteToken := TPSToken(ADictionary.Objects[lIndex]);
 
     if SubstituteToken is TExpressionToken then
@@ -1882,6 +1950,7 @@ begin
   Stack := TObjectStack.Create;
   GraphicStateStack := TObjectStack.Create;
   Dictionary := TStringList.Create;
+  Dictionary.CaseSensitive := True;
   CurrentGraphicState := TGraphicState.Create;
 end;
 

+ 31 - 1
packages/fpvectorial/src/fpvtocanvas.pas

@@ -153,6 +153,8 @@ var
   CurX, CurY: Integer; // Not modified by ADestX, etc
   CurveLength: Integer;
   t: Double;
+  // For polygons
+  Points: array of TPoint;
 begin
   PosX := 0;
   PosY := 0;
@@ -165,10 +167,38 @@ 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;
   ADest.Pen.FPColor := CurPath.Pen.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
   begin
     //WriteLn('j = ', j);