fpvectorial: svg - improves text span and viewbox support, now text already shows in text_test_1.svg

git-svn-id: trunk@44392 -
This commit is contained in:
sekelsenmat 2014-03-10 06:32:43 +00:00
parent 91b0b4fb35
commit 68648a037f
2 changed files with 70 additions and 24 deletions

View File

@ -149,9 +149,7 @@ type
spbfFontColor, spbfFontSize, spbfFontName, spbfFontBold, spbfFontItalic, spbfFontColor, spbfFontSize, spbfFontName, spbfFontBold, spbfFontItalic,
spbfFontUnderline, spbfFontStrikeThrough, spbfAlignment, spbfFontUnderline, spbfFontStrikeThrough, spbfAlignment,
// Page style // Page style
sseMarginTop, sseMarginBottom, sseMarginLeft, sseMarginRight, sseMarginTop, sseMarginBottom, sseMarginLeft, sseMarginRight
// Positioning
ssePosition
); );
TvSetStyleElements = set of TvSetStyleElement; TvSetStyleElements = set of TvSetStyleElement;
@ -170,6 +168,9 @@ type
{ TvStyle } { TvStyle }
TvStyle = class TvStyle = class
protected
FExtraDebugStr: string;
public
Name: string; Name: string;
Parent: TvStyle; // Can be nil Parent: TvStyle; // Can be nil
Kind: TvStyleKind; Kind: TvStyleKind;
@ -182,17 +183,15 @@ type
// Page style // Page style
MarginTop, MarginBottom, MarginLeft, MarginRight: Double; // in mm MarginTop, MarginBottom, MarginLeft, MarginRight: Double; // in mm
SuppressSpacingBetweenSameParagraphs : Boolean; SuppressSpacingBetweenSameParagraphs : Boolean;
// Positioning
X, Y: Double;
// //
SetElements: TvSetStyleElements; SetElements: TvSetStyleElements;
// //
Constructor Create; Constructor Create;
function GetKind: TvStyleKind; // takes care of parenting function GetKind: TvStyleKind; // takes care of parenting
procedure Clear(); procedure Clear(); virtual;
procedure CopyFrom(AFrom: TvStyle); procedure CopyFrom(AFrom: TvStyle);
procedure ApplyOver(AFrom: TvStyle); procedure ApplyOver(AFrom: TvStyle); virtual;
function CreateStyleCombinedWithParent: TvStyle; function CreateStyleCombinedWithParent: TvStyle;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; virtual; function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; virtual;
end; end;
@ -1757,9 +1756,7 @@ begin
[Self.ClassName, Name, lParentName]); [Self.ClassName, Name, lParentName]);
if spbfPenColor in SetElements then if spbfPenColor in SetElements then
begin
lStr := lStr + Format('Pen.Color==%s', [TvEntity.GenerateDebugStrForFPColor(Pen.Color)]); lStr := lStr + Format('Pen.Color==%s', [TvEntity.GenerateDebugStrForFPColor(Pen.Color)]);
end;
{ // Pen, Brush and Font { // Pen, Brush and Font
spbfPenColor, spbfPenStyle, spbfPenWidth, spbfPenColor, spbfPenStyle, spbfPenWidth,
spbfBrushColor, spbfBrushStyle, spbfBrushGradient, spbfBrushColor, spbfBrushStyle, spbfBrushGradient,
@ -1777,6 +1774,7 @@ begin
BoolToStr(Font.Underline), BoolToStr(Font.Underline),
BoolToStr(Font.StrikeThrough), BoolToStr(Font.StrikeThrough),
GetEnumName(TypeInfo(TvTextAnchor), integer(TextAnchor))} GetEnumName(TypeInfo(TvTextAnchor), integer(TextAnchor))}
lStr := lStr + FExtraDebugStr;
Result := ADestRoutine(lStr, APageItem); Result := ADestRoutine(lStr, APageItem);
end; end;

View File

