mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-24 16:59:15 +02:00
fpvectorial: Finishes the basic support for CSS inside SVG
git-svn-id: trunk@54206 -
This commit is contained in:
parent
b8ab9927c7
commit
d177b138b7
@ -51,6 +51,7 @@ function CoordToCanvasX(ACoord: Double; ADestX: Integer; AMulX: Double): Integer
|
|||||||
function CoordToCanvasY(ACoord: Double; ADestY: Integer; AMulY: Double): Integer; inline;
|
function CoordToCanvasY(ACoord: Double; ADestY: Integer; AMulY: Double): Integer; inline;
|
||||||
// Other routines
|
// Other routines
|
||||||
function SeparateString(AString: string; ASeparator: char): T10Strings;
|
function SeparateString(AString: string; ASeparator: char): T10Strings;
|
||||||
|
procedure SeparateStringInTwo(AString: string; ASeparator: char; out AStart, AEnd: string);
|
||||||
function Make3DPoint(AX, AY, AZ: Double): T3DPoint; overload; inline;
|
function Make3DPoint(AX, AY, AZ: Double): T3DPoint; overload; inline;
|
||||||
function Make3DPoint(AX, AY: Double): T3DPoint; overload; inline;
|
function Make3DPoint(AX, AY: Double): T3DPoint; overload; inline;
|
||||||
function Point2D(AX, AY: Double): T2DPoint; inline;
|
function Point2D(AX, AY: Double): T2DPoint; inline;
|
||||||
@ -262,6 +263,16 @@ begin
|
|||||||
Result.Y := AY;
|
Result.Y := AY;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure SeparateStringInTwo(AString: string; ASeparator: char; out AStart,
|
||||||
|
AEnd: string);
|
||||||
|
var
|
||||||
|
lPosSep: SizeInt;
|
||||||
|
begin
|
||||||
|
lPosSep := Pos(ASeparator, AString);
|
||||||
|
AStart := Copy(AString, 0, lPosSep-1);
|
||||||
|
AEnd := Copy(AString, lPosSep+1, Length(AString));
|
||||||
|
end;
|
||||||
|
|
||||||
function Make3DPoint(AX, AY, AZ: Double): T3DPoint;
|
function Make3DPoint(AX, AY, AZ: Double): T3DPoint;
|
||||||
begin
|
begin
|
||||||
Result.X := AX;
|
Result.X := AX;
|
||||||
|
@ -69,13 +69,15 @@ type
|
|||||||
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
|
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TvSVGVectorialReader = class;
|
||||||
|
|
||||||
{ TSVG_CSS_Style }
|
{ TSVG_CSS_Style }
|
||||||
|
|
||||||
TSVG_CSS_Style = class(TvStyle)
|
TSVG_CSS_Style = class(TvStyle)
|
||||||
public
|
public
|
||||||
CSSName, CSSData: string;
|
CSSName, CSSData: string;
|
||||||
function MatchesClass(AClassName: string): Boolean;
|
function MatchesClass(AClassName: string): Boolean;
|
||||||
procedure ParseCSSData();
|
procedure ParseCSSData(AReader: TvSVGVectorialReader);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSVGPathTokenizer }
|
{ TSVGPathTokenizer }
|
||||||
@ -125,8 +127,8 @@ type
|
|||||||
ADestEntity: TvEntityWithPen; ADestStyle: TvStyle = nil;
|
ADestEntity: TvEntityWithPen; ADestStyle: TvStyle = nil;
|
||||||
AUseFillAsPen: Boolean = False): TvSetPenBrushAndFontElements;
|
AUseFillAsPen: Boolean = False): TvSetPenBrushAndFontElements;
|
||||||
function ReadSVGStyleToStyleLists(AValue: string; AStyleKeys, AStyleValues: TStringList): TvSetPenBrushAndFontElements;
|
function ReadSVGStyleToStyleLists(AValue: string; AStyleKeys, AStyleValues: TStringList): TvSetPenBrushAndFontElements;
|
||||||
function ReadSVGPenStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPen): TvSetPenBrushAndFontElements;
|
function ReadSVGPenStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPen; ADestStyle: TvStyle = nil): TvSetPenBrushAndFontElements;
|
||||||
function ReadSVGBrushStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenAndBrush): TvSetPenBrushAndFontElements;
|
function ReadSVGBrushStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenAndBrush; ADestStyle: TvStyle = nil): TvSetPenBrushAndFontElements;
|
||||||
function ReadSVGFontStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenBrushAndFont; ADestStyle: TvStyle = nil): TvSetPenBrushAndFontElements;
|
function ReadSVGFontStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenBrushAndFont; ADestStyle: TvStyle = nil): TvSetPenBrushAndFontElements;
|
||||||
procedure ReadSVGGeneralStyleWithKeyAndValue(AData: TvVectorialPage;
|
procedure ReadSVGGeneralStyleWithKeyAndValue(AData: TvVectorialPage;
|
||||||
AKey, AValue: string; ADestEntity: TvEntity);
|
AKey, AValue: string; ADestEntity: TvEntity);
|
||||||
@ -217,7 +219,7 @@ var
|
|||||||
lNameModified: string;
|
lNameModified: string;
|
||||||
begin
|
begin
|
||||||
lNameModified := '.' + AClassName;
|
lNameModified := '.' + AClassName;
|
||||||
Result := (lNameModified = AClassName);
|
Result := (lNameModified = CSSName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -231,22 +233,9 @@ end;
|
|||||||
.fil0 {fill:#EEEED4}
|
.fil0 {fill:#EEEED4}
|
||||||
]]>
|
]]>
|
||||||
}
|
}
|
||||||
procedure TSVG_CSS_Style.ParseCSSData;
|
procedure TSVG_CSS_Style.ParseCSSData(AReader: TvSVGVectorialReader);
|
||||||
var
|
|
||||||
lSplitter: TStringList;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
lSplitter: TStringList.Create;
|
SetElements += AReader.ReadSVGStyle(nil, CSSData, nil, Self, False);
|
||||||
try
|
|
||||||
lSplitter.Delimiter := ';';
|
|
||||||
lSplitter.DelimitedText := CSSData;
|
|
||||||
for i := 0 to lSplitter.Count-1 do
|
|
||||||
begin
|
|
||||||
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
lSplitter.Free;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSVGTextSpanStyle }
|
{ TSVGTextSpanStyle }
|
||||||
@ -843,7 +832,7 @@ function TvSVGVectorialReader.ReadSVGStyle(AData: TvVectorialPage; AValue: strin
|
|||||||
var
|
var
|
||||||
lStr, lStyleKeyStr, lStyleValueStr: String;
|
lStr, lStyleKeyStr, lStyleValueStr: String;
|
||||||
lStrings: TStringList;
|
lStrings: TStringList;
|
||||||
i, lPosEqual: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := [];
|
Result := [];
|
||||||
if AValue = '' then Exit;
|
if AValue = '' then Exit;
|
||||||
@ -857,10 +846,8 @@ begin
|
|||||||
for i := 0 to lStrings.Count-1 do
|
for i := 0 to lStrings.Count-1 do
|
||||||
begin
|
begin
|
||||||
lStr := lStrings.Strings[i];
|
lStr := lStrings.Strings[i];
|
||||||
lPosEqual := Pos(':', lStr);
|
SeparateStringInTwo(lStr, ':', lStyleKeyStr, lStyleValueStr);
|
||||||
lStyleKeyStr := Copy(lStr, 0, lPosEqual-1);
|
|
||||||
lStyleKeyStr := LowerCase(Trim(lStyleKeyStr));
|
lStyleKeyStr := LowerCase(Trim(lStyleKeyStr));
|
||||||
lStyleValueStr := Copy(lStr, lPosEqual+1, Length(lStr));
|
|
||||||
lStyleValueStr := Trim(lStyleValueStr);
|
lStyleValueStr := Trim(lStyleValueStr);
|
||||||
if ADestEntity <> nil then
|
if ADestEntity <> nil then
|
||||||
begin
|
begin
|
||||||
@ -875,11 +862,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
if ADestStyle <> nil then
|
if ADestStyle <> nil then
|
||||||
begin
|
begin
|
||||||
{ReadSVGPenStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, ADestEntity);
|
Result += ReadSVGPenStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, nil, ADestStyle);
|
||||||
ReadSVGGeneralStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, ADestEntity);
|
//Result += ReadSVGGeneralStyleWithKeyAndValue(AData, lStyleKeyStr, lStyleValueStr, nil, ADestStyle);
|
||||||
Result := Result + ReadSVGPenStyleWithKeyAndValue('stroke', lStyleValueStr, ADestEntity)}
|
if AUseFillAsPen and (lStyleKeyStr = 'fill') then
|
||||||
Result := Result + ReadSVGFontStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, nil, ADestStyle);
|
Result += ReadSVGPenStyleWithKeyAndValue('stroke', lStyleValueStr, nil, ADestStyle);
|
||||||
//Result := Result + ReadSVGBrushStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, ADestEntity as TvEntityWithPenAndBrush);
|
Result += ReadSVGFontStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, nil, ADestStyle);
|
||||||
|
Result += ReadSVGBrushStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, nil, ADestStyle);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
@ -893,7 +881,7 @@ function TvSVGVectorialReader.ReadSVGStyleToStyleLists(AValue: string;
|
|||||||
var
|
var
|
||||||
lStr, lStyleKeyStr, lStyleValueStr: String;
|
lStr, lStyleKeyStr, lStyleValueStr: String;
|
||||||
lStrings: TStringList;
|
lStrings: TStringList;
|
||||||
i, lPosEqual: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := [];
|
Result := [];
|
||||||
if AValue = '' then Exit;
|
if AValue = '' then Exit;
|
||||||
@ -906,9 +894,7 @@ begin
|
|||||||
for i := 0 to lStrings.Count-1 do
|
for i := 0 to lStrings.Count-1 do
|
||||||
begin
|
begin
|
||||||
lStr := lStrings.Strings[i];
|
lStr := lStrings.Strings[i];
|
||||||
lPosEqual := Pos(':', lStr);
|
SeparateStringInTwo(lStr, ':', lStyleKeyStr, lStyleValueStr);
|
||||||
lStyleKeyStr := Copy(lStr, 0, lPosEqual-1);
|
|
||||||
lStyleValueStr := Copy(lStr, lPosEqual+1, Length(lStr));
|
|
||||||
AStyleKeys.Add(lStyleKeyStr);
|
AStyleKeys.Add(lStyleKeyStr);
|
||||||
AStyleValues.Add(lStyleValueStr);
|
AStyleValues.Add(lStyleValueStr);
|
||||||
end;
|
end;
|
||||||
@ -918,33 +904,58 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TvSVGVectorialReader.ReadSVGPenStyleWithKeyAndValue(AKey,
|
function TvSVGVectorialReader.ReadSVGPenStyleWithKeyAndValue(AKey,
|
||||||
AValue: string; ADestEntity: TvEntityWithPen): TvSetPenBrushAndFontElements;
|
AValue: string; ADestEntity: TvEntityWithPen; ADestStyle: TvStyle = nil): TvSetPenBrushAndFontElements;
|
||||||
var
|
var
|
||||||
OldAlpha: Word;
|
OldAlpha: Word;
|
||||||
|
lValueInt: Int64;
|
||||||
begin
|
begin
|
||||||
Result := [];
|
Result := [];
|
||||||
if AKey = 'stroke' then
|
if AKey = 'stroke' then
|
||||||
begin
|
begin
|
||||||
// We store and restore the old alpha to support the "-opacity" element
|
// We store and restore the old alpha to support the "-opacity" element
|
||||||
OldAlpha := ADestEntity.Pen.Color.Alpha;
|
if ADestEntity <> nil then
|
||||||
if ADestEntity.Pen.Style = psClear then ADestEntity.Pen.Style := psSolid;
|
begin
|
||||||
|
OldAlpha := ADestEntity.Pen.Color.Alpha;
|
||||||
|
if ADestEntity.Pen.Style = psClear then ADestEntity.Pen.Style := psSolid;
|
||||||
|
end;
|
||||||
|
if ADestStyle <> nil then
|
||||||
|
begin
|
||||||
|
OldAlpha := ADestStyle.Pen.Color.Alpha;
|
||||||
|
if ADestStyle.Pen.Style = psClear then ADestStyle.Pen.Style := psSolid;
|
||||||
|
end;
|
||||||
|
|
||||||
if AValue = 'none' then ADestEntity.Pen.Style := fpcanvas.psClear
|
if AValue = 'none' then
|
||||||
|
begin
|
||||||
|
if ADestEntity <> nil then ADestEntity.Pen.Style := fpcanvas.psClear;
|
||||||
|
if ADestStyle <> nil then ADestStyle.Pen.Style := fpcanvas.psClear;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
ADestEntity.Pen.Color := ReadSVGColor(AValue);
|
if ADestEntity <> nil then
|
||||||
ADestEntity.Pen.Color.Alpha := OldAlpha;
|
begin
|
||||||
|
ADestEntity.Pen.Color := ReadSVGColor(AValue);
|
||||||
|
ADestEntity.Pen.Color.Alpha := OldAlpha;
|
||||||
|
end;
|
||||||
|
if ADestStyle <> nil then
|
||||||
|
begin
|
||||||
|
ADestStyle.Pen.Color := ReadSVGColor(AValue);
|
||||||
|
ADestStyle.Pen.Color.Alpha := OldAlpha;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
Result := Result + [spbfPenColor, spbfPenStyle];
|
Result := Result + [spbfPenColor, spbfPenStyle];
|
||||||
end
|
end
|
||||||
else if AKey = 'stroke-width' then
|
else if AKey = 'stroke-width' then
|
||||||
begin
|
begin
|
||||||
ADestEntity.Pen.Width := Round(StringWithUnitToFloat(AValue, sckXSize));
|
lValueInt := Round(StringWithUnitToFloat(AValue, sckXSize));
|
||||||
|
if ADestEntity <> nil then ADestEntity.Pen.Width := lValueInt;
|
||||||
|
if ADestStyle <> nil then ADestStyle.Pen.Width := lValueInt;
|
||||||
Result := Result + [spbfPenWidth];
|
Result := Result + [spbfPenWidth];
|
||||||
end
|
end
|
||||||
else if AKey = 'stroke-opacity' then
|
else if AKey = 'stroke-opacity' then
|
||||||
begin
|
begin
|
||||||
ADestEntity.Pen.Color.Alpha := Round(StrToFloat(AValue, FPointSeparator)*$FFFF);
|
lValueInt := Round(StrToFloat(AValue, FPointSeparator)*$FFFF);
|
||||||
|
if ADestEntity <> nil then ADestEntity.Pen.Color.Alpha := lValueInt;
|
||||||
|
if ADestStyle <> nil then ADestStyle.Pen.Color.Alpha := lValueInt;
|
||||||
end
|
end
|
||||||
else if AKey = 'stroke-linecap' then
|
else if AKey = 'stroke-linecap' then
|
||||||
begin
|
begin
|
||||||
@ -959,7 +970,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TvSVGVectorialReader.ReadSVGBrushStyleWithKeyAndValue(AKey,
|
function TvSVGVectorialReader.ReadSVGBrushStyleWithKeyAndValue(AKey,
|
||||||
AValue: string; ADestEntity: TvEntityWithPenAndBrush): TvSetPenBrushAndFontElements;
|
AValue: string; ADestEntity: TvEntityWithPenAndBrush; ADestStyle: TvStyle = nil): TvSetPenBrushAndFontElements;
|
||||||
var
|
var
|
||||||
OldAlpha: Word;
|
OldAlpha: Word;
|
||||||
Len: Integer;
|
Len: Integer;
|
||||||
@ -987,14 +998,34 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// We store and restore the old alpha to support the "-opacity" element
|
// We store and restore the old alpha to support the "-opacity" element
|
||||||
OldAlpha := ADestEntity.Brush.Color.Alpha;
|
if ADestEntity <> nil then
|
||||||
if ADestEntity.Brush.Style = bsClear then ADestEntity.Brush.Style := bsSolid;
|
begin
|
||||||
|
OldAlpha := ADestEntity.Brush.Color.Alpha;
|
||||||
|
if ADestEntity.Brush.Style = bsClear then ADestEntity.Brush.Style := bsSolid;
|
||||||
|
end;
|
||||||
|
if ADestStyle <> nil then
|
||||||
|
begin
|
||||||
|
OldAlpha := ADestStyle.Brush.Color.Alpha;
|
||||||
|
if ADestStyle.Brush.Style = bsClear then ADestStyle.Brush.Style := bsSolid;
|
||||||
|
end;
|
||||||
|
|
||||||
if AValue = 'none' then ADestEntity.Brush.Style := fpcanvas.bsClear
|
if AValue = 'none' then
|
||||||
|
begin
|
||||||
|
if ADestEntity <> nil then ADestEntity.Brush.Style := fpcanvas.bsClear;
|
||||||
|
if ADestStyle <> nil then ADestStyle.Brush.Style := fpcanvas.bsClear;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
ADestEntity.Brush.Color := ReadSVGColor(AValue);
|
if ADestEntity <> nil then
|
||||||
ADestEntity.Brush.Color.Alpha := OldAlpha;
|
begin
|
||||||
|
ADestEntity.Brush.Color := ReadSVGColor(AValue);
|
||||||
|
ADestEntity.Brush.Color.Alpha := OldAlpha;
|
||||||
|
end;
|
||||||
|
if ADestStyle <> nil then
|
||||||
|
begin
|
||||||
|
ADestStyle.Brush.Color := ReadSVGColor(AValue);
|
||||||
|
ADestStyle.Brush.Color.Alpha := OldAlpha;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := Result + [spbfBrushColor, spbfBrushStyle];
|
Result := Result + [spbfBrushColor, spbfBrushStyle];
|
||||||
@ -1303,8 +1334,25 @@ end;
|
|||||||
|
|
||||||
procedure TvSVGVectorialReader.ApplyCSSClass(AData: TvVectorialPage;
|
procedure TvSVGVectorialReader.ApplyCSSClass(AData: TvVectorialPage;
|
||||||
AValue: string; ADestEntity: TvEntityWithPen);
|
AValue: string; ADestEntity: TvEntityWithPen);
|
||||||
|
var
|
||||||
|
i, j: Integer;
|
||||||
|
lCurStyle: TSVG_CSS_Style;
|
||||||
|
lAllClasses: T10Strings;
|
||||||
begin
|
begin
|
||||||
|
lAllClasses := SeparateString(AValue, ' ');
|
||||||
|
for i := 0 to High(lAllClasses)-1 do
|
||||||
|
begin
|
||||||
|
if lAllClasses[i] = '' then Break;
|
||||||
|
for j := 0 to FCSSDefs.Count-1 do
|
||||||
|
begin
|
||||||
|
lCurStyle := TSVG_CSS_Style(FCSSDefs.Items[j]);
|
||||||
|
if lCurStyle.MatchesClass(lAllClasses[i]) then
|
||||||
|
begin
|
||||||
|
lCurStyle.ApplyIntoEntity(ADestEntity);
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TvSVGVectorialReader.IsEntityStyleField(AFieldName: string): Boolean;
|
function TvSVGVectorialReader.IsEntityStyleField(AFieldName: string): Boolean;
|
||||||
@ -1483,7 +1531,7 @@ begin
|
|||||||
lCurStyle.CSSName := Trim(lCurName);
|
lCurStyle.CSSName := Trim(lCurName);
|
||||||
lCurStyle.CSSData := Trim(lCurData);
|
lCurStyle.CSSData := Trim(lCurData);
|
||||||
FCSSDefs.Add(lCurStyle);
|
FCSSDefs.Add(lCurStyle);
|
||||||
lCurStyle.ParseCSSData();
|
lCurStyle.ParseCSSData(Self);
|
||||||
lParserState := 0;
|
lParserState := 0;
|
||||||
lCurName := '';
|
lCurName := '';
|
||||||
lCurData := '';
|
lCurData := '';
|
||||||
|
Loading…
Reference in New Issue
Block a user