mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
468 lines
12 KiB
C++
468 lines
12 KiB
C++
#ifdef flagGUI
|
||
|
||
#include <CtrlLib/CtrlLib.h>
|
||
#include "Functions4U_Gui.h"
|
||
|
||
using namespace Upp;
|
||
|
||
//NAMESPACE_UPP
|
||
|
||
inline bool iscidplus(int c) {
|
||
return iscib(c) || c == '.' || (c >= '0' && c <= '9');
|
||
}
|
||
|
||
String CParserPlus::ReadIdPlus() {
|
||
if(!IsId())
|
||
ThrowError("missing id");
|
||
String result;
|
||
const char *b = term;
|
||
const char *p = b;
|
||
while(iscidplus(*p))
|
||
p++;
|
||
term = p;
|
||
DoSpaces();
|
||
return String(b, (int)(uintptr_t)(p - b));
|
||
}
|
||
|
||
Drawing EquationDraw::Text(String text, bool italic, int offsetX, int offsetY, double betw) {
|
||
Font fnt;
|
||
|
||
int _pos1, _pos2;
|
||
if ((_pos1 = text.Find('_', 0)) >= 0) {
|
||
String sub = text.Right(text.GetCount()-_pos1-1);
|
||
if ((_pos2 = sub.Find('_', 0)) >= 0)
|
||
sub = sub.Left(_pos2) + ',' + sub.Right(sub.GetCount()-_pos2-1);
|
||
return SubSup(text.Left(_pos1), sub, "");
|
||
}
|
||
fnt.Face(Font::ROMAN);
|
||
fnt.Height(400);
|
||
fnt.Italic(italic);
|
||
|
||
FontInfo fi = fnt.Info();
|
||
int width = 0;
|
||
WString wtext(text);
|
||
for (int i = 0; i < wtext.GetCount(); ++i)
|
||
width += fi.GetWidth(wtext[i]);
|
||
|
||
width += 10;
|
||
width = int(width*betw);
|
||
ImageDraw idw(width, fnt.GetCy());
|
||
idw.DrawRect(Size(width, fnt.GetCy()), White);
|
||
idw.DrawText(offsetX, offsetY, text, fnt);
|
||
|
||
DrawingDraw dw(width/3, fnt.GetCy()/3);
|
||
dw.DrawImage(0, 0, width/3, fnt.GetCy()/3, idw);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::SubSup(Drawing &drwText, Drawing &drwSub, Drawing &drwSup) {
|
||
Size szText = drwText.GetSize();
|
||
Size szSub = (2/3.)*drwSub.GetSize();
|
||
Size szSup = (2/3.)*drwSup.GetSize();
|
||
|
||
int width = szText.cx + max(szSup.cx, szSub.cx);
|
||
int deltay = szSup.cy/2;
|
||
|
||
DrawingDraw dw(width, szText.cy + szSup.cy/2 + szSub.cy/2);
|
||
|
||
dw.DrawDrawing(0, deltay, szText.cx, szText.cy, drwText);
|
||
dw.DrawDrawing(szText.cx, 0, szSup.cx, szSup.cy, drwSup);
|
||
dw.DrawDrawing(szText.cx, deltay + szText.cy - szSub.cy/2, szSub.cx, szSub.cy, drwSub);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::SubSup(String text, String sub, String sup) {
|
||
Drawing textdraw = Text(text, true);
|
||
Drawing subdraw = Text(sub, true);
|
||
Drawing supdraw = Text(sup, true);
|
||
|
||
return SubSup(textdraw, subdraw, supdraw);
|
||
}
|
||
|
||
Drawing EquationDraw::SubSup(Drawing &drwText, String sub, String sup) {
|
||
Drawing subdraw = Text(sub, true);
|
||
Drawing supdraw = Text(sup, true);
|
||
|
||
return SubSup(drwText, subdraw, supdraw);
|
||
}
|
||
|
||
Drawing EquationDraw::SubSupInv(Drawing &drwText, Drawing &drwSub, Drawing &drwSup)
|
||
{
|
||
double factor = 0.6;
|
||
|
||
Size szText = drwText.GetSize();
|
||
Size szSub = factor*drwSub.GetSize();
|
||
Size szSup = factor*drwSup.GetSize();
|
||
|
||
int width = szText.cx + max(szSup.cx, szSub.cx);
|
||
int deltay = szSup.cy/2;
|
||
|
||
DrawingDraw dw(width, szText.cy + szSup.cy/2 + szSub.cy/2);
|
||
|
||
dw.DrawDrawing(width-szText.cx, deltay, szText.cx, szText.cy, drwText);
|
||
dw.DrawDrawing(0, 0, szSup.cx, szSup.cy, drwSup);
|
||
dw.DrawDrawing(0, deltay + szText.cy - szSub.cy/2, szSub.cx, szSub.cy, drwSub);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::SubSupInv(String text, String sub, String sup) {
|
||
Drawing textdraw = Text(text, true);
|
||
Drawing subdraw = Text(sub, true);
|
||
Drawing supdraw = Text(sup, true);
|
||
|
||
return SubSupInv(textdraw, subdraw, supdraw);
|
||
}
|
||
|
||
Drawing EquationDraw::SubSupInv(Drawing &drwText, String sub, String sup) {
|
||
Drawing subdraw = Text(sub, true);
|
||
Drawing supdraw = Text(sup, true);
|
||
|
||
return SubSupInv(drwText, subdraw, supdraw);
|
||
}
|
||
|
||
Drawing EquationDraw::JoinCenter(Drawing &left, Drawing &right) {
|
||
Size szLeft = left.GetSize();
|
||
Size szRight = right.GetSize();
|
||
|
||
int width = szLeft.cx + szRight.cx;
|
||
int height = max(szLeft.cy, szRight.cy);
|
||
|
||
DrawingDraw dw(width, height);
|
||
|
||
dw.DrawDrawing(0, height == szLeft.cy? 0: (height-szLeft.cy)/2, szLeft.cx, szLeft.cy, left);
|
||
dw.DrawDrawing(szLeft.cx, height == szRight.cy? 0: (height-szRight.cy)/2, szRight.cx, szRight.cy, right);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::JoinFlex(Drawing &left, double betw1, Drawing &right, double betw2) {
|
||
Size szLeft = left.GetSize();
|
||
Size szRight = right.GetSize();
|
||
|
||
int width = int(szLeft.cx*betw1 + szRight.cx*betw2);
|
||
int height = max(szLeft.cy, szRight.cy);
|
||
|
||
DrawingDraw dw(width, height);
|
||
|
||
dw.DrawDrawing(0, 0, szLeft.cx, height, left);
|
||
dw.DrawDrawing(int(szLeft.cx*betw1), 0, szRight.cx, height, right);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::NumDenom(Drawing &num, Drawing &denom) {
|
||
Size szNum = num.GetSize();
|
||
Size szDenom = denom.GetSize();
|
||
|
||
int width = max(szNum.cx, szDenom.cx);
|
||
int height = szNum.cy + szDenom.cy;
|
||
|
||
DrawingDraw dw(width, height);
|
||
|
||
dw.DrawDrawing(width == szNum.cx? 0: (width-szNum.cx)/2, 0, szNum.cx, szNum.cy, num);
|
||
dw.DrawDrawing(width == szDenom.cx? 0: (width-szDenom.cx)/2, szNum.cy, szDenom.cx, szDenom.cy, denom);
|
||
dw.DrawLine(0, szNum.cy, width, szNum.cy, 1);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::Bracket(Drawing &data) {
|
||
Drawing pizq = Text("(", true, 0, 0, 1.3);
|
||
Drawing pder = Text(")");
|
||
Drawing parizq = JoinFlex(pizq, 1, data, 1);
|
||
|
||
return JoinFlex(parizq, 1, pder, 1);
|
||
}
|
||
|
||
Drawing EquationDraw::Sqrt(Drawing &right) {
|
||
Drawing left = Text("√");
|
||
|
||
Size szLeft = left.GetSize();
|
||
Size szRight = right.GetSize();
|
||
|
||
int width = 2*szLeft.cx + szRight.cx;
|
||
int height = max(szLeft.cy, szRight.cy);
|
||
|
||
DrawingDraw dw(width, height);
|
||
|
||
dw.DrawDrawing(0, 0, szLeft.cx, height, left);
|
||
dw.DrawDrawing(szLeft.cx, 1, szRight.cx, height-1, right);
|
||
dw.DrawLine(szLeft.cx, 1, width-szLeft.cx, 1, 1);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::Exponent(Drawing &right) {
|
||
Drawing left = Text("e");
|
||
|
||
return EquationDraw::Exp(left, right);
|
||
}
|
||
|
||
Drawing EquationDraw::Der(Drawing &data) {
|
||
return EquationDraw::Function("d", data);
|
||
}
|
||
|
||
Drawing EquationDraw::Abs(Drawing &data) {
|
||
Drawing pizq = Text("|", true, 0, 0, 1.3);
|
||
Drawing pder = Text("|");
|
||
Drawing parizq = JoinFlex(pizq, 1, data, 1);
|
||
|
||
return JoinFlex(parizq, 1, pder, 1);
|
||
}
|
||
|
||
Drawing EquationDraw::Integral(Drawing &data, Drawing &sub, Drawing &sup) {
|
||
Drawing left = Text("∫");
|
||
Drawing right = SubSupInv(data, sub, sup);
|
||
|
||
Size szLeft = left.GetSize();
|
||
Size szRight = right.GetSize();
|
||
|
||
int sqWidth = int(szLeft.cx*1.5);
|
||
int width = sqWidth + szRight.cx;
|
||
int height = szRight.cy;
|
||
|
||
DrawingDraw dw(width, height);
|
||
|
||
dw.DrawDrawing(0, 0, (int)(szLeft.cx*1.5), height, left);
|
||
dw.DrawDrawing(sqWidth, 0, szRight.cx, height, right);
|
||
|
||
return dw;
|
||
}
|
||
|
||
Drawing EquationDraw::Summat(Drawing &data, Drawing &sub, Drawing &sup) {
|
||
Drawing left = Text("∑", true, 0, -20);
|
||
Drawing right = SubSupInv(data, sub, sup);
|
||
|
||
Size szLeft = left.GetSize();
|
||
Size szRight = right.GetSize();
|
||
|
||
int sqWidth = int(szLeft.cx*1.3);
|
||
int width = sqWidth + szRight.cx;
|
||
int height = szRight.cy;
|
||
|
||
DrawingDraw dw(width, height);
|
||
|
||
dw.DrawDrawing(0, 0, (int)(szLeft.cx*1.1), height, left);
|
||
dw.DrawDrawing(sqWidth, 0, szRight.cx, height, right);
|
||
|
||
return dw;
|
||
}
|
||
Drawing EquationDraw::Exp(Drawing &data, Drawing &exp) {
|
||
Drawing foo = Text("");
|
||
|
||
return SubSup(data, foo, exp);
|
||
}
|
||
|
||
Drawing EquationDraw::Function(String function, Drawing &content) {
|
||
Drawing fundraw = Text(function);
|
||
Drawing pardraw = Bracket(content);
|
||
|
||
return JoinCenter(fundraw, pardraw);
|
||
}
|
||
|
||
Drawing EquationDraw::Equal(Drawing &left, Drawing &right) {
|
||
Drawing equal = Text(" = ");
|
||
Drawing leftdraw = JoinCenter(left, equal);
|
||
|
||
return JoinCenter(leftdraw, right);
|
||
}
|
||
|
||
String EquationDraw::ReplaceSymbols(String var) {
|
||
for (int i = 0; i < symbols.GetCount(); ++i) {
|
||
String letter = ToLower(symbols.GetKey(i));
|
||
if (var.Find(letter) >= 0)
|
||
var.Replace(letter, symbols[i].Mid(2));
|
||
letter = ToUpper(symbols.GetKey(i));
|
||
if (var.Find(letter) >= 0)
|
||
var.Replace(letter, symbols[i].Mid(0, 2));
|
||
}
|
||
return var;
|
||
}
|
||
|
||
String EquationDraw::TermTrig(CParserPlus& p) {
|
||
if (p.Id("sin")) return "sin";
|
||
if (p.Id("cos")) return "cos";
|
||
if (p.Id("tan")) return "tan";
|
||
if (p.Id("sinh")) return "sinh";
|
||
if (p.Id("cosh")) return "cosh";
|
||
if (p.Id("tanh")) return "tanh";
|
||
if (p.Id("asin")) return "asin";
|
||
if (p.Id("acos")) return "acos";
|
||
if (p.Id("atan")) return "atan";
|
||
return Null;
|
||
}
|
||
|
||
Drawing EquationDraw::Term(CParserPlus& p, bool noBracket) {
|
||
if(p.Id("integral")) {
|
||
p.PassChar('(');
|
||
Drawing data = Exp(p);
|
||
p.PassChar(',');
|
||
Drawing sub = Exp(p);
|
||
p.PassChar(',');
|
||
Drawing sup = Exp(p);
|
||
p.PassChar(')');
|
||
return EquationDraw::Integral(data, sub, sup);
|
||
}
|
||
if(p.Id("summation")) {
|
||
p.PassChar('(');
|
||
Drawing data = Exp(p);
|
||
p.PassChar(',');
|
||
Drawing sub = Exp(p);
|
||
p.PassChar(',');
|
||
Drawing sup = Exp(p);
|
||
p.PassChar(')');
|
||
return EquationDraw::Summat(data, sub, sup);
|
||
}
|
||
if(p.Id("sqrt")) {
|
||
p.PassChar('(');
|
||
Drawing x = Exp(p);
|
||
p.PassChar(')');
|
||
return EquationDraw::Sqrt(x);
|
||
}
|
||
if(p.Id("exp")) {
|
||
p.PassChar('(');
|
||
Drawing x = Exp(p);
|
||
p.PassChar(')');
|
||
return EquationDraw::Exponent(x);
|
||
}
|
||
if(p.Id("der")) {
|
||
p.PassChar('(');
|
||
Drawing x = Exp(p);
|
||
p.PassChar(')');
|
||
return EquationDraw::Der(x);
|
||
}
|
||
if(p.Id("abs")) {
|
||
p.PassChar('(');
|
||
Drawing x = Exp(p);
|
||
p.PassChar(')');
|
||
return EquationDraw::Abs(x);
|
||
}
|
||
String trig = TermTrig(p);
|
||
if (!IsNull(trig)) {
|
||
p.PassChar('(');
|
||
Drawing x = Exp(p);
|
||
p.PassChar(')');
|
||
return EquationDraw::Function(trig, x);
|
||
}
|
||
if(p.IsId())
|
||
return EquationDraw::Text(ReplaceSymbols(p.ReadId()));
|
||
if(p.Char('(')) {
|
||
Drawing x = Exp(p);
|
||
p.PassChar(')');
|
||
if (noBracket)
|
||
return x;
|
||
else
|
||
return EquationDraw::Bracket(x);
|
||
}
|
||
if(p.Char('-')) {
|
||
Drawing left = Text("-");
|
||
Drawing term = EquationDraw::Term(p);
|
||
return EquationDraw::JoinCenter(left, term);
|
||
}
|
||
return EquationDraw::Text(FormatDouble(p.ReadDouble()));
|
||
}
|
||
|
||
Drawing EquationDraw::Mul(CParserPlus& p) {
|
||
Drawing x = Term(p);
|
||
for(;;) {
|
||
if(p.Char('*')) {
|
||
Drawing mult = EquationDraw::Text(" ");
|
||
Drawing left = EquationDraw::JoinCenter(x, mult);
|
||
Drawing y = Term(p, false);
|
||
x = EquationDraw::JoinCenter(left, y);
|
||
} else if(p.Char('/')) {
|
||
Drawing y = Term(p, true);
|
||
x = EquationDraw::NumDenom(x, y);
|
||
} else if(p.Char('^')) {
|
||
Drawing y = Term(p, false);
|
||
x = EquationDraw::Exp(x, y);
|
||
} else
|
||
return x;
|
||
}
|
||
}
|
||
|
||
Drawing EquationDraw::Exp(CParserPlus& p) {
|
||
Drawing x = Mul(p);
|
||
for(;;) {
|
||
if(p.Char('+')) {
|
||
Drawing plus = EquationDraw::Text("+");
|
||
Drawing left = EquationDraw::JoinCenter(x, plus);
|
||
Drawing y = Mul(p);
|
||
x = EquationDraw::JoinCenter(left, y);
|
||
} else if(p.Char('-')) {
|
||
Drawing minus = EquationDraw::Text("-");
|
||
Drawing left = EquationDraw::JoinCenter(x, minus);
|
||
Drawing y = Mul(p);
|
||
x = EquationDraw::JoinCenter(left, y);
|
||
} else if(p.Char('=')) {
|
||
Drawing y = Mul(p);
|
||
x = EquationDraw::Equal(x, y);
|
||
} else
|
||
return x;
|
||
}
|
||
}
|
||
|
||
EquationDraw::EquationDraw() {
|
||
symbols.GetAdd("alpha") = "Αα";
|
||
symbols.GetAdd("nu") = "Νν";
|
||
symbols.GetAdd("beta") = "Ββ";
|
||
symbols.GetAdd("xi") = "Ξξ";
|
||
symbols.GetAdd("gamma") = "Γγ";
|
||
symbols.GetAdd("omicron") = "Οο";
|
||
symbols.GetAdd("delta") = "Δδ";
|
||
symbols.GetAdd("pi") = "Ππ";
|
||
symbols.GetAdd("epsilon") = "Εε";
|
||
symbols.GetAdd("rho") = "Ρρ";
|
||
symbols.GetAdd("zeta") = "Ζζ";
|
||
symbols.GetAdd("sigma") = "Σσ";
|
||
symbols.GetAdd("eta") = " Ηη";
|
||
symbols.GetAdd("tau") = "Ττ";
|
||
symbols.GetAdd("theta") = "Θθ";
|
||
symbols.GetAdd("upsilon") = "Υυ";
|
||
symbols.GetAdd("iota") = "Ιι";
|
||
symbols.GetAdd("phi") = "Φφ";
|
||
symbols.GetAdd("kappa") = "Κκ";
|
||
symbols.GetAdd("chi") = "Χχ";
|
||
symbols.GetAdd("lambda") = "Λλ";
|
||
symbols.GetAdd("psi") = "Ψψ";
|
||
symbols.GetAdd("mu") = "Μμ";
|
||
symbols.GetAdd("omega") = "Ωω";
|
||
}
|
||
|
||
Drawing DrawEquation(const String &str) {
|
||
EquationDraw equation;
|
||
|
||
CParserPlus p(str);
|
||
try {
|
||
if(p.IsId()) {
|
||
String id;
|
||
CParser::Pos pos = p.GetPos();
|
||
id = p.ReadId();
|
||
p.SetPos(pos);
|
||
return equation.Exp(p);
|
||
} else
|
||
return equation.Exp(p);
|
||
}
|
||
catch(CParser::Error e) {
|
||
String res;
|
||
res << "ERROR: " << e;
|
||
return EquationDraw::Text(res);
|
||
}
|
||
}
|
||
|
||
QtfRichObject QtfEquation(const String &str) {
|
||
Drawing drw = DrawEquation(str);
|
||
|
||
Size sz = drw.GetSize();
|
||
DrawingDraw dw(sz);
|
||
dw.DrawDrawing(0, 0, sz.cx, sz.cy, drw);
|
||
|
||
return QtfRichObject(CreateDrawingObject(dw.GetResult(), sz, sz));
|
||
}
|
||
|
||
|
||
#endif
|
||
|