From 829ea72a9d12d571e43e02a243eb292cf7b09075 Mon Sep 17 00:00:00 2001 From: ask Date: Sun, 13 Feb 2011 17:28:51 +0000 Subject: [PATCH] TAChart: Use IChartDrawer to draw labels git-svn-id: trunk@29531 - --- components/tachart/tachartaxis.pas | 23 +++++---- components/tachart/tacustomseries.pas | 17 ++++--- components/tachart/tadrawutils.pas | 22 +++++++++ components/tachart/tagraph.pas | 8 ++-- components/tachart/tatypes.pas | 67 +++++++++++++-------------- 5 files changed, 78 insertions(+), 59 deletions(-) diff --git a/components/tachart/tachartaxis.pas b/components/tachart/tachartaxis.pas index 69a5493872..fbe13d74be 100644 --- a/components/tachart/tachartaxis.pas +++ b/components/tachart/tachartaxis.pas @@ -479,8 +479,7 @@ var ADrawer.PrepareSimplePen(TickColor); LineZ(ATickRect.TopLeft, ATickRect.BottomRight); ALabelCenter += AZOffset; - Marks.DrawLabel( - ADrawer.Canvas, ALabelCenter, ALabelCenter, AText, prevLabelPoly); + Marks.DrawLabel(ADrawer, ALabelCenter, ALabelCenter, AText, prevLabelPoly); end; procedure DrawXMark(AY: Integer; AMark: Double; const AText: String); @@ -492,13 +491,13 @@ var if Grid.Visible then begin ADrawer.Pen := Grid; ADrawer.SetBrushParams(bsClear, clTAColor); - TryApplyStripes(ADrawer, stripeIndex); - BarZ(prevCoord + 1, AClipRect.Top + 1, x, AClipRect.Bottom); + if TryApplyStripes(ADrawer, stripeIndex) then + BarZ(prevCoord + 1, AClipRect.Top + 1, x, AClipRect.Bottom); LineZ(Point(x, AClipRect.Top), Point(x, AClipRect.Bottom)); prevCoord := x; end; - d := TickLength + Marks.CenterOffset(ADrawer.Canvas, AText).cy; + d := TickLength + Marks.CenterOffset(ADrawer, AText).cy; if Alignment = calTop then d := -d; DrawLabelAndTick( @@ -514,13 +513,13 @@ var if Grid.Visible then begin ADrawer.Pen := Grid; ADrawer.SetBrushParams(bsClear, clTAColor); - TryApplyStripes(ADrawer, stripeIndex); - BarZ(AClipRect.Left + 1, prevCoord, AClipRect.Right, y); + if TryApplyStripes(ADrawer, stripeIndex) then + BarZ(AClipRect.Left + 1, prevCoord, AClipRect.Right, y); LineZ(Point(AClipRect.Left, y), Point(AClipRect.Right, y)); prevCoord := y; end; - d := TickLength + Marks.CenterOffset(ADrawer.Canvas, AText).cx; + d := TickLength + Marks.CenterOffset(ADrawer, AText).cx; if Alignment = calLeft then d := -d; DrawLabelAndTick( @@ -544,7 +543,7 @@ begin end; if Grid.Visible and TryApplyStripes(ADrawer, stripeIndex) then if IsVertical then - BarZ(AClipRect.Left + 1, AClipRect.Top, AClipRect.Right, prevCoord) + BarZ(AClipRect.Left + 1, AClipRect.Top + 1, AClipRect.Right, prevCoord) else BarZ(prevCoord + 1, AClipRect.Top + 1, AClipRect.Right, AClipRect.Bottom); end; @@ -566,7 +565,7 @@ begin calBottom: p.Y := FTitleRect.Bottom + d; end; p += AZOffset; - Title.DrawLabel(ADrawer.Canvas, p, p, Title.Caption, dummy); + Title.DrawLabel(ADrawer, p, p, Title.Caption, dummy); end; function TChartAxis.GetDisplayName: string; @@ -650,7 +649,7 @@ procedure TChartAxis.Measure( if AFirstPass then t += SOME_DIGIT; d := IfThen(Marks.DistanceToCenter, 2, 1); - with Marks.MeasureLabel(ADrawer.Canvas, t) do begin + with Marks.MeasureLabel(ADrawer, t) do begin Result.cx := Max(cx div d, Result.cx); Result.cy := Max(cy div d, Result.cy); end; @@ -663,7 +662,7 @@ procedure TChartAxis.Measure( begin if not Title.Visible or (Title.Caption = '') then exit(0); - sz := Title.MeasureLabel(ADrawer.Canvas, Title.Caption); + sz := Title.MeasureLabel(ADrawer, Title.Caption); Result := IfThen(IsVertical, sz.cx, sz.cy) + Title.Distance; end; diff --git a/components/tachart/tacustomseries.pas b/components/tachart/tacustomseries.pas index 8751fb385d..894a706951 100644 --- a/components/tachart/tacustomseries.pas +++ b/components/tachart/tacustomseries.pas @@ -24,8 +24,8 @@ interface uses Classes, Graphics, SysUtils, - TAChartAxis, TAChartUtils, TACustomSource, TAGraph, TALegend, TASources, - TAStyles, TATypes; + TAChartAxis, TAChartUtils, TACustomSource, TADrawUtils, TAGraph, TALegend, + TASources, TAStyles, TATypes; const DEF_AXIS_INDEX = -1; @@ -202,7 +202,7 @@ type procedure PrepareGraphPoints( const AExtent: TDoubleRect; AFilterByExtent: Boolean); procedure UpdateGraphPoints(AIndex: Integer); - procedure UpdateMargins(ACanvas: TCanvas; var AMargins: TRect); override; + procedure UpdateMargins(ADrawer: IChartDrawer; var AMargins: TRect); override; procedure UpdateMinXRange; property UseReticule: Boolean read FUseReticule write SetUseReticule default false; @@ -744,6 +744,7 @@ end; procedure TBasicPointSeries.DrawLabels(ACanvas: TCanvas); var prevLabelPoly: TPointArray; + drawer: IChartDrawer; procedure DrawLabel( const AText: String; const ADataPoint: TPoint; ADir: TLabelDirection); @@ -754,14 +755,15 @@ var center: TPoint; begin if AText = '' then exit; - center := ADataPoint + OFFSETS[ADir] * Marks.CenterOffset(ACanvas, AText); - Marks.DrawLabel(ACanvas, ADataPoint, center, AText, prevLabelPoly); + center := ADataPoint + OFFSETS[ADir] * Marks.CenterOffset(drawer, AText); + Marks.DrawLabel(drawer, ADataPoint, center, AText, prevLabelPoly); end; var g: TDoublePoint; i: Integer; begin + drawer := TCanvasDrawer.Create(ACanvas); if not Marks.IsMarkLabelsVisible then exit; for i := 0 to Count - 1 do begin g := GetGraphPoint(i); @@ -898,7 +900,8 @@ begin FGraphPoints[i - FLoBound].Y += AxisToGraphY(Source[i]^.YList[AIndex]); end; -procedure TBasicPointSeries.UpdateMargins(ACanvas: TCanvas; var AMargins: TRect); +procedure TBasicPointSeries.UpdateMargins( + ADrawer: IChartDrawer; var AMargins: TRect); const LABEL_TO_BORDER = 4; var @@ -916,7 +919,7 @@ begin dir := GetLabelDirection(i); d := IfThen(Marks.DistanceToCenter, 2, 1); - with Marks.MeasureLabel(ACanvas, labelText) do + with Marks.MeasureLabel(ADrawer, labelText) do dist := IfThen(dir in [ldLeft, ldRight], cx, cy) div d; m[dir] := Max(m[dir], dist + Marks.Distance + LABEL_TO_BORDER); end; diff --git a/components/tachart/tadrawutils.pas b/components/tachart/tadrawutils.pas index ae7397cc1c..61f9fb18b4 100644 --- a/components/tachart/tadrawutils.pas +++ b/components/tachart/tadrawutils.pas @@ -55,13 +55,16 @@ type { IChartDrawer } IChartDrawer = interface + procedure AddToFontOrientation(ADelta: Integer); procedure ClippingStart(const AClipRect: TRect); + procedure ClippingStart; procedure ClippingStop; procedure FillRect(AX1, AY1, AX2, AY2: Integer); function GetCanvas: TCanvas; function HasCanvas: Boolean; procedure Line(AX1, AY1, AX2, AY2: Integer); procedure Line(const AP1, AP2: TPoint); + procedure Polygon(const APoints: array of TPoint); procedure PrepareSimplePen(AColor: TChartColor); procedure RadialPie( AX1, AY1, AX2, AY2: Integer; @@ -113,6 +116,8 @@ type procedure SetFont(AFont: TFPCustomFont); procedure SetPen(APen: TFPCustomPen); public + procedure AddToFontOrientation(ADelta: Integer); + procedure ClippingStart; procedure ClippingStart(const AClipRect: TRect); procedure ClippingStop; constructor Create(ACanvas: TCanvas); @@ -121,6 +126,7 @@ type function HasCanvas: Boolean; procedure Line(AX1, AY1, AX2, AY2: Integer); procedure Line(const AP1, AP2: TPoint); + procedure Polygon(const APoints: array of TPoint); procedure PrepareSimplePen(AColor: TChartColor); procedure RadialPie( AX1, AY1, AX2, AY2: Integer; @@ -323,12 +329,23 @@ end; { TCanvasDrawer } +procedure TCanvasDrawer.AddToFontOrientation(ADelta: Integer); +begin + with FCanvas.Font do + Orientation := Orientation + ADelta; +end; + procedure TCanvasDrawer.ClippingStart(const AClipRect: TRect); begin FCanvas.ClipRect := AClipRect; FCanvas.Clipping := true; end; +procedure TCanvasDrawer.ClippingStart; +begin + FCanvas.Clipping := true; +end; + procedure TCanvasDrawer.ClippingStop; begin FCanvas.Clipping := false; @@ -364,6 +381,11 @@ begin FCanvas.Line(AP1, AP2); end; +procedure TCanvasDrawer.Polygon(const APoints: array of TPoint); +begin + FCanvas.Polygon(APoints); +end; + procedure TCanvasDrawer.PrepareSimplePen(AColor: TChartColor); begin TADrawUtils.PrepareSimplePen(FCanvas, AColor); diff --git a/components/tachart/tagraph.pas b/components/tachart/tagraph.pas index 3368a4a548..52e4f72d56 100644 --- a/components/tachart/tagraph.pas +++ b/components/tachart/tagraph.pas @@ -63,7 +63,7 @@ type procedure SetDepth(AValue: TChartDistance); virtual; abstract; procedure SetTitle(const AValue: String); virtual; abstract; procedure SetZPosition(AValue: TChartDistance); virtual; abstract; - procedure UpdateMargins(ACanvas: TCanvas; var AMargins: TRect); virtual; + procedure UpdateMargins(ADrawer: IChartDrawer; var AMargins: TRect); virtual; procedure VisitSources( AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData); virtual; @@ -858,7 +858,7 @@ begin Result := FMargins.Data; for i := 0 to SeriesCount - 1 do if Series[i].Active then - Series[i].UpdateMargins(ADrawer.Canvas, Result); + Series[i].UpdateMargins(ADrawer, Result); end; function TChart.GetSeriesCount: Integer; @@ -1285,9 +1285,9 @@ begin end; procedure TBasicChartSeries.UpdateMargins( - ACanvas: TCanvas; var AMargins: TRect); + ADrawer: IChartDrawer; var AMargins: TRect); begin - Unused(ACanvas, AMargins); + Unused(ADrawer, AMargins); end; procedure TBasicChartSeries.VisitSources( diff --git a/components/tachart/tatypes.pas b/components/tachart/tatypes.pas index e2902b539b..4551aecfd0 100644 --- a/components/tachart/tatypes.pas +++ b/components/tachart/tatypes.pas @@ -128,7 +128,7 @@ type private function GetDistanceToCenter: Boolean; function LabelAngle: Double; inline; - procedure PutLabelFontTo(ACanvas: TCanvas); + procedure PutLabelFontTo(ADrawer: IChartDrawer); procedure SetAttachment(AValue: TChartMarkAttachment); procedure SetDistanceToCenter(AValue: Boolean); protected @@ -160,14 +160,14 @@ type destructor Destroy; override; public - procedure Assign(Source: TPersistent); override; - function CenterOffset(ACanvas: TCanvas; const AText: String): TSize; + procedure Assign(ASource: TPersistent); override; + function CenterOffset(ADrawer: IChartDrawer; const AText: String): TSize; procedure DrawLabel( - ACanvas: TCanvas; const ADataPoint, ALabelCenter: TPoint; + ADrawer: IChartDrawer; const ADataPoint, ALabelCenter: TPoint; const AText: String; var APrevLabelPoly: TPointArray); function GetLabelPolygon(ASize: TPoint): TPointArray; function IsMarkLabelsVisible: Boolean; - function MeasureLabel(ACanvas: TCanvas; const AText: String): TSize; + function MeasureLabel(ADrawer: IChartDrawer; const AText: String): TSize; procedure SetAdditionalAngle(AAngle: Double); public property DistanceToCenter: Boolean @@ -482,10 +482,10 @@ end; { TGenericChartMarks } -procedure TGenericChartMarks.Assign(Source: TPersistent); +procedure TGenericChartMarks.Assign(ASource: TPersistent); begin - if Source is Self.ClassType then - with TGenericChartMarks(Source) do begin + if ASource is Self.ClassType then + with TGenericChartMarks(ASource) do begin Self.FClipped := FClipped; Self.FDistance := FDistance; Self.FFormat := FFormat; @@ -498,15 +498,15 @@ begin Self.FOverlapPolicy := FOverlapPolicy; Self.FStyle := FStyle; end; - inherited Assign(Source); + inherited Assign(ASource); end; function TGenericChartMarks.CenterOffset( - ACanvas: TCanvas; const AText: String): TSize; + ADrawer: IChartDrawer; const AText: String): TSize; begin Result := Point(Distance, Distance); if not DistanceToCenter then - Result += MeasureLabel(ACanvas, AText) div 2; + Result += MeasureLabel(ADrawer, AText) div 2; end; constructor TGenericChartMarks.Create(AOwner: TCustomChart); @@ -532,16 +532,15 @@ begin end; procedure TGenericChartMarks.DrawLabel( - ACanvas: TCanvas; const ADataPoint, ALabelCenter: TPoint; + ADrawer: IChartDrawer; const ADataPoint, ALabelCenter: TPoint; const AText: String; var APrevLabelPoly: TPointArray); var - wasClipping: Boolean = false; labelPoly: TPointArray; ptText: TPoint; i: Integer; begin - PutLabelFontTo(ACanvas); - ptText := MultiLineTextExtent(ACanvas, AText); + PutLabelFontTo(ADrawer); + ptText := ADrawer.TextExtent(AText); labelPoly := GetLabelPolygon(ptText); for i := 0 to High(labelPoly) do labelPoly[i] += ALabelCenter; @@ -553,23 +552,21 @@ begin exit; APrevLabelPoly := labelPoly; - if not Clipped and ACanvas.Clipping then begin - ACanvas.Clipping := false; - wasClipping := true; - end; + if not Clipped then + ADrawer.ClippingStop; - ACanvas.Pen.Assign(LinkPen); - ACanvas.Line(ADataPoint, ALabelCenter); - ACanvas.Brush.Assign(LabelBrush); + ADrawer.Pen := LinkPen; + ADrawer.Line(ADataPoint, ALabelCenter); + ADrawer.Brush := LabelBrush; if IsMarginRequired then begin - ACanvas.Pen.Assign(Frame); - ACanvas.Polygon(labelPoly); + ADrawer.Pen := Frame; + ADrawer.Polygon(labelPoly); end; ptText := RotatePoint(-ptText div 2, LabelAngle) + ALabelCenter; - MultiLineTextOut(ACanvas, ptText, AText, taLeftJustify, 0); - if wasClipping then - ACanvas.Clipping := true; + ADrawer.TextOut.Pos(ptText).Text(AText).Done; + if not Clipped then + ADrawer.ClippingStart; end; function TGenericChartMarks.GetDistanceToCenter: Boolean; @@ -603,24 +600,22 @@ begin end; function TGenericChartMarks.MeasureLabel( - ACanvas: TCanvas; const AText: String): TSize; + ADrawer: IChartDrawer; const AText: String): TSize; var sz: TPoint; begin - PutLabelFontTo(ACanvas); - sz := MultiLineTextExtent(ACanvas, AText); + PutLabelFontTo(ADrawer); + sz := ADrawer.TextExtent(AText); if IsMarginRequired then sz += Point(MARKS_MARGIN_X, MARKS_MARGIN_Y) * 2; Result := MeasureRotatedRect(sz, LabelAngle); end; -procedure TGenericChartMarks.PutLabelFontTo(ACanvas: TCanvas); +procedure TGenericChartMarks.PutLabelFontTo(ADrawer: IChartDrawer); begin - with ACanvas.Font do begin - Assign(LabelFont); - if FAdditionalAngle <> 0 then - Orientation := Orientation + RadToOrient(FAdditionalAngle); - end; + ADrawer.Font := LabelFont; + if FAdditionalAngle <> 0 then + ADrawer.AddToFontOrientation(RadToOrient(FAdditionalAngle)); end; procedure TGenericChartMarks.SetAdditionalAngle(AAngle: Double);