mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 09:39:43 +01:00 
			
		
		
		
	fpvectorial-svg: Implements support for reading PNG raster images inside SVG
git-svn-id: trunk@42309 -
This commit is contained in:
		
							parent
							
								
									fe0a06d109
								
							
						
					
					
						commit
						9230dae80f
					
				@ -26,6 +26,7 @@ uses
 | 
				
			|||||||
  {$ifdef USE_LCL_CANVAS}
 | 
					  {$ifdef USE_LCL_CANVAS}
 | 
				
			||||||
  Graphics, LCLIntf, LCLType,
 | 
					  Graphics, LCLIntf, LCLType,
 | 
				
			||||||
  {$endif}
 | 
					  {$endif}
 | 
				
			||||||
 | 
					  base64,
 | 
				
			||||||
  fpvectorial, fpimage, zstream;
 | 
					  fpvectorial, fpimage, zstream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type
 | 
					type
 | 
				
			||||||
@ -65,8 +66,11 @@ function SolveNumericallyAngle(ANumericalEquation: TNumericalEquation;
 | 
				
			|||||||
// Compression/Decompression
 | 
					// Compression/Decompression
 | 
				
			||||||
procedure DeflateBytes(var ASource, ADest: TFPVUByteArray);
 | 
					procedure DeflateBytes(var ASource, ADest: TFPVUByteArray);
 | 
				
			||||||
procedure DeflateStream(ASource, ADest: TStream);
 | 
					procedure DeflateStream(ASource, ADest: TStream);
 | 
				
			||||||
// ASCII85
 | 
					// Binary to Text encodings
 | 
				
			||||||
procedure DecodeASCII85(ASource: string; var ADest: TFPVUByteArray);
 | 
					procedure DecodeASCII85(ASource: string; var ADest: TFPVUByteArray);
 | 
				
			||||||
 | 
					procedure DecodeBase64(ASource: string; ADest: TStream);
 | 
				
			||||||
 | 
					// Byte array to stream conversion
 | 
				
			||||||
 | 
					procedure ByteArrayToStream(ASource: TFPVUByteArray; ADest: TStream);
 | 
				
			||||||
// Debug
 | 
					// Debug
 | 
				
			||||||
procedure FPVUDebug(AStr: string);
 | 
					procedure FPVUDebug(AStr: string);
 | 
				
			||||||
procedure FPVUDebugLn(AStr: string);
 | 
					procedure FPVUDebugLn(AStr: string);
 | 
				
			||||||
@ -577,6 +581,29 @@ begin
 | 
				
			|||||||
  end;
 | 
					  end;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure DecodeBase64(ASource: string; ADest: TStream);
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  lSourceStream: TStringStream;
 | 
				
			||||||
 | 
					  lDecoder: TBase64DecodingStream;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  lSourceStream := TStringStream.Create(ASource);
 | 
				
			||||||
 | 
					  lDecoder := TBase64DecodingStream.Create(lSourceStream);
 | 
				
			||||||
 | 
					  try
 | 
				
			||||||
 | 
					    ADest.CopyFrom(lDecoder, lDecoder.Size);
 | 
				
			||||||
 | 
					  finally
 | 
				
			||||||
 | 
					    lDecoder.Free;
 | 
				
			||||||
 | 
					    lSourceStream.Free;
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure ByteArrayToStream(ASource: TFPVUByteArray; ADest: TStream);
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  i: Integer;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  for i := 0 to Length(ASource)-1 do
 | 
				
			||||||
 | 
					    ADest.WriteByte(ASource[i]);
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
procedure FPVUDebug(AStr: string);
 | 
					procedure FPVUDebug(AStr: string);
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  FPVDebugBuffer := FPVDebugBuffer + AStr;
 | 
					  FPVDebugBuffer := FPVDebugBuffer + AStr;
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,8 @@ interface
 | 
				
			|||||||
uses
 | 
					uses
 | 
				
			||||||
  Classes, SysUtils, math,
 | 
					  Classes, SysUtils, math,
 | 
				
			||||||
  fpimage, fpcanvas, laz2_xmlread, laz2_dom, fgl,
 | 
					  fpimage, fpcanvas, laz2_xmlread, laz2_dom, fgl,
 | 
				
			||||||
 | 
					  // image data formats
 | 
				
			||||||
 | 
					  fpreadpng,
 | 
				
			||||||
  fpvectorial, fpvutils, lazutf8, TypInfo;
 | 
					  fpvectorial, fpvutils, lazutf8, TypInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type
 | 
					type
 | 
				
			||||||
@ -78,10 +80,11 @@ type
 | 
				
			|||||||
    function ReadSVGPenStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPen): TvSetPenBrushAndFontElements;
 | 
					    function ReadSVGPenStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPen): TvSetPenBrushAndFontElements;
 | 
				
			||||||
    function ReadSVGBrushStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenAndBrush): TvSetPenBrushAndFontElements;
 | 
					    function ReadSVGBrushStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenAndBrush): TvSetPenBrushAndFontElements;
 | 
				
			||||||
    function ReadSVGFontStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenBrushAndFont): TvSetPenBrushAndFontElements;
 | 
					    function ReadSVGFontStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenBrushAndFont): TvSetPenBrushAndFontElements;
 | 
				
			||||||
    function ReadSVGGeneralStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPen): TvSetPenBrushAndFontElements;
 | 
					    function ReadSVGGeneralStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntity): TvSetPenBrushAndFontElements;
 | 
				
			||||||
    function IsAttributeFromStyle(AStr: string): Boolean;
 | 
					    function IsAttributeFromStyle(AStr: string): Boolean;
 | 
				
			||||||
    procedure ApplyLayerStyles(ADestEntity: TvEntity);
 | 
					    procedure ApplyLayerStyles(ADestEntity: TvEntity);
 | 
				
			||||||
    function ReadSpaceSeparatedFloats(AInput: string): TDoubleArray;
 | 
					    function ReadSpaceSeparatedFloats(AInput: string; AOtherSeparators: string): TDoubleArray;
 | 
				
			||||||
 | 
					    function ReadSpaceSeparatedStrings(AInput: string; AOtherSeparators: string): TStringList;
 | 
				
			||||||
    procedure ReadSVGTransformationMatrix(AMatrix: string; out AA, AB, AC, AD, AE, AF: Double);
 | 
					    procedure ReadSVGTransformationMatrix(AMatrix: string; out AA, AB, AC, AD, AE, AF: Double);
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    procedure ReadDefsFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
 | 
					    procedure ReadDefsFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
 | 
				
			||||||
