function GetBounds: CRectangle; override;
var ascentHistogram, baseLineHistogram: Histogram; bnds,b: Rectangle; i,j,aX,bX,aY,bY: integer; sidePoints: RectangleSidePoints; delta: integer; needCorrection: boolean; begin bnds:=Bounds; needCorrection:=false; if TextBlock(Parent).TextOrientation then //vertical begin ascentHistogram:=Histogram.Create(bnds.Width+1); baseLineHistogram:= Histogram.Create(bnds.Width+1); for i := 0 to ItemsCount - 1 do for j := 0 to RectangularObjectCollection(Items[i]).ItemsCount - 1 do begin b := RectangularObjectCollection(self.Items[i]).Items[j].Bounds; sidePoints := b.SidePoints; aX :=sidePoints[0].X-bnds.Left; bX := sidePoints[2].X - bnds.Left; ascentHistogram[aX]:=ascentHistogram[aX]+1; baseLineHistogram[bX]:=baseLineHistogram[bX]+1; end; baseLineHistogram.Smooth(2); ascentHistogram.Smooth(2); baseLine:=baseLineHistogram.MaxIndex; ascentLine:=ascentHistogram.MaxIndex; baseLineHistogram.Free; ascentHistogram.Free; delta:=bnds.Width*BASELINE_THRESHOLD div 100; needCorrection := (ascentLine7 then //the line is long - probably all Caps.. begin if TextBlock(Parent).ItemsCount=1 then // if there is only one line in the block - its probably header in all CAPS begin //TODO: Mark as header //assume 23 and 26% of the height correctedBounds:=Bounds.Clone; if TextBlock(Parent).TextOrientation then //vertical correctedBounds.Grow(correctedBounds.Left+correctedBounds.Width*123 div 100,correctedBounds.Bottom) else correctedBounds.Grow(correctedBounds.Right,correctedBounds.Top+correctedBounds.Height*123 div 100); InvalidateBounds; baseLine:=delta; //0 ascentLine:=delta*26 div 100; // Give 26% to CAPS end end; end; end;
var i, j: integer; ascFit, baseLineFit: TLineBestFit; b: Rectangle; sidePoints: RectangleSidePoints; aX, aY, bX, bY, cnt: integer; begin ascFit := TLineBestFit.Create; baseLineFit := TLineBestFit.Create; aX := 0; aY := 0; bX := 0; bY := 0; cnt := 0; if TextBlock(Parent).TextOrientation then //vertical begin for i := 0 to ItemsCount - 1 do for j := 0 to RectangularObjectCollection(Items[i]).ItemsCount - 1 do begin b := RectangularObjectCollection(self.Items[i]).Items[j].Bounds; sidePoints := b.SidePoints; aX := aX + sidePoints[0].X; bX := bX + sidePoints[2].X; aY := aY + sidePoints[0].Y; bY := bY + sidePoints[2].Y;
baseLineFit.Add(sidePoints[2].Y,sidePoints[2].X); ascFit.Add(sidePoints[0].Y,sidePoints[0].X); Inc(cnt); end; if not baseLineFit.BestFit(baseLineSlope, baseLineOffset) then begin baseLineSlope := 0; baseLineOffset := 0; end; if not ascFit.BestFit(ascentLineSlope, ascentLineOffset) then begin ascentLineSlope := 0; ascentLineOffset := 0; end; ay := ay div cnt; by := by div cnt; ax := ax div cnt; bx := bx div cnt; baseLine:=Round(bx+baseLineOffset)-Bounds.Left; ascentLine :=Round(ax+ascentLineOffset)-Bounds.Left; end else //horizontal begin for i := 0 to ItemsCount - 1 do for j := 0 to RectangularObjectCollection(Items[i]).ItemsCount - 1 do begin b := RectangularObjectCollection(self.Items[i]).Items[j].Bounds; sidePoints := b.SidePoints; aX := aX + sidePoints[1].X; bX := bX + sidePoints[3].X; aY := aY + sidePoints[1].Y; bY := bY + sidePoints[3].Y; baseLineFit.Add(sidePoints[3].X, sidePoints[3].Y); ascFit.Add(sidePoints[1].X, sidePoints[1].Y); Inc(cnt); end; if not baseLineFit.BestFit(baseLineSlope, baseLineOffset) then begin baseLineSlope := 0; baseLineOffset := 0; end; if not ascFit.BestFit(ascentLineSlope, ascentLineOffset) then begin ascentLineSlope := 0; ascentLineOffset := 0; end; ay := ay div cnt; by := by div cnt; ax := ax div cnt; bx := bx div cnt; baseLine:=Round(by+baseLineOffset)-Bounds.Top; ascentLine:=Round(ay+ascentLineOffset)-Bounds.Top; end;
baseLineFit.Free; ascFit.Free;
end;