fpvectorial: Fixes setting the font info for formulas and improves SVG layer and text reading

git-svn-id: trunk@39727 -
This commit is contained in:
sekelsenmat 2013-01-02 10:33:09 +00:00
parent ba73becf3e
commit 865a07f674
2 changed files with 106 additions and 37 deletions

View File

@ -110,6 +110,10 @@ type
Zero is the normal, horizontal, orientation, directed to the right. Zero is the normal, horizontal, orientation, directed to the right.
} }
Orientation: Double; Orientation: Double;
Bold: boolean;
Italic: boolean;
Underline: boolean;
StrikeTrough: boolean;
end; end;
{ Coordinates and polyline segments } { Coordinates and polyline segments }
@ -275,6 +279,17 @@ type
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
end; end;
{ TvEntityWithPenBrushAndFont }
TvEntityWithPenBrushAndFont = class(TvEntityWithPenAndBrush)
public
Font: TvFont;
constructor Create; override;
procedure ApplyFontToCanvas(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; AMulX: Double = 1.0);
procedure Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
end;
TvClipMode = (vcmNonzeroWindingRule, vcmEvenOddRule); TvClipMode = (vcmNonzeroWindingRule, vcmEvenOddRule);
TPath = class(TvEntityWithPenAndBrush) TPath = class(TvEntityWithPenAndBrush)
@ -319,10 +334,9 @@ type
{ TvText } { TvText }
TvText = class(TvEntityWithPenAndBrush) TvText = class(TvEntityWithPenBrushAndFont)
public public
Value: TStringList; Value: TStringList;
Font: TvFont;
constructor Create; override; constructor Create; override;
destructor Destroy; override; destructor Destroy; override;
function TryToSelect(APos: TPoint; var ASubpart: Cardinal): TvFindEntityResult; override; function TryToSelect(APos: TPoint; var ASubpart: Cardinal): TvFindEntityResult; override;
@ -528,7 +542,7 @@ type
{ TvFormula } { TvFormula }
TvFormula = class(TvEntityWithPenAndBrush) TvFormula = class(TvEntityWithPenBrushAndFont)
private private
FCurIndex: Integer; FCurIndex: Integer;
SpacingBetweenElementsX: Integer; SpacingBetweenElementsX: Integer;
@ -1123,6 +1137,43 @@ begin
ApplyBrushToCanvas(ADest); ApplyBrushToCanvas(ADest);
end; end;
{ TvEntityWithPenBrushAndFont }
constructor TvEntityWithPenBrushAndFont.Create;
begin
inherited Create;
Font.Color := colBlack;
end;
procedure TvEntityWithPenBrushAndFont.ApplyFontToCanvas(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; AMulX: Double = 1.0);
var
i: Integer;
{$ifdef USE_LCL_CANVAS}
ALCLDest: TCanvas absolute ADest;
{$endif}
//
LowerDim: T3DPoint;
begin
ADest.Font.Size := Round(AmulX * Font.Size);
ADest.Font.Bold := Font.Bold;
ADest.Font.Italic := Font.Italic;
ADest.Font.Underline := Font.Underline;
ADest.Font.StrikeTrough := Font.StrikeTrough;
{$ifdef USE_LCL_CANVAS}
ALCLDest.Font.Orientation := Round(Font.Orientation * 16);
{$endif}
ADest.Font.FPColor := AdjustColorToBackground(Font.Color, ARenderInfo);
end;
procedure TvEntityWithPenBrushAndFont.Render(ADest: TFPCustomCanvas;
ARenderInfo: TvRenderInfo; ADestX: Integer; ADestY: Integer; AMulX: Double;
AMulY: Double);
begin
inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY);
ApplyFontToCanvas(ADest, ARenderInfo, AMulX);
end;
{ TPath } { TPath }
constructor TPath.Create; constructor TPath.Create;
@ -1584,6 +1635,7 @@ constructor TvText.Create;
begin begin
inherited Create; inherited Create;
Value := TStringList.Create; Value := TStringList.Create;
Font.Color := colBlack;
end; end;
destructor TvText.Destroy; destructor TvText.Destroy;
@ -1618,21 +1670,13 @@ procedure TvText.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; ADest
var var
i: Integer; i: Integer;
{$ifdef USE_LCL_CANVAS}
ALCLDest: TCanvas absolute ADest;
{$endif}
// //
LowerDim: T3DPoint; LowerDim: T3DPoint;
begin begin
inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY); inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY);
ADest.Font.Size := Round(AmulX * Font.Size); // Don't draw anything if we have alpha=zero
{ ADest.Pen.Style := psSolid; if Font.Color.Alpha = 0 then Exit;
ADest.Pen.FPColor := colBlack;
ADest.Brush.Style := bsClear;}
{$ifdef USE_LCL_CANVAS}
ALCLDest.Font.Orientation := Round(Font.Orientation * 16);
{$endif}
// TvText supports multiple lines // TvText supports multiple lines
for i := 0 to Value.Count - 1 do for i := 0 to Value.Count - 1 do
@ -2684,6 +2728,8 @@ procedure TvFormula.Render(ADest: TFPCustomCanvas; ARenderInfo: TvRenderInfo; AD
var var
lElement: TvFormulaElement; lElement: TvFormulaElement;
begin begin
inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY);
// First position all elements // First position all elements
PositionSubparts(ADest, Left, Top); PositionSubparts(ADest, Left, Top);
@ -3321,6 +3367,7 @@ end;
function TvVectorialPage.AddLayer(AName: string): TvLayer; function TvVectorialPage.AddLayer(AName: string): TvLayer;
begin begin
Result := TvLayer.Create; Result := TvLayer.Create;
Result.Name := AName;
AddEntity(Result); AddEntity(Result);
end; end;