@ -89,6 +92,7 @@ type
 | 
				
			|||||||
    function ReadEntityFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
					    function ReadEntityFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
				
			||||||
    function ReadCircleFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
					    function ReadCircleFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
				
			||||||
    function ReadEllipseFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
					    function ReadEllipseFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
				
			||||||
 | 
					    function ReadImageFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
				
			||||||
    procedure ReadLayerFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
 | 
					    procedure ReadLayerFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
 | 
				
			||||||
    function ReadLineFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
					    function ReadLineFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
				
			||||||
    function ReadPathFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
					    function ReadPathFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
				
			||||||
@ -923,7 +927,7 @@ begin
 | 
				
			|||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TvSVGVectorialReader.ReadSVGGeneralStyleWithKeyAndValue(AKey,
 | 
					function TvSVGVectorialReader.ReadSVGGeneralStyleWithKeyAndValue(AKey,
 | 
				
			||||||
  AValue: string; ADestEntity: TvEntityWithPen): TvSetPenBrushAndFontElements;
 | 
					  AValue: string; ADestEntity: TvEntity): TvSetPenBrushAndFontElements;
 | 
				
			||||||
var
 | 
					var
 | 
				
			||||||
  // transform
 | 
					  // transform
 | 
				
			||||||
  MA, MB, MC, MD, ME, MF: Double;
 | 
					  MA, MB, MC, MD, ME, MF: Double;
 | 
				
			||||||
@ -949,7 +953,7 @@ begin
 | 
				
			|||||||
      begin
 | 
					      begin
 | 
				
			||||||
        lFunctionName := lTokenizer.Tokens.Items[i].StrValue;
 | 
					        lFunctionName := lTokenizer.Tokens.Items[i].StrValue;
 | 
				
			||||||
        lParamStr := lTokenizer.Tokens.Items[i+1].StrValue;
 | 
					        lParamStr := lTokenizer.Tokens.Items[i+1].StrValue;
 | 
				
			||||||
        lMatrixElements := ReadSpaceSeparatedFloats(lParamStr);
 | 
					        lMatrixElements := ReadSpaceSeparatedFloats(lParamStr, ',');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if lFunctionName = 'matrix' then
 | 
					        if lFunctionName = 'matrix' then
 | 
				
			||||||
        begin
 | 
					        begin
 | 
				
			||||||
