RichText, RichEdit: Developing Diagram

This commit is contained in:
Mirek Fidler 2025-07-27 09:35:53 +02:00
parent 3c2b20fd03
commit 6e83c52ef2
11 changed files with 185 additions and 35 deletions

View file

@ -1,15 +1,15 @@
LAYOUT(TextToSvgPathLayout, 704, 588) LAYOUT(TextToSvgPathLayout, 704, 588)
ITEM(Label, dv___0, SetLabel(t_("Text")).LeftPosZ(8, 33).TopPosZ(28, 19)) ITEM(Upp::Label, dv___0, SetLabel(t_("Text")).LeftPosZ(8, 33).TopPosZ(28, 19))
ITEM(EditString, text, HSizePosZ(44, 8).TopPosZ(28, 19)) ITEM(Upp::EditString, text, HSizePosZ(44, 8).TopPosZ(28, 19))
ITEM(Label, dv___2, SetLabel(t_("Font")).LeftPosZ(8, 33).TopPosZ(4, 19)) ITEM(Upp::Label, dv___2, SetLabel(t_("Font")).LeftPosZ(8, 33).TopPosZ(4, 19))
ITEM(DropList, face, LeftPosZ(44, 188).TopPosZ(4, 19)) ITEM(Upp::DropList, face, LeftPosZ(44, 188).TopPosZ(4, 19))
ITEM(Label, dv___4, SetLabel(t_("Height")).LeftPosZ(252, 39).TopPosZ(4, 19)) ITEM(Upp::Label, dv___4, SetLabel(t_("Height")).LeftPosZ(252, 39).TopPosZ(4, 19))
ITEM(WithDropChoice<EditInt>, height, LeftPosZ(292, 56).TopPosZ(4, 19)) ITEM(Upp::WithDropChoice<Upp::EditInt>, height, LeftPosZ(292, 56).TopPosZ(4, 19))
ITEM(Option, bold, SetLabel(t_("Bold")).LeftPosZ(356, 52).TopPosZ(4, 20)) ITEM(Upp::Option, bold, SetLabel(t_("Bold")).LeftPosZ(356, 52).TopPosZ(4, 20))
ITEM(Option, italic, SetLabel(t_("Italic")).LeftPosZ(408, 52).TopPosZ(4, 20)) ITEM(Upp::Option, italic, SetLabel(t_("Italic")).LeftPosZ(408, 52).TopPosZ(4, 20))
ITEM(LineEdit, svgpath, HSizePosZ(8, 8).VSizePosZ(52, 268)) ITEM(Upp::LineEdit, svgpath, HSizePosZ(8, 8).VSizePosZ(52, 268))
UNTYPED(preview, HSizePosZ(8, 8).BottomPosZ(4, 260)) UNTYPED(preview, HSizePosZ(8, 8).BottomPosZ(4, 260))
ITEM(Button, copy, SetLabel(t_("Copy path to clipboard")).RightPosZ(8, 128).TopPosZ(4, 20)) ITEM(Upp::Button, copy, SetLabel(t_("Copy path to clipboard")).RightPosZ(8, 128).TopPosZ(4, 20))
ITEM(Option, singleline, SetLabel(t_("Single line")).LeftPosZ(484, 80).TopPosZ(4, 20)) ITEM(Upp::Option, singleline, SetLabel(t_("Single line")).LeftPosZ(484, 80).TopPosZ(4, 20))
END_LAYOUT END_LAYOUT

View file

