mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-23 04:39:36 +02:00
Merged revision(s) 51232 #d593e000f8, 51257 #804a4b285a, 51262 #094f14ccb8, 51297 #cb29b6e05a from trunk:
fpvectorial: Supported rotated linear gradients. Support entity- and page-relative coordinates for gradient vectors. ........ fpvectorial: Support all linear gradients, translate and rotate for rectangles, circles, ellipses. ........ fpvectorial: Complete rotation and translation for all 2d segments of TPath ........ fpvectorial: Fix rendering of rotated text ........ git-svn-id: branches/fixes_1_6@51324 -
This commit is contained in:
parent
be08d09833
commit
18ead5d0f9
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,7 @@ type
|
||||
function FPColorToRGBHexString(AColor: TFPColor): string;
|
||||
function RGBToFPColor(AR, AG, AB: byte): TFPColor; inline;
|
||||
function MixColors(AColor1, AColor2: TFPColor; APos, AMax: Double): TFPColor;
|
||||
function GradientColor(AColors: TvGradientColors; AValue: Double): TFPColor;
|
||||
// Coordinate Conversion routines
|
||||
function CanvasCoordsToFPVectorial(AY: Integer; AHeight: Integer): Integer; inline;
|
||||
function CanvasTextPosToFPVectorial(AY: Integer; ACanvasHeight, ATextHeight: Integer): Integer;
|
||||
@ -49,7 +50,9 @@ function CoordToCanvasX(ACoord: Double; ADestX: Integer; AMulX: Double): Integer
|
||||
function CoordToCanvasY(ACoord: Double; ADestY: Integer; AMulY: Double): Integer; inline;
|
||||
// Other routines
|
||||
function SeparateString(AString: string; ASeparator: char): T10Strings;
|
||||
function Make3DPoint(AX, AY, AZ: Double): T3DPoint;
|
||||
function Make3DPoint(AX, AY, AZ: Double): T3DPoint; overload; inline;
|
||||
function Make3DPoint(AX, AY: Double): T3DPoint; overload; inline;
|
||||
function Point2D(AX, AY: Double): T2DPoint; inline;
|
||||
// Mathematical routines
|
||||
function LineEquation_GetPointAndTangentForLength(AStart, AEnd: T3DPoint; ADistance: Double; out AX, AY, ATangentAngle: Double): Boolean;
|
||||
procedure EllipticalArcToBezier(Xc, Yc, Rx, Ry, startAngle, endAngle: Double; var P1, P2, P3, P4: T3DPoint);
|
||||
@ -64,12 +67,15 @@ function BezierEquation_GetPointAndTangentForLength(P1, P2, P3, P4: T3DPoint;
|
||||
function CalcEllipseCenter(x1,y1, x2,y2, rx,ry, phi: Double; fa, fs: Boolean;
|
||||
out cx,cy, lambda: Double): Boolean;
|
||||
function CalcEllipsePointAngle(x,y, rx,ry, cx,cy, phi: Double): Double;
|
||||
procedure CalcEllipsePoint(angle, rx,ry, cx,cy, phi: Double; out x,y: Double);
|
||||
procedure CalcEllipsePoint(t, rx,ry, cx,cy, phi: Double; out x,y: Double);
|
||||
procedure ConvertPathToPolygons(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double;
|
||||
var PolygonPoints: TPointsArray; var PolygonStartIndexes: TIntegerDynArray);
|
||||
procedure ConvertPathToPoints(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double; var Points: TPointsArray);
|
||||
function GetLinePolygonIntersectionPoints(ACoord: Double;
|
||||
const APoints: T2DPointsArray; ACoordIsX: Boolean): T2DPointsArray;
|
||||
function Rotate2DPoint(P, RotCenter: TPoint; alpha:double): TPoint;
|
||||
function Rotate3DPointInXY(P, RotCenter: T3DPoint; alpha:double): T3DPoint;
|
||||
procedure NormalizeRect(var ARect: TRect);
|
||||
// Transformation matrix operations
|
||||
// See http://www.useragentman.com/blog/2011/01/07/css3-matrix-transform-for-the-mathematically-challenged/
|
||||
procedure ConvertTransformationMatrixToOperations(AA, AB, AC, AD, AE, AF: Double; out ATranslateX, ATranslateY, AScaleX, AScaleY, ASkewX, ASkewY, ARotate: Double);
|
||||
@ -115,12 +121,48 @@ begin
|
||||
Result.Alpha := $FFFF;
|
||||
end;
|
||||
|
||||
{@@ Returns AColor1 if APos = 0, AColor2 if APos = AMax, or interpolates between }
|
||||
function MixColors(AColor1, AColor2: TFPColor; APos, AMax: Double): TFPColor;
|
||||
var
|
||||
f1, f2: Double;
|
||||
begin
|
||||
Result.Alpha := Round(AColor1.Alpha * APos / AMax + AColor2.Alpha * (AMax - APos) / AMax);
|
||||
Result.Red := Round(AColor1.Red * APos / AMax + AColor2.Red * (AMax - APos) / AMax);
|
||||
Result.Green := Round(AColor1.Green * APos / AMax + AColor2.Green * (AMax - APos) / AMax);
|
||||
Result.Blue := Round(AColor1.Blue * APos / AMax + AColor2.Blue * (AMax - APos) / AMax);
|
||||
f1 := (AMax - APos) / AMax;
|
||||
f2 := APos / AMax;
|
||||
Result.Alpha := Round(AColor1.Alpha * f1 + AColor2.Alpha * f2);
|
||||
Result.Red := Round(AColor1.Red * f1 + AColor2.Red * f2);
|
||||
Result.Green := Round(AColor1.Green * f1 + AColor2.Green * f2);
|
||||
Result.Blue := Round(AColor1.Blue * f1 + AColor2.Blue * f2);
|
||||
end;
|
||||
|
||||
{@@ Assigns a color to the specified value. The color is interpolated between
|
||||
the colors defined in AColors.
|
||||
}
|
||||
function GradientColor(AColors: TvGradientColors; AValue: Double): TFPColor;
|
||||
var
|
||||
i: Integer;
|
||||
c1, c2: TFPColor;
|
||||
p1, p2: Double;
|
||||
begin
|
||||
// Return first color if AValue is below the first color position
|
||||
if AValue <= AColors[0].Position then
|
||||
Result := AColors[0].Color
|
||||
else
|
||||
// Return last color if AValue is above the last color position
|
||||
if AValue >= AColors[High(AColors)].Position then
|
||||
Result := AColors[High(AColors)].Color
|
||||
else
|
||||
// Find pair of colors positions which bracket the specified value and
|
||||
// interpolate color
|
||||
for i:= High(AColors)-1 downto 0 do
|
||||
if AValue >= AColors[i].Position then
|
||||
begin
|
||||
c1 := AColors[i].Color;
|
||||
c2 := AColors[i+1].Color;
|
||||
p1 := AColors[i].Position;
|
||||
p2 := AColors[i+1].Position;
|
||||
Result := MixColors(c1, c2, AValue - p1, p2 - p1);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ Converts the coordinate system from a TCanvas to FPVectorial
|
||||
@ -193,6 +235,12 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function Point2D(AX, AY: Double): T2DPoint;
|
||||
begin
|
||||
Result.X := AX;
|
||||
Result.Y := AY;
|
||||
end;
|
||||
|
||||
function Make3DPoint(AX, AY, AZ: Double): T3DPoint;
|
||||
begin
|
||||
Result.X := AX;
|
||||
@ -200,6 +248,13 @@ begin
|
||||
Result.Z := AZ;
|
||||
end;
|
||||
|
||||
function Make3DPoint(AX, AY: Double): T3DPoint;
|
||||
begin
|
||||
Result.X := AX;
|
||||
Result.Y := AY;
|
||||
Result.Z := 0;
|
||||
end;
|
||||
|
||||
{ Considering a counter-clockwise arc, elliptical and alligned to the axises
|
||||
|
||||
An elliptical Arc can be converted to
|
||||
@ -252,7 +307,8 @@ var
|
||||
lLineAngle: Double; // to X axis
|
||||
begin
|
||||
Result := False;
|
||||
lLineAngle := arctan((AEnd.Y-AStart.Y) / (AEnd.X - AStart.X));
|
||||
// lLineAngle := arctan((AEnd.Y-AStart.Y) / (AEnd.X - AStart.X));
|
||||
lLineAngle := arctan2(AEnd.Y - AStart.Y, AEnd.X - AStart.X);
|
||||
AX := AStart.X + ADistance * Cos(lLineAngle);
|
||||
AY := AStart.Y + ADistance * Sin(lLineAngle);
|
||||
end;
|
||||
@ -471,7 +527,7 @@ begin
|
||||
P := Rotate3dPointInXY(Make3dPoint(x-cx, y-cy, 0), Make3dPoint(0, 0, 0), phi);
|
||||
// Correctly speaking, above line should use -phi, instead of phi. But
|
||||
// Make3DPointInXY seems to define the angle in the opposite way.
|
||||
Result := arctan2(P.Y, P.X);
|
||||
Result := arctan2(P.Y/ry, P.X/rx);
|
||||
if Result < 0 then Result := TWO_PI + Result;
|
||||
end;
|
||||
|
||||
@ -479,18 +535,18 @@ end;
|
||||
parameters:
|
||||
- rx, ry: major and minor radius
|
||||
- phi: rotation angle of the ellipse (angle between major axis and x axis)
|
||||
- angle: angle from ellipse center between x axis and the point
|
||||
- t: angle between x axis and line from ellipse center to point
|
||||
|
||||
parameterized:
|
||||
x = Cx + RX*cos(t)*cos(phi) - RY*sin(t)*sin(phi) [1]
|
||||
y = Cy + RY*sin(t)*cos(phi) + RX*cos(t)*sin(phi) [2] }
|
||||
procedure CalcEllipsePoint(angle, rx,ry, cx,cy, phi: Double; out x,y: Double);
|
||||
x = cx + rx*cos(t)*cos(phi) - ry*sin(t)*sin(phi) [1]
|
||||
y = cy + ry*sin(t)*cos(phi) + rx*cos(t)*sin(phi) [2] }
|
||||
procedure CalcEllipsePoint(t, rx,ry, cx,cy, phi: Double; out x,y: Double);
|
||||
var
|
||||
P: T3dPoint;
|
||||
cost, sint: Extended;
|
||||
cosphi, sinphi: Extended;
|
||||
begin
|
||||
SinCos(angle, sint, cost);
|
||||
SinCos(t, sint, cost);
|
||||
SinCos(phi, sinphi, cosphi);
|
||||
x := cx + rx*cost*cosphi - ry*sint*sinphi;
|
||||
y := cy + ry*sint*cosphi + rx*cost*sinphi;
|
||||
@ -616,10 +672,10 @@ begin
|
||||
CoordX3 := CoordToCanvasX(Cur2DBSegment.X3, ADestX, AMulX);
|
||||
CoordY3 := CoordToCanvasY(Cur2DBSegment.Y3, ADestY, AMulY);
|
||||
AddBezierToPoints(
|
||||
Make2DPoint(CoordX, CoordY),
|
||||
Make2DPoint(CoordX2, CoordY2),
|
||||
Make2DPoint(CoordX3, CoordY3),
|
||||
Make2DPoint(CoordX4, CoordY4),
|
||||
Make3DPoint(CoordX, CoordY, 0),
|
||||
Make3DPoint(CoordX2, CoordY2, 0),
|
||||
Make3DPoint(CoordX3, CoordY3, 0),
|
||||
Make3DPoint(CoordX4, CoordY4, 0),
|
||||
Points);
|
||||
end;
|
||||
else
|
||||
@ -631,6 +687,77 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function CompareDbl(P1, P2: Pointer): Integer;
|
||||
var
|
||||
val1, val2: ^Double;
|
||||
begin
|
||||
val1 := P1;
|
||||
val2 := P2;
|
||||
Result := CompareValue(val1^, val2^);
|
||||
end;
|
||||
|
||||
{@@ Calculates the intersection points of a vertical (ACoordIsX = true) or
|
||||
horizontal (ACoordIsX = false) line with border of the polygon specified
|
||||
by APoints. Returns the coordinates of the intersection points }
|
||||
function GetLinePolygonIntersectionPoints(ACoord: Double;
|
||||
const APoints: T2DPointsArray; ACoordIsX: Boolean): T2DPointsArray;
|
||||
const
|
||||
EPS = 1e-9;
|
||||
var
|
||||
j: Integer;
|
||||
dx, dy: Double;
|
||||
xval, yval: Double;
|
||||
val: ^Double;
|
||||
list: TFPList;
|
||||
begin
|
||||
list := TFPList.Create;
|
||||
if ACoordIsX then
|
||||
begin
|
||||
for j:=0 to High(APoints) - 1 do
|
||||
begin
|
||||
if ((APoints[j].X <= ACoord) and (ACoord < APoints[j+1].X)) or
|
||||
((APoints[j+1].X <= ACoord) and (ACoord < APoints[j].X)) then
|
||||
begin
|
||||
dx := APoints[j+1].X - APoints[j].X; // can't be zero here
|
||||
dy := APoints[j+1].Y - APoints[j].Y;
|
||||
New(val);
|
||||
val^ := APoints[j].Y + (ACoord - APoints[j].X) * dy / dx;
|
||||
list.Add(val);
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
for j:=0 to High(APoints) - 1 do
|
||||
if ((APoints[j].Y <= ACoord) and (ACoord < APoints[j+1].Y)) or
|
||||
((APoints[j+1].Y <= ACoord) and (ACoord < APoints[j].Y)) then
|
||||
begin
|
||||
dy := APoints[j+1].Y - APoints[j].Y; // can't be zero here
|
||||
dx := APoints[j+1].X - APoints[j].X;
|
||||
New(val);
|
||||
val^ := APoints[j].X + (ACoord - APoints[j].Y) * dx / dy;
|
||||
list.Add(val);
|
||||
end;
|
||||
end;
|
||||
|
||||
// Sort intersection coordinates in ascending order
|
||||
list.Sort(@CompareDbl);
|
||||
SetLength(Result, list.Count);
|
||||
if ACoordIsX then
|
||||
for j:=0 to list.Count-1 do
|
||||
Result[j] := Point2D(ACoord, Double(list[j]^))
|
||||
else
|
||||
for j:=0 to list.Count-1 do
|
||||
Result[j] := Point2D(Double(list[j]^), ACoord);
|
||||
|
||||
// Clean-up
|
||||
for j:=list.Count-1 downto 0 do
|
||||
begin
|
||||
val := List[j];
|
||||
Dispose(val);
|
||||
end;
|
||||
list.Free;
|
||||
end;
|
||||
|
||||
// Rotates a point P around RotCenter
|
||||
function Rotate2DPoint(P, RotCenter: TPoint; alpha:double): TPoint;
|
||||
var
|
||||
@ -654,8 +781,27 @@ begin
|
||||
SinCos(alpha, sinus, cosinus);
|
||||
P.x := P.x - RotCenter.x;
|
||||
P.y := P.y - RotCenter.y;
|
||||
result.x := Round(p.x*cosinus + p.y*sinus) + RotCenter.x;
|
||||
result.y := Round(-p.x*sinus + p.y*cosinus) + RotCenter.y;
|
||||
result.x := Round( p.x*cosinus + p.y*sinus) + RotCenter.x;
|
||||
result.y := Round(-p.x*sinus + p.y*cosinus) + RotCenter.y;
|
||||
result.z := P.z;
|
||||
end;
|
||||
|
||||
procedure NormalizeRect(var ARect: TRect);
|
||||
var
|
||||
tmp: Integer;
|
||||
begin
|
||||
if ARect.Left > ARect.Right then
|
||||
begin
|
||||
tmp := ARect.Left;
|
||||
ARect.left := ARect.Right;
|
||||
ARect.Right := tmp;
|
||||
end;
|
||||
if ARect.Top > ARect.Bottom then
|
||||
begin
|
||||
tmp := ARect.Top;
|
||||
ARect.Top := ARect.Bottom;
|
||||
ARect.Bottom := tmp;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Current Transformation Matrix
|
||||
|
@ -100,15 +100,18 @@ type
|
||||
// debug symbols
|
||||
FPathNumber: Integer;
|
||||
function ReadSVGColor(AValue: string): TFPColor;
|
||||
function ReadSVGGradientColorStyle(AValue: STring): TFPColor;
|
||||
function ReadSVGStyle(AValue: string; ADestEntity: TvEntityWithPen; ADestStyle: TvStyle = nil; AUseFillAsPen: Boolean = False): TvSetPenBrushAndFontElements;
|
||||
function ReadSVGGradientColorStyle(AValue: String): TFPColor;
|
||||
function ReadSVGStyle(AData: TvVectorialPage; AValue: string;
|
||||
ADestEntity: TvEntityWithPen; ADestStyle: TvStyle = nil;
|
||||
AUseFillAsPen: Boolean = False): TvSetPenBrushAndFontElements;
|
||||
function ReadSVGStyleToStyleLists(AValue: string; AStyleKeys, AStyleValues: TStringList): TvSetPenBrushAndFontElements;
|
||||
function ReadSVGPenStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPen): TvSetPenBrushAndFontElements;
|
||||
function ReadSVGBrushStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenAndBrush): TvSetPenBrushAndFontElements;
|
||||
function ReadSVGFontStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntityWithPenBrushAndFont; ADestStyle: TvStyle = nil): TvSetPenBrushAndFontElements;
|
||||
function ReadSVGGeneralStyleWithKeyAndValue(AKey, AValue: string; ADestEntity: TvEntity): TvSetPenBrushAndFontElements;
|
||||
procedure ReadSVGGeneralStyleWithKeyAndValue(AData: TvVectorialPage;
|
||||
AKey, AValue: string; ADestEntity: TvEntity);
|
||||
function IsAttributeFromStyle(AStr: string): Boolean;
|
||||
procedure ApplyLayerStyles(ADestEntity: TvEntity);
|
||||
procedure ApplyLayerStyles(AData: TvVectorialPage; ADestEntity: TvEntity);
|
||||
function ReadSpaceSeparatedFloats(AInput: string; AOtherSeparators: string): TDoubleArray;
|
||||
procedure ReadSVGTransformationMatrix(AMatrix: string; out AA, AB, AC, AD, AE, AF: Double);
|
||||
//
|
||||
@ -137,6 +140,7 @@ type
|
||||
function StringWithUnitToFloat(AStr: string; ACoordKind: TSVGCoordinateKind = sckUnknown;
|
||||
ADefaultUnit: TSVGUnit = suPX; ATargetUnit: TSVGUnit = suPX): Double;
|
||||
function StringFloatZeroToOneToWord(AStr: string): Word;
|
||||
function StringWithPercentToFloat(AStr: String): Double;
|
||||
|
||||
procedure ConvertSVGCoordinatesToFPVCoordinates(
|
||||
const AData: TvVectorialPage;
|
||||
@ -173,8 +177,8 @@ const
|
||||
// 90 inches per pixel = (1 / 90) * 25.4 = 0.2822
|
||||
// FLOAT_MILIMETERS_PER_PIXEL = 0.3528; // DPI 72 = 1 / 72 inches per pixel
|
||||
|
||||
FLOAT_MILIMETERS_PER_PIXEL = 1; //0.2822; // DPI 90 = 1 / 90 inches per pixel => Actually I changed the value! Because otherwise it looks ugly!
|
||||
FLOAT_PIXELS_PER_MILIMETER = 1 / FLOAT_MILIMETERS_PER_PIXEL; // DPI 90 = 1 / 90 inches per pixel
|
||||
FLOAT_MILLIMETERS_PER_PIXEL = 1; //0.2822; // DPI 90 = 1 / 90 inches per pixel => Actually I changed the value! Because otherwise it looks ugly!
|
||||
FLOAT_PIXELS_PER_MILIMETER = 1 / FLOAT_MILLIMETERS_PER_PIXEL; // DPI 90 = 1 / 90 inches per pixel
|
||||
|
||||
FLOAT_POINTS_PER_PIXEL = 0.75; // For conversion
|
||||
FLOAT_PIXEL_PER_POINT = 1 / FLOAT_POINTS_PER_PIXEL; // For conversion
|
||||
@ -753,7 +757,7 @@ begin
|
||||
end;
|
||||
|
||||
// style="fill:none;stroke:black;stroke-width:3"
|
||||
function TvSVGVectorialReader.ReadSVGStyle(AValue: string;
|
||||
function TvSVGVectorialReader.ReadSVGStyle(AData: TvVectorialPage; AValue: string;
|
||||
ADestEntity: TvEntityWithPen; ADestStyle: TvStyle = nil;
|
||||
AUseFillAsPen: Boolean = False): TvSetPenBrushAndFontElements;
|
||||
var
|
||||
@ -781,7 +785,7 @@ begin
|
||||
if ADestEntity <> nil then
|
||||
begin
|
||||
ReadSVGPenStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, ADestEntity);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lStyleKeyStr, lStyleValueStr, ADestEntity);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lStyleKeyStr, lStyleValueStr, ADestEntity);
|
||||
if AUseFillAsPen and (lStyleKeyStr = 'fill') then
|
||||
Result := Result + ReadSVGPenStyleWithKeyAndValue('stroke', lStyleValueStr, ADestEntity)
|
||||
else if ADestEntity is TvText then
|
||||
@ -1031,8 +1035,8 @@ begin
|
||||
ADestStyle.SetElements := ADestStyle.SetElements + Result;
|
||||
end;
|
||||
|
||||
function TvSVGVectorialReader.ReadSVGGeneralStyleWithKeyAndValue(AKey,
|
||||
AValue: string; ADestEntity: TvEntity): TvSetPenBrushAndFontElements;
|
||||
procedure TvSVGVectorialReader.ReadSVGGeneralStyleWithKeyAndValue(AData: TvVectorialPage;
|
||||
AKey, AValue: string; ADestEntity: TvEntity);
|
||||
var
|
||||
// transform
|
||||
MA, MB, MC, MD, ME, MF: Double;
|
||||
@ -1087,7 +1091,17 @@ begin
|
||||
end
|
||||
else if lFunctionName = 'rotate' then
|
||||
begin
|
||||
ADestEntity.Rotate(lMatrixElements[0], Make3DPoint(0, 0, 0));
|
||||
lMRotate := -DegToRad(lMatrixElements[0]);
|
||||
// "-" because of orientation of svg coordinate system
|
||||
lMTranslateX := 0;
|
||||
lMTranslateY := 0;
|
||||
if Length(lMatrixElements) > 1 then
|
||||
lMTranslateX := lMatrixElements[1];
|
||||
if Length(lMatrixElements) > 2 then
|
||||
lMTranslateY := lMatrixElements[2];
|
||||
ConvertSVGCoordinatesToFPVCoordinates(AData,
|
||||
lMTranslateX, lMTranslateY, lMTranslateX, lMTranslateY);
|
||||
ADestEntity.Rotate(lMRotate, Make3DPoint(lMTranslateX, lMTranslateY));
|
||||
end;
|
||||
|
||||
Inc(i, 2);
|
||||
@ -1114,7 +1128,8 @@ begin
|
||||
(AStr = 'font-weight') or (AStr = 'text-anchor');
|
||||
end;
|
||||
|
||||
procedure TvSVGVectorialReader.ApplyLayerStyles(ADestEntity: TvEntity);
|
||||
procedure TvSVGVectorialReader.ApplyLayerStyles(AData: TvVectorialPage;
|
||||
ADestEntity: TvEntity);
|
||||
var
|
||||
lStringsKeys, lStringsValues: TStringList;
|
||||
i, j: Integer;
|
||||
@ -1137,7 +1152,7 @@ begin
|
||||
if ADestEntity is TvEntityWithPenBrushAndFont then
|
||||
ReadSVGFontStyleWithKeyAndValue(lCurKey, lCurValue, ADestEntity as TvEntityWithPenBrushAndFont);
|
||||
// transform
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lCurKey, lCurValue, ADestEntity);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lCurKey, lCurValue, ADestEntity);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -1235,7 +1250,7 @@ var
|
||||
lBrushEntity: TvEntityWithPenAndBrush;
|
||||
lCurEntity: TvEntity;
|
||||
lGradientColor: TvGradientColor;
|
||||
x1, x2, y1, y2: string;
|
||||
x1, y1, x2, y2: Double;
|
||||
begin
|
||||
lCurNode := ANode.FirstChild;
|
||||
while Assigned(lCurNode) do
|
||||
@ -1307,24 +1322,76 @@ begin
|
||||
lBrushEntity := TvEntityWithPenAndBrush.Create(nil);
|
||||
|
||||
// <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
x1 := 0;
|
||||
x2 := 0;
|
||||
y1 := 0;
|
||||
y2 := 0;
|
||||
for i := 0 to lCurNode.Attributes.Length - 1 do
|
||||
begin
|
||||
lAttrName := lCurNode.Attributes.Item[i].NodeName;
|
||||
lAttrValue := lCurNode.Attributes.Item[i].NodeValue;
|
||||
lAttrName := lowercase(lCurNode.Attributes.Item[i].NodeName);
|
||||
lAttrValue := lowercase(lCurNode.Attributes.Item[i].NodeValue);
|
||||
if lAttrName = 'id' then
|
||||
lBrushEntity.Name := lAttrValue
|
||||
else if lAttrName = 'x1' then
|
||||
x1 := lAttrValue
|
||||
else if lAttrName = 'x2' then
|
||||
x2 := lAttrValue
|
||||
else if lAttrName = 'y1' then
|
||||
y1 := lAttrValue
|
||||
else if lAttrName = 'y2' then
|
||||
y2 := lAttrValue;
|
||||
else
|
||||
if lAttrName = 'x1' then
|
||||
begin
|
||||
if lAttrValue[Length(lAttrValue)] = '%' then
|
||||
Include(lBrushEntity.Brush.Gradient_flags, gfRelStartX);
|
||||
x1 := StringWithPercentToFloat(lAttrValue);
|
||||
end else
|
||||
if lAttrName = 'x2' then
|
||||
begin
|
||||
if lAttrValue[Length(lAttrValue)] = '%' then
|
||||
Include(lBrushEntity.Brush.Gradient_flags, gfRelEndX);
|
||||
x2 := StringWithPercentToFloat(lAttrValue);
|
||||
end else
|
||||
if lAttrName = 'y1' then
|
||||
begin
|
||||
if lAttrValue[Length(lAttrValue)] = '%' then
|
||||
Include(lBrushEntity.Brush.Gradient_flags, gfRelStartY);
|
||||
y1 := StringWithPercentToFloat(lAttrValue);
|
||||
end else
|
||||
if lAttrName = 'y2' then
|
||||
begin
|
||||
if lAttrValue[Length(lAttrValue)] = '%' then
|
||||
Include(lBrushEntity.Brush.Gradient_flags, gfRelEndY);
|
||||
y2 := StringWithPercentToFloat(lAttrValue);
|
||||
end else
|
||||
if lAttrName = 'gradientunits' then
|
||||
begin
|
||||
if lAttrValue = 'userspaceonuse' then
|
||||
Include(lBrushEntity.Brush.Gradient_flags, gfRelToUserSpace)
|
||||
else if lAttrValue = 'objectboundingbox' then
|
||||
Exclude(lBrushEntity.Brush.Gradient_flags, gfRelToUserSpace);
|
||||
end;
|
||||
end;
|
||||
if x2 = x1 then
|
||||
lBrushEntity.Brush.Gradient_start.X := x1;
|
||||
lBrushEntity.Brush.Gradient_end.X := x2;
|
||||
lBrushEntity.Brush.Gradient_start.Y := y1;
|
||||
lBrushEntity.Brush.Gradient_end.Y := y2;
|
||||
ConvertSVGCoordinatesToFPVCoordinates(AData, x1, y1, x1, y1);
|
||||
ConvertSVGCoordinatesToFPVCoordinates(AData, x2, y2, x2, y2);
|
||||
if not (gfRelStartX in lBrushEntity.Brush.Gradient_flags) then
|
||||
lBrushEntity.Brush.Gradient_start.X := x1;
|
||||
if not (gfRelEndX in lBrushEntity.Brush.Gradient_flags) then
|
||||
lBrushEntity.Brush.Gradient_end.X := x2;
|
||||
if not (gfRelStartY in lBrushEntity.Brush.Gradient_flags) then
|
||||
lBrushEntity.Brush.Gradient_start.Y := y1;
|
||||
if not (gfRelEndY in lBrushEntity.Brush.Gradient_flags) then
|
||||
lBrushEntity.Brush.Gradient_end.Y := y2;
|
||||
if (lBrushEntity.Brush.Gradient_start.X = 0) and
|
||||
(lBrushEntity.Brush.Gradient_start.Y = 0) and
|
||||
(lBrushEntity.Brush.Gradient_end.X = 0) and
|
||||
(lBrushEntity.Brush.Gradient_end.Y = 0) then
|
||||
begin
|
||||
lBrushEntity.Brush.Gradient_start.X := 0.0;
|
||||
lBrushEntity.Brush.Gradient_start.Y := 0.0;
|
||||
lBrushEntity.Brush.Gradient_end.X := 1.0;
|
||||
lBrushEntity.Brush.Gradient_end.Y := 1.0;
|
||||
end;
|
||||
if lBrushEntity.Brush.Gradient_start.X = lBrushEntity.Brush.Gradient_end.X then
|
||||
lBrushEntity.Brush.Kind := bkVerticalGradient
|
||||
else if y2=y1 then
|
||||
else if lBrushEntity.Brush.Gradient_start.Y = lBrushEntity.Brush.Gradient_end.Y then
|
||||
lBrushEntity.Brush.Kind := bkHorizontalGradient
|
||||
else
|
||||
lBrushEntity.Brush.Kind := bkOtherLinearGradient;
|
||||
@ -1341,7 +1408,8 @@ begin
|
||||
lAttrName := lCurSubNode.Attributes.Item[i].NodeName;
|
||||
lAttrValue := lCurSubNode.Attributes.Item[i].NodeValue;
|
||||
if lAttrName = 'offset' then
|
||||
lGradientColor.Position := StringWithUnitToFloat(lAttrValue)
|
||||
lGradientColor.Position := StringWithPercentToFloat(lAttrValue)
|
||||
// use as fraction 0..1
|
||||
else if lAttrName = 'style' then
|
||||
lGradientColor.Color := ReadSVGGradientColorStyle(lAttrValue)
|
||||
else if lAttrName = 'stop-color' then
|
||||
@ -1433,7 +1501,7 @@ end;
|
||||
function TvSVGVectorialReader.ReadCircleFromNode(ANode: TDOMNode;
|
||||
AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
|
||||
var
|
||||
cx, cy, cr, dtmp: double;
|
||||
cx, cy, cr, tmp: double;
|
||||
lCircle: TvCircle;
|
||||
i: Integer;
|
||||
lNodeName, lNodeValue: DOMString;
|
||||
@ -1448,7 +1516,7 @@ begin
|
||||
lCircle.Brush.Style := bsSolid;
|
||||
lCircle.Brush.Color := colBlack;
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lCircle);
|
||||
ApplyLayerStyles(AData, lCircle);
|
||||
|
||||
// read the attributes
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
@ -1456,27 +1524,36 @@ begin
|
||||
lNodeName := ANode.Attributes.Item[i].NodeName;
|
||||
lNodeValue := ANode.Attributes.Item[i].NodeValue;
|
||||
if lNodeName = 'cx' then
|
||||
cx := StringWithUnitToFloat(lNodeValue, sckX, suPX, suMM)
|
||||
cx := StringWithUnitToFloat(lNodeValue) //, sckX, suPX, suMM)
|
||||
else if lNodeName = 'cy' then
|
||||
cy := StringWithUnitToFloat(lNodeValue, sckY, suPX, suMM)
|
||||
cy := StringWithUnitToFloat(lNodeValue) //, sckY, suPX, suMM)
|
||||
else if lNodeName = 'r' then
|
||||
cr := StringWithUnitToFloat(lNodeValue, sckXSize, suPX, suMM)
|
||||
cr := StringWithUnitToFloat(lNodeValue) //, sckXSize, suPX, suMM)
|
||||
else if lNodeName = 'id' then
|
||||
lCircle.Name := lNodeValue
|
||||
else if lNodeName = 'style' then
|
||||
ReadSVGStyle(lNodeValue, lCircle)
|
||||
lCircle.Name := lNodeValue;
|
||||
end;
|
||||
|
||||
ConvertSVGCoordinatesToFPVCoordinates(AData, cx, cy, cx, cy);
|
||||
ConvertSVGSizeToFPVSize(AData, cr, cr, lCircle.Radius, tmp);
|
||||
lCircle.X := lCircle.X + cx;
|
||||
lCircle.Y := lCircle.Y + cy;
|
||||
|
||||
// Make sure that transformations are read after geometry and position
|
||||
// of cirlce is known.
|
||||
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(AData, lNodeValue, lCircle)
|
||||
else if IsAttributeFromStyle(lNodeName) then
|
||||
begin
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lCircle);
|
||||
ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lCircle);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lCircle);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName, lNodeValue, lCircle);
|
||||
end;
|
||||
end;
|
||||
|
||||
lCircle.X := lCircle.X + cx;
|
||||
lCircle.Y := lCircle.Y + cy;
|
||||
lCircle.Radius := lCircle.Radius + cr;
|
||||
|
||||
Result := lCircle;
|
||||
end;
|
||||
|
||||
@ -1499,7 +1576,7 @@ begin
|
||||
lEllipse.Brush.Style := bsSolid;
|
||||
lEllipse.Brush.Color := colBlack;
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lEllipse);
|
||||
ApplyLayerStyles(AData, lEllipse);
|
||||
|
||||
// read the attributes
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
@ -1515,22 +1592,28 @@ begin
|
||||
else if lNodeName = 'ry' then
|
||||
cry := StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'id' then
|
||||
lEllipse.Name := ANode.Attributes.Item[i].NodeValue
|
||||
else if lNodeName = 'style' then
|
||||
ReadSVGStyle(lNodeValue, lEllipse)
|
||||
lEllipse.Name := ANode.Attributes.Item[i].NodeValue;
|
||||
end;
|
||||
|
||||
ConvertSVGCoordinatesToFPVCoordinates(AData, cx, cy, lEllipse.X, lEllipse.Y);
|
||||
ConvertSVGSizeToFPVSize(AData, crx, cry, lEllipse.HorzHalfAxis, lEllipse.VertHalfAxis);
|
||||
|
||||
// Make sure that transformations are read after geometry and position
|
||||
// of ellipse is known.
|
||||
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(AData, lNodeValue, lEllipse)
|
||||
else if IsAttributeFromStyle(lNodeName) then
|
||||
begin
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lEllipse);
|
||||
ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lEllipse);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lEllipse);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName, lNodeValue, lEllipse);
|
||||
end;
|
||||
end;
|
||||
|
||||
ConvertSVGCoordinatesToFPVCoordinates(
|
||||
AData, cx, cy, lEllipse.X, lEllipse.Y);
|
||||
ConvertSVGDeltaToFPVDelta(
|
||||
AData, crx, cry, lEllipse.HorzHalfAxis, lEllipse.VertHalfAxis);
|
||||
|
||||
Result := lEllipse;
|
||||
end;
|
||||
|
||||
@ -1572,7 +1655,7 @@ begin
|
||||
lText := nil;//TvText.Create(nil);
|
||||
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lText);
|
||||
ApplyLayerStyles(AData, lText);
|
||||
|
||||
// read the attributes
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
@ -1584,7 +1667,7 @@ begin
|
||||
else if lNodeName = 'svg:y' then
|
||||
ly := ly + StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'draw:style-name' then
|
||||
ReadSVGStyle(lNodeValue, lText);
|
||||
ReadSVGStyle(AData, lNodeValue, lText);
|
||||
end;
|
||||
|
||||
// Get the text contents
|
||||
@ -1648,7 +1731,7 @@ begin
|
||||
lText := TvText.Create(nil);
|
||||
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lText);
|
||||
ApplyLayerStyles(AData, lText);
|
||||
|
||||
{// read the attributes
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
@ -1777,7 +1860,7 @@ begin
|
||||
begin
|
||||
//ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lImage);
|
||||
//ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lImage);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lImage);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName, lNodeValue, lImage);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1802,7 +1885,7 @@ begin
|
||||
lImage.Y := lImage.Y + lImage.Height / 2;
|
||||
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lImage);
|
||||
ApplyLayerStyles(AData, lImage);
|
||||
|
||||
Result := lImage;
|
||||
end;
|
||||
@ -1931,18 +2014,20 @@ begin
|
||||
lPath.Pen.Style := psClear;
|
||||
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lPath);
|
||||
ApplyLayerStyles(AData, lPath);
|
||||
|
||||
// Add the entity styles
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := ANode.Attributes.Item[i].NodeName;
|
||||
if lNodeName = 'style' then
|
||||
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lPath)
|
||||
ReadSVGStyle(AData, ANode.Attributes.Item[i].NodeValue, lPath)
|
||||
else if IsAttributeFromStyle(lNodeName) then
|
||||
begin
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
end;
|
||||
end;
|
||||
//
|
||||
@ -1975,7 +2060,7 @@ begin
|
||||
lPath.Brush.Color := colBlack;
|
||||
lPath.Brush.Style := bsClear;
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lPath);
|
||||
ApplyLayerStyles(AData, lPath);
|
||||
// Add the pen/brush/name
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
begin
|
||||
@ -1983,12 +2068,15 @@ begin
|
||||
if lNodeName = 'id' then
|
||||
lPath.Name := ANode.Attributes.Item[i].NodeValue
|
||||
else if lNodeName = 'style' then
|
||||
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lPath)
|
||||
ReadSVGStyle(AData, 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);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGBrushStyleWithKeyAndValue(lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -2459,7 +2547,7 @@ begin
|
||||
lPath.Brush.Style := bsClear;
|
||||
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lPath);
|
||||
ApplyLayerStyles(AData, lPath);
|
||||
|
||||
// now read the other attributes
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
@ -2468,12 +2556,15 @@ begin
|
||||
if lNodeName = 'id' then
|
||||
lPath.Name := ANode.Attributes.Item[i].NodeValue
|
||||
else if lNodeName = 'style' then
|
||||
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lPath)
|
||||
ReadSVGStyle(AData, 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);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGBrushStyleWithKeyAndValue(lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -2486,6 +2577,7 @@ var
|
||||
lRect: TvRectangle;
|
||||
i: Integer;
|
||||
lNodeName: DOMString;
|
||||
lNodeValue: String;
|
||||
begin
|
||||
lx := 0.0;
|
||||
ly := 0.0;
|
||||
@ -2500,45 +2592,53 @@ begin
|
||||
lRect.Brush.Style := bsSolid;
|
||||
lRect.Brush.Color := colBlack;
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lRect);
|
||||
ApplyLayerStyles(AData, lRect);
|
||||
|
||||
// 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(ANode.Attributes.Item[i].NodeValue)
|
||||
lx := StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'y' then
|
||||
ly := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
ly := StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'rx' then
|
||||
lrx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
lrx := StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'ry' then
|
||||
lry := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
lry := StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'width' then
|
||||
cx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
cx := StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'height' then
|
||||
cy := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
cy := StringWithUnitToFloat(lNodeValue)
|
||||
else if lNodeName = 'id' then
|
||||
lRect.Name := ANode.Attributes.Item[i].NodeValue
|
||||
else if lNodeName = 'style' then
|
||||
ReadSVGStyle(ANode.Attributes.Item[i].NodeValue, lRect)
|
||||
else if IsAttributeFromStyle(lNodeName) then
|
||||
begin
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lRect);
|
||||
ReadSVGBrushStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lRect);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, ANode.Attributes.Item[i].NodeValue, lRect);
|
||||
end;
|
||||
lRect.Name := lNodeValue;
|
||||
end;
|
||||
|
||||
ConvertSVGCoordinatesToFPVCoordinates(
|
||||
AData, lx, ly, lRect.X, lRect.Y);
|
||||
ConvertSVGSizeToFPVSize(
|
||||
AData, cx, cy, lRect.CX, lRect.CY);
|
||||
ConvertSVGSizeToFPVSize(
|
||||
AData, lrx, lry, lRect.RX, lRect.RY);
|
||||
ConvertSVGCoordinatesToFPVCoordinates(AData, lx, ly, lRect.X, lRect.Y);
|
||||
ConvertSVGSizeToFPVSize(AData, cx, cy, lRect.CX, lRect.CY);
|
||||
ConvertSVGSizeToFPVSize(AData, lrx, lry, lRect.RX, lRect.RY);
|
||||
lRect.RX := Abs(lRect.RX) * 2;
|
||||
lRect.RY := Abs(lRect.RY) * 2;
|
||||
|
||||
// Make sure that transformations are read after geometry and position
|
||||
// of rectangle is known.
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := ANode.Attributes.Item[i].NodeName;
|
||||
if lNodeName = 'style' then
|
||||
ReadSVGStyle(AData, lNodeValue, lRect)
|
||||
else if IsAttributeFromStyle(lNodeName) then
|
||||
begin
|
||||
ReadSVGPenStyleWithKeyAndValue(lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lRect);
|
||||
ReadSVGBrushStyleWithKeyAndValue(lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lRect);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName,
|
||||
ANode.Attributes.Item[i].NodeValue, lRect);
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := lRect;
|
||||
end;
|
||||
|
||||
@ -2627,12 +2727,13 @@ var
|
||||
|
||||
procedure ReadTextSpans(ACurNode: TDOMNode);
|
||||
var
|
||||
j: Integer;
|
||||
i,j: Integer;
|
||||
lCurNode: TDOMNode;
|
||||
lTextStr: string;
|
||||
lText: TvText;
|
||||
lCText: TvCurvedText;
|
||||
lInsertedEntity, lInsertedSubEntity: TvEntity;
|
||||
s: String;
|
||||
begin
|
||||
lCurNode := ACurNode.FirstChild;
|
||||
while lCurNode <> nil do
|
||||
@ -2714,25 +2815,23 @@ var
|
||||
end;
|
||||
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lCText);
|
||||
ApplyLayerStyles(AData, lCText);
|
||||
|
||||
// Apply the layer style
|
||||
ApplyStackStylesToText(lCText);
|
||||
end
|
||||
else
|
||||
if lNodeValue <> '' then
|
||||
begin
|
||||
lText := lParagraph.AddText(lNodeValue);
|
||||
|
||||
lText.Font.Size := 10;
|
||||
lText.Name := lName;
|
||||
// Apply the layer style
|
||||
ApplyLayerStyles(lText);
|
||||
|
||||
ApplyLayerStyles(AData, lText);
|
||||
// Apply the layer style
|
||||
ApplyStackStylesToText(lText);
|
||||
end;
|
||||
|
||||
|
||||
lCurNode := lCurNode.NextSibling;
|
||||
end;
|
||||
end;
|
||||
@ -2766,11 +2865,11 @@ begin
|
||||
lParagraph.Name := lName;
|
||||
end
|
||||
else if lNodeName = 'style' then
|
||||
ReadSVGStyle(lNodeValue, nil, lCurStyle)
|
||||
ReadSVGStyle(AData, lNodeValue, nil, lCurStyle)
|
||||
else if IsAttributeFromStyle(lNodeName) then
|
||||
begin
|
||||
ReadSVGFontStyleWithKeyAndValue(lNodeName, lNodeValue, nil, lCurStyle);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lParagraph);
|
||||
// ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName, lNodeValue, lParagraph);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2792,6 +2891,15 @@ begin
|
||||
// These other lines can be positioned, so they need to appear as independent TvText elements
|
||||
ReadTextSpans(ANode);
|
||||
|
||||
// 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 IsAttributeFromStyle(lNodeName) then
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName, lNodeValue, lParagraph);
|
||||
end;
|
||||
|
||||
// Finalization
|
||||
lCurObject := lTextSpanStack.Pop();
|
||||
if lCurObject <> nil then lCurObject.Free;
|
||||
@ -2849,14 +2957,14 @@ begin
|
||||
lNodeValue := ANode.Attributes.Item[i].NodeValue;
|
||||
if lNodeName = 'style' then
|
||||
begin
|
||||
ReadSVGStyle(lNodeValue, lInsert);
|
||||
ReadSVGStyle(AData, lNodeValue, lInsert);
|
||||
end
|
||||
else if IsAttributeFromStyle(lNodeName) then
|
||||
begin
|
||||
lInsert.SetElements += ReadSVGPenStyleWithKeyAndValue(lNodeName, lNodeValue, lInsert);
|
||||
lInsert.SetElements += ReadSVGBrushStyleWithKeyAndValue(lNodeName, lNodeValue, lInsert);
|
||||
lInsert.SetElements += ReadSVGFontStyleWithKeyAndValue(lNodeName, lNodeValue, lInsert);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(lNodeName, lNodeValue, lInsert);
|
||||
ReadSVGGeneralStyleWithKeyAndValue(AData, lNodeName, lNodeValue, lInsert);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2947,7 +3055,7 @@ var
|
||||
procedure DoProcessMM_End();
|
||||
begin
|
||||
if ATargetUnit = suPX then
|
||||
Result := Result / FLOAT_MILIMETERS_PER_PIXEL;
|
||||
Result := Result / FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
DoViewBoxAdjust();
|
||||
end;
|
||||
|
||||
@ -2955,7 +3063,7 @@ var
|
||||
begin
|
||||
Result := StrToFloat(ValueStr, FPointSeparator);
|
||||
case ATargetUnit of
|
||||
suMM: Result := Result * FLOAT_MILIMETERS_PER_PIXEL;
|
||||
suMM: Result := Result * FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
suPT: Result := Result * FLOAT_POINTS_PER_PIXEL;
|
||||
end;
|
||||
DoViewBoxAdjust();
|
||||
@ -3027,12 +3135,25 @@ begin
|
||||
Result := Round(StrToFloat(AStr, FPointSeparator) * $FFFF);
|
||||
end;
|
||||
|
||||
{@@ Converts a number string to a floating-point number. If the string has a
|
||||
% character at its end then it is removed, and the numerical value is
|
||||
divided by 100. }
|
||||
function TvSVGVectorialReader.StringWithPercentToFloat(AStr: String): Double;
|
||||
begin
|
||||
if AStr[Length(AStr)] = '%' then
|
||||
begin
|
||||
Delete(AStr, Length(AStr), 1);
|
||||
Result := 0.01 * StrToFloat(trim(AStr), FPointSeparator);
|
||||
end else
|
||||
Result := StrToFloat(AStr, FPointSeparator);
|
||||
end;
|
||||
|
||||
procedure TvSVGVectorialReader.ConvertSVGCoordinatesToFPVCoordinates(
|
||||
const AData: TvVectorialPage; const ASrcX, ASrcY: Double;
|
||||
var ADestX,ADestY: Double; ADoViewBoxAdjust: Boolean = True);
|
||||
begin
|
||||
ADestX := ASrcX * FLOAT_MILIMETERS_PER_PIXEL;
|
||||
ADestY := AData.Height - ASrcY * FLOAT_MILIMETERS_PER_PIXEL;
|
||||
ADestX := ASrcX * FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
ADestY := AData.Height - ASrcY * FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
if ViewBoxAdjustment and ADoViewBoxAdjust then
|
||||
begin
|
||||
ADestX := (ASrcX - ViewBox_Left) * Page_Width / ViewBox_Width;
|
||||
@ -3044,8 +3165,8 @@ procedure TvSVGVectorialReader.ConvertSVGDeltaToFPVDelta(
|
||||
const AData: TvVectorialPage; const ASrcX, ASrcY: Double; var ADestX,
|
||||
ADestY: Double; ADoViewBoxAdjust: Boolean = True);
|
||||
begin
|
||||
ADestX := ASrcX * FLOAT_MILIMETERS_PER_PIXEL;
|
||||
ADestY := - ASrcY * FLOAT_MILIMETERS_PER_PIXEL;
|
||||
ADestX := ASrcX * FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
ADestY := - ASrcY * FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
if ViewBoxAdjustment and ADoViewBoxAdjust then
|
||||
begin
|
||||
ADestX := ASrcX * Page_Width / ViewBox_Width;
|
||||
@ -3057,8 +3178,8 @@ procedure TvSVGVectorialReader.ConvertSVGSizeToFPVSize(
|
||||
const AData: TvVectorialPage; const ASrcX, ASrcY: Double; var ADestX,
|
||||
ADestY: Double; ADoViewBoxAdjust: Boolean = True);
|
||||
begin
|
||||
ADestX := ASrcX * FLOAT_MILIMETERS_PER_PIXEL;
|
||||
ADestY := ASrcY * FLOAT_MILIMETERS_PER_PIXEL;
|
||||
ADestX := ASrcX * FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
ADestY := ASrcY * FLOAT_MILLIMETERS_PER_PIXEL;
|
||||
if ViewBoxAdjustment and ADoViewBoxAdjust then
|
||||
begin
|
||||
ADestX := ASrcX * Page_Width / ViewBox_Width;
|
||||
|
Loading…
Reference in New Issue
Block a user