fpvectorial: Greatly improves the FPV tokens debug information and fixes the svg style reading for paths

git-svn-id: trunk@39726 -
This commit is contained in:
sekelsenmat 2013-01-02 09:59:56 +00:00
parent 84b0c8d37e
commit ba73becf3e
2 changed files with 150 additions and 22 deletions

View File

@ -138,6 +138,7 @@ type
Previous: TPathSegment; Previous: TPathSegment;
Next: TPathSegment; Next: TPathSegment;
procedure Move(ADeltaX, ADeltaY: Double); virtual; procedure Move(ADeltaX, ADeltaY: Double); virtual;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; virtual;
end; end;
{@@ {@@
@ -154,6 +155,7 @@ type
public public
X, Y: Double; X, Y: Double;
procedure Move(ADeltaX, ADeltaY: Double); override; procedure Move(ADeltaX, ADeltaY: Double); override;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
end; end;
T2DSegmentWithPen = class(T2DSegment) T2DSegmentWithPen = class(T2DSegment)
@ -228,11 +230,13 @@ type
procedure Move(ADeltaX, ADeltaY: Double); virtual; procedure Move(ADeltaX, ADeltaY: Double); virtual;
procedure MoveSubpart(ADeltaX, ADeltaY: Double; ASubpart: Cardinal); virtual; procedure MoveSubpart(ADeltaX, ADeltaY: Double; ASubpart: Cardinal); virtual;
function GetSubpartCount: Integer; virtual; function GetSubpartCount: Integer; virtual;
procedure PositionSubparts(ADest: TFPCustomCanvas; ABaseX, ABaseY: Double); virtual;
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0; procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); virtual; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); virtual;
function AdjustColorToBackground(AColor: TFPColor; ARenderInfo: TvRenderInfo): TFPColor; function AdjustColorToBackground(AColor: TFPColor; ARenderInfo: TvRenderInfo): TFPColor;
function GetNormalizedPos(APage: TvVectorialPage; ANewMin, ANewMax: Double): T3DPoint; function GetNormalizedPos(APage: TvVectorialPage; ANewMin, ANewMax: Double): T3DPoint;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; virtual; function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; virtual;
function GenerateDebugStrForFPColor(AColor: TFPColor): string;
end; end;
TvEntityClass = class of TvEntity; TvEntityClass = class of TvEntity;
@ -242,6 +246,7 @@ type
TvNamedEntity = class(TvEntity) TvNamedEntity = class(TvEntity)
public public
Name: string; Name: string;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
end; end;
{ TvEntityWithPen } { TvEntityWithPen }
@ -301,6 +306,7 @@ type
function GetSubpartCount: Integer; override; function GetSubpartCount: Integer; override;
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0; procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
end; end;
{@@ {@@
@ -322,6 +328,7 @@ type
function TryToSelect(APos: TPoint; var ASubpart: Cardinal): TvFindEntityResult; override; function TryToSelect(APos: TPoint; var ASubpart: Cardinal): TvFindEntityResult; override;
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0; procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
end; end;
{@@ {@@
@ -542,7 +549,7 @@ type
// //
function CalculateHeight(ADest: TFPCustomCanvas): Double; // in milimeters function CalculateHeight(ADest: TFPCustomCanvas): Double; // in milimeters
function CalculateWidth(ADest: TFPCustomCanvas): Double; // in milimeters function CalculateWidth(ADest: TFPCustomCanvas): Double; // in milimeters
procedure PositionElements(ADest: TFPCustomCanvas; ABaseX, ABaseY: Double); procedure PositionSubparts(ADest: TFPCustomCanvas; ABaseX, ABaseY: Double); override;
procedure CalculateBoundingBox(ADest: TFPCustomCanvas; var ALeft, ATop, ARight, ABottom: Double); override; procedure CalculateBoundingBox(ADest: TFPCustomCanvas; var ALeft, ATop, ARight, ABottom: Double); override;
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0; procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
@ -567,6 +574,7 @@ type
procedure Clear; override; procedure Clear; override;
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0; procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
end; end;
{@@ {@@
@ -730,6 +738,7 @@ type
// //
function AddPoint(AX, AY, AZ: Double): TvPoint; function AddPoint(AX, AY, AZ: Double): TvPoint;
{ Drawing methods } { Drawing methods }
procedure PositionEntitySubparts(ADest: TFPCustomCanvas; ABaseX, ABaseY: Double);
procedure DrawBackground(ADest: TFPCustomCanvas); procedure DrawBackground(ADest: TFPCustomCanvas);
procedure Render(ADest: TFPCustomCanvas; procedure Render(ADest: TFPCustomCanvas;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0);
@ -897,6 +906,15 @@ begin
end; end;
function TPathSegment.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
APageItem: Pointer): Pointer;
var
lStr: string;
begin
lStr := Format('[%s]', [Self.ClassName]);
Result := ADestRoutine(lStr, APageItem);
end;
{ T2DSegment } { T2DSegment }
procedure T2DSegment.Move(ADeltaX, ADeltaY: Double); procedure T2DSegment.Move(ADeltaX, ADeltaY: Double);
@ -905,6 +923,15 @@ begin
Y := Y + ADeltaY; Y := Y + ADeltaY;
end; end;
function T2DSegment.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
APageItem: Pointer): Pointer;
var
lStr: string;
begin
lStr := Format('[%s] X=%f Y=%f', [Self.ClassName, X, Y]);
Result := ADestRoutine(lStr, APageItem);
end;
{ T2DBezierSegment } { T2DBezierSegment }
procedure T2DBezierSegment.Move(ADeltaX, ADeltaY: Double); procedure T2DBezierSegment.Move(ADeltaX, ADeltaY: Double);
@ -988,6 +1015,12 @@ begin
Result := 0; Result := 0;
end; end;
procedure TvEntity.PositionSubparts(ADest: TFPCustomCanvas; ABaseX,
ABaseY: Double);
begin
end;
procedure TvEntity.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer; procedure TvEntity.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer;
ADestY: Integer; AMulX: Double; AMulY: Double); ADestY: Integer; AMulX: Double; AMulY: Double);
begin begin
@ -1024,7 +1057,23 @@ function TvEntity.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
var var
lStr: string; lStr: string;
begin begin
lStr := Format('[%s]', [Self.ClassName]); lStr := Format('[%s] X=%f Y=%f', [Self.ClassName, X, Y]);
Result := ADestRoutine(lStr, APageItem);
end;
function TvEntity.GenerateDebugStrForFPColor(AColor: TFPColor): string;
begin
Result := IntToHex(AColor.Red div $100, 2) + IntToHex(AColor.Green div $100, 2) + IntToHex(AColor.Blue div $100, 2) + IntToHex(AColor.Alpha div $100, 2);
end;
{ TvNamedEntity }
function TvNamedEntity.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
APageItem: Pointer): Pointer;
var
lStr: string;
begin
lStr := Format('[%s] Name=%s X=%f Y=%f', [Self.ClassName, Name, X, Y]);
Result := ADestRoutine(lStr, APageItem); Result := ADestRoutine(lStr, APageItem);
end; end;
@ -1505,6 +1554,30 @@ begin
{$endif} {$endif}
end; end;
function TPath.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
APageItem: Pointer): Pointer;
var
lStr: string;
lCurPathSeg: TPathSegment;
begin
lStr := Format('[%s] Name=%s Pen.Color=%s Pen.Style=%s Brush.Color=%s Brush.Style=%s',
[Self.ClassName, Self.Name,
GenerateDebugStrForFPColor(Pen.Color),
GetEnumName(TypeInfo(TFPPenStyle), integer(Pen.Style)),
GenerateDebugStrForFPColor(Brush.Color),
GetEnumName(TypeInfo(TFPBrushStyle), integer(Brush.Style))
]);
Result := ADestRoutine(lStr, APageItem);
// Add sub-entities
PrepareForSequentialReading();
lCurPathSeg := Next();
while lCurPathSeg <> nil do
begin
lCurPathSeg.GenerateDebugTree(ADestRoutine, Result);
lCurPathSeg := Next();
end;
end;
{ TvText } { TvText }
constructor TvText.Create; constructor TvText.Create;
@ -1577,6 +1650,15 @@ begin
end; end;
end; end;
function TvText.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
APageItem: Pointer): Pointer;
var
lStr: string;
begin
lStr := Format('[%s] Name=%s X=%f Y=%f Text=%s', [Self.ClassName, Name, X, Y, Value.Text]);
Result := ADestRoutine(lStr, APageItem);
end;
{ TvCircle } { TvCircle }
procedure TvCircle.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer; procedure TvCircle.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer;
@ -2498,7 +2580,7 @@ begin
Width := Result; Width := Result;
end; end;
procedure TvFormula.PositionElements(ADest: TFPCustomCanvas; ABaseX, ABaseY: Double); procedure TvFormula.PositionSubparts(ADest: TFPCustomCanvas; ABaseX, ABaseY: Double);
var var
lElement: TvFormulaElement; lElement: TvFormulaElement;
lPosX: Double = 0; lPosX: Double = 0;
@ -2539,30 +2621,30 @@ begin
lCentralizeFactorAdj := 0; lCentralizeFactorAdj := 0;
end; end;
lElement.Formula.PositionElements(ADest, lElement.Left + lCentralizeFactor, lElement.Top); lElement.Formula.PositionSubparts(ADest, lElement.Left + lCentralizeFactor, lElement.Top);
lElement.AdjacentFormula.PositionElements(ADest, lElement.Left + lCentralizeFactorAdj, lElement.Top - lElement.Formula.Height - 3); lElement.AdjacentFormula.PositionSubparts(ADest, lElement.Left + lCentralizeFactorAdj, lElement.Top - lElement.Formula.Height - 3);
end; end;
fekRoot: fekRoot:
begin begin
// Give a factor for the root drawing // Give a factor for the root drawing
lElement.Formula.PositionElements(ADest, lElement.Left + 10, lElement.Top); lElement.Formula.PositionSubparts(ADest, lElement.Left + 10, lElement.Top);
end; end;
fekPower: fekPower:
begin begin
lElement.Formula.PositionElements(ADest, lElement.Left, lElement.Top); lElement.Formula.PositionSubparts(ADest, lElement.Left, lElement.Top);
lElement.AdjacentFormula.PositionElements(ADest, lElement.Left + lElement.Formula.Width, lElement.Top); lElement.AdjacentFormula.PositionSubparts(ADest, lElement.Left + lElement.Formula.Width, lElement.Top);
end; end;
fekSubscript: fekSubscript:
begin begin
lElement.Formula.PositionElements(ADest, lElement.Left, lElement.Top); lElement.Formula.PositionSubparts(ADest, lElement.Left, lElement.Top);
lElement.AdjacentFormula.PositionElements(ADest, lElement.Left + lElement.Formula.Width, lElement.Top - lElement.Formula.Height / 2); lElement.AdjacentFormula.PositionSubparts(ADest, lElement.Left + lElement.Formula.Width, lElement.Top - lElement.Formula.Height / 2);
end; end;
fekSummation: fekSummation:
begin begin
// main/bottom formula // main/bottom formula
lElement.Formula.PositionElements(ADest, lElement.Left, lElement.Top - 30); lElement.Formula.PositionSubparts(ADest, lElement.Left, lElement.Top - 30);
// top formula // top formula
lElement.AdjacentFormula.PositionElements(ADest, lElement.Left, lElement.Top); lElement.AdjacentFormula.PositionSubparts(ADest, lElement.Left, lElement.Top);
end; end;
end; end;
@ -2603,7 +2685,7 @@ var
lElement: TvFormulaElement; lElement: TvFormulaElement;
begin begin
// First position all elements // First position all elements
PositionElements(ADest, Left, Top); PositionSubparts(ADest, Left, Top);
// Now draw them all // Now draw them all
lElement := GetFirstElement(); lElement := GetFirstElement();
@ -2701,6 +2783,23 @@ begin
end; end;
end; end;
function TvEntityWithSubEntities.GenerateDebugTree(
ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer;
var
lStr: string;
lCurEntity: TvEntity;
begin
lStr := Format('[%s] Name=%s', [Self.ClassName, Self.Name]);
Result := ADestRoutine(lStr, APageItem);
// Add sub-entities
lCurEntity := GetFirstEntity();
while lCurEntity <> nil do
begin
lCurEntity.GenerateDebugTree(ADestRoutine, Result);
lCurEntity := GetNextEntity();
end;
end;
{ TvInsert } { TvInsert }
procedure TvInsert.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer; procedure TvInsert.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer;
@ -3277,6 +3376,15 @@ begin
Result := lPoint; Result := lPoint;
end; end;
procedure TvVectorialPage.PositionEntitySubparts(ADest: TFPCustomCanvas; ABaseX,
ABaseY: Double);
var
i: Integer;
begin
for i := 0 to GetEntitiesCount()-1 do
GetEntity(0).PositionSubparts(ADest, ABaseX, ABaseY);
end;
procedure TvVectorialPage.DrawBackground(ADest: TFPCustomCanvas); procedure TvVectorialPage.DrawBackground(ADest: TFPCustomCanvas);
begin begin
ADest.Pen.Style := psClear; ADest.Pen.Style := psClear;

View File

@ -15,7 +15,7 @@ interface
uses uses
Classes, SysUtils, math, Classes, SysUtils, math,
fpimage, fpcanvas, xmlread, dom, fgl, fpimage, fpcanvas, xmlread, dom, fgl,
fpvectorial, fpvutils; fpvectorial, fpvutils, lazutf8;
type type
TSVGTokenType = ( TSVGTokenType = (
@ -785,6 +785,8 @@ begin
cy := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) cy := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'r' then else if lNodeName = 'r' then
cr := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) cr := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'id' then
lCircle.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'style' then else if lNodeName = 'style' then
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lCircle) ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lCircle)
else if IsAttributeFromStyle(lNodeName) then else if IsAttributeFromStyle(lNodeName) then
@ -833,6 +835,8 @@ begin
crx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) crx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'ry' then else if lNodeName = 'ry' then
cry := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) cry := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'id' then
lEllipse.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'style' then else if lNodeName = 'style' then
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lEllipse) ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lEllipse)
else if IsAttributeFromStyle(lNodeName) then else if IsAttributeFromStyle(lNodeName) then
@ -903,17 +907,15 @@ end;
procedure TvSVGVectorialReader.ReadPathFromNode(ANode: TDOMNode; procedure TvSVGVectorialReader.ReadPathFromNode(ANode: TDOMNode;
AData: TvVectorialPage; ADoc: TvVectorialDocument); AData: TvVectorialPage; ADoc: TvVectorialDocument);
var var
lNodeName, lStyleStr, lDStr: WideString; lNodeName, lDStr: WideString;
i: Integer; i: Integer;
lPath: TPath; lPath: TPath;
begin begin
for i := 0 to ANode.Attributes.Length - 1 do for i := 0 to ANode.Attributes.Length - 1 do
begin begin
lNodeName := ANode.Attributes.Item[i].NodeName; lNodeName := ANode.Attributes.Item[i].NodeName;
if lNodeName = 'style' then if lNodeName = 'd' then
lStyleStr := ANode.Attributes.Item[i].NodeValue lDStr := ANode.Attributes.Item[i].NodeValue;
else if lNodeName = 'd' then
lDStr := ANode.Attributes.Item[i].NodeValue
end; end;
AData.StartPath(); AData.StartPath();
@ -923,8 +925,20 @@ begin
lPath.Pen.Style := psClear; lPath.Pen.Style := psClear;
lPath.Brush.Color := colBlack; lPath.Brush.Color := colBlack;
lPath.Brush.Style := bsSolid; lPath.Brush.Style := bsSolid;
// Add the pen/brush // Add the pen/brush/name
ReadSVGStyle(lStyleStr, lPath); for i := 0 to ANode.Attributes.Length - 1 do
begin
lNodeName := ANode.Attributes.Item[i].NodeName;
if lNodeName = 'id' then
lPath.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'style' then
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lPath)
else if IsAttributeFromStyle(lNodeName) then
begin
ReadSVGPenStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lPath);
ReadSVGBrushStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lPath);
end;
end;
end; end;
// Documentation: http://www.w3.org/TR/SVG/paths.html // Documentation: http://www.w3.org/TR/SVG/paths.html
@ -1183,7 +1197,9 @@ begin
for i := 0 to ANode.Attributes.Length - 1 do for i := 0 to ANode.Attributes.Length - 1 do
begin begin
lNodeName := ANode.Attributes.Item[i].NodeName; lNodeName := ANode.Attributes.Item[i].NodeName;
if lNodeName = 'style' then if lNodeName = 'id' then
lPath.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'style' then
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lPath) ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lPath)
else if IsAttributeFromStyle(lNodeName) then else if IsAttributeFromStyle(lNodeName) then
begin begin
@ -1225,6 +1241,8 @@ begin
cx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) cx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'height' then else if lNodeName = 'height' then
cy := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) cy := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'id' then
lRect.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'style' then else if lNodeName = 'style' then
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lRect) ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lRect)
else if IsAttributeFromStyle(lNodeName) then else if IsAttributeFromStyle(lNodeName) then
@ -1265,6 +1283,8 @@ begin
lx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) lx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'y' then else if lNodeName = 'y' then
ly := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) ly := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'id' then
lText.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
else if lNodeName = 'style' then else if lNodeName = 'style' then
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lText, True) ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lText, True)
else if IsAttributeFromStyle(lNodeName) then else if IsAttributeFromStyle(lNodeName) then