View File

@ -70,6 +70,7 @@ type
procedure ReadEntityFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument); procedure ReadEntityFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
procedure ReadCircleFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument); procedure ReadCircleFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
procedure ReadEllipseFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument); procedure ReadEllipseFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
procedure ReadLayerFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
procedure ReadLineFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument); procedure ReadLineFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
procedure ReadPathFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument); procedure ReadPathFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument);
procedure ReadPathFromString(AStr: string; AData: TvVectorialPage; ADoc: TvVectorialDocument); procedure ReadPathFromString(AStr: string; AData: TvVectorialPage; ADoc: TvVectorialDocument);
@ -700,7 +701,9 @@ begin
if AValue = 'none' then ADestEntity.Brush.Style := fpcanvas.bsClear if AValue = 'none' then ADestEntity.Brush.Style := fpcanvas.bsClear
else ADestEntity.Brush.Color := ReadSVGColor(AValue) else ADestEntity.Brush.Color := ReadSVGColor(AValue)
end; end
else if AKey = 'fill-opacity' then
ADestEntity.Brush.Color.Alpha := StrToInt(AValue)*$101;
end; end;
procedure TvSVGVectorialReader.ReadSVGFontStyleWithKeyAndValue(AKey, procedure TvSVGVectorialReader.ReadSVGFontStyleWithKeyAndValue(AKey,
@ -709,23 +712,33 @@ begin
// SVG text uses "fill" to indicate the pen color of the text, very unintuitive as // SVG text uses "fill" to indicate the pen color of the text, very unintuitive as
// "fill" is usually for brush in other elements // "fill" is usually for brush in other elements
if AKey = 'fill' then if AKey = 'fill' then
ADestEntity.Font.Color := ReadSVGColor(AValue)
else if AKey = 'fill-opacity' then
ADestEntity.Font.Color.Alpha := StrToInt(AValue)*$101
else if AKey = 'font-size' then
ADestEntity.Font.Size := StrToInt(AValue)
else if AKey = 'font-family' then
ADestEntity.Font.Name := AValue
else if AKey = 'font-weight' then
begin begin
ADestEntity.Font.Color := ReadSVGColor(AValue); case LowerCase(AValue) of
'bold': ADestEntity.Font.Bold := True;
end;
end; end;
end; end;
function TvSVGVectorialReader.IsAttributeFromStyle(AStr: string): Boolean; function TvSVGVectorialReader.IsAttributeFromStyle(AStr: string): Boolean;
begin begin
Result := (AStr = 'stroke') or (AStr = 'stroke-width') or Result := (AStr = 'stroke') or (AStr = 'stroke-width') or
(AStr = 'fill'); (AStr = 'fill') or (AStr = 'fill-opacity') or
(AStr = 'font-size') or (AStr = 'fill-family') or
(AStr = 'font-weight');
end; end;
procedure TvSVGVectorialReader.ReadEntityFromNode(ANode: TDOMNode; procedure TvSVGVectorialReader.ReadEntityFromNode(ANode: TDOMNode;
AData: TvVectorialPage; ADoc: TvVectorialDocument); AData: TvVectorialPage; ADoc: TvVectorialDocument);
var var
lEntityName, lLayerName: DOMString; lEntityName: DOMString;
lCurNode, lLayerNameNode: TDOMNode;
lLayer: TvLayer;
begin begin
lEntityName := LowerCase(ANode.NodeName); lEntityName := LowerCase(ANode.NodeName);
case lEntityName of case lEntityName of
@ -736,24 +749,7 @@ begin
'polygon', 'polyline': ReadPolyFromNode(ANode, AData, ADoc); 'polygon', 'polyline': ReadPolyFromNode(ANode, AData, ADoc);
'rect': ReadRectFromNode(ANode, AData, ADoc); 'rect': ReadRectFromNode(ANode, AData, ADoc);
'text': ReadTextFromNode(ANode, AData, ADoc); 'text': ReadTextFromNode(ANode, AData, ADoc);
// Layers 'g': ReadLayerFromNode(ANode, AData, ADoc);
'g':
begin
// if we are already inside a layer, something may be wrong...
//if ALayer <> nil then raise Exception.Create('[TvSVGVectorialReader.ReadEntityFromNode] A layer inside a layer was found!');
lLayerNameNode := ANode.Attributes.GetNamedItem('id');
lLayerName := '';
if lLayerNameNode <> nil then lLayerName := lLayerNameNode.NodeValue;
lLayer := AData.AddLayerAndSetAsCurrent(lLayerName);
lCurNode := ANode.FirstChild;
while Assigned(lCurNode) do
begin
ReadEntityFromNode(lCurNode, AData, ADoc);
lCurNode := lCurNode.NextSibling;
end;
end;
end; end;
end; end;
@ -854,6 +850,32 @@ begin
AData.AddEntity(lEllipse); AData.AddEntity(lEllipse);
end; end;
procedure TvSVGVectorialReader.ReadLayerFromNode(ANode: TDOMNode;
AData: TvVectorialPage; ADoc: TvVectorialDocument);
var
lNodeName: DOMString;
lLayerName: string = '';
lCurNode, lLayerNameNode: TDOMNode;
lLayer: TvLayer;
i: Integer;
begin
for i := 0 to ANode.Attributes.Length - 1 do
begin
lNodeName := ANode.Attributes.Item[i].NodeName;
if lNodeName = 'id' then
lLayerName := UTF16ToUTF8(ANode.Attributes.Item[i].NodeValue);
end;
lLayer := AData.AddLayerAndSetAsCurrent(lLayerName);
lCurNode := ANode.FirstChild;
while Assigned(lCurNode) do
begin
ReadEntityFromNode(lCurNode, AData, ADoc);
lCurNode := lCurNode.NextSibling;
end;
end;
procedure TvSVGVectorialReader.ReadLineFromNode(ANode: TDOMNode; procedure TvSVGVectorialReader.ReadLineFromNode(ANode: TDOMNode;
AData: TvVectorialPage; ADoc: TvVectorialDocument); AData: TvVectorialPage; ADoc: TvVectorialDocument);
var var