@ -55,6 +55,15 @@ type
function GetList: TList; function GetList: TList;
end; end;
{ TSVGTextSpanStyle }
TSVGTextSpanStyle = class(TvStyle)
public
PositionSet: Boolean;
X, Y: Double;
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
end;
{ TSVGPathTokenizer } { TSVGPathTokenizer }
TSVGPathTokenizer = class TSVGPathTokenizer = class
@ -70,6 +79,8 @@ type
function DebugOutTokensAsString: string; function DebugOutTokensAsString: string;
end; end;
TSVGCoordinateKind = (sckUnknown, sckX, sckY);
{ TvSVGVectorialReader } { TvSVGVectorialReader }
TvSVGVectorialReader = class(TvCustomVectorialReader) TvSVGVectorialReader = class(TvCustomVectorialReader)
@ -77,6 +88,9 @@ type
FPointSeparator, FCommaSeparator: TFormatSettings; FPointSeparator, FCommaSeparator: TFormatSettings;
FSVGPathTokenizer: TSVGPathTokenizer; FSVGPathTokenizer: TSVGPathTokenizer;
FLayerStylesKeys, FLayerStylesValues: TFPList; // of TStringList; FLayerStylesKeys, FLayerStylesValues: TFPList; // of TStringList;
// View box adjustment
ViewBoxAdjustment: Boolean;
ViewBox_Width, ViewBox_Height, Page_Width, Page_Height: Double;
// Defs section // Defs section
FBrushDefs: TFPList; // of TvEntityWithPenAndBrush; FBrushDefs: TFPList; // of TvEntityWithPenAndBrush;
// debug symbols // debug symbols
@ -113,7 +127,7 @@ type
function ReadTextFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity; function ReadTextFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
function ReadUseFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity; function ReadUseFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
// //
function StringWithUnitToFloat(AStr: string): Double; function StringWithUnitToFloat(AStr: string; ACoordKind: TSVGCoordinateKind = sckUnknown): Double;
function StringFloatZeroToOneToWord(AStr: string): Word; function StringFloatZeroToOneToWord(AStr: string): Word;
procedure ConvertSVGCoordinatesToFPVCoordinates( procedure ConvertSVGCoordinatesToFPVCoordinates(
const AData: TvVectorialPage; const AData: TvVectorialPage;
@ -145,6 +159,17 @@ const
FLOAT_MILIMETERS_PER_PIXEL = 5*0.2822; // DPI 90 = 1 / 90 inches per pixel => Actually I changed the value by this factor! Because otherwise it looks ugly! FLOAT_MILIMETERS_PER_PIXEL = 5*0.2822; // DPI 90 = 1 / 90 inches per pixel => Actually I changed the value by this factor! Because otherwise it looks ugly!
FLOAT_PIXELS_PER_MILIMETER = 1 / FLOAT_MILIMETERS_PER_PIXEL; // DPI 90 = 1 / 90 inches per pixel FLOAT_PIXELS_PER_MILIMETER = 1 / FLOAT_MILIMETERS_PER_PIXEL; // DPI 90 = 1 / 90 inches per pixel
{ TSVGTextSpanStyle }
function TSVGTextSpanStyle.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
APageItem: Pointer): Pointer;
begin
FExtraDebugStr := '';
if PositionSet then
FExtraDebugStr := FExtraDebugStr + Format(' X=%f Y=%f', [X, Y]);
Result:=inherited GenerateDebugTree(ADestRoutine, APageItem);
end;
{ TSVGObjectStack } { TSVGObjectStack }
function TSVGObjectStack.GetList: TList; function TSVGObjectStack.GetList: TList;
@ -2319,8 +2344,8 @@ var
lx, ly: double; lx, ly: double;
lText: TvText; lText: TvText;
lParagraph: TvParagraph; lParagraph: TvParagraph;
lTextSpanStack: TSVGObjectStack; lTextSpanStack: TSVGObjectStack; // of TSVGTextSpanStyle
lCurStyle: TvStyle; lCurStyle: TSVGTextSpanStyle;
i: Integer; i: Integer;
lNodeName, lNodeValue: DOMString; lNodeName, lNodeValue: DOMString;
@ -2330,9 +2355,14 @@ var
begin begin
for j := 0 to lTextSpanStack.GetList().Count-1 do for j := 0 to lTextSpanStack.GetList().Count-1 do
begin begin
lCurStyle := TvStyle(lTextSpanStack.GetList().Items[j]); lCurStyle := TSVGTextSpanStyle(lTextSpanStack.GetList().Items[j]);
if ADest.Style = nil then ADest.Style := TvStyle.Create; if ADest.Style = nil then ADest.Style := TvStyle.Create;
ADest.Style.ApplyOver(lCurStyle); ADest.Style.ApplyOver(lCurStyle);
if lCurStyle.PositionSet then
begin
ADest.X := ADest.X + lCurStyle.X; // or substitute completely ?
ADest.Y := ADest.Y + lCurStyle.Y;
end;
end; end;
end; end;
@ -2350,7 +2380,7 @@ var
if lNodeName = 'tspan' then if lNodeName = 'tspan' then
begin begin
lCurStyle := TvStyle.Create; lCurStyle := TSVGTextSpanStyle.Create;
lTextSpanStack.Push(lCurStyle); lTextSpanStack.Push(lCurStyle);
// read the attributes // read the attributes
@ -2360,13 +2390,13 @@ var
lNodeValue := lCurNode.Attributes.Item[j].NodeValue; lNodeValue := lCurNode.Attributes.Item[j].NodeValue;
if lNodeName = 'x' then if lNodeName = 'x' then
begin begin
Include(lCurStyle.SetElements, ssePosition); lCurStyle.PositionSet := True;
lCurStyle.X := StringWithUnitToFloat(lNodeValue) lCurStyle.X := StringWithUnitToFloat(lNodeValue, sckX)
end end
else if lNodeName = 'y' then else if lNodeName = 'y' then
begin begin
Include(lCurStyle.SetElements, ssePosition); lCurStyle.PositionSet := True;
lCurStyle.Y := StringWithUnitToFloat(lNodeValue) lCurStyle.Y := StringWithUnitToFloat(lNodeValue, sckY)
end end
//else if lNodeName = 'id' then //else if lNodeName = 'id' then
// lText.Name := lNodeValue // lText.Name := lNodeValue
@ -2417,9 +2447,9 @@ begin
lNodeName := ANode.Attributes.Item[i].NodeName; lNodeName := ANode.Attributes.Item[i].NodeName;
lNodeValue := ANode.Attributes.Item[i].NodeValue; lNodeValue := ANode.Attributes.Item[i].NodeValue;
if lNodeName = 'x' then if lNodeName = 'x' then
lx := lx + StringWithUnitToFloat(lNodeValue) lx := lx + StringWithUnitToFloat(lNodeValue, sckX)
else if lNodeName = 'y' then else if lNodeName = 'y' then
ly := ly + StringWithUnitToFloat(lNodeValue) ly := ly + StringWithUnitToFloat(lNodeValue, sckY)
else if lNodeName = 'id' then else if lNodeName = 'id' then
lText.Name := lNodeValue lText.Name := lNodeValue
else if lNodeName = 'style' then else if lNodeName = 'style' then
@ -2512,7 +2542,7 @@ begin
Result := lInsert; Result := lInsert;
end; end;
function TvSVGVectorialReader.StringWithUnitToFloat(AStr: string): Double; function TvSVGVectorialReader.StringWithUnitToFloat(AStr: string; ACoordKind: TSVGCoordinateKind = sckUnknown): Double;
var var
UnitStr, ValueStr: string; UnitStr, ValueStr: string;
Len: Integer; Len: Integer;
@ -2552,6 +2582,10 @@ begin
else // If there is no unit, just use StrToFloat else // If there is no unit, just use StrToFloat
begin begin
Result := StrToFloat(AStr, FPointSeparator); Result := StrToFloat(AStr, FPointSeparator);
if ViewBoxAdjustment and (ACoordKind = sckX) then
Result := Result * Page_Width / ViewBox_Width;
if ViewBoxAdjustment and (ACoordKind = sckY) then
Result := Result * Page_Height / ViewBox_Height;
end; end;
end; end;
@ -2693,6 +2727,7 @@ var
lx, ly, lx2, ly2: Double; lx, ly, lx2, ly2: Double;
begin begin
FPathNumber := 0; FPathNumber := 0;
ViewBoxAdjustment := False;
// ---------------- // ----------------
// Read the properties of the <svg> tag // Read the properties of the <svg> tag
@ -2704,6 +2739,8 @@ begin
lDocNeedsSizeAutoDetection := False; lDocNeedsSizeAutoDetection := False;
AData.Height := StringWithUnitToFloat(lStr); AData.Height := StringWithUnitToFloat(lStr);
end; end;
Page_Width := AData.Width;
Page_Height := AData.Height;
{$ifdef SVG_MERGE_LAYER_STYLES} {$ifdef SVG_MERGE_LAYER_STYLES}
FLayerStylesKeys.Clear; FLayerStylesKeys.Clear;
@ -2721,9 +2758,20 @@ begin
if lNodeName = 'viewBox' then if lNodeName = 'viewBox' then
begin begin
lViewBox := ReadSpaceSeparatedFloats(lNodeValue, ''); lViewBox := ReadSpaceSeparatedFloats(lNodeValue, '');
if lDocNeedsSizeAutoDetection then // Has only ViewBox
begin
lDocNeedsSizeAutoDetection := False; lDocNeedsSizeAutoDetection := False;
AData.Width := lViewBox[2] - lViewBox[0]; AData.Width := lViewBox[2] - lViewBox[0];
AData.Height := lViewBox[3] - lViewBox[1]; AData.Height := lViewBox[3] - lViewBox[1];
ViewBox_Width := 0;
ViewBox_Height := 0;
end
else // Has both viewBox and width/height!
begin
ViewBox_Width := lViewBox[2] - lViewBox[0];
ViewBox_Height := lViewBox[3] - lViewBox[1];
ViewBoxAdjustment := True;
end;
end end
else if lNodeName = 'style' then else if lNodeName = 'style' then
begin begin