@ -27,6 +27,7 @@ IMAGE_ID(PaperA__UHD)
IMAGE_ID(MoveFront__UHD) IMAGE_ID(MoveFront__UHD)
IMAGE_ID(MoveBack__UHD) IMAGE_ID(MoveBack__UHD)
IMAGE_ID(Size__UHD) IMAGE_ID(Size__UHD)
IMAGE_ID(FontSvg__UHD)
IMAGE_ID(DisplayGrid) IMAGE_ID(DisplayGrid)
IMAGE_ID(Diagram) IMAGE_ID(Diagram)
IMAGE_ID(RoundRect) IMAGE_ID(RoundRect)
@ -54,6 +55,7 @@ IMAGE_ID(PaperA)
IMAGE_ID(MoveFront) IMAGE_ID(MoveFront)
IMAGE_ID(MoveBack) IMAGE_ID(MoveBack)
IMAGE_ID(Size) IMAGE_ID(Size)
IMAGE_ID(FontSvg)
IMAGE_BEGIN_DATA IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,237,217,81,138,194,48,20,70,97,151,51,203,114,255,155,112,200,67,176,136,218,73,39,241,220,191,158,15,242,166) IMAGE_DATA(120,156,237,217,81,138,194,48,20,70,97,151,51,203,114,255,155,112,200,67,176,136,218,73,39,241,220,191,158,15,242,166)
@ -480,3 +482,44 @@ IMAGE_DATA(181,63,185,239,255,63,31,147,220,109,255,55,75,250,249,237,143,83,220
IMAGE_DATA(162,254,58,106,175,162,254,58,106,175,162,254,42,234,175,163,246,42,234,175,162,254,58,106,175,162,254,58,106,175,162,254) IMAGE_DATA(162,254,58,106,175,162,254,58,106,175,162,254,42,234,175,163,246,42,234,175,162,254,58,106,175,162,254,58,106,175,162,254)
IMAGE_DATA(73,146,36,25,224,21,2,152,45,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) IMAGE_DATA(73,146,36,25,224,21,2,152,45,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
IMAGE_END_DATA(448, 1) IMAGE_END_DATA(448, 1)
IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,237,152,217,145,219,48,12,64,89,78,102,155,96,21,249,78,41,104,33,29,161,137,244,147,132,147,213,68,246,90)
IMAGE_DATA(22,110,144,18,222,12,190,178,38,174,71,201,206,183,159,237,71,43,138,162,40,138,162,40,138,162,184,40,253,111,192,103)
IMAGE_DATA(252,38,4,238,254,190,184,47,99,255,195,5,138,51,239,162,60,186,31,90,103,202,163,123,227,225,207,246,110,235,129,125)
IMAGE_DATA(20,57,80,191,235,104,60,42,174,139,183,63,245,62,187,54,17,254,140,168,119,217,117,137,240,167,222,101,215,37,202,159)
IMAGE_DATA(122,14,93,147,237,29,134,237,255,255,7,66,243,121,183,213,51,232,190,88,249,84,20,26,127,32,161,222,98,62,198,187)
IMAGE_DATA(168,158,65,118,236,191,55,60,207,118,255,111,87,250,14,89,254,200,25,30,104,191,11,92,193,167,122,135,241,24,251,214)
IMAGE_DATA(60,187,175,54,79,201,61,90,185,95,13,214,222,236,99,156,189,234,179,168,252,57,199,211,157,125,172,232,80,249,115,140)
IMAGE_DATA(228,249,124,55,135,134,15,229,207,87,50,220,89,209,161,242,231,53,89,238,108,177,10,229,207,87,178,221,89,201,161,242)
IMAGE_DATA(231,17,108,249,222,92,217,159,158,83,102,8,220,89,120,199,10,119,149,59,179,76,188,221,205,246,229,57,208,183,93,19)
IMAGE_DATA(102,247,231,185,62,47,178,93,57,10,239,59,163,133,227,79,228,243,244,168,46,47,178,61,153,97,230,18,102,124,246,224)
IMAGE_DATA(155,26,60,230,201,185,67,229,207,35,51,249,211,19,234,160,230,204,140,153,161,246,128,206,117,112,246,104,121,39,145,145)
IMAGE_DATA(183,252,121,132,179,179,62,73,29,150,46,115,243,150,63,143,140,123,28,185,175,35,178,102,138,194,220,229,207,63,168,243)
IMAGE_DATA(235,142,53,80,29,246,152,101,182,23,222,119,23,118,33,205,191,125,254,213,217,222,245,83,224,244,98,233,177,102,166,145)
IMAGE_DATA(241,106,119,239,122,242,238,107,203,129,196,191,247,132,211,43,103,142,20,178,189,176,234,155,179,203,217,106,215,208,19,235)
IMAGE_DATA(152,117,222,175,226,153,153,125,57,171,221,18,96,212,209,13,243,114,188,205,14,216,213,205,153,215,12,129,231,171,80,145)
IMAGE_DATA(229,49,50,115,103,239,96,53,111,182,0,234,66,132,100,248,211,153,121,43,116,209,105,107,97,195,221,163,21,217,243,188)
IMAGE_DATA(99,96,179,247,8,152,53,88,192,117,246,10,49,118,7,140,240,172,197,210,33,110,173,96,144,51,123,151,145,174,104,233)
IMAGE_DATA(205,231,119,158,21,220,188,191,20,185,62,62,63,159,189,95,235,24,61,141,29,127,87,204,134,194,135,113,221,22,126,71)
IMAGE_DATA(229,29,247,200,250,14,101,6,10,231,32,165,59,245,161,237,65,154,183,7,229,153,45,162,189,217,64,97,189,30,187,220)
IMAGE_DATA(227,237,238,168,205,179,247,72,111,52,115,214,0,196,26,53,33,197,178,6,104,49,191,31,50,220,201,130,58,203,205,239)
IMAGE_DATA(232,30,179,119,179,74,128,112,190,90,168,245,109,12,135,144,241,57,109,143,217,123,89,41,80,48,95,13,157,88,87,23)
IMAGE_DATA(126,142,114,214,25,217,59,89,45,80,48,99,9,84,7,142,156,150,58,116,116,222,17,217,251,88,53,60,161,238,30,78)
IMAGE_DATA(206,1,226,57,154,222,164,57,238,30,200,156,51,7,36,214,96,121,22,199,203,61,229,143,60,58,99,206,84,58,49,55)
IMAGE_DATA(213,95,234,121,146,179,55,178,247,176,114,88,59,228,177,95,32,158,187,15,48,174,185,194,102,151,239,232,196,156,92,103)
IMAGE_DATA(169,231,74,251,202,222,193,234,193,221,231,17,72,200,37,245,85,210,23,21,16,158,95,241,47,128,49,235,35,58,49,151)
IMAGE_DATA(20,79,127,164,231,87,232,247,186,65,201,129,138,243,145,152,67,122,47,64,112,126,133,141,63,212,217,247,128,28,82,127)
IMAGE_DATA(154,224,252,10,27,127,48,32,135,196,31,110,206,46,204,81,161,131,114,62,40,115,68,248,211,132,57,42,228,116,231,243)
IMAGE_DATA(55,162,252,145,230,185,123,72,161,206,91,75,148,63,3,20,230,186,115,72,161,204,26,21,231,111,68,250,51,40,135,98)
IMAGE_DATA(230,76,57,27,20,231,111,68,251,211,132,249,238,26,82,174,236,79,23,230,188,99,72,153,217,31,139,188,229,208,121,160)
IMAGE_DATA(112,182,212,157,90,236,17,137,185,172,243,74,115,223,41,164,115,142,244,39,178,175,87,80,123,189,99,104,152,217,31,107)
IMAGE_DATA(186,176,142,43,7,170,38,122,47,127,6,229,144,237,140,35,242,0,35,143,165,179,71,148,67,118,51,166,230,234,1,57)
IMAGE_DATA(172,242,121,214,117,165,176,0,136,185,208,249,124,143,222,40,116,97,125,171,135,21,156,249,113,29,66,198,217,251,232,154)
IMAGE_DATA(134,132,72,107,93,49,184,123,60,195,99,183,28,47,189,238,6,23,56,169,235,10,97,237,78,19,212,0,111,206,234,77)
IMAGE_DATA(119,151,61,250,227,160,173,127,230,240,154,45,8,235,129,167,176,232,177,59,245,40,193,170,167,25,194,123,174,56,65,143)
IMAGE_DATA(224,220,163,148,213,61,242,118,167,181,252,223,33,232,223,162,138,49,159,25,238,216,204,51,205,116,104,53,160,229,251,113)
IMAGE_DATA(20,224,216,247,25,25,119,172,135,116,230,195,168,125,22,151,50,189,217,19,229,208,200,179,178,59,207,100,184,4,109,30)
IMAGE_DATA(111,246,120,207,1,227,90,73,99,243,201,242,62,226,231,153,43,220,187,81,99,185,83,88,160,125,30,173,114,103,10,95)
IMAGE_DATA(56,207,228,89,223,205,69,81,20,69,17,198,31,18,202,155,177,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
IMAGE_END_DATA(1216, 1)

View file

@ -8,11 +8,9 @@ LAYOUT(SizeLayout, 212, 164)
END_LAYOUT END_LAYOUT
LAYOUT(SelectSymbolLayout, 596, 572) LAYOUT(SelectSymbolLayout, 596, 572)
ITEM(Upp::Switch, group, SetLabel(t_("All\nSymbols\nArrows\nShapes\nDingbats\nMathematical")).LeftPosZ(4, 400).TopPosZ(4, 19)) ITEM(Upp::Switch, group, SetLabel(t_("All\nSymbols\nArrows\nShapes\nDingbats\nMathematical")).LeftPosZ(208, 400).TopPosZ(4, 19))
ITEM(Upp::EditString, search, LeftPosZ(408, 184).TopPosZ(4, 19)) ITEM(Upp::EditString, search, LeftPosZ(4, 184).TopPosZ(4, 19))
ITEM(Upp::RichTextView, symbols, LeftPosZ(4, 588).TopPosZ(28, 432)) ITEM(Upp::RichTextView, symbols, LeftPosZ(4, 588).TopPosZ(28, 432))
ITEM(Upp::RichTextView, variants, LeftPosZ(4, 588).TopPosZ(464, 68)) ITEM(Upp::RichTextView, variants, LeftPosZ(4, 588).TopPosZ(464, 104))
ITEM(Upp::Button, ok, SetLabel(t_("OK")).LeftPosZ(456, 64).TopPosZ(540, 24))
ITEM(Upp::Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(526, 64).TopPosZ(540, 24))
END_LAYOUT END_LAYOUT

View file

@ -87,18 +87,17 @@ void DiagramEditor::Skin()
{ {
SetBar(); SetBar();
int cy = GetStdFontCy();
Size shape_sz = Size(DPI(24), cy);
Size icon_sz = IconSz();
shape.ClearList(); shape.ClearList();
for(int i = 0; i < DiagramItem::SHAPE_COUNT; i++) { shape.SetLineCy(icon_sz.cy);
for(int i = 0; i < DiagramItem::SHAPE_SVGPATH; i++) {
DiagramItem m; DiagramItem m;
m.pt[0] = Point(2, 2); m.pt[0] = Point(2, 2);
m.pt[1] = Point(shape_sz.cx - 2, cy - 2); m.pt[1] = Point(icon_sz.cx - 2, icon_sz.cy - 2);
m.width = DPI(1); m.width = DPI(1);
m.shape = i; m.shape = i;
shape.Add(i, MakeIcon(m, shape_sz)); shape.Add(i, MakeIcon(m, icon_sz));
} }
struct Dialine : DiagramItem { struct Dialine : DiagramItem {
@ -111,6 +110,7 @@ void DiagramEditor::Skin()
}; };
auto LDL = [=](DropList& dl, bool left) { auto LDL = [=](DropList& dl, bool left) {
dl.SetLineCy(icon_sz.cy);
dl.ClearList(); dl.ClearList();
for(int i = DiagramItem::CAP_NONE; i < DiagramItem::CAP_COUNT; i++) { for(int i = DiagramItem::CAP_NONE; i < DiagramItem::CAP_COUNT; i++) {
dl.Add(i, CapIcon(left ? i : 0, left ? 0 : i)); dl.Add(i, CapIcon(left ? i : 0, left ? 0 : i));
@ -121,10 +121,11 @@ void DiagramEditor::Skin()
LDL(line_end, false); LDL(line_end, false);
line_dash.ClearList(); line_dash.ClearList();
line_dash.SetLineCy(icon_sz.cy);
for(int i = 0; i < DiagramItem::DASH_COUNT; i++) { for(int i = 0; i < DiagramItem::DASH_COUNT; i++) {
Dialine m; Dialine m;
m.dash = i; m.dash = i;
line_dash.Add(i, MakeIcon(m, shape_sz)); line_dash.Add(i, MakeIcon(m, icon_sz));
} }
} }

View file

@ -36,7 +36,7 @@ struct ColumnPopUp : Ctrl {
const VectorMap<String, Vector<Tuple<int, String>>>& UnicodeSymbols(); const VectorMap<String, Vector<Tuple<int, String>>>& UnicodeSymbols();
bool SelectUnicodeSymbol(int& codepoint, Font& font); String SelectFontSymbolSvg(Sizef& sz);
class DiagramEditor : public Ctrl, Diagram::PaintInfo { class DiagramEditor : public Ctrl, Diagram::PaintInfo {
public: public:
@ -127,7 +127,7 @@ private:
double GetZoom() const { return DPI(1) * 0.01 * zoom_percent; } double GetZoom() const { return DPI(1) * 0.01 * zoom_percent; }
void Map(Point& p); void Map(Point& p);
Image MakeIcon(DiagramItem& m, Size isz); Image MakeIcon(DiagramItem& m, Size isz);
Size IconSz() { return Size(DPI(24), GetStdFontCy()); } Size IconSz() { return Size(DPI(24), DPI(16)); }
Image ShapeIcon(int i); Image ShapeIcon(int i);
Image CapIcon(int start, int end); Image CapIcon(int start, int end);
Image DashIcon(int i); Image DashIcon(int i);

View file

@ -332,7 +332,7 @@ void DiagramEditor::RightDown(Point p, dword keyflags)
shape.columns = 3; shape.columns = 3;
shape.isz = IconSz() + Size(DPI(4), DPI(4)); shape.isz = IconSz() + Size(DPI(4), DPI(4));
shape.WhenPaintItem = [=](Draw& w, Size isz, int ii, bool sel) { shape.WhenPaintItem = [=](Draw& w, Size isz, int ii, bool sel) {
PopPaint(w, ShapeIcon(ii), sel); PopPaint(w, ii == DiagramItem::SHAPE_SVGPATH ? DiagramImg::FontSvg() : ShapeIcon(ii), sel);
}; };
tool = -1; tool = -1;
@ -341,6 +341,14 @@ void DiagramEditor::RightDown(Point p, dword keyflags)
if(si < 0) if(si < 0)
return; return;
Sizef size;
String svgpath;
if(si == DiagramItem::SHAPE_SVGPATH) {
svgpath = SelectFontSymbolSvg(size);
if(IsNull(svgpath))
return;
}
CancelSelection(); CancelSelection();
@ -369,7 +377,16 @@ void DiagramEditor::RightDown(Point p, dword keyflags)
m.pt[1] = p; m.pt[1] = p;
} }
m.shape = si; // shape must be set before SetAttrs to avoid Normalise m.shape = si; // shape must be set before SetAttrs to avoid Normalise
SetAttrs(ATTR_ALL & ~ATTR_SHAPE); m.data = svgpath;
m.size = size;
if(si == DiagramItem::SHAPE_SVGPATH) {
m.ink = Null;
m.paper = Black();
m.pt[1] = m.pt[0] + size;
SetAttrs(ATTR_ALL & ~(ATTR_SHAPE|ATTR_PAPER|ATTR_INK));
}
else
SetAttrs(ATTR_ALL & ~ATTR_SHAPE);
Sync(); Sync();
} }

View file

@ -2,7 +2,46 @@
namespace Upp { namespace Upp {
String AsSvgPath(Font font, int c, Sizef& sz) {
struct TextToSvg : FontGlyphConsumer {
String t; // here we accumulate the SVG path text
Rectf bounds = Rectf(DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX);
Pointf offset = Pointf(0, 0);
double scale = 1;
void Put(Pointf p) {
bounds.left = min(bounds.left, p.x);
bounds.right = max(bounds.right, p.x);
bounds.top = min(bounds.top, p.y);
bounds.bottom = max(bounds.bottom, p.y);
bounds.Union(p);
p = (p + offset) * scale;
t << Format("%.2f %.2f ", p.x, p.y);
}
virtual void Move(Pointf p) { t << 'M'; Put(p); }
virtual void Line(Pointf p) { t << 'L'; Put(p); }
virtual void Quadratic(Pointf p1, Pointf p2) { t << 'Q'; Put(p1); Put(p2); }
virtual void Cubic(Pointf p1, Pointf p2, Pointf p3) { t << 'C'; Put(p1); Put(p2); Put(p2); }
virtual void Close() { t << 'Z'; }
} t;
font.Render(t, 0, 0, c);
t.t.Clear();
t.offset = -t.bounds.TopLeft();
t.scale = 100 / t.bounds.GetHeight();
sz = t.bounds.GetSize() * t.scale;
font.Render(t, 0, 0, c);
return t.t;
}
struct SelectSymbolDlg : WithSelectSymbolLayout<TopWindow> { struct SelectSymbolDlg : WithSelectSymbolLayout<TopWindow> {
Vector<Tuple<Sizef, String>> svg;
int result;
SelectSymbolDlg(); SelectSymbolDlg();
void Sync(); void Sync();
@ -11,7 +50,7 @@ struct SelectSymbolDlg : WithSelectSymbolLayout<TopWindow> {
SelectSymbolDlg::SelectSymbolDlg() SelectSymbolDlg::SelectSymbolDlg()
{ {
CtrlLayoutOKCancel(*this, "Insert"); CtrlLayout(*this, "Insert symbol");
search.NullText(t_("Search")); search.NullText(t_("Search"));
search.SetFilter(CharFilterDefaultToUpperAscii); search.SetFilter(CharFilterDefaultToUpperAscii);
group <<= 0; group <<= 0;
@ -19,6 +58,10 @@ SelectSymbolDlg::SelectSymbolDlg()
symbols.NoHyperlinkDecoration(); symbols.NoHyperlinkDecoration();
symbols.WhenLink << [=](const String& s) { Variants(Atoi(s)); }; symbols.WhenLink << [=](const String& s) { Variants(Atoi(s)); };
result = -1;
variants.NoHyperlinkDecoration();
variants.WhenLink << [=](const String& s) { result = Atoi(s); Break(IDOK); };
} }
void SelectSymbolDlg::Sync() void SelectSymbolDlg::Sync()
@ -39,21 +82,39 @@ void SelectSymbolDlg::Sync()
void SelectSymbolDlg::Variants(int codepoint) void SelectSymbolDlg::Variants(int codepoint)
{ {
String qtf = "[A5 "; String qtf = "[A5 ";
Index<Image> h;
for(int i = 0; i < Font::GetFaceCount(); i++) { for(int i = 0; i < Font::GetFaceCount(); i++) {
Font fnt(i, 10); Font fnt(i, 10);
if(HasCodepoint(fnt, codepoint)) { if(HasCodepoint(fnt, codepoint)) {
qtf << "[!" << fnt.GetFaceName() << "! " << WString(codepoint, 1) << "] "; Sizef szf0;
String svgpath = AsSvgPath(fnt, codepoint, szf0);
Size szf = szf0 * DPI(1);
Size sz((int)ceil(szf.cx), (int)ceil(szf.cy));
ImagePainter sw(sz);
sw.Clear();
sw.Scale(DPI(1));
sw.Path(svgpath).Fill(SBlack());
Image img = sw;
if(h.Find(img) < 0) {
qtf << "[^" << h.GetCount() << "^ " << " " << AsQTF(CreatePNGObject(img, sz.cx, sz.cy)) << "], ";
h.Add(img);
svg.Add(MakeTuple(szf0, svgpath));
}
} }
} }
variants.SetQTF(qtf); variants.SetQTF(qtf);
} }
bool SelectUnicodeSymbol(int& codepoint, Font& font) String SelectFontSymbolSvg(Sizef& sz)
{ {
SelectSymbolDlg dlg; SelectSymbolDlg dlg;
dlg.Sync(); dlg.Sync();
dlg.Run(); if(dlg.Execute() != IDOK || dlg.result < 0 || dlg.result >= dlg.svg.GetCount())
return true; return Null;
Tuple<Sizef, String> h = dlg.svg[dlg.result];
sz = h.a;
return h.b;
} }
} }

View file

@ -30,6 +30,8 @@ void DiagramItem::Reset()
width = 2; width = 2;
ink = Black(); ink = Black();
paper = White(); paper = White();
data.Clear();
size = Null;
cap[0] = cap[1] = CAP_NONE; cap[0] = cap[1] = CAP_NONE;
dash = 0; dash = 0;
@ -138,6 +140,10 @@ void DiagramItem::Save(StringBuffer& r) const
return String("null"); return String("null");
return Format("%02x%02x%02x", (int)c.GetR(), (int)c.GetG(), (int)c.GetB()); return Format("%02x%02x%02x", (int)c.GetR(), (int)c.GetG(), (int)c.GetB());
}; };
if(data.GetCount())
r << " data " << AsCString(data);
if(!IsNull(size))
r << " size " << size.cx << ' ' << size.cy;
if(ink != Black()) if(ink != Black())
r << " ink " << col(ink); r << " ink " << col(ink);
if(paper != White()) if(paper != White())
@ -195,6 +201,14 @@ void DiagramItem::Load(CParser& p)
else else
if(p.Id("dash")) if(p.Id("dash"))
dash = clamp(p.ReadInt(), 0, (int)DASH_COUNT); dash = clamp(p.ReadInt(), 0, (int)DASH_COUNT);
else
if(p.Id("data"))
data = p.ReadString();
else
if(p.Id("size")) {
size.cx = p.ReadDouble();
size.cy = p.ReadDouble();
}
else else
p.Skip(); p.Skip();
} }

View file

@ -16,6 +16,8 @@ struct DiagramItem : Point2 {
double width; double width;
Color ink; Color ink;
Color paper; Color paper;
Sizef size;
String data;
enum { enum {
SHAPE_LINE, SHAPE_LINE,
@ -34,6 +36,7 @@ struct DiagramItem : Point2 {
SHAPE_ARROWDOWN, SHAPE_ARROWDOWN,
SHAPE_ARROWUP, SHAPE_ARROWUP,
SHAPE_ARROWVERT, SHAPE_ARROWVERT,
SHAPE_SVGPATH,
SHAPE_COUNT, SHAPE_COUNT,
}; };

View file

@ -8,6 +8,7 @@ Index<String> DiagramItem::Shape = { "line", "rect", "round_rect",
"triangle1", "triangle2", "triangle1", "triangle2",
"arrow_left", "arrow_right", "arrow_horz", "arrow_left", "arrow_right", "arrow_horz",
"arrow_down", "arrow_up", "arrow_vert", "arrow_down", "arrow_up", "arrow_vert",
"svgpath",
}; };
Vector<Pointf> DiagramItem::GetConnections() const Vector<Pointf> DiagramItem::GetConnections() const
@ -305,6 +306,14 @@ void DiagramItem::Paint(Painter& w, dword style, const Index<Pointf> *conn) cons
.Close(); .Close();
} }
break; break;
case SHAPE_SVGPATH:
if(data.GetCount() && !IsNull(size)) {
w.Begin();
w.Offset(r.TopLeft());
w.Scale(w1 / size.cx, h / size.cy);
w.Path(data);
}
break;
default: default:
w.Rectangle(r); w.Rectangle(r);
break; break;
@ -320,6 +329,10 @@ void DiagramItem::Paint(Painter& w, dword style, const Index<Pointf> *conn) cons
DoDash(); DoDash();
Stroke(); Stroke();
break; break;
case SHAPE_SVGPATH:
if(data.GetCount() && !IsNull(size))
w.End();
break;
} }
int txt_cy = txt.GetHeight(pi.zoom, text_rect.GetWidth()); int txt_cy = txt.GetHeight(pi.zoom, text_rect.GetWidth());

View file

@ -4,12 +4,12 @@ using namespace Upp;
GUI_APP_MAIN GUI_APP_MAIN
{ {
/* int cp; /*
int cp;
Font fnt; Font fnt;
SelectUnicodeSymbol(cp, fnt); SelectUnicodeSymbol(cp, fnt);
return; return;
*/ //*/
TopWindow app; TopWindow app;
app.Sizeable().Zoomable(); app.Sizeable().Zoomable();
DiagramEditor de; DiagramEditor de;