@ -1024,17 +1028,25 @@ begin
 | 
				
			|||||||
  end;
 | 
					  end;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TvSVGVectorialReader.ReadSpaceSeparatedFloats(AInput: string
 | 
					function TvSVGVectorialReader.ReadSpaceSeparatedFloats(AInput: string;
 | 
				
			||||||
  ): TDoubleArray;
 | 
					  AOtherSeparators: string): TDoubleArray;
 | 
				
			||||||
var
 | 
					var
 | 
				
			||||||
  lStrings: TStringList;
 | 
					  lStrings: TStringList;
 | 
				
			||||||
 | 
					  lInputStr: string;
 | 
				
			||||||
  lMatrixElements: array of Double;
 | 
					  lMatrixElements: array of Double;
 | 
				
			||||||
  i: Integer;
 | 
					  i: Integer;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  lStrings := TStringList.Create;
 | 
					  lStrings := TStringList.Create;
 | 
				
			||||||
  try
 | 
					  try
 | 
				
			||||||
    lStrings.Delimiter := ' ';
 | 
					    lStrings.Delimiter := ' ';
 | 
				
			||||||
    lStrings.DelimitedText := AInput;
 | 
					    // now other separator too
 | 
				
			||||||
 | 
					    lInputStr := AInput;
 | 
				
			||||||
 | 
					    for i := 1 to Length(AOtherSeparators) do
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
 | 
					      lInputStr := StringReplace(lInputStr, AOtherSeparators[i], ' ', [rfReplaceAll]);
 | 
				
			||||||
 | 
					    end;
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    lStrings.DelimitedText := lInputStr;
 | 
				
			||||||
    SetLength(lMatrixElements, lStrings.Count);
 | 
					    SetLength(lMatrixElements, lStrings.Count);
 | 
				
			||||||
    for i := 0 to lStrings.Count-1 do
 | 
					    for i := 0 to lStrings.Count-1 do
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
@ -1047,6 +1059,24 @@ begin
 | 
				
			|||||||
  end;
 | 
					  end;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TvSVGVectorialReader.ReadSpaceSeparatedStrings(AInput: string;
 | 
				
			||||||
 | 
					  AOtherSeparators: string): TStringList;
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  i: Integer;
 | 
				
			||||||
 | 
					  lInputStr: String;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  Result := TStringList.Create;
 | 
				
			||||||
 | 
					  Result.Delimiter := ' ';
 | 
				
			||||||
 | 
					  // now other separator too
 | 
				
			||||||
 | 
					  lInputStr := AInput;
 | 
				
			||||||
 | 
					  for i := 1 to Length(AOtherSeparators) do
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					    lInputStr := StringReplace(lInputStr, AOtherSeparators[i], ' ', [rfReplaceAll]);
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  Result.DelimitedText := lInputStr;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// transform="matrix(0.860815 0 -0 1.07602 354.095 482.177)"=>matrix(a, b, c, d, e, f)
 | 
					// transform="matrix(0.860815 0 -0 1.07602 354.095 482.177)"=>matrix(a, b, c, d, e, f)
 | 
				
			||||||
// See http://apike.ca/prog_svg_transform.html
 | 
					// See http://apike.ca/prog_svg_transform.html
 | 
				
			||||||
