diff --git a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas index 45639d55c..456ca58f8 100644 --- a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas +++ b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas @@ -37,9 +37,10 @@ implementation const // FILE_NAME = '../../../other/chart/bars.ods'; // FILE_NAME = '../../../other/chart/area.ods'; + FILE_NAME = '../../../other/chart/area-sameImg.ods'; // FILE_NAME = '../../../other/chart/pie.ods'; // FILE_NAME = '../../../other/chart/scatter.ods'; - FILE_NAME = '../../../other/chart/regression.ods'; +// FILE_NAME = '../../../other/chart/regression.ods'; { TForm1 } diff --git a/components/fpspreadsheet/source/common/fpschart.pas b/components/fpspreadsheet/source/common/fpschart.pas index 77cf4e749..d4f675fe8 100644 --- a/components/fpspreadsheet/source/common/fpschart.pas +++ b/components/fpspreadsheet/source/common/fpschart.pas @@ -6,7 +6,7 @@ unit fpsChart; interface uses - Classes, SysUtils, Contnrs, fpsTypes, fpsUtils; + Classes, SysUtils, Contnrs, FPImage, fpsTypes, fpsUtils; const clsNoLine = -2; @@ -55,6 +55,7 @@ type CenterX, CenterY: Double; // 0.0 ... 1.0 Angle: Double; // degrees constructor Create; + destructor Destroy; override; end; TsChartGradientList = class(TFPObjectList) @@ -92,7 +93,7 @@ type LineColor: TsColor; LineDistance: Double; // mm LineAngle: Double; // degrees - Filled: Boolean; // filled with background color or not + destructor Destroy; override; end; TsChartHatchList = class(TFPObjectList) @@ -101,19 +102,38 @@ type procedure SetItem(AIndex: Integer; AValue: TsChartHatch); public function AddHatch(AName: String; AStyle: TsChartHatchStyle; - ALineColor: TsColor; ALineDistance, ALineAngle: Double; AFilled: Boolean): Integer; + ALineColor: TsColor; ALineDistance, ALineAngle: Double): Integer; function FindByName(AName: String): TsChartHatch; function IndexOfName(AName: String): Integer; property Items[AIndex: Integer]: TsChartHatch read GetItem write SetItem; default; end; - TsChartFillStyle = (cfsNoFill, cfsSolid, cfsGradient, cfsHatched); + TsChartImage = class + Name: String; + Image: TFPCustomImage; + Width, Height: Double; // mm + destructor Destroy; override; + end; + + TsChartImagelist = class(TFPObjectList) + private + function GetItem(AIndex: Integer): TsChartImage; + procedure SetItem(AIndex: Integer; AValue: TsChartImage); + public + function AddImage(AName: String; AImage: TFPCustomImage): Integer; + function FindByName(AName: String): TsChartImage; + function IndexOfName(AName: String): Integer; + property Items[Aindex: Integer]: TsChartImage read GetItem write SetItem; default; + end; + + TsChartFillStyle = (cfsNoFill, cfsSolid, cfsGradient, cfsHatched, cfsSolidHatched, cfsImage); TsChartFill = class Style: TsChartFillStyle; Color: TsColor; Gradient: Integer; Hatch: Integer; + Image: Integer; Transparency: Double; // 0.0 ... 1.0 end; @@ -519,6 +539,7 @@ type FLineStyles: TsChartLineStyleList; FGradients: TsChartGradientList; FHatches: TsChartHatchList; + FImages: TsChartImageList; function GetCategoryLabelRange: TsChartRange; public @@ -596,6 +617,7 @@ type property LineStyles: TsChartLineStyleList read FLineStyles; property Gradients: TsChartGradientList read FGradients; property Hatches: TsChartHatchList read FHatches; + property Images: TsChartImageList read FImages; end; TsChartList = class(TObjectList) @@ -621,6 +643,12 @@ begin EndIntensity := 1.0; end; +destructor TsChartGradient.Destroy; +begin + Name := ''; + inherited; +end; + { TsChartGradientList } @@ -729,10 +757,19 @@ begin end; +{ TsChartHatch } + +destructor TsChartHatch.Destroy; +begin + Name := ''; + inherited; +end; + + { TsChartHatchList } function TsChartHatchList.AddHatch(AName: String; AStyle: TsChartHatchStyle; - ALineColor: TsColor; ALineDistance, ALineAngle: Double; AFilled: Boolean): Integer; + ALineColor: TsColor; ALineDistance, ALineAngle: Double): Integer; var item: TsChartHatch; begin @@ -750,7 +787,6 @@ begin item.LineColor := ALineColor; item.LineDistance := ALineDistance; item.LineAngle := ALineAngle; - item.Filled := AFilled; end; function TsChartHatchList.FindByName(AName: String): TsChartHatch; @@ -783,6 +819,62 @@ begin end; +{ TsChartImage } + +destructor TsChartImage.Destroy; +begin + Name := ''; + Image.Free; + inherited; +end; + + +{ TsChartImageList } + +function TsChartImageList.AddImage(AName: String; AImage: TFPCustomImage): Integer; +var + item: TsChartImage; +begin + Result := IndexOfName(AName); + if Result = -1 then + begin + item := TsChartImage.Create; + item.Name := AName; + Result := inherited Add(item); + end; + Items[Result].Image := AImage; +end; + +function TsChartImageList.FindByName(AName: String): TsChartImage; +var + idx: Integer; +begin + idx := IndexOfName(AName); + if idx <> -1 then + Result := Items[idx] + else + Result := nil; +end; + +function TsChartImageList.GetItem(AIndex: Integer): TsChartImage; +begin + Result := TsChartImage(inherited Items[AIndex]); +end; + +function TsChartImageList.IndexOfName(AName: String): Integer; +begin + for Result := 0 to Count-1 do + if SameText(Items[Result].Name, AName) then + exit; + Result := -1; +end; + +procedure TsChartImageList.SetItem(AIndex: Integer; AValue: TsChartImage); +begin + inherited Items[AIndex] := AValue; +end; + + { TsChartLineStyle } function TsChartLineStyle.GetID: String; @@ -1094,6 +1186,8 @@ end; destructor TsChartSeries.Destroy; begin + FLabelBackground.Free; + FLabelBorder.Free; FLabelFont.Free; FLine.Free; FFill.Free; @@ -1511,6 +1605,7 @@ begin FGradients := TsChartGradientList.Create; FHatches := TsChartHatchList.Create; + FImages := TsChartImageList.Create; FSheetIndex := 0; FRow := 0; @@ -1576,6 +1671,7 @@ begin FSubtitle.Free; FFloor.Free; FPlotArea.Free; + FImages.Free; FHatches.Free; FGradients.Free; FLineStyles.Free; diff --git a/components/fpspreadsheet/source/common/fpsopendocumentchart.pas b/components/fpspreadsheet/source/common/fpsopendocumentchart.pas index 1fe8bfa80..b3b3649b8 100644 --- a/components/fpspreadsheet/source/common/fpsopendocumentchart.pas +++ b/components/fpspreadsheet/source/common/fpsopendocumentchart.pas @@ -5,7 +5,7 @@ unit fpsOpenDocumentChart; interface uses - Classes, SysUtils, StrUtils, + Classes, SysUtils, StrUtils, Contnrs, FPImage, {$IF FPC_FULLVERSION >= 20701} zipper, {$ELSE} @@ -24,6 +24,7 @@ type FPointSeparatorSettings: TFormatSettings; FNumberFormatList: TStrings; FPieSeriesStartAngle: Integer; + FStreamList: TFPObjectList; function FindStyleNode(AStyleNodes: TDOMNode; AStyleName: String): TDOMNode; procedure GetChartFillProps(ANode: TDOMNode; AChart: TsChart; AFill: TsChartFill); procedure GetChartLineProps(ANode: TDOMNode; AChart: TsChart; ALine: TsChartLine); @@ -48,13 +49,15 @@ type procedure ReadChartTitleProps(ANode, AStyleNode: TDOMNode; AChart: TsChart; ATitle: TsChartText); procedure ReadChartTitleStyle(AStyleNode: TDOMNode; AChart: TsChart; ATitle: TsChartText); + procedure ReadObjectFillImages(ANode: TDOMNode; AChart: TsChart; ARoot: String); procedure ReadObjectGradientStyles(ANode: TDOMNode; AChart: TsChart); procedure ReadObjectHatchStyles(ANode: TDOMNode; AChart: TsChart); procedure ReadObjectLineStyles(ANode: TDOMNode; AChart: TsChart); protected procedure ReadChartFiles(AStream: TStream; AFileList: String); procedure ReadChart(AChartNode, AStyleNode: TDOMNode; AChart: TsChart); - procedure ReadObjectStyles(ANode: TDOMNode; AChart: TsChart); + procedure ReadObjectStyles(ANode: TDOMNode; AChart: TsChart; ARoot: String); + procedure ReadPictureFile(AStream: TStream; AFileName: String); public constructor Create(AReader: TsBasicSpreadReader); override; destructor Destroy; override; @@ -303,6 +306,42 @@ begin end; +{------------------------------------------------------------------------------} +{ internal picture storage } +{------------------------------------------------------------------------------} +type + TStreamItem = class + Name: String; + Stream: TStream; + destructor Destroy; override; + end; + +destructor TStreamItem.Destroy; +begin + Stream.Free; + inherited; +end; + +type + TStreamList = class(TFPObjectList) + public + function FindByName(AName: String): TStream; + end; + +function TStreamList.FindByName(AName: String): TStream; +var + i: Integer; +begin + for i := 0 to Count-1 do + if TStreamItem(Items[i]).Name = AName then + begin + Result := TStreamItem(Items[i]).Stream; + exit; + end; + Result := nil; +end; + + {------------------------------------------------------------------------------} { TsSpreadOpenDocChartReader } {------------------------------------------------------------------------------} @@ -317,12 +356,14 @@ begin FChartFiles := TStringList.Create; FNumberFormatList := TsChartNumberFormatList.Create; FNumberFormatList.NameValueSeparator := ':'; + FStreamList := TStreamList.Create; FPieSeriesStartAngle := 999; end; destructor TsSpreadOpenDocChartReader.Destroy; begin + FStreamList.Free; FNumberFormatList.Free; FChartFiles.Free; inherited; @@ -367,6 +408,9 @@ var sc: String; sn: String; opacity: Double; + img: TsChartImage; + value: Double; + rel: Boolean; begin nodeName := ANode.NodeName; @@ -390,17 +434,41 @@ begin end; 'hatch': begin - AFill.Style := cfsHatched; + sc := GetAttrValue(ANode, 'draw:fill-hatch-solid'); + if sc = 'true' then + AFill.Style := cfsSolidHatched + else + AFill.Style := cfsHatched; sn := GetAttrValue(ANode, 'draw:fill-hatch-name'); if sn <> '' then AFill.Hatch := AChart.Hatches.IndexOfName(UnASCIIName(sn)); sc := GetAttrValue(ANode, 'draw:fill-color'); if sc <> '' then AFill.Color := HTMLColorStrToColor(sc); - sc := GetAttrValue(ANode, 'draw:fill-hatch-solid'); - // AFill.Hatch.Filled := (sc = 'true'); // !!!! FIX ME: Filled should not be part of the style + end; + 'bitmap': + begin + sn := GetAttrValue(ANode, 'draw:fill-image-name'); + if sn <> '' then + begin + AFill.Style := cfsImage; + AFill.Image := AChart.Images.IndexOfName(UnASCIIName(sn)); + img := AChart.Images[AFill.Image]; + sc := GetAttrValue(ANode, 'draw:fill-image-width'); + if (sc <> '') and EvalLengthStr(sc, value, rel) then + img.Width := value + else + img.Width := -1; + sc := GetAttrValue(ANode, 'draw:fill-image-height'); + if (sc <> '') and EvalLengthStr(sc, value, rel) then + img.Height := value + else + img.Height := -1; + end else + AFill.Style := cfsSolid; end; end; + s := GetAttrValue(ANode, 'draw:opacity'); if (s <> '') and TryPercentStrToFloat(s, opacity) then AFill.Transparency := 1.0 - opacity; @@ -770,8 +838,8 @@ procedure TsSpreadOpenDocChartReader.ReadChartFiles(AStream: TStream; AFileList: String); var sa: TStringArray; - i: Integer; - fn: String; + i, p: Integer; + root, fn: String; contentFile: String = ''; stylesFile: String = ''; XMLStream: TStream; @@ -789,7 +857,9 @@ begin if fn = 'content.xml' then contentFile := sa[i] else if fn = 'styles.xml' then - stylesFile := sa[i]; + stylesFile := sa[i] + else if pos('/Pictures/', sa[i]) > 0 then + ReadPictureFile(AStream, sa[i]); end; for i := 0 to TsWorkbook(Reader.Workbook).GetChartCount-1 do @@ -822,7 +892,9 @@ begin if not ok then raise Exception.Create('ODS chart reader: error reading styles file "' + stylesFile + '"'); - ReadObjectStyles(doc.DocumentElement.FindNode('office:styles'), chart); + p := pos('/', stylesFile); + root := copy(stylesFile, 1, p); + ReadObjectStyles(doc.DocumentElement.FindNode('office:styles'), chart, root); FreeAndNil(doc); end; @@ -1421,7 +1493,7 @@ end; { Reads the styles stored in the Object files. } procedure TsSpreadOpenDocChartReader.ReadObjectStyles(ANode: TDOMNode; - AChart: TsChart); + AChart: TsChart; ARoot: String); var nodeName: String; begin @@ -1437,11 +1509,38 @@ begin ReadObjectHatchStyles(ANode, AChart); 'draw:gradient': // gradient definition ReadObjectGradientStyles(ANode, AChart); + 'draw:fill-image': + ReadObjectFillImages(ANode, AChart, ARoot); end; ANode := ANode.NextSibling; end; end; +procedure TsSpreadOpenDocChartReader.ReadObjectFillImages(ANode: TDOMNode; + AChart: TsChart; ARoot: String); +var + styleName: String; + imgFileName: string; + imgStream: TStream; + img: TFPCustomImage; +begin + styleName := GetAttrValue(ANode, 'draw:display-name'); + if styleName = '' then + styleName := GetAttrValue(ANode, 'draw:name'); + + imgFileName := GetAttrValue(ANode, 'xlink:href'); + if imgFileName = '' then + exit; + + imgStream := TStreamList(FStreamList).FindByName(ARoot + imgFileName); + if imgStream <> nil then + begin + img := TFPMemoryImage.Create(0, 0); // do not destroy this image here! + img.LoadFromStream(imgStream); + AChart.Images.AddImage(styleName, img); + end; +end; + procedure TsSpreadOpenDocChartReader.ReadObjectGradientStyles(ANode: TDOMNode; AChart: TsChart); var @@ -1547,8 +1646,7 @@ begin else hatchAngle := 0; - AChart.Hatches.AddHatch(styleName, hatchStyle, hatchColor, hatchDist, hatchAngle, false); - AChart.Hatches.AddHatch(styleName+' filled', hatchStyle, hatchColor, hatchDist, hatchAngle, true); + AChart.Hatches.AddHatch(styleName, hatchStyle, hatchColor, hatchDist, hatchAngle); end; { Reads the line styles stored as "draw:stroke-dash" nodes in the chart's @@ -1591,6 +1689,31 @@ begin AChart.LineStyles.Add(styleName, dots1Length, dots1, dots2Length, dots2, distance, rel1 or rel2 or relDist); end; +procedure TsSpreadOpenDocChartReader.ReadPictureFile(AStream: TStream; + AFileName: String); +var + memStream: TMemoryStream; + img: TFPCustomImage; + item: TStreamItem; +begin + memStream := TMemoryStream.Create; + try + if UnzipToStream(AStream, AFileName, memStream) then + begin + memstream.Position := 0; + item := TStreamItem.Create; + item.Name := AFileName; + item.Stream := TMemoryStream.Create; + item.Stream.CopyFrom(memStream, memStream.Size); + item.Stream.Position := 0; + FStreamList.Add(item); + end; + finally + memstream.Free; + end; +end; + + {------------------------------------------------------------------------------} { TsSpreadOpenDocChartWriter } {------------------------------------------------------------------------------} @@ -1879,10 +2002,10 @@ begin [ ASCIIName(gradient.Name) ] ); end; - cfsHatched: + cfsHatched, cfsSolidHatched: begin hatch := AChart.Hatches[AFill.Hatch]; - if hatch.Filled then + if AFill.Style = cfsSolidHatched then fillStr := 'draw:fill-hatch-solid="true" '; Result := Format( 'draw:fill="hatch" draw:fill-color="%s" ' + diff --git a/components/fpspreadsheet/source/common/fpsutils.pas b/components/fpspreadsheet/source/common/fpsutils.pas index 0fce6f1f5..4b4b4a37b 100644 --- a/components/fpspreadsheet/source/common/fpsutils.pas +++ b/components/fpspreadsheet/source/common/fpsutils.pas @@ -123,8 +123,8 @@ function GetCellRangeString_R1C1(ASheet1, ASheet2: String; function SheetNameNeedsQuotes(ASheet: String): Boolean; // OpenDocument Syntax -function TryStrToCellRange_ODS(const AStr: String; out ASheet1, ASheet2: String; - out ARow1, ACol1, ARow2, ACol2: Cardinal; out AFlags: TsRelFlags): Boolean; +function TryStrToCellRange_ODS(const AStr: String; var ASheet1, ASheet2: String; + var ARow1, ACol1, ARow2, ACol2: Cardinal; var AFlags: TsRelFlags): Boolean; function GetCellRangeString_ODS(ASheet1, ASheet2: String; ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: TsRelFlags = rfAllRel; WithBrackets: Boolean = true): String; overload; @@ -1345,8 +1345,8 @@ end; Extracts sheets names and cell coordinates from a cell range string in OpenDocument syntax, e.g. "Table1.A1:Table2.B4" -------------------------------------------------------------------------------} -function TryStrToCellRange_ODS(const AStr: String; out ASheet1, ASheet2: String; - out ARow1, ACol1, ARow2, ACol2: Cardinal; out AFlags: TsRelFlags): Boolean; +function TryStrToCellRange_ODS(const AStr: String; var ASheet1, ASheet2: String; + var ARow1, ACol1, ARow2, ACol2: Cardinal; var AFlags: TsRelFlags): Boolean; var p: Integer; cell1Str, cell2Str: String; diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas index 8bf2ce608..b5e1b9869 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas @@ -18,9 +18,9 @@ interface uses // RTL/FCL - Classes, SysUtils, Types, + Classes, Contnrs, SysUtils, Types, // LCL - LCLVersion, Forms, Controls, Graphics, Dialogs, + LCLVersion, Forms, Controls, Graphics, GraphUtil, Dialogs, // TAChart TATypes, TATextElements, TAChartUtils, TALegend, TACustomSource, TACustomSeries, TASeries, TARadialSeries, TAFitUtils, TAFuncSeries, @@ -102,6 +102,7 @@ type FWorkbookSource: TsWorkbookSource; FWorkbook: TsWorkbook; FWorkbookChartIndex: Integer; + FBrushBitmaps: TFPObjectList; procedure SetChart(AValue: TChart); procedure SetWorkbookChartIndex(AValue: Integer); procedure SetWorkbookSource(AValue: TsWorkbookSource); @@ -120,12 +121,14 @@ type procedure UpdateChartAxisLabels(AWorkbookChart: TsChart); procedure UpdateChartBackground(AWorkbookChart: TsChart); procedure UpdateBarSeries(AWorkbookChart: TsChart); - procedure UpdateChartBrush(AWorkbookFill: TsChartFill; ABrush: TBrush); + procedure UpdateChartBrush(AWorkbookChart: TsChart; AWorkbookFill: TsChartFill; ABrush: TBrush); procedure UpdateChartLegend(AWorkbookLegend: TsChartLegend; ALegend: TChartLegend); procedure UpdateChartPen(AWorkbookLine: TsChartLine; APen: TPen); procedure UpdateChartSeriesMarks(AWorkbookSeries: TsChartSeries; AChartSeries: TChartSeries); procedure UpdateChartTitle(AWorkbookTitle: TsChartText; AChartTitle: TChartTitle); + procedure UpdateAreaSeries(AWorkbookSeries: TsAreaSeries; AChartSeries: TAreaSeries); + procedure UpdateBarSeries(AWorkbookSeries: TsBarSeries; AChartSeries: TBarSeries); procedure UpdateLineSeries(AWorkbookSeries: TsLineSeries; AChartSeries: TLineSeries); procedure UpdatePieSeries(AWorkbookSeries: TsPieSeries; AChartSeries: TPieSeries); procedure UpdateScatterSeries(AWorkbookSeries: TsScatterSeries; AChartSeries: TLineSeries); @@ -622,6 +625,7 @@ end; constructor TsWorkbookChartLink.Create(AOwner: TComponent); begin inherited; + FBrushBitmaps := TFPObjectList.Create; FWorkbookChartIndex := -1; end; @@ -632,6 +636,7 @@ end; destructor TsWorkbookChartLink.Destroy; begin if FWorkbookSource <> nil then FWorkbookSource.RemoveListener(self); + FBrushBitmaps.Free; inherited; end; @@ -668,16 +673,9 @@ begin case ASeries.ChartType of ctArea: - begin - UpdateChartBrush(ASeries.Fill, TAreaSeries(ser).AreaBrush); - UpdateChartPen(ASeries.Line, TAreaSeries(ser).AreaContourPen); - TAreaSeries(ser).AreaLinesPen.Style := psClear; - end; + UpdateAreaSeries(TsAreaSeries(ASeries), TAreaSeries(ser)); ctBar: - begin - UpdateChartBrush(ASeries.Fill, TBarSeries(ser).BarBrush); - UpdateChartPen(ASeries.Line, TBarSeries(ser).BarPen); - end; + UpdateBarSeries(TsBarSeries(ASeries), TBarSeries(ser)); ctLine: UpdateLineSeries(TsLineSeries(ASeries), TLineSeries(ser)); ctScatter: @@ -863,6 +861,21 @@ begin UpdateChart; end; +procedure TsWorkbookChartLink.UpdateAreaSeries(AWorkbookSeries: TsAreaSeries; + AChartSeries: TAreaSeries); +begin + UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.AreaBrush); + UpdateChartPen(AWorkbookSeries.Line, AChartSeries.AreaContourPen); + AChartSeries.AreaLinesPen.Style := psClear; +end; + +procedure TsWorkbookChartLink.UpdateBarSeries(AWorkbookSeries: TsBarSeries; + AChartSeries: TBarSeries); +begin + UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.BarBrush); + UpdateChartPen(AWorkbookSeries.Line, AChartSeries.BarPen); +end; + procedure TsWorkbookChartLink.UpdateChart; var ch: TsChart; @@ -1036,18 +1049,42 @@ begin end; end; -procedure TsWorkbookChartLink.UpdateChartBrush(AWorkbookFill: TsChartFill; - ABrush: TBrush); +procedure TsWorkbookChartLink.UpdateChartBrush(AWorkbookChart: TsChart; + AWorkbookFill: TsChartFill; ABrush: TBrush); +var + img: TsChartImage; + png: TCustomBitmap; + w, h, ppi: Integer; begin if (AWorkbookFill <> nil) and (ABrush <> nil) then begin ABrush.Color := Convert_sColor_to_Color(AWorkbookFill.Color); - if AWorkbookFill.Style = cfsNoFill then - ABrush.Style := bsClear - else - ABrush.Style := bsSolid; - // NOTE: TAChart will ignore gradient. - // To be completed: hatched filles. + case AWorkbookFill.Style of + cfsNoFill: + ABrush.Style := bsClear; + cfsSolid: + ABrush.Style := bsSolid; + cfsGradient: + ABrush.Style := bsSolid; // NOTE: TAChart cannot display gradients + cfsHatched, cfsSolidHatched: + ABrush.Style := bsSolid; + cfsImage: + begin + img := AWorkbookChart.Images[AWorkbookFill.Image]; + if img <> nil then + begin + ppi := GetParentForm(FChart).PixelsPerInch; + w := mmToPx(img.Width, ppi); + h := mmToPx(img.Height, ppi); + png := TPortableNetworkGraphic.Create; + png.Assign(img.Image); + ScaleImg(png, w, h); + FBrushBitmaps.Add(png); + ABrush.Bitmap := png; + end else + ABrush.Style := bsSolid; + end; + end; end; end; @@ -1065,7 +1102,7 @@ begin begin Convert_sFont_to_Font(AWorkbookLegend.Font, ALegend.Font); UpdateChartPen(AWorkbookLegend.Border, ALegend.Frame); - UpdateChartBrush(AWorkbookLegend.Background, ALegend.BackgroundBrush); + UpdateChartBrush(AWorkbookLegend.Chart, AWorkbookLegend.Background, ALegend.BackgroundBrush); ALegend.Frame.Visible := (ALegend.Frame.Style <> psClear); ALegend.Alignment := LEG_POS[AWorkbookLegend.Position]; ALegend.UseSidebar := not AWorkbookLegend.CanOverlapPlotArea; @@ -1137,7 +1174,7 @@ begin end; UpdateChartPen(AWorkbookSeries.LabelBorder, AChartSeries.Marks.Frame); - UpdateChartBrush(AWorkbookSeries.LabelBackground, AChartSeries.Marks.LabelBrush); + UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.LabelBackground, AChartSeries.Marks.LabelBrush); end; {@@ Updates title and footer of the linked TAChart. @@ -1153,7 +1190,7 @@ begin AChartTitle.WordWrap := true; Convert_sFont_to_Font(AWorkbookTitle.Font, AChartTitle.Font); UpdateChartPen(AWorkbookTitle.Border, AChartTitle.Frame); - UpdateChartBrush(AWorkbookTitle.Background, AChartTitle.Brush); + UpdateChartBrush(AWorkbookTitle.Chart, AWorkbookTitle.Background, AChartTitle.Brush); AChartTitle.Font.Orientation := round(AWorkbookTitle.RotationAngle * 10); AChartTitle.Frame.Visible := (AChartTitle.Frame.Style <> psClear); end; @@ -1185,7 +1222,7 @@ begin AChartSeries.ShowPoints := AWorkbookSeries.ShowSymbols; if AChartSeries.ShowPoints then begin - UpdateChartBrush(AWorkbookSeries.Fill, AChartSeries.Pointer.Brush); + UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.Pointer.Brush); AChartSeries.Pointer.Pen.Color := AChartSeries.LinePen.Color; AChartSeries.Pointer.Style := POINTER_STYLES[AWorkbookSeries.Symbol]; AChartSeries.Pointer.HorizSize := mmToPx(AWorkbookSeries.SymbolWidth, ppi);