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;
|
||||
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);
|
||||
var
|
||||
r, c: Cardinal;
|
||||
x, y, w, h: Double;
|
||||
nodeName: String;
|
||||
x: Double = 0.0;
|
||||
y: Double = 0.0;
|
||||
w: Double = 0.0;
|
||||
h: Double = 0.0;
|
||||
dx: Double = 0.0;
|
||||
dy: Double = 0.0;
|
||||
sx: 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;
|
||||
nodeName: String;
|
||||
i, idx: Integer;
|
||||
href: String;
|
||||
img: PsImage;
|
||||
@ -5131,10 +5174,14 @@ procedure TsSpreadOpenDocReader.ReadShape(ANode: TDOMNode;
|
||||
{$ENDIF}
|
||||
begin
|
||||
nodeName := ANode.NodeName;
|
||||
x := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:x')));
|
||||
y := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:y')));
|
||||
w := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:width')));
|
||||
h := PtsToMM(HTMLLengthStrToPts(GetAttrValue(ANode, 'svg:height')));
|
||||
attr := GetAttrValue(ANode, 'svg:x');
|
||||
if attr <> '' then x := PtsToMM(HTMLLengthStrToPts(attr));
|
||||
attr := GetAttrValue(ANode, 'svg:y');
|
||||
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;
|
||||
while Assigned(childNode) do
|
||||
begin
|
||||
@ -5185,10 +5232,10 @@ procedure TsSpreadOpenDocReader.ReadShape(ANode: TDOMNode;
|
||||
dx := x;
|
||||
end;
|
||||
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;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -267,43 +267,6 @@ begin
|
||||
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;
|
||||
begin
|
||||
Result.Color := LumModOff(AColor.Color, AIntensity, 0.0);
|
||||
|
@ -62,6 +62,8 @@ function CreateTempStream(AWorkbook: TsBasicWorkbook;
|
||||
AFileNameBase: String): TStream;
|
||||
procedure DestroyTempStream(AStream: TStream);
|
||||
|
||||
function EvalLengthStr(AText: String; out AValue: Double; out Relative: Boolean): Boolean;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@ -231,6 +233,51 @@ begin
|
||||
else
|
||||
Result := '';
|
||||
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 }
|
||||
{------------------------------------------------------------------------------}
|
||||
|
@ -342,20 +342,20 @@ type
|
||||
|
||||
TDateMode = (dm1900, dm1904); //DATEMODE values, 5.28
|
||||
|
||||
// Adjusts Excel float (date, date/time, time) with the file's base date to get a TDateTime
|
||||
function ConvertExcelDateTimeToDateTime
|
||||
(const AExcelDateNum: Double; ADateMode: TDateMode): TDateTime;
|
||||
// Adjusts Excel float (date, date/time, time) with the file's base date to get a TDateTime
|
||||
function ConvertExcelDateTimeToDateTime
|
||||
(const AExcelDateNum: Double; ADateMode: TDateMode): TDateTime;
|
||||
|
||||
// Adjusts TDateTime with the file's base date to get
|
||||
// an Excel float value representing a time/date/datetime
|
||||
function ConvertDateTimeToExcelDateTime
|
||||
(const ADateTime: TDateTime; ADateMode: TDateMode): Double;
|
||||
// Adjusts TDateTime with the file's base date to get
|
||||
// an Excel float value representing a time/date/datetime
|
||||
function ConvertDateTimeToExcelDateTime
|
||||
(const ADateTime: TDateTime; ADateMode: TDateMode): Double;
|
||||
|
||||
// Converts the error byte read from cells or formulas to fps error value
|
||||
function ConvertFromExcelError(AValue: Byte): TsErrorValue;
|
||||
// Converts the error byte read from cells or formulas to fps error value
|
||||
function ConvertFromExcelError(AValue: Byte): TsErrorValue;
|
||||
|
||||
// Converts an fps error value to the byte code needed in xls files
|
||||
function ConvertToExcelError(AValue: TsErrorValue): byte;
|
||||
// Converts an fps error value to the byte code needed in xls files
|
||||
function ConvertToExcelError(AValue: TsErrorValue): byte;
|
||||
|
||||
type
|
||||
{ TsSheetData }
|
||||
@ -5984,6 +5984,5 @@ begin
|
||||
WriteXF(AStream, TsWorkbook(Workbook).GetPointerToCellFormat(i), 0);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user