fpspreadsheet: Support reading of rotated images from ods files.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9753 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
9ec7cea591
commit
9b1fe48c83
@ -5111,16 +5111,59 @@ procedure TsSpreadOpenDocReader.ReadShape(ANode: TDOMNode;
|
|||||||
ARow: Cardinal = UNASSIGNED_ROW_COL_INDEX;
|
ARow: Cardinal = UNASSIGNED_ROW_COL_INDEX;
|
||||||
ACol: Cardinal = UNASSIGNED_ROW_COL_INDEX);
|
ACol: Cardinal = UNASSIGNED_ROW_COL_INDEX);
|
||||||
|
|
||||||
|
// Example for s: skewX (7.75940943781828E-017) rotate (1.0471975511966) translate (0.014cm -0.023cm)
|
||||||
|
procedure AnalyzeTransform(s: String; var SkewX, RotAngle, dX, dY: Double);
|
||||||
|
var
|
||||||
|
sa: TStringArray;
|
||||||
|
i: Integer;
|
||||||
|
valueStr: String;
|
||||||
|
relative: Boolean;
|
||||||
|
begin
|
||||||
|
SkewX := 0.0;
|
||||||
|
RotAngle := 0.0;
|
||||||
|
dX := 0.0;
|
||||||
|
dy := 0.0;
|
||||||
|
sa := s.Split(' ');
|
||||||
|
for i := 0 to High(sa) do
|
||||||
|
case sa[i] of
|
||||||
|
'skewX':
|
||||||
|
begin
|
||||||
|
valueStr := Copy(sa[i+1], 2, Length(sa[+1])-2);
|
||||||
|
SkewX := StrToFloatDef(valueStr, 0.0, FPointSeparatorSettings);
|
||||||
|
end;
|
||||||
|
'rotate':
|
||||||
|
begin
|
||||||
|
valueStr := Copy(sa[i+1], 2, Length(sa[+1])-2);
|
||||||
|
RotAngle := RadToDeg(StrToFloatDef(valueStr, 0.0, FPointSeparatorSettings));
|
||||||
|
end;
|
||||||
|
'translate':
|
||||||
|
begin
|
||||||
|
valueStr := Copy(sa[i+1], 2, Length(sa[+1])-2);
|
||||||
|
EvalLengthStr(valueStr, dX, relative);
|
||||||
|
valueStr := Copy(sa[i+2], 2, Length(sa[+2])-2);
|
||||||
|
EvalLengthStr(valueStr, dX, relative);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure ReadDrawFrame(ANode: TDOMNode; AHLink: String);
|
procedure ReadDrawFrame(ANode: TDOMNode; AHLink: String);
|
||||||
var
|
var
|
||||||
r, c: Cardinal;
|
r, c: Cardinal;
|
||||||
x, y, w, h: Double;
|
x: Double = 0.0;
|
||||||
nodeName: String;
|
y: Double = 0.0;
|
||||||
|
w: Double = 0.0;
|
||||||
|
h: Double = 0.0;
|
||||||
dx: Double = 0.0;
|
dx: Double = 0.0;
|
||||||
dy: Double = 0.0;
|
dy: Double = 0.0;
|
||||||
sx: Double = 1.0;
|
sx: Double = 1.0;
|
||||||
sy: Double = 1.0;
|
sy: Double = 1.0;
|
||||||
|
attr: String = '';
|
||||||
|
transfSkew: Double = 0.0;
|
||||||
|
transfAngle: Double = 0.0;
|
||||||
|
transfDX: Double = 0.0;
|
||||||
|
transfDY: Double = 0.0;
|
||||||
childNode: TDOMNode;
|
childNode: TDOMNode;
|
||||||
|
nodeName: String;
|
||||||
i, idx: Integer;
|
i, idx: Integer;
|
||||||
href: String;
|
href: String;
|
||||||
img: PsImage;
|
img: PsImage;
|
||||||
@ -5131,10 +5174,14 @@ procedure TsSpreadOpenDocReader.ReadShape(ANode: TDOMNode;
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
begin
|
begin
|
||||||
nodeName := ANode.NodeName;
|
nodeName := ANode.NodeName;
|
||||||
x := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:x')));
|
attr := GetAttrValue(ANode, 'svg:x');
|
||||||
y := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:y')));
|
if attr <> '' then x := PtsToMM(HTMLLengthStrToPts(attr));
|
||||||
w := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:width')));
|
attr := GetAttrValue(ANode, 'svg:y');
|
||||||
h := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:height')));
|
if attr <> '' then y := PtsToMM(HTMLLengthStrToPts(attr));
|
||||||
|
attr := GetAttrValue(ANode, 'svg:width');
|
||||||
|
if attr <> '' then h := PtsToMM(HTMLLengthStrToPts(attr));
|
||||||
|
attr := GetAttrValue(ANode, 'draw:transform');
|
||||||
|
if attr <> '' then AnalyzeTransform(attr, transfSkew, transfAngle, transfDX, transfDY);
|
||||||
childNode := ANode.FirstChild;
|
childNode := ANode.FirstChild;
|
||||||
while Assigned(childNode) do
|
while Assigned(childNode) do
|
||||||
begin
|
begin
|
||||||
@ -5185,10 +5232,10 @@ procedure TsSpreadOpenDocReader.ReadShape(ANode: TDOMNode;
|
|||||||
dx := x;
|
dx := x;
|
||||||
end;
|
end;
|
||||||
idx := WriteImage(r, c, idx, dx, dy, sx, sy);
|
idx := WriteImage(r, c, idx, dx, dy, sx, sy);
|
||||||
if AHLink <> '' then begin
|
img := GetPointerToImage(idx);
|
||||||
img := GetPointerToImage(idx);
|
img^.RotationAngle := transfAngle;
|
||||||
|
if AHLink <> '' then
|
||||||
img^.HyperlinkTarget := AHLink;
|
img^.HyperlinkTarget := AHLink;
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -267,43 +267,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Extracts the length from an ods length string, e.g. "3.5cm" or "300%". In the
|
|
||||||
former case AValue become 35 (in millimeters), in the latter case AValue is
|
|
||||||
300 and Relative becomes true }
|
|
||||||
function EvalLengthStr(AText: String; out AValue: Double; out Relative: Boolean): Boolean;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
res: Integer;
|
|
||||||
units: String;
|
|
||||||
begin
|
|
||||||
Result := false;
|
|
||||||
|
|
||||||
if AText = '' then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
units := '';
|
|
||||||
for i := Length(AText) downto 1 do
|
|
||||||
if AText[i] in ['%', 'm', 'c', 'p', 't', 'i', 'n'] then
|
|
||||||
begin
|
|
||||||
units := AText[i] + units;
|
|
||||||
Delete(AText, i, 1);
|
|
||||||
end;
|
|
||||||
Val(AText, AValue, res);
|
|
||||||
Result := (res = 0);
|
|
||||||
if res = 0 then
|
|
||||||
begin
|
|
||||||
Relative := false;
|
|
||||||
case units of
|
|
||||||
'%': Relative := true;
|
|
||||||
'mm': ;
|
|
||||||
'cm': AValue := AValue * 10;
|
|
||||||
'pt': AValue := PtsToMM(AValue);
|
|
||||||
'in': AValue := InToMM(AValue);
|
|
||||||
else Result := false;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function ModifyColor(AColor: TsChartColor; AIntensity: double): TsChartColor;
|
function ModifyColor(AColor: TsChartColor; AIntensity: double): TsChartColor;
|
||||||
begin
|
begin
|
||||||
Result.Color := LumModOff(AColor.Color, AIntensity, 0.0);
|
Result.Color := LumModOff(AColor.Color, AIntensity, 0.0);
|
||||||
|
@ -62,6 +62,8 @@ function CreateTempStream(AWorkbook: TsBasicWorkbook;
|
|||||||
AFileNameBase: String): TStream;
|
AFileNameBase: String): TStream;
|
||||||
procedure DestroyTempStream(AStream: TStream);
|
procedure DestroyTempStream(AStream: TStream);
|
||||||
|
|
||||||
|
function EvalLengthStr(AText: String; out AValue: Double; out Relative: Boolean): Boolean;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -231,6 +233,51 @@ begin
|
|||||||
else
|
else
|
||||||
Result := '';
|
Result := '';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Extracts the length from an ods length string, e.g. "3.5cm" or "300%". In the
|
||||||
|
ormer case AValue become 35 (in millimeters), in the latter case AValue is
|
||||||
|
00 and Relative becomes true
|
||||||
|
|
||||||
|
@param AText Length string to be analyzed, e.g. "3.5cm"
|
||||||
|
@param AValue Numerical value, in cm, or as integer percentage
|
||||||
|
@param Relative If true the parameter AValue is a percentage, otherwise a length in millimeters
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function EvalLengthStr(AText: String; out AValue: Double; out Relative: Boolean): Boolean;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
res: Integer;
|
||||||
|
units: String;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
|
||||||
|
if AText = '' then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
units := '';
|
||||||
|
for i := Length(AText) downto 1 do
|
||||||
|
if AText[i] in ['%', 'm', 'c', 'p', 't', 'i', 'n'] then
|
||||||
|
begin
|
||||||
|
units := AText[i] + units;
|
||||||
|
Delete(AText, i, 1);
|
||||||
|
end;
|
||||||
|
Val(AText, AValue, res);
|
||||||
|
Result := (res = 0);
|
||||||
|
if res = 0 then
|
||||||
|
begin
|
||||||
|
Relative := false;
|
||||||
|
case units of
|
||||||
|
'%': Relative := true;
|
||||||
|
'mm': ;
|
||||||
|
'cm': AValue := AValue * 10;
|
||||||
|
'pt': AValue := PtsToMM(AValue);
|
||||||
|
'in': AValue := InToMM(AValue);
|
||||||
|
else Result := false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
{ Unzipping }
|
{ Unzipping }
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
|
@ -342,20 +342,20 @@ type
|
|||||||
|
|
||||||
TDateMode = (dm1900, dm1904); //DATEMODE values, 5.28
|
TDateMode = (dm1900, dm1904); //DATEMODE values, 5.28
|
||||||
|
|
||||||
// Adjusts Excel float (date, date/time, time) with the file's base date to get a TDateTime
|
// Adjusts Excel float (date, date/time, time) with the file's base date to get a TDateTime
|
||||||
function ConvertExcelDateTimeToDateTime
|
function ConvertExcelDateTimeToDateTime
|
||||||
(const AExcelDateNum: Double; ADateMode: TDateMode): TDateTime;
|
(const AExcelDateNum: Double; ADateMode: TDateMode): TDateTime;
|
||||||
|
|
||||||
// Adjusts TDateTime with the file's base date to get
|
// Adjusts TDateTime with the file's base date to get
|
||||||
// an Excel float value representing a time/date/datetime
|
// an Excel float value representing a time/date/datetime
|
||||||
function ConvertDateTimeToExcelDateTime
|
function ConvertDateTimeToExcelDateTime
|
||||||
(const ADateTime: TDateTime; ADateMode: TDateMode): Double;
|
(const ADateTime: TDateTime; ADateMode: TDateMode): Double;
|
||||||
|
|
||||||
// Converts the error byte read from cells or formulas to fps error value
|
// Converts the error byte read from cells or formulas to fps error value
|
||||||
function ConvertFromExcelError(AValue: Byte): TsErrorValue;
|
function ConvertFromExcelError(AValue: Byte): TsErrorValue;
|
||||||
|
|
||||||
// Converts an fps error value to the byte code needed in xls files
|
// Converts an fps error value to the byte code needed in xls files
|
||||||
function ConvertToExcelError(AValue: TsErrorValue): byte;
|
function ConvertToExcelError(AValue: TsErrorValue): byte;
|
||||||
|
|
||||||
type
|
type
|
||||||
{ TsSheetData }
|
{ TsSheetData }
|
||||||
@ -5984,6 +5984,5 @@ begin
|
|||||||
WriteXF(AStream, TsWorkbook(Workbook).GetPointerToCellFormat(i), 0);
|
WriteXF(AStream, TsWorkbook(Workbook).GetPointerToCellFormat(i), 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user