mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 15:19:19 +02: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