procedure TvSVGVectorialReader.ReadSVGTransformationMatrix(
 | 
					procedure TvSVGVectorialReader.ReadSVGTransformationMatrix(
 | 
				
			||||||
@ -1054,7 +1084,7 @@ procedure TvSVGVectorialReader.ReadSVGTransformationMatrix(
 | 
				
			|||||||
var
 | 
					var
 | 
				
			||||||
  lMatrixElements: array of Double;
 | 
					  lMatrixElements: array of Double;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  lMatrixElements := ReadSpaceSeparatedFloats(AMatrix);
 | 
					  lMatrixElements := ReadSpaceSeparatedFloats(AMatrix, '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  AA := lMatrixElements[0];
 | 
					  AA := lMatrixElements[0];
 | 
				
			||||||
  AB := lMatrixElements[1];
 | 
					  AB := lMatrixElements[1];
 | 
				
			||||||
@ -1177,6 +1207,7 @@ begin
 | 
				
			|||||||
    'circle': Result := ReadCircleFromNode(ANode, AData, ADoc);
 | 
					    'circle': Result := ReadCircleFromNode(ANode, AData, ADoc);
 | 
				
			||||||
    'ellipse': Result := ReadEllipseFromNode(ANode, AData, ADoc);
 | 
					    'ellipse': Result := ReadEllipseFromNode(ANode, AData, ADoc);
 | 
				
			||||||
    'g': ReadLayerFromNode(ANode, AData, ADoc);
 | 
					    'g': ReadLayerFromNode(ANode, AData, ADoc);
 | 
				
			||||||
 | 
					    'image': Result := ReadImageFromNode(ANode, AData, ADoc);
 | 
				
			||||||
    'line': Result := ReadLineFromNode(ANode, AData, ADoc);
 | 
					    'line': Result := ReadLineFromNode(ANode, AData, ADoc);
 | 
				
			||||||
    'path': Result := ReadPathFromNode(ANode, AData, ADoc);
 | 
					    'path': Result := ReadPathFromNode(ANode, AData, ADoc);
 | 
				
			||||||
    'polygon', 'polyline': Result := ReadPolyFromNode(ANode, AData, ADoc);
 | 
					    'polygon', 'polyline': Result := ReadPolyFromNode(ANode, AData, ADoc);
 | 
				
			||||||
@ -1192,7 +1223,7 @@ var
 | 
				
			|||||||
  cx, cy, cr, dtmp: double;
 | 
					  cx, cy, cr, dtmp: double;
 | 
				
			||||||
  lCircle: TvCircle;
 | 
					  lCircle: TvCircle;
 | 
				
			||||||
  i: Integer;
 | 
					  i: Integer;
 | 
				
			||||||
  lNodeName: DOMString;
 | 
					  lNodeName, lNodeValue: DOMString;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  cx := 0.0;
 | 
					  cx := 0.0;
 | 
				
			||||||
  cy := 0.0;
 | 
					  cy := 0.0;
 | 
				
			||||||
@ -1210,21 +1241,22 @@ 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;
 | 
				
			||||||
 | 
					    lNodeValue := ANode.Attributes.Item[i].NodeName;
 | 
				
			||||||
    if  lNodeName = 'cx' then
 | 
					    if  lNodeName = 'cx' then
 | 
				
			||||||
      cx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
 | 
					      cx := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
    else if lNodeName = 'cy' then
 | 
					    else if lNodeName = 'cy' then
 | 
				
			||||||
      cy := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
 | 
					      cy := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
    else if lNodeName = 'r' then
 | 
					    else if lNodeName = 'r' then
 | 
				
			||||||
      cr := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
 | 
					      cr := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
    else if lNodeName = 'id' then
 | 
					    else if lNodeName = 'id' then
 | 
				
			||||||
      lCircle.Name := ANode.Attributes.Item[i].NodeValue
 | 
					      lCircle.Name := lNodeValue
 | 
				
			||||||
    else if lNodeName = 'style' then
 | 
					    else if lNodeName = 'style' then
 | 
				
			||||||
      ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lCircle)
 | 
					      ReadSVGStyle(lNodeValue, lCircle)
 | 
				
			||||||
    else if IsAttributeFromStyle(lNodeName) then
 | 
					    else if IsAttributeFromStyle(lNodeName) then
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
      ReadSVGPenStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lCircle);
 | 
					      ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lCircle);
 | 
				
			||||||
      ReadSVGBrushStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lCircle);
 | 
					      ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lCircle);
 | 
				
			||||||
      ReadSVGGeneralStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lCircle);
 | 
					      ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lCircle);
 | 
				
			||||||
    end;
 | 
					    end;
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1242,7 +1274,7 @@ var
 | 
				
			|||||||
  cx, cy, crx, cry: double;
 | 
					  cx, cy, crx, cry: double;
 | 
				
			||||||
  lEllipse: TvEllipse;
 | 
					  lEllipse: TvEllipse;
 | 
				
			||||||
  i: Integer;
 | 
					  i: Integer;
 | 
				
			||||||
  lNodeName: DOMString;
 | 
					  lNodeName, lNodeValue: DOMString;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  cx := 0.0;
 | 
					  cx := 0.0;
 | 
				
			||||||
  cy := 0.0;
 | 
					  cy := 0.0;
 | 
				
			||||||
