mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-22 19:59:37 +02:00
fpvectorial: Much improves the ODG reader, adding a lot of structural work for styles and page sizes and starts more entities
git-svn-id: trunk@39853 -
This commit is contained in:
parent
f3812f0464
commit
c30b0c2636
@ -114,7 +114,7 @@ type
|
||||
Bold: boolean;
|
||||
Italic: boolean;
|
||||
Underline: boolean;
|
||||
StrikeTrough: boolean;
|
||||
StrikeThrough: boolean;
|
||||
end;
|
||||
|
||||
{ Coordinates and polyline segments }
|
||||
@ -264,6 +264,7 @@ type
|
||||
Pen: TvPen;
|
||||
constructor Create; override;
|
||||
procedure ApplyPenToCanvas(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo);
|
||||
procedure AssignPen(APen: TvPen);
|
||||
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
|
||||
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||
end;
|
||||
@ -277,8 +278,10 @@ type
|
||||
Brush: TvBrush;
|
||||
constructor Create; override;
|
||||
procedure ApplyBrushToCanvas(ADest: TFPCustomCanvas);
|
||||
procedure AssignBrush(ABrush: TvBrush);
|
||||
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
|
||||
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
|
||||
end;
|
||||
|
||||
{ TvEntityWithPenBrushAndFont }
|
||||
@ -288,8 +291,10 @@ type
|
||||
Font: TvFont;
|
||||
constructor Create; override;
|
||||
procedure ApplyFontToCanvas(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; AMulX: Double = 1.0);
|
||||
procedure AssignFont(AFont: TvFont);
|
||||
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
|
||||
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
|
||||
function GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer; override;
|
||||
end;
|
||||
|
||||
TvClipMode = (vcmNonzeroWindingRule, vcmEvenOddRule);
|
||||
@ -1113,6 +1118,13 @@ begin
|
||||
ADest.Pen.Style := Pen.Style;
|
||||
end;
|
||||
|
||||
procedure TvEntityWithPen.AssignPen(APen: TvPen);
|
||||
begin
|
||||
Pen.Style := APen.Style;
|
||||
Pen.Color := APen.Color;
|
||||
Pen.Width := APen.Width;
|
||||
end;
|
||||
|
||||
procedure TvEntityWithPen.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer;
|
||||
ADestY: Integer; AMulX: Double; AMulY: Double);
|
||||
begin
|
||||
@ -1135,6 +1147,12 @@ begin
|
||||
ADest.Brush.Style := Brush.Style;
|
||||
end;
|
||||
|
||||
procedure TvEntityWithPenAndBrush.AssignBrush(ABrush: TvBrush);
|
||||
begin
|
||||
Brush.Style := ABrush.Style;
|
||||
Brush.Color := ABrush.Color;
|
||||
end;
|
||||
|
||||
procedure TvEntityWithPenAndBrush.Render(ADest: TFPCustomCanvas;
|
||||
ARenderInfo: TvRenderInfo; ADestX: Integer; ADestY: Integer; AMulX: Double; AMulY: Double);
|
||||
begin
|
||||
@ -1142,6 +1160,22 @@ begin
|
||||
ApplyBrushToCanvas(ADest);
|
||||
end;
|
||||
|
||||
function TvEntityWithPenAndBrush.GenerateDebugTree(
|
||||
ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer;
|
||||
var
|
||||
lStr: string;
|
||||
lCurPathSeg: TPathSegment;
|
||||
begin
|
||||
lStr := Format('[%s] Name=%s Pen.Color=%s Pen.Style=%s Brush.Color=%s Brush.Style=%s',
|
||||
[Self.ClassName, Self.Name,
|
||||
GenerateDebugStrForFPColor(Pen.Color),
|
||||
GetEnumName(TypeInfo(TFPPenStyle), integer(Pen.Style)),
|
||||
GenerateDebugStrForFPColor(Brush.Color),
|
||||
GetEnumName(TypeInfo(TFPBrushStyle), integer(Brush.Style))
|
||||
]);
|
||||
Result := ADestRoutine(lStr, APageItem);
|
||||
end;
|
||||
|
||||
|
||||
{ TvEntityWithPenBrushAndFont }
|
||||
|
||||
@ -1164,13 +1198,25 @@ begin
|
||||
ADest.Font.Bold := Font.Bold;
|
||||
ADest.Font.Italic := Font.Italic;
|
||||
ADest.Font.Underline := Font.Underline;
|
||||
ADest.Font.StrikeTrough := Font.StrikeTrough;
|
||||
ADest.Font.StrikeTrough := Font.StrikeThrough;
|
||||
{$ifdef USE_LCL_CANVAS}
|
||||
ALCLDest.Font.Orientation := Round(Font.Orientation * 16);
|
||||
{$endif}
|
||||
ADest.Font.FPColor := AdjustColorToBackground(Font.Color, ARenderInfo);
|
||||
end;
|
||||
|
||||
procedure TvEntityWithPenBrushAndFont.AssignFont(AFont: TvFont);
|
||||
begin
|
||||
Font.Color := AFont.Color;
|
||||
Font.Size := AFont.Size;
|
||||
Font.Name := AFont.Name;
|
||||
Font.Orientation := AFont.Orientation;
|
||||
Font.Bold := AFont.Bold;
|
||||
Font.Italic := AFont.Italic;
|
||||
Font.Underline := AFont.Underline;
|
||||
Font.StrikeThrough := AFont.StrikeThrough;
|
||||
end;
|
||||
|
||||
procedure TvEntityWithPenBrushAndFont.Render(ADest: TFPCustomCanvas;
|
||||
ARenderInfo: TvRenderInfo; ADestX: Integer; ADestY: Integer; AMulX: Double;
|
||||
AMulY: Double);
|
||||
@ -1179,6 +1225,25 @@ begin
|
||||
ApplyFontToCanvas(ADest, ARenderInfo, AMulX);
|
||||
end;
|
||||
|
||||
function TvEntityWithPenBrushAndFont.GenerateDebugTree(
|
||||
ADestRoutine: TvDebugAddItemProc; APageItem: Pointer): Pointer;
|
||||
var
|
||||
lStr: string;
|
||||
lCurPathSeg: TPathSegment;
|
||||
begin
|
||||
Result := inherited GenerateDebugTree(ADestRoutine, APageItem);
|
||||
// Add the font debug info in a sub-item
|
||||
lStr := Format('[Font] Color=%s Size=%d Name=%s Orientation=%f Bold=%s Italic=%s Underline=%s StrikeThrough=%s',
|
||||
[GenerateDebugStrForFPColor(Font.Color),
|
||||
Font.Size, Font.Name, Font.Orientation,
|
||||
BoolToStr(Font.Bold),
|
||||
BoolToStr(Font.Italic),
|
||||
BoolToStr(Font.Underline),
|
||||
BoolToStr(Font.StrikeThrough)
|
||||
]);
|
||||
ADestRoutine(lStr, Result);
|
||||
end;
|
||||
|
||||
{ TPath }
|
||||
|
||||
constructor TPath.Create;
|
||||
|
@ -91,21 +91,52 @@ type
|
||||
procedure TokenizePathString(AStr: string);
|
||||
end; }
|
||||
|
||||
TODGMasterPage = class
|
||||
public
|
||||
Name: string;
|
||||
PageLayoutName: string;
|
||||
StyleName: string;
|
||||
end;
|
||||
|
||||
TODGStyle = class(TvEntityWithPenBrushAndFont)
|
||||
public
|
||||
end;
|
||||
|
||||
TODGPageLayout = class
|
||||
public
|
||||
Name: string;
|
||||
MarginTop, MarginBottom, MarginLeft, MarginRight: Double;
|
||||
PageWidth, PageHeight: Double;
|
||||
end;
|
||||
|
||||
{ TvODGVectorialReader }
|
||||
|
||||
TvODGVectorialReader = class(TvCustomVectorialReader)
|
||||
private
|
||||
FPointSeparator, FCommaSeparator: TFormatSettings;
|
||||
FStyles: TFPList; // of TvEntityWithPenBrushAndFont;
|
||||
FStyles: TFPList; // of TODGStyle;
|
||||
FAutomaticStyles: TFPList; // of TODGStyle;
|
||||
FPageLayouts: TFPList; // of TODGPageLayout;
|
||||
FMasterPages: TFPList; // of TODGMasterPage;
|
||||
//FSVGPathTokenizer: TSVGPathTokenizer;
|
||||
//
|
||||
procedure DeleteStyle(data,arg:pointer);
|
||||
procedure ApplyGraphicAttributeToEntity(ANodeName, ANodeValue: string; ADest: TvEntityWithPen);
|
||||
procedure ApplyStyleByNameToEntity(AStyleName: string; ADest: TvEntityWithPen);
|
||||
procedure ApplyTextStyleByNameToEntity(AStyleName: string; ADest: TvEntityWithPen);
|
||||
procedure ApplyMasterPageToPage(AMasterPageName: string; ADest: TvVectorialPage);
|
||||
//
|
||||
procedure ReadStyleNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
procedure ReadStyleStyleNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
//
|
||||
procedure ReadElement(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
procedure ReadEllipseNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
procedure ReadFrameNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
procedure ReadLineNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
procedure ReadPathNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
//
|
||||
procedure ReadStylesMasterPage(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
procedure ReadStylesPageLayout(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
//
|
||||
function ReadSVGColor(AValue: string): TFPColor;
|
||||
function GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
||||
@ -123,6 +154,7 @@ type
|
||||
procedure ReadFromStream(AStream: TStream; AData: TvVectorialDocument); override;
|
||||
procedure ReadFromFile(AFileName: string; AData: TvVectorialDocument); override;
|
||||
procedure ReadFromContentXMLDocument(AXMLDocument: TXMLDocument; AData: TvVectorialDocument);
|
||||
procedure ReadFromStylesXMLDocument(AXMLDocument: TXMLDocument; AData: TvVectorialDocument);
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -312,7 +344,188 @@ end;}
|
||||
|
||||
procedure TvODGVectorialReader.DeleteStyle(data, arg: pointer);
|
||||
begin
|
||||
TvEntityWithPenBrushAndFont(data).Free;
|
||||
TObject(data).Free;
|
||||
end;
|
||||
|
||||
procedure TvODGVectorialReader.ApplyGraphicAttributeToEntity(ANodeName,
|
||||
ANodeValue: string; ADest: TvEntityWithPen);
|
||||
var
|
||||
i: Integer;
|
||||
lColor: TFPColor;
|
||||
lDestBrush: TvEntityWithPenAndBrush absolute ADest;
|
||||
lDestFont: TvEntityWithPenBrushAndFont absolute ADest;
|
||||
begin
|
||||
case ANodeName of
|
||||
// "none", "solid"
|
||||
'draw:fill':
|
||||
begin
|
||||
if not (ADest is TvEntityWithPenAndBrush) then Exit;
|
||||
case ANodeValue of
|
||||
'none': lDestBrush.Brush.Style := bsClear;
|
||||
'solid': lDestBrush.Brush.Style := bsSolid;
|
||||
end;
|
||||
end;
|
||||
// "#ffffff"
|
||||
'draw:fill-color':
|
||||
begin
|
||||
if not (ADest is TvEntityWithPenAndBrush) then Exit;
|
||||
lColor := ReadSVGColor(ANodeValue);
|
||||
lDestBrush.Brush.Color := lColor;
|
||||
end;
|
||||
// Values: "justify", "center", "left"
|
||||
'draw:textarea-horizontal-align':
|
||||
begin
|
||||
end;
|
||||
// Values: "middle"
|
||||
'draw:textarea-vertical-align':
|
||||
begin
|
||||
end;
|
||||
// true-false
|
||||
'draw:auto-grow-height':
|
||||
begin
|
||||
end;
|
||||
// true-false
|
||||
'draw:auto-grow-width':
|
||||
begin
|
||||
end;
|
||||
// "none", "dash"
|
||||
'draw:stroke':
|
||||
begin
|
||||
case ANodeValue of
|
||||
'none': ADest.Pen.Style := psClear;
|
||||
'dash': ADest.Pen.Style := psDash;
|
||||
end;
|
||||
end;
|
||||
// "Fine_20_Dashed_20__28_var_29_"
|
||||
'draw:stroke-dash':
|
||||
begin
|
||||
end;
|
||||
// "Arrow"
|
||||
'draw:marker-start':
|
||||
begin
|
||||
end;
|
||||
// "0.45cm"
|
||||
'draw:marker-start-width':
|
||||
begin
|
||||
end;
|
||||
// "Circle"
|
||||
'draw:marker-end':
|
||||
begin
|
||||
end;
|
||||
// "0.45cm"
|
||||
'draw:marker-end-width':
|
||||
begin
|
||||
end;
|
||||
// "Transparency_20_1"
|
||||
'draw:opacity-name':
|
||||
begin
|
||||
end;
|
||||
// "0.1cm"
|
||||
'svg:stroke-width': ADest.Pen.Width := Round(StringWithUnitToFloat(ANodeValue));
|
||||
// "#000000"
|
||||
'svg:stroke-color': ADest.Pen.Color := ReadSVGColor(ANodeValue);
|
||||
// "0cm"
|
||||
'fo:min-height':
|
||||
begin
|
||||
end;
|
||||
// "0cm"
|
||||
'fo:min-width':
|
||||
begin
|
||||
end;
|
||||
// "wrap"
|
||||
'fo:wrap-option':
|
||||
begin
|
||||
end;
|
||||
// "0.175cm"
|
||||
'fo:padding-top':
|
||||
begin
|
||||
end;
|
||||
// "0.175cm"
|
||||
'fo:padding-bottom':
|
||||
begin
|
||||
end;
|
||||
// "0.3cm"
|
||||
'fo:padding-left':
|
||||
begin
|
||||
end;
|
||||
// "0.3cm"
|
||||
'fo:padding-right':
|
||||
begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Don't apply font properties here, because there is a separate method for this
|
||||
procedure TvODGVectorialReader.ApplyStyleByNameToEntity(AStyleName: string;
|
||||
ADest: TvEntityWithPen);
|
||||
var
|
||||
i: Integer;
|
||||
lCurStyle: TvEntityWithPenBrushAndFont;
|
||||
begin
|
||||
for i := 0 to FStyles.Count-1 do
|
||||
begin
|
||||
lCurStyle := TvEntityWithPenBrushAndFont(FStyles.Items[i]);
|
||||
if lCurStyle.Name = AStyleName then
|
||||
begin
|
||||
ADest.AssignPen(lCurStyle.Pen);
|
||||
if ADest is TvEntityWithPenAndBrush then
|
||||
TvEntityWithPenAndBrush(ADest).AssignBrush(lCurStyle.Brush);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TvODGVectorialReader.ApplyTextStyleByNameToEntity(AStyleName: string;
|
||||
ADest: TvEntityWithPen);
|
||||
var
|
||||
i: Integer;
|
||||
lCurStyle: TvEntityWithPenBrushAndFont;
|
||||
begin
|
||||
for i := 0 to FStyles.Count-1 do
|
||||
begin
|
||||
lCurStyle := TvEntityWithPenBrushAndFont(FStyles.Items[i]);
|
||||
if lCurStyle.Name = AStyleName then
|
||||
begin
|
||||
if ADest is TvEntityWithPenBrushAndFont then
|
||||
TvEntityWithPenBrushAndFont(ADest).AssignFont(lCurStyle.Font);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TvODGVectorialReader.ApplyMasterPageToPage(AMasterPageName: string;
|
||||
ADest: TvVectorialPage);
|
||||
var
|
||||
i: Integer;
|
||||
lMasterPage: TODGMasterPage;
|
||||
lMasterPageLayout: TODGPageLayout;
|
||||
begin
|
||||
// Find the Master Page
|
||||
for i := 0 to FMasterPages.Count-1 do
|
||||
begin
|
||||
lMasterPage := TODGMasterPage(FMasterPages.Items[i]);
|
||||
if lMasterPage.Name = AMasterPageName then Break
|
||||
else lMasterPage := nil;
|
||||
end;
|
||||
|
||||
if lMasterPage = nil then
|
||||
raise Exception.Create(Format('[TvODGVectorialReader.ApplyMasterPageToPage] Master page not found: %s', [AMasterPageName]));
|
||||
|
||||
// Find the Master Page Properties
|
||||
for i := 0 to FPageLayouts.Count-1 do
|
||||
begin
|
||||
lMasterPageLayout := TODGPageLayout(FPageLayouts.Items[i]);
|
||||
if lMasterPageLayout.Name = lMasterPage.PageLayoutName then Break
|
||||
else lMasterPageLayout := nil;
|
||||
end;
|
||||
|
||||
if lMasterPageLayout = nil then
|
||||
raise Exception.Create(Format('[TvODGVectorialReader.ApplyMasterPageToPage] Master page layout not found: %s', [lMasterPage.PageLayoutName]));
|
||||
|
||||
ADest.Width := lMasterPageLayout.PageWidth;
|
||||
ADest.Height := lMasterPageLayout.PageHeight;
|
||||
end;
|
||||
|
||||
procedure TvODGVectorialReader.ReadStyleNode(ANode: TDOMNode;
|
||||
@ -338,22 +551,41 @@ var
|
||||
lStyle: TvEntityWithPenBrushAndFont;
|
||||
lGraphicPropertiesNode: TDOMNode;
|
||||
i: Integer;
|
||||
lNodeName: DOMString;
|
||||
lNodeName, lNodeValue: DOMString;
|
||||
begin
|
||||
lStyle := TvEntityWithPenBrushAndFont.Create;
|
||||
lStyle := TODGStyle.Create;
|
||||
|
||||
// Read attributes of the main style tag
|
||||
// <style:style style:name="gr4" style:family="graphic" style:parent-style-name="standard">;
|
||||
for i := 0 to lGraphicPropertiesNode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := LowerCase(ANode.Attributes.Item[i].NodeName);
|
||||
case lNodeName of
|
||||
'style:parent-style-name':
|
||||
begin
|
||||
lNodeValue := LowerCase(ANode.Attributes.Item[i].NodeValue);
|
||||
case lNodeValue of
|
||||
// "standard"
|
||||
'standard': Continue;
|
||||
// "objectwithoutfill"
|
||||
'objectwithoutfill':
|
||||
begin
|
||||
lStyle.Brush.Style := bsClear;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Read graphic properties
|
||||
lGraphicPropertiesNode := ANode.FindNode('style:graphic-properties');
|
||||
if lGraphicPropertiesNode <> nil then
|
||||
begin
|
||||
for i := 0 to lGraphicPropertiesNode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := lGraphicPropertiesNode.Attributes.Item[i].NodeName;
|
||||
case lNodeName of
|
||||
//'draw:fill':
|
||||
'draw:fill-color':
|
||||
begin
|
||||
//lColor := lStyle.Brush.Color;
|
||||
end;
|
||||
end;
|
||||
lNodeName := LowerCase(lGraphicPropertiesNode.Attributes.Item[i].NodeName);
|
||||
lNodeValue := LowerCase(lGraphicPropertiesNode.Attributes.Item[i].NodeValue);
|
||||
ApplyGraphicAttributeToEntity(lNodeName, lNodeValue, lStyle);
|
||||
end;
|
||||
end;
|
||||
FStyles.Add(lStyle);
|
||||
@ -367,6 +599,9 @@ begin
|
||||
Str := LowerCase(ANode.NodeName);
|
||||
case Str of
|
||||
'draw:ellipse': ReadEllipseNode(ANode, AData, ADoc);
|
||||
'draw:frame': ReadFrameNode(ANode, AData, ADoc);
|
||||
'draw:line': ReadLineNode(ANode, AData, ADoc);
|
||||
'draw:path': ReadPathNode(ANode, AData, ADoc);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -408,10 +643,14 @@ begin
|
||||
crx := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) / 2
|
||||
else if lNodeName = 'svg:height' then
|
||||
cry := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue) / 2
|
||||
// else if lNodeName = 'id' then
|
||||
// lEllipse.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
|
||||
// else if lNodeName = 'draw:style-name' then
|
||||
// AddStyleToElement(ANode.Attributes.Item[i].NodeValue, lEllipse);
|
||||
else if lNodeName = 'draw:style-name' then
|
||||
ApplyStyleByNameToEntity(ANode.Attributes.Item[i].NodeValue, lEllipse)
|
||||
else if lNodeName = 'draw:text-style-name' then
|
||||
ApplyTextStyleByNameToEntity(ANode.Attributes.Item[i].NodeValue, lEllipse)
|
||||
// else if lNodeName = 'id' then
|
||||
// lEllipse.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
|
||||
else
|
||||
ApplyGraphicAttributeToEntity(lNodeName, ANode.Attributes.Item[i].NodeValue, lEllipse);
|
||||
end;
|
||||
|
||||
// The svg:x and svg:y coordinates are relative to the top-left in ODG,
|
||||
@ -419,7 +658,7 @@ begin
|
||||
cx := cx + crx;
|
||||
cy := cy + cry;
|
||||
|
||||
ConvertODGDeltaToFPVDelta(
|
||||
ConvertODGCoordinatesToFPVCoordinates(
|
||||
AData, cx, cy, lEllipse.X, lEllipse.Y);
|
||||
ConvertODGDeltaToFPVDelta(
|
||||
AData, crx, cry, lEllipse.HorzHalfAxis, lEllipse.VertHalfAxis);
|
||||
@ -427,6 +666,163 @@ begin
|
||||
AData.AddEntity(lEllipse);
|
||||
end;
|
||||
|
||||
{
|
||||
<draw:frame draw:style-name="gr12" draw:text-style-name="P2" draw:layer="layout" svg:width="4.5cm" svg:height="1.25cm" svg:x="4cm" svg:y="20cm">
|
||||
<draw:text-box><text:p text:style-name="P2"><text:span text:style-name="T1">Kesäyö</text:span></text:p></draw:text-box>
|
||||
</draw:frame>
|
||||
}
|
||||
procedure TvODGVectorialReader.ReadFrameNode(ANode: TDOMNode;
|
||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
{
|
||||
<draw:line draw:style-name="gr9" draw:text-style-name="P1" draw:layer="layout"
|
||||
svg:x1="14cm" svg:y1="22.5cm" svg:x2="14cm" svg:y2="23.5cm"><text:p/></draw:line>
|
||||
<draw:line draw:style-name="gr9" draw:text-style-name="P1" draw:layer="layout"
|
||||
svg:x1="14cm" svg:y1="23.5cm" svg:x2="13.5cm" svg:y2="25.5cm"><text:p/></draw:line>
|
||||
}
|
||||
procedure TvODGVectorialReader.ReadLineNode(ANode: TDOMNode;
|
||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
var
|
||||
x1, y1, x2, y2: double;
|
||||
lPath: TPath;
|
||||
i: Integer;
|
||||
lNodeName: DOMString;
|
||||
begin
|
||||
x1 := 0.0;
|
||||
y1 := 0.0;
|
||||
x2 := 0.0;
|
||||
y2 := 0.0;
|
||||
|
||||
lPath := TPath.Create;
|
||||
|
||||
// read the attributes
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := ANode.Attributes.Item[i].NodeName;
|
||||
if lNodeName = 'svg:x1' then
|
||||
x1 := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
else if lNodeName = 'svg:y1' then
|
||||
y1 := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
else if lNodeName = 'svg:x2' then
|
||||
x2 := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
else if lNodeName = 'svg:y2' then
|
||||
y2 := StringWithUnitToFloat(ANode.Attributes.Item[i].NodeValue)
|
||||
else if lNodeName = 'draw:style-name' then
|
||||
ApplyStyleByNameToEntity(ANode.Attributes.Item[i].NodeValue, lPath)
|
||||
else if lNodeName = 'draw:text-style-name' then
|
||||
ApplyTextStyleByNameToEntity(ANode.Attributes.Item[i].NodeValue, lPath)
|
||||
// else if lNodeName = 'id' then
|
||||
// lEllipse.Name := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue)
|
||||
else
|
||||
ApplyGraphicAttributeToEntity(lNodeName, ANode.Attributes.Item[i].NodeValue, lPath);
|
||||
end;
|
||||
|
||||
ConvertODGCoordinatesToFPVCoordinates(
|
||||
AData, x1, y1, x1, y1);
|
||||
ConvertODGCoordinatesToFPVCoordinates(
|
||||
AData, x2, y2, x2, y2);
|
||||
|
||||
lPath.AppendMoveToSegment(x1, y1);
|
||||
lPath.AppendLineToSegment(x2, y2);
|
||||
AData.AddEntity(lPath);
|
||||
end;
|
||||
|
||||
{
|
||||
<draw:path draw:style-name="gr11" draw:text-style-name="P1" draw:layer="layout"
|
||||
svg:width="9.429cm" svg:height="4.491cm"
|
||||
draw:transform="skewX (-4.3967693286338E-017) rotate (0.417482757076965) translate (6.73314019682066cm 26.0928070675985cm)"
|
||||
svg:viewBox="0 0 9430 4492" svg:d="m0 5c688-5 1345-23 2075 66 1374 167-412 989 814 1282 591 141 1129 504 1795 401 694-107 1142 607 1686 945 551 342 1077 719 1509 1195l501 355 549 243 501-238">
|
||||
<text:p/></draw:path>
|
||||
}
|
||||
procedure TvODGVectorialReader.ReadPathNode(ANode: TDOMNode;
|
||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
{
|
||||
<office:master-styles>
|
||||
<style:master-page style:name="Oletus" style:page-layout-name="PM0" draw:style-name="Mdp1"/>
|
||||
</office:master-styles>
|
||||
}
|
||||
procedure TvODGVectorialReader.ReadStylesMasterPage(ANode: TDOMNode;
|
||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
var
|
||||
lMasterPage: TODGMasterPage;
|
||||
i: Integer;
|
||||
lNodeName, lNodeValue: string;
|
||||
begin
|
||||
lMasterPage := TODGMasterPage.Create;
|
||||
|
||||
// Read properties
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := LowerCase(ANode.Attributes.Item[i].NodeName);
|
||||
lNodeValue := ANode.Attributes.Item[i].NodeValue;
|
||||
|
||||
case lNodeName of
|
||||
'style:name': lMasterPage.Name := lNodeValue;
|
||||
'style:page-layout-name': lMasterPage.PageLayoutName := lNodeValue;
|
||||
'draw:style-name': lMasterPage.StyleName := lNodeValue;
|
||||
end;
|
||||
end;
|
||||
FMasterPages.Add(lMasterPage);
|
||||
end;
|
||||
|
||||
{
|
||||
<style:page-layout style:name="PM0">
|
||||
<style:page-layout-properties fo:margin-top="1cm" fo:margin-bottom="1cm"
|
||||
fo:margin-left="1cm" fo:margin-right="1cm"
|
||||
fo:page-width="21cm" fo:page-height="29.7cm"
|
||||
style:print-orientation="portrait"/>
|
||||
</style:page-layout>
|
||||
}
|
||||
procedure TvODGVectorialReader.ReadStylesPageLayout(ANode: TDOMNode;
|
||||
AData: TvVectorialPage; ADoc: TvVectorialDocument);
|
||||
var
|
||||
lPageLayout: TODGPageLayout;
|
||||
lPageLayoutPropertiesNode: TDOMNode;
|
||||
i: Integer;
|
||||
lNodeName, lNodeValue: string;
|
||||
begin
|
||||
lPageLayout := TODGPageLayout.Create;
|
||||
|
||||
// Read properties
|
||||
for i := 0 to ANode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := LowerCase(ANode.Attributes.Item[i].NodeName);
|
||||
lNodeValue := ANode.Attributes.Item[i].NodeValue;
|
||||
|
||||
case lNodeName of
|
||||
'style:name': lPageLayout.Name := lNodeValue;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Read properties in the internal item
|
||||
lPageLayoutPropertiesNode := ANode.FindNode('style:page-layout-properties');
|
||||
if lPageLayoutPropertiesNode <> nil then
|
||||
begin
|
||||
for i := 0 to lPageLayoutPropertiesNode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := LowerCase(lPageLayoutPropertiesNode.Attributes.Item[i].NodeName);
|
||||
lNodeValue := lPageLayoutPropertiesNode.Attributes.Item[i].NodeValue;
|
||||
|
||||
case lNodeName of
|
||||
'fo:margin-top': lPageLayout.MarginTop := StringWithUnitToFloat(lNodeValue);
|
||||
'fo:margin-bottom':lPageLayout.MarginBottom := StringWithUnitToFloat(lNodeValue);
|
||||
'fo:margin-left': lPageLayout.MarginLeft := StringWithUnitToFloat(lNodeValue);
|
||||
'fo:margin-right':lPageLayout.MarginRight := StringWithUnitToFloat(lNodeValue);
|
||||
'fo:page-width': lPageLayout.PageWidth := StringWithUnitToFloat(lNodeValue);
|
||||
'fo:page-height': lPageLayout.PageHeight := StringWithUnitToFloat(lNodeValue);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
FPageLayouts.Add(lPageLayout);
|
||||
end;
|
||||
|
||||
function TvODGVectorialReader.ReadSVGColor(AValue: string): TFPColor;
|
||||
var
|
||||
lValue, lStr: string;
|
||||
@ -874,12 +1270,21 @@ begin
|
||||
|
||||
// FSVGPathTokenizer := TSVGPathTokenizer.Create;
|
||||
FStyles := TFPList.Create;
|
||||
FAutomaticStyles := TFPList.Create;
|
||||
FPageLayouts := TFPList.Create;
|
||||
FMasterPages := TFPList.Create;
|
||||
end;
|
||||
|
||||
destructor TvODGVectorialReader.Destroy;
|
||||
begin
|
||||
FStyles.ForEachCall(@DeleteStyle, nil);
|
||||
FStyles.Free;
|
||||
FAutomaticStyles.ForEachCall(@DeleteStyle, nil);
|
||||
FAutomaticStyles.Free;
|
||||
FPageLayouts.ForEachCall(@DeleteStyle, nil);
|
||||
FPageLayouts.Free;
|
||||
FMasterPages.ForEachCall(@DeleteStyle, nil);
|
||||
FMasterPages.Free;
|
||||
// FSVGPathTokenizer.Free;
|
||||
|
||||
inherited Destroy;
|
||||
@ -929,6 +1334,7 @@ begin
|
||||
UnZip.OutputPath:=FilePath;
|
||||
FileList:=TStringList.Create;
|
||||
FileList.Add('content.xml');
|
||||
FileList.Add('styles.xml');
|
||||
try
|
||||
Unzip.UnZipFiles(AFileName,FileList);
|
||||
finally
|
||||
@ -938,21 +1344,30 @@ begin
|
||||
|
||||
Doc:=nil;
|
||||
try
|
||||
//process the xml file
|
||||
// First read the master styles
|
||||
ReadXMLFile(Doc,FilePath+'styles.xml');
|
||||
DeleteFile(FilePath+'styles.xml');
|
||||
ReadFromStylesXMLDocument(Doc, AData);
|
||||
|
||||
// Now process the contents
|
||||
ReadXMLFile(Doc,FilePath+'content.xml');
|
||||
DeleteFile(FilePath+'content.xml');
|
||||
|
||||
ReadFromContentXMLDocument(Doc, AData);
|
||||
finally
|
||||
Doc.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
<draw:page draw:name="page1" draw:style-name="dp1" draw:master-page-name="Oletus">
|
||||
}
|
||||
procedure TvODGVectorialReader.ReadFromContentXMLDocument(
|
||||
AXMLDocument: TXMLDocument; AData: TvVectorialDocument);
|
||||
var
|
||||
BodyNode, DrawingNode, PageNode, ElementNode: TDOMNode;
|
||||
CurPage: TvVectorialPage;
|
||||
i: Integer;
|
||||
lNodeName, lNodeValue: String;
|
||||
begin
|
||||
BodyNode := AXMLDocument.DocumentElement.FindNode('office:body');
|
||||
if not Assigned(BodyNode) then raise Exception.Create('[TvODGVectorialReader.ReadFromContentXMLDocument] node office:body not found');
|
||||
@ -967,6 +1382,16 @@ begin
|
||||
CurPage := aData.AddPage();
|
||||
//CurPage..AddWorksheet(GetAttrValue(TableNode,'table:name'));
|
||||
|
||||
//process attributes of the page
|
||||
for i := 0 to PageNode.Attributes.Length - 1 do
|
||||
begin
|
||||
lNodeName := LowerCase(PageNode.Attributes.Item[i].NodeName);
|
||||
lNodeValue := PageNode.Attributes.Item[i].NodeValue;
|
||||
case lNodeName of
|
||||
'draw:master-page-name': ApplyMasterPageToPage(lNodeValue, CurPage);
|
||||
end;
|
||||
end;
|
||||
|
||||
//process each element inside the page
|
||||
ElementNode := PageNode.FirstChild;
|
||||
while Assigned(ElementNode) do
|
||||
@ -980,6 +1405,50 @@ begin
|
||||
end; //while Assigned(PageNode)
|
||||
end;
|
||||
|
||||
procedure TvODGVectorialReader.ReadFromStylesXMLDocument(
|
||||
AXMLDocument: TXMLDocument; AData: TvVectorialDocument);
|
||||
var
|
||||
DocStylesNode, AutomaticStylesNode, MasterStylesNode, ElementNode: TDOMNode;
|
||||
CurPage: TvVectorialPage;
|
||||
i: Integer;
|
||||
lNodeName: String;
|
||||
begin
|
||||
DocStylesNode := AXMLDocument.DocumentElement;//.FindNode('office:document-styles');
|
||||
if not Assigned(DocStylesNode) then raise Exception.Create('[TvODGVectorialReader.ReadFromStylesXMLDocument] node document-styles not found');
|
||||
|
||||
AutomaticStylesNode := DocStylesNode.FindNode('office:automatic-styles');
|
||||
if Assigned(AutomaticStylesNode) then
|
||||
begin
|
||||
//process each master style
|
||||
ElementNode := AutomaticStylesNode.FirstChild;
|
||||
while Assigned(ElementNode) do
|
||||
begin
|
||||
lNodeName := LowerCase(ElementNode.NodeName);
|
||||
case lNodeName of
|
||||
'style:page-layout': ReadStylesPageLayout(ElementNode, CurPage, AData);
|
||||
end;
|
||||
|
||||
ElementNode := ElementNode.NextSibling;
|
||||
end; //while Assigned(MasterStyleNode)
|
||||
end;
|
||||
|
||||
MasterStylesNode := DocStylesNode.FindNode('office:master-styles');
|
||||
if Assigned(MasterStylesNode) then
|
||||
begin
|
||||
//process each master style
|
||||
ElementNode := MasterStylesNode.FirstChild;
|
||||
while Assigned(ElementNode) do
|
||||
begin
|
||||
lNodeName := LowerCase(ElementNode.NodeName);
|
||||
case lNodeName of
|
||||
'style:master-page': ReadStylesMasterPage(ElementNode, CurPage, AData);
|
||||
end;
|
||||
|
||||
ElementNode := ElementNode.NextSibling;
|
||||
end; //while Assigned(MasterStyleNode)
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
RegisterVectorialReader(TvODGVectorialReader, vfODG);
|
||||
|
Loading…
Reference in New Issue
Block a user