TAChart: TBasicPointSeries uses uninitialized variables
Original Reporter info from Mantis: Marcin Wiazowski
-
Reporter name:
Original Reporter info from Mantis: Marcin Wiazowski
- Reporter name:
Description:
TAChart: TBasicPointSeries uses uninitialized variables
Please launch the attached Reproduce application.
a) After start, bars' marks are invisible. Minimize the application, and maximize it again (so chart will be repainted) - right bar's mark will become visible then (left bar's mark should stay invisible - this is OK).
b) Press "Add data" button - a bar will be added, but its mark will be truncated. Minimize the application, and maximize it again (so chart will be repainted) - bar will not be truncated anymore.
The problem manifests itself in TBasicPointSeries.UpdateMargins() - there is a loop:
for i := FLoBound to FUpBound do begin
FLoBound and FUpBound are used as a range of data, that is potentially visible on the chart - it's much faster to perform painting through FLoBound..FUpBound than through 0..Source.Count-1. They are initialized in a TBasicPointSeries.FindExtentInterval call, but - interestingly - at every chart painting, TBasicPointSeries.FindExtentInterval() is called AFTER TBasicPointSeries.UpdateMargins() - so, each time, TBasicPointSeries.UpdateMargins() uses out-of-date FLoBound and FUpBound!
Some symptoms:
-
FLoBound and FUpBound are NOT initialized in TBasicPointSeries.Create, so they are both 0 - although they should reflect default data source's state.
-
FLoBound and FUpBound are NOT reinitialized when data source is changed (for example some data points have been deleted) - so they may be out of bounds.
-
FLoBound and FUpBound are NOT reinitialized when a new data source is assigned to TBasicPointSeries.Source - so they may be out of bounds.
The attached patch sets FLoBound to 0 and FUpBound to Source.Count-1 each time, when data source changes, and also in TBasicPointSeries.Create - so iterations will be slow, but, at least, there is no more danger of out-of-bounds memory accesses. The patch is very rough, and should be only treated as a reference (there was a need to access strict protected fields from an other class, so I changed declarations and made some hacking - some code redesigning should solve this).
But a long-term solution should also, during the chart painting, call the TBasicPointSeries.FindExtentInterval() before the TBasicPointSeries.UpdateMargins(), to make painting as fast as it should be.
Regards