@ -1261,23 +1293,24 @@ 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;
 | 
				
			||||||
 | 
					    lNodeValue := ANode.Attributes.Item[i].NodeName;
 | 
				
			||||||
    if  lNodeName = 'cx' then
 | 
					    if  lNodeName = 'cx' then
 | 
				
			||||||
      cx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
 | 
					      cx := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
    else if lNodeName = 'cy' then
 | 
					    else if lNodeName = 'cy' then
 | 
				
			||||||
      cy := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
 | 
					      cy := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
    else if lNodeName = 'rx' then
 | 
					    else if lNodeName = 'rx' then
 | 
				
			||||||
      crx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
 | 
					      crx := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
    else if lNodeName = 'ry' then
 | 
					    else if lNodeName = 'ry' then
 | 
				
			||||||
      cry := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
 | 
					      cry := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
    else if lNodeName = 'id' then
 | 
					    else if lNodeName = 'id' then
 | 
				
			||||||
      lEllipse.Name := ANode.Attributes.Item[i].NodeValue
 | 
					      lEllipse.Name := ANode.Attributes.Item[i].NodeValue
 | 
				
			||||||
    else if lNodeName = 'style' then
 | 
					    else if lNodeName = 'style' then
 | 
				
			||||||
      ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lEllipse)
 | 
					      ReadSVGStyle(lNodeValue, lEllipse)
 | 
				
			||||||
    else if IsAttributeFromStyle(lNodeName) then
 | 
					    else if IsAttributeFromStyle(lNodeName) then
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
      ReadSVGPenStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lEllipse);
 | 
					      ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lEllipse);
 | 
				
			||||||
      ReadSVGBrushStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lEllipse);
 | 
					      ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lEllipse);
 | 
				
			||||||
      ReadSVGGeneralStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lEllipse);
 | 
					      ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lEllipse);
 | 
				
			||||||
    end;
 | 
					    end;
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1289,6 +1322,95 @@ begin
 | 
				
			|||||||
  Result := lEllipse;
 | 
					  Result := lEllipse;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// <image width="92.5" x="0" y="0" height="76.0429"
 | 
				
			||||||
 | 
					//  xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKMAAACGCAYAA
 | 
				
			||||||
 | 
					//  ACxDToF......" clip-path="url(#Clip0)" transform="matrix(1 0 0 1 0 0)"/>
 | 
				
			||||||
 | 
					function TvSVGVectorialReader.ReadImageFromNode(ANode: TDOMNode;
 | 
				
			||||||
 | 
					  AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  lImage: TvRasterImage;
 | 
				
			||||||
 | 
					  lx, ly, lw, lh: Double;
 | 
				
			||||||
 | 
					  i: Integer;
 | 
				
			||||||
 | 
					  lNodeName, lNodeValue: DOMString;
 | 
				
			||||||
 | 
					  lImageDataParts: TStringList;
 | 
				
			||||||
 | 
					  lImageDataBase64: string;
 | 
				
			||||||
 | 
					  lImageData: array of Byte;
 | 
				
			||||||
 | 
					  lImageDataStream: TMemoryStream;
 | 
				
			||||||
 | 
					  lImageReader: TFPCustomImageReader;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  lImage := TvRasterImage.Create;
 | 
				
			||||||
 | 
					  lx := 0;
 | 
				
			||||||
 | 
					  ly := 0;
 | 
				
			||||||
 | 
					  lw := 0;
 | 
				
			||||||
 | 
					  lh := 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Apply the layer style
 | 
				
			||||||
 | 
					  //ApplyLayerStyles(lEllipse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // read the attributes
 | 
				
			||||||
 | 
					  for i := 0 to ANode.Attributes.Length - 1 do
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					    lNodeName := ANode.Attributes.Item[i].NodeName;
 | 
				
			||||||
 | 
					    lNodeValue := ANode.Attributes.Item[i].NodeValue;
 | 
				
			||||||
 | 
					    if  lNodeName = 'x' then
 | 
				
			||||||
 | 
					      lx := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
 | 
					    else if lNodeName = 'y' then
 | 
				
			||||||
 | 
					      ly := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
 | 
					    else if lNodeName = 'width' then
 | 
				
			||||||
 | 
					      lw := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
 | 
					    else if lNodeName = 'height' then
 | 
				
			||||||
 | 
					      lh := StringWithUnitToFloat(lNodeValue)
 | 
				
			||||||
 | 
					    else if lNodeName = 'xlink:href' then
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
 | 
					      lImageDataParts := ReadSpaceSeparatedStrings(lNodeValue, ':;,');
 | 
				
			||||||
 | 
					      try
 | 
				
			||||||
 | 
					        if (lImageDataParts.Strings[0] = 'data') and
 | 
				
			||||||
 | 
					           (lImageDataParts.Strings[1] = 'image/png') and
 | 
				
			||||||
 | 
					           (lImageDataParts.Strings[2] = 'base64') then
 | 
				
			||||||
 | 
					        begin
 | 
				
			||||||
 | 
					          lImageReader := TFPReaderPNG.Create;
 | 
				
			||||||
 | 
					          lImageDataStream := TMemoryStream.Create;
 | 
				
			||||||
 | 
					          try
 | 
				
			||||||
 | 
					            lImageDataBase64 := lImageDataParts.Strings[3];
 | 
				
			||||||
 | 
					            DecodeBase64(lImageDataBase64, lImageDataStream);
 | 
				
			||||||
 | 
					            lImageDataStream.Position := 0;
 | 
				
			||||||
 | 
					            lImage.CreateRGB888Image(10, 10);
 | 
				
			||||||
 | 
					            lImage.RasterImage.LoadFromStream(lImageDataStream, lImageReader);
 | 
				
			||||||
 | 
					          finally
 | 
				
			||||||
 | 
					            lImageDataStream.Free;
 | 
				
			||||||
 | 
					            lImageReader.Free;
 | 
				
			||||||
 | 
					          end;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					          raise Exception.Create('[TvSVGVectorialReader.ReadImageFromNode] Unimplemented image format');
 | 
				
			||||||
 | 
					      finally
 | 
				
			||||||
 | 
					        lImageDataParts.Free;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    else if lNodeName = 'id' then
 | 
				
			||||||
 | 
					      lImage.Name := lNodeValue
 | 
				
			||||||
 | 
					{    else if lNodeName = 'style' then
 | 
				
			||||||
 | 
					      ReadSVGStyle(lNodeValue, lImage)}
 | 
				
			||||||
 | 
					    else if IsAttributeFromStyle(lNodeName) then
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
 | 
					      //ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lImage);
 | 
				
			||||||
 | 
					      //ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lImage);
 | 
				
			||||||
 | 
					      ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lImage);
 | 
				
			||||||
 | 
					    end;
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Record translate data
 | 
				
			||||||
 | 
					  lx := lx + lImage.X;
 | 
				
			||||||
 | 
					  ly := ly + lImage.Y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ConvertSVGCoordinatesToFPVCoordinates(
 | 
				
			||||||
 | 
					        AData, lx, ly, lImage.X, lImage.Y);
 | 
				
			||||||
 | 
					  ConvertSVGDeltaToFPVDelta(
 | 
				
			||||||
 | 
					        AData, lw, lh, lImage.Width, lImage.Height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Result := lImage;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
procedure TvSVGVectorialReader.ReadLayerFromNode(ANode: TDOMNode;
 | 
					procedure TvSVGVectorialReader.ReadLayerFromNode(ANode: TDOMNode;
 | 
				
			||||||
  AData: TvVectorialPage; ADoc: TvVectorialDocument);
 | 
					  AData: TvVectorialPage; ADoc: TvVectorialDocument);
 | 
				
			||||||
var
 | 
					var
 | 
				
			||||||
@ -2037,7 +2159,7 @@ var
 | 
				
			|||||||
  lXLink: DOMString = '';
 | 
					  lXLink: DOMString = '';
 | 
				
			||||||
  lInsertedEntity: TvEntity;
 | 
					  lInsertedEntity: TvEntity;
 | 
				
			||||||
  i: Integer;
 | 
					  i: Integer;
 | 
				
			||||||
  lNodeName: DOMString;
 | 
					  lNodeName, lNodeValue: DOMString;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  Result := nil;
 | 
					  Result := nil;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2061,6 +2183,24 @@ begin
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  lInsert := TvInsert.Create;
 | 
					  lInsert := TvInsert.Create;
 | 
				
			||||||
  lInsert.InsertEntity := lInsertedEntity;
 | 
					  lInsert.InsertEntity := lInsertedEntity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Apply the styles
 | 
				
			||||||
 | 
					  // read the attributes
 | 
				
			||||||
 | 
					  for i := 0 to ANode.Attributes.Length - 1 do
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					    lNodeName := ANode.Attributes.Item[i].NodeName;
 | 
				
			||||||
 | 
					    lNodeValue := ANode.Attributes.Item[i].NodeValue;
 | 
				
			||||||
 | 
					    {if lNodeName = 'style' then
 | 
				
			||||||
 | 
					      ReadSVGStyle(lNodeValue, lText)
 | 
				
			||||||
 | 
					    else} if IsAttributeFromStyle(lNodeName) then
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
 | 
					      {ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lText);
 | 
				
			||||||
 | 
					      ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lText);
 | 
				
			||||||
 | 
					      ReadSVGFontStyleWithKeyAndValue(lNodeName, lNodeValue, lText);}
 | 
				
			||||||
 | 
					      ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lInsert);
 | 
				
			||||||
 | 
					    end;
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Result := lInsert;
 | 
					  Result := lInsert;
 | 
				
			||||||
