GraphWPF - DrawGraphic - улучшения, DrawText и TextOut с параметром FontType, Font.WithSize, Font.WithStyle, Font.WithColor, Font.WithName
This commit is contained in:
parent
49032ed2be
commit
a2bac8dedb
|
|
@ -4,8 +4,8 @@ begin
|
|||
Window.Title := 'Графики функций';
|
||||
var ww := Window.Width / 2;
|
||||
var hh := Window.Height / 2;
|
||||
DrawGraph(x -> sin(4 * x) + cos(3 * x), -5, 5, 0, 0, ww, hh);
|
||||
DrawGraph(x -> x * x, -5, 5, ww - 1, 0, ww, hh);
|
||||
DrawGraph(x -> exp(x), -5, 5, 0, hh-1, ww, hh);
|
||||
DrawGraph(x -> x*cos(2*x-1), -5, 5, ww - 1, hh-1, ww, hh);
|
||||
DrawGraph(x -> sin(4 * x) + cos(3 * x), -5, 5, 0, 0, ww, hh, 'sin(4 * x) + cos(3 * x)');
|
||||
DrawGraph(x -> x * x, -5, 5, ww - 1, 0, ww, hh, 'x * x');
|
||||
DrawGraph(x -> exp(x), -5, 5, 0, hh-1, ww, hh, 'exp(x)');
|
||||
DrawGraph(x -> x*cos(2*x-1), -5, 5, ww - 1, hh-1, ww, hh, 'x * cos(2*x-1)');
|
||||
end.
|
||||
|
|
@ -56,6 +56,8 @@ type
|
|||
//{{{--doc: Конец секции 1 }}}
|
||||
|
||||
function GetBrush(c: Color): GBrush;
|
||||
function GetFontFamily(name: string): FontFamily;
|
||||
|
||||
|
||||
//{{{doc: Начало секции 2 }}}
|
||||
|
||||
|
|
@ -123,7 +125,7 @@ type
|
|||
tf := new Typeface('Arial');
|
||||
sz: real := 14;
|
||||
c: GColor := Colors.Black;
|
||||
procedure SetNameP(s: string) := tf := new Typeface(new FontFamily(s),FontStyles.Normal,FontWeights.Normal,FontStretches.Normal);
|
||||
procedure SetNameP(s: string) := tf := new Typeface(GetFontFamily(s),FontStyles.Normal,FontWeights.Normal,FontStretches.Normal);
|
||||
function GetName := tf.FontFamily.ToString;
|
||||
procedure SetName(s: string) := Invoke(SetNameP,s);
|
||||
procedure SetFSP(fs: FontStyle);
|
||||
|
|
@ -135,11 +137,11 @@ type
|
|||
FontStyle.Italic: s := FontStyles.Italic;
|
||||
FontStyle.BoldItalic: begin s := FontStyles.Italic; w := FontWeights.Bold; end;
|
||||
end;
|
||||
tf := new Typeface(new FontFamily(Name),s,w,FontStretches.Normal);
|
||||
tf := new Typeface(GetFontFamily(Name),s,w,FontStretches.Normal);
|
||||
end;
|
||||
procedure SetFS(fs: FontStyle) := Invoke(SetFSP,fs);
|
||||
function TypefaceClone := tf;
|
||||
function BrushConstruct := GetBrush(c);
|
||||
property BrushClone: GBrush read GetBrush(c);
|
||||
property TypefaceClone: Typeface read tf;
|
||||
public
|
||||
/// Цвет шрифта
|
||||
property Color: GColor read c write c;
|
||||
|
|
@ -149,6 +151,38 @@ type
|
|||
property Size: real read sz write sz;
|
||||
/// Стиль шрифта
|
||||
property Style: FontStyle write SetFS;
|
||||
/// Декоратор стиля шрифта
|
||||
function WithStyle(fs: FontStyle): FontType;
|
||||
begin
|
||||
Result := new FontType;
|
||||
Result.sz := sz;
|
||||
Result.Color := c;
|
||||
Result.Style := fs;
|
||||
end;
|
||||
/// Декоратор цвета шрифта
|
||||
function WithColor(c: GColor): FontType;
|
||||
begin
|
||||
Result := new FontType;
|
||||
Result.tf := tf;
|
||||
Result.sz := sz;
|
||||
Result.Color := c;
|
||||
end;
|
||||
/// Декоратор размера шрифта
|
||||
function WithSize(sz: real): FontType;
|
||||
begin
|
||||
Result := new FontType;
|
||||
Result.tf := tf;
|
||||
Result.sz := sz;
|
||||
Result.Color := c;
|
||||
end;
|
||||
/// Декоратор стиля шрифта
|
||||
function WithName(name: string): FontType;
|
||||
begin
|
||||
Result := new FontType;
|
||||
Result.sz := sz;
|
||||
Result.Color := c;
|
||||
Result.tf := new Typeface(GetFontFamily(name),tf.Style,tf.Weight,FontStretches.Normal);
|
||||
end;
|
||||
end;
|
||||
|
||||
// -----------------------------------------------------
|
||||
|
|
@ -453,6 +487,9 @@ procedure DrawText(r: GRect; text: string; c: GColor; align: Alignment := Alignm
|
|||
procedure DrawText(r: GRect; number: integer; c: GColor; align: Alignment := Alignment.Center; angle: real := 0.0);
|
||||
/// Выводит вещественное в прямоугольник
|
||||
procedure DrawText(r: GRect; number: real; c: GColor; align: Alignment := Alignment.Center; angle: real := 0.0);
|
||||
/// Выводит строку в прямоугольник к координатами левого верхнего угла (x,y) указанным шрифтом
|
||||
procedure DrawText(x, y, w, h: real; text: string; f: FontType; align: Alignment; angle: real);
|
||||
|
||||
|
||||
/// Выводит строку в позицию (x,y)
|
||||
procedure TextOut(x, y: real; text: string; align: Alignment := Alignment.LeftTop; angle: real := 0.0);
|
||||
|
|
@ -466,6 +503,8 @@ procedure TextOut(x, y: real; text: integer; c: GColor; align: Alignment := Alig
|
|||
procedure TextOut(x, y: real; text: real; align: Alignment := Alignment.LeftTop; angle: real := 0.0);
|
||||
/// Выводит вещественное в позицию (x,y) цветом c
|
||||
procedure TextOut(x, y: real; text: real; c: GColor; align: Alignment := Alignment.LeftTop; angle: real := 0.0);
|
||||
/// Выводит строку в позицию (x,y) указанным шрифтом
|
||||
procedure TextOut(x, y: real; text: string; f: FontType; align: Alignment := Alignment.LeftTop; angle: real := 0.0);
|
||||
|
||||
/// Ширина текста при выводе
|
||||
function TextWidth(text: string): real;
|
||||
|
|
@ -582,6 +621,7 @@ procedure __FinalizeModule__;
|
|||
implementation
|
||||
|
||||
var BrushesDict := new Dictionary<Color,GBrush>;
|
||||
var FontFamiliesDict := new Dictionary<string,FontFamily>;
|
||||
|
||||
function GetBrush(c: Color): GBrush;
|
||||
begin
|
||||
|
|
@ -594,6 +634,16 @@ begin
|
|||
else Result := BrushesDict[c];
|
||||
end;
|
||||
|
||||
function GetFontFamily(name: string): FontFamily;
|
||||
begin
|
||||
if not (name in FontFamiliesDict) then
|
||||
begin
|
||||
var b := new FontFamily(name);
|
||||
FontFamiliesDict[name] := b;
|
||||
Result := b
|
||||
end
|
||||
else Result := FontFamiliesDict[name];
|
||||
end;
|
||||
|
||||
procedure Redraw(d: ()->()) := app.Dispatcher.Invoke(d);
|
||||
function getApp: Application := app;
|
||||
|
|
@ -778,14 +828,23 @@ begin
|
|||
ReleaseDC(dc);
|
||||
end;
|
||||
|
||||
var RusCultureInfo := new System.Globalization.CultureInfo('ru-ru');
|
||||
|
||||
function FormText(text: string) :=
|
||||
new FormattedText(text,new System.Globalization.CultureInfo('ru-ru'), FlowDirection.LeftToRight,
|
||||
Font.TypefaceClone, Font.Size, Font.BrushConstruct);
|
||||
new FormattedText(text, RusCultureInfo, FlowDirection.LeftToRight,
|
||||
Font.tf, Font.Size, Font.BrushClone);
|
||||
|
||||
function FormTextC(text: string; c: GColor): FormattedText :=
|
||||
new FormattedText(text,new System.Globalization.CultureInfo('ru-ru'), FlowDirection.LeftToRight,
|
||||
Font.TypefaceClone, Font.Size, GetBrush(c));
|
||||
function FormTextFont(text: string; f: FontType): FormattedText;
|
||||
begin
|
||||
var tf := new Typeface(GetFontFamily(f.Name),f.tf.Style,f.tf.Weight,f.tf.Stretch);
|
||||
Result := new FormattedText(text,RusCultureInfo, FlowDirection.LeftToRight, tf, f.Size, f.BrushClone);
|
||||
end;
|
||||
|
||||
function FormTextC(text: string; c: GColor): FormattedText;
|
||||
begin
|
||||
Result := new FormattedText(text,RusCultureInfo, FlowDirection.LeftToRight, Font.TypefaceClone, Font.Size, GetBrush(c));
|
||||
end;
|
||||
|
||||
function TextWidthP(text: string) := FormText(text).Width;
|
||||
function TextHeightP(text: string) := FormText(text).Height;
|
||||
|
||||
|
|
@ -800,60 +859,42 @@ type TextV = auto class
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TextPFull(x,y: real; text: string; angle,x0,y0: real);
|
||||
procedure TextPFull(x,y: real; text: string; angle,x0,y0: real; f: FontType);
|
||||
begin
|
||||
var dc: DrawingContext;
|
||||
var ft := FormTextFont(text,f);
|
||||
var dc := GetDC();
|
||||
var RT := new RotateTransform(angle,x0,y0);
|
||||
dc.PushTransform(RT);
|
||||
if CurrentCoordType = StandardCoords then
|
||||
begin
|
||||
dc := GetDC();
|
||||
var RT := new RotateTransform(angle,x0,y0);
|
||||
dc.PushTransform(RT);
|
||||
dc.DrawText(FormText(text),new Point(x,y));
|
||||
dc.Pop();
|
||||
dc.DrawText(ft,new Point(x,y));
|
||||
end
|
||||
else
|
||||
begin
|
||||
var m := Host.RenderTransform.Value;
|
||||
var mt := new MatrixTransform(1/m.M11,0,0,1/m.M22,x,y);
|
||||
dc := GetDC();
|
||||
var RT := new RotateTransform(angle,x0,y0);
|
||||
dc.PushTransform(RT);
|
||||
dc.PushTransform(mt);
|
||||
dc.DrawText(FormText(text),new Point(0,0));
|
||||
|
||||
dc.DrawText(ft,new Point(0,0));
|
||||
|
||||
dc.Pop();
|
||||
dc.Pop();
|
||||
end;
|
||||
end;
|
||||
dc.Pop();
|
||||
//dc.DrawRectangle(Brushes.White,nil,new GRect(new Point(x,y),TextV.Create(text).TextSize));
|
||||
ReleaseDC(dc);
|
||||
end;
|
||||
|
||||
procedure TextPFull(x,y: real; text: string; angle,x0,y0: real; c: Color);
|
||||
begin
|
||||
var dc: DrawingContext;
|
||||
if CurrentCoordType = StandardCoords then
|
||||
begin
|
||||
dc := GetDC();
|
||||
var RT := new RotateTransform(angle,x0,y0);
|
||||
dc.PushTransform(RT);
|
||||
dc.DrawText(FormTextC(text,c),new Point(x,y));
|
||||
dc.Pop();
|
||||
end
|
||||
else
|
||||
begin
|
||||
var m := Host.RenderTransform.Value;
|
||||
var mt := new MatrixTransform(1/m.M11,0,0,1/m.M22,x,y);
|
||||
dc := GetDC();
|
||||
var RT := new RotateTransform(angle,x0,y0);
|
||||
dc.PushTransform(RT);
|
||||
dc.PushTransform(mt);
|
||||
dc.DrawText(FormTextC(text,c),new Point(0,0));
|
||||
dc.Pop();
|
||||
dc.Pop();
|
||||
end;
|
||||
//dc.DrawRectangle(Brushes.White,nil,new GRect(new Point(x,y),TextV.Create(text).TextSize));
|
||||
ReleaseDC(dc);
|
||||
TextPFull(x,y,text,angle,x0,y0,Font.WithColor(c));
|
||||
end;
|
||||
|
||||
procedure TextPFull(x,y: real; text: string; angle,x0,y0: real);
|
||||
begin
|
||||
TextPFull(x,y,text,angle,x0,y0,Font);
|
||||
end;
|
||||
|
||||
|
||||
var dpic := new Dictionary<string, BitmapImage>;
|
||||
|
||||
function GetBitmapImage(fname: string): BitmapImage;
|
||||
|
|
@ -1082,6 +1123,7 @@ procedure FillPolygonPC(points: array of Point; c: GColor) := PolygonPFull(point
|
|||
|
||||
procedure DrawTextP(x,y: real; text: string; angle,x0,y0: real) := TextPFull(x,y,text,angle,x0,y0);
|
||||
procedure DrawTextPC(x,y: real; text: string; angle,x0,y0: real; c: GColor) := TextPFull(x,y,text,angle,x0,y0,c);
|
||||
procedure DrawTextPFont(x,y: real; text: string; angle,x0,y0: real; f: FontType) := TextPFull(x,y,text,angle,x0,y0,f);
|
||||
|
||||
procedure EllipseNew(x,y,r1,r2: real)
|
||||
:= InvokeVisual(DrawGeometryP,VE.Create(()->EllipseGeometry.Create(Pnt(x,y),r1,r2)));
|
||||
|
|
@ -1184,6 +1226,7 @@ procedure TextOutHelper(x,y: real; text: string; angle: real; x0,y0: real) := In
|
|||
procedure TextOutHelper(x,y: real; text: string; angle: real; c: GColor; x0,y0: real) := InvokeVisual(DrawTextPC,x,y,text,angle,x0,y0,c);
|
||||
//procedure TextOut(x,y: real; number: integer; c: GColor) := TextOut(x,y,'' + number,c);
|
||||
//procedure TextOut(x,y: real; number: real; c: GColor) := TextOut(x,y,'' + number,c);
|
||||
procedure TextOutHelper(x,y: real; text: string; angle: real; x0,y0: real; f: FontType) := InvokeVisual(DrawTextPFont,x,y,text,angle,x0,y0,f);
|
||||
|
||||
procedure DrawTextHelper(var x, y, x0, y0: real; w, h: real; text: string; align: Alignment := Alignment.Center);
|
||||
begin
|
||||
|
|
@ -1239,8 +1282,6 @@ procedure DrawText(x, y, w, h: real; text: string; c: GColor; align: Alignment;
|
|||
begin
|
||||
var (x0,y0) := (x,y);
|
||||
DrawTextHelper(x, y, x0, y0, w, h, text, align);
|
||||
//FillCircle(x0,y0,0.1,Colors.Blue);
|
||||
//FillCircle(x,y,0.1,Colors.Red);
|
||||
TextOutHelper(x,y,text,angle,c,x0,y0)
|
||||
end;
|
||||
/// Выводит целое в прямоугольник к координатами левого верхнего угла (x,y)
|
||||
|
|
@ -1264,6 +1305,14 @@ procedure DrawText(r: GRect; number: integer; c: GColor; align: Alignment; angle
|
|||
/// Выводит вещественное в прямоугольник
|
||||
procedure DrawText(r: GRect; number: real; c: GColor; align: Alignment; angle: real) := DrawText(r.x,r.y,r.Width,r.Height,number,c,align,angle);
|
||||
|
||||
/// Выводит строку в прямоугольник к координатами левого верхнего угла (x,y) данным шрифтом
|
||||
procedure DrawText(x, y, w, h: real; text: string; f: FontType; align: Alignment; angle: real);
|
||||
begin
|
||||
var (x0,y0) := (x,y);
|
||||
DrawTextHelper(x, y, x0, y0, w, h, text, align);
|
||||
TextOutHelper(x,y,text,angle,x0,y0,f)
|
||||
end;
|
||||
|
||||
{function ConvertAlign(align: Alignment): Alignment;
|
||||
begin
|
||||
Result := align;
|
||||
|
|
@ -1286,6 +1335,8 @@ procedure TextOut(x, y: real; text: integer; c: GColor; align: Alignment; angle:
|
|||
procedure TextOut(x, y: real; text: real; align: Alignment; angle: real) := TextOut(x, y, ''+text,align,angle);
|
||||
procedure TextOut(x, y: real; text: real; c: GColor; align: Alignment; angle: real) := TextOut(x, y, ''+text, c,align,angle);
|
||||
|
||||
procedure TextOut(x, y: real; text: string; f: FontType; align: Alignment; angle: real) := DrawText(x, y, 0, 0, text, f, align, angle);
|
||||
|
||||
|
||||
type
|
||||
FS = auto class
|
||||
|
|
@ -1295,7 +1346,9 @@ type
|
|||
title: string;
|
||||
marginY := 6;
|
||||
marginX := 6;
|
||||
spaceBetweenTextAndGraph := 4;
|
||||
XTicksPrecision := 3;
|
||||
YTicksPrecision := 5;
|
||||
spaceBetweenTextAndGraph := 6;
|
||||
|
||||
constructor (a, b, min, max, x, y, w, h: real; f: real -> real; XTicks: real := 1; YTicks: real := 1; title: string := '');
|
||||
begin
|
||||
|
|
@ -1322,9 +1375,16 @@ type
|
|||
procedure CorrectBounds;
|
||||
begin
|
||||
//var digits := 5;
|
||||
var tw := TextWidth('-99.9');
|
||||
if real.IsNaN(XTicks) then
|
||||
XTicks := Ticks(b-a);
|
||||
if real.IsNaN(YTicks) then
|
||||
YTicks := Ticks(max-min);
|
||||
var th := TextHeight('0');
|
||||
w -= marginX * 2 + spaceBetweenTextAndGraph + tw;
|
||||
var tw := GetRY0.Step(YTicks).TakeWhile(ry -> ry <= max).Select(y -> TextWidth(y.Round(YTicksPrecision).ToString)).Max;
|
||||
var dd := TextWidth(b.Round(xTicksPrecision).ToString)/2;
|
||||
|
||||
//var tw := TextWidth('-99.9');
|
||||
w -= marginX * 2 + spaceBetweenTextAndGraph + tw + dd;
|
||||
h -= marginY * 2 + spaceBetweenTextAndGraph + th;
|
||||
x += marginX + spaceBetweenTextAndGraph + tw;
|
||||
y += marginY;
|
||||
|
|
@ -1335,10 +1395,6 @@ type
|
|||
end;
|
||||
mx := w / (b - a);
|
||||
my := h / (max - min);
|
||||
if real.IsNaN(XTicks) then
|
||||
XTicks := Ticks(b-a);
|
||||
if real.IsNaN(YTicks) then
|
||||
YTicks := Ticks(max-min);
|
||||
end;
|
||||
|
||||
function Apply(xx: real) := Pnt(x + mx * (xx - a), y + my * (max - f(xx)));
|
||||
|
|
@ -1347,6 +1403,26 @@ type
|
|||
function ScreenToRealX(xx: real) := (xx - x) / mx + a;
|
||||
function ScreenToRealY(yy: real) := (y + h - yy) / my + min;
|
||||
|
||||
function GetRX0: real;
|
||||
begin
|
||||
var xt := XTicks * Trunc(Abs(a)/XTicks);
|
||||
var rx0: real;
|
||||
if a <= 0 then
|
||||
rx0 := -xt
|
||||
else rx0 := xt + XTicks;
|
||||
Result := rx0;
|
||||
end;
|
||||
|
||||
function GetRY0: real;
|
||||
begin
|
||||
var yt := YTicks * Trunc(Abs(min)/YTicks);
|
||||
var ry0: real;
|
||||
if min <= 0 then
|
||||
ry0 := -yt
|
||||
else ry0 := yt + YTicks;
|
||||
Result := ry0;
|
||||
end;
|
||||
|
||||
procedure Draw;
|
||||
var AxisColor := GrayColor(112);
|
||||
begin
|
||||
|
|
@ -1354,40 +1430,34 @@ type
|
|||
CorrectBounds;
|
||||
Pen.Color := Colors.LightGray;
|
||||
var sx := mx * XTicks;
|
||||
var xt := XTicks * Trunc(Abs(a)/XTicks);
|
||||
var rx0: real;
|
||||
if a <= 0 then
|
||||
rx0 := -xt
|
||||
else rx0 := xt + XTicks;
|
||||
//var rx0 := a;
|
||||
|
||||
var rx0 := GetRX0;
|
||||
|
||||
var x0 := RealToScreenX(rx0);
|
||||
while x0<=x+w+0.000001 do
|
||||
begin
|
||||
if Abs(rx0)<0.000001 then
|
||||
Line(x0,y,x0,y+h,AxisColor)
|
||||
else Line(x0,y,x0,y+h);
|
||||
TextOut(x0,y+h+4,rx0.Round(3),Alignment.CenterTop);
|
||||
TextOut(x0,y+h+4,rx0.Round(XTicksPrecision),Alignment.CenterTop);
|
||||
x0 += sx;
|
||||
rx0 += XTicks;
|
||||
end;
|
||||
|
||||
var sy := my * YTicks;
|
||||
var yt := YTicks * Trunc(Abs(min)/YTicks);
|
||||
var ry0: real;
|
||||
if min <= 0 then
|
||||
ry0 := -yt
|
||||
else ry0 := yt + YTicks;
|
||||
//var ry0 := min;
|
||||
//var y0 := y + h;
|
||||
|
||||
var ry0 := GetRY0;
|
||||
|
||||
if title<>'' then
|
||||
TextOut(x+w/2,y-spaceBetweenTextAndGraph,Title,Alignment.CenterBottom);
|
||||
TextOut(x+w/2,y-spaceBetweenTextAndGraph,Title,Font.WithSize(Font.Size*1.15){.WithStyle(FontStyle.Bold)},Alignment.CenterBottom);
|
||||
var y0 := RealToScreenY(ry0);
|
||||
|
||||
while y0>=y-0.000001 do
|
||||
begin
|
||||
if Abs(ry0)<0.000001 then
|
||||
Line(x,y0,x+w,y0,AxisColor)
|
||||
else Line(x,y0,x+w,y0);
|
||||
TextOut(x-4,y0,ry0.Round(5),Alignment.RightCenter);
|
||||
TextOut(x-4,y0,ry0.Round(YTicksPrecision),Alignment.RightCenter);
|
||||
y0 -= sy;
|
||||
ry0 += YTicks;
|
||||
end;
|
||||
|
|
|
|||
Loading…
Reference in a new issue