end;
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2175,7 +2315,7 @@ var
 | 
				
			|||||||
  {$ifdef SVG_MERGE_LAYER_STYLES}
 | 
					  {$ifdef SVG_MERGE_LAYER_STYLES}
 | 
				
			||||||
  lLayerStyleKeys, lLayerStyleValues: TStringList;
 | 
					  lLayerStyleKeys, lLayerStyleValues: TStringList;
 | 
				
			||||||
  {$endif}
 | 
					  {$endif}
 | 
				
			||||||
  lNodeName: DOMString;
 | 
					  lNodeName, lNodeValue: DOMString;
 | 
				
			||||||
  ANode: TDOMElement;
 | 
					  ANode: TDOMElement;
 | 
				
			||||||
  i: Integer;
 | 
					  i: Integer;
 | 
				
			||||||
  lCurEntity: TvEntity;
 | 
					  lCurEntity: TvEntity;
 | 
				
			||||||
@ -2200,23 +2340,24 @@ 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;
 | 
				
			||||||
 | 
					    lNodeValue := ANode.Attributes.Item[i].NodeValue;
 | 
				
			||||||
    if lNodeName = 'viewBox' then
 | 
					    if lNodeName = 'viewBox' then
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
      lViewBox := ReadSpaceSeparatedFloats(ANode.Attributes.Item[i].NodeValue);
 | 
					      lViewBox := ReadSpaceSeparatedFloats(lNodeValue, '');
 | 
				
			||||||
      AData.Width := lViewBox[2] - lViewBox[0];
 | 
					      AData.Width := lViewBox[2] - lViewBox[0];
 | 
				
			||||||
      AData.Height := lViewBox[3] - lViewBox[1];
 | 
					      AData.Height := lViewBox[3] - lViewBox[1];
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    else if lNodeName = 'style' then
 | 
					    else if lNodeName = 'style' then
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
      {$ifdef SVG_MERGE_LAYER_STYLES}
 | 
					      {$ifdef SVG_MERGE_LAYER_STYLES}
 | 
				
			||||||
      ReadSVGStyleToStyleLists(ANode.Attributes.Item[i].NodeValue, lLayerStyleKeys, lLayerStyleValues);
 | 
					      ReadSVGStyleToStyleLists(lNodeValue, lLayerStyleKeys, lLayerStyleValues);
 | 
				
			||||||
      {$endif}
 | 
					      {$endif}
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    else if IsAttributeFromStyle(lNodeName) then
 | 
					    else if IsAttributeFromStyle(lNodeName) then
 | 
				
			||||||
    begin
 | 
					    begin
 | 
				
			||||||
      {$ifdef SVG_MERGE_LAYER_STYLES}
 | 
					      {$ifdef SVG_MERGE_LAYER_STYLES}
 | 
				
			||||||
      lLayerStyleKeys.Add(lNodeName);
 | 
					      lLayerStyleKeys.Add(lNodeName);
 | 
				
			||||||
      lLayerStyleValues.Add(ANode.Attributes.Item[i].NodeValue);
 | 
					      lLayerStyleValues.Add(lNodeValue);
 | 
				
			||||||
      {$endif}
 | 
					      {$endif}
 | 
				
			||||||
    end;
 | 
					    end;
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user