From dac1f1ea87d4750593c45c47aae4d49d02b89e1c Mon Sep 17 00:00:00 2001 From: cxl Date: Sat, 13 Jul 2019 07:30:16 +0000 Subject: [PATCH] Painter: SVG fixes git-svn-id: svn://ultimatepp.org/upp/trunk@13492 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Parser.h | 2 +- uppsrc/Core/parser.cpp | 16 ++ uppsrc/Painter/Painter.h | 3 - uppsrc/Painter/PainterPath.cpp | 73 ++++----- uppsrc/Painter/Path.cpp | 1 - uppsrc/Painter/SvgArc.cpp | 2 +- uppsrc/Painter/SvgBounds.cpp | 13 +- uppsrc/Painter/SvgInternal.h | 4 +- uppsrc/Painter/SvgParser.cpp | 13 +- uppsrc/Painter/SvgUtil.cpp | 290 ++++++++++++++++----------------- 10 files changed, 220 insertions(+), 197 deletions(-) diff --git a/uppsrc/Core/Parser.h b/uppsrc/Core/Parser.h index 5a1187d44..8bf0c33d9 100644 --- a/uppsrc/Core/Parser.h +++ b/uppsrc/Core/Parser.h @@ -61,7 +61,7 @@ public: uint32 ReadNumber(int base = 10); uint64 ReadNumber64(int base = 10); bool IsDouble() const { return IsInt(); } - bool IsDouble2() const { return IsInt() || IsChar('.'); } + bool IsDouble2() const; double ReadDouble(); bool IsString() const { return IsChar('\"'); }; String ReadOneString(bool chkend = true); diff --git a/uppsrc/Core/parser.cpp b/uppsrc/Core/parser.cpp index d3290c8df..44ca87baa 100644 --- a/uppsrc/Core/parser.cpp +++ b/uppsrc/Core/parser.cpp @@ -306,6 +306,22 @@ uint64 CParser::ReadNumber64(int base) return n; } +bool CParser::IsDouble2() const +{ + const char *t = term; + if(*t == '-' || *t == '+') { + t++; + while(*t <= ' ') + t++; + } + if(*t == '.') { + t++; + while(*t <= ' ') + t++; + } + return IsDigit(*t); +} + double CParser::ReadDouble() { LTIMING("ReadDouble"); diff --git a/uppsrc/Painter/Painter.h b/uppsrc/Painter/Painter.h index 7ced7ffe6..4d6c4a2b8 100644 --- a/uppsrc/Painter/Painter.h +++ b/uppsrc/Painter/Painter.h @@ -173,9 +173,6 @@ protected: virtual void BeginOnPathOp(double q, bool absolute) = 0; protected: - static bool ReadBool(CParser& p); - static double ReadDouble(CParser& p); - static Pointf ReadPoint(CParser& p, Pointf current, bool rel); void DoArc0(double theta, double th_sweep, const Xform2D& m); void DoArc(const Pointf& c, const Pointf& r, double angle, double sweep, double xangle); void DoSvgArc(const Pointf& rr, double xangle, int large, int sweep, diff --git a/uppsrc/Painter/PainterPath.cpp b/uppsrc/Painter/PainterPath.cpp index db895500e..c8d4d32ff 100644 --- a/uppsrc/Painter/PainterPath.cpp +++ b/uppsrc/Painter/PainterPath.cpp @@ -2,30 +2,6 @@ namespace Upp { -bool Painter::ReadBool(CParser& p) -{ - while(p.Char(',')); - if(p.Char('1')) return true; - p.Char('0'); - return false; -} - -double Painter::ReadDouble(CParser& p) -{ - while(p.Char(',')); - return p.IsDouble2() ? p.ReadDouble() : 0; -} - -Pointf Painter::ReadPoint(CParser& p, Pointf current, bool rel) -{ - Pointf t; - t.x = ReadDouble(p); - t.y = ReadDouble(p); - if(rel) - t += current; - return t; -} - Painter& Painter::Path(CParser& p) { Pointf current(0, 0); @@ -35,13 +11,26 @@ Painter& Painter::Path(CParser& p) p.Spaces(); bool rel = IsLower(c); Pointf t, t1, t2; + auto ReadDouble = [&] { + while(p.Char(',')); + return p.IsDouble2() ? p.ReadDouble() : 0; + }; + auto ReadPointP = [&](Pointf current, bool rel) { + Pointf t; + t.x = ReadDouble(); + t.y = ReadDouble(); + if(rel) + t += current; + return t; + }; + auto ReadPoint = [&]() { return ReadPointP(current, rel); }; switch(ToUpper(c)) { case 'M': - current = ReadPoint(p, current, rel); + current = ReadPoint(); Move(current); case 'L': while(p.IsDouble2()) { - current = ReadPoint(p, current, rel); + current = ReadPoint(); Line(current); } done = true; @@ -66,43 +55,49 @@ Painter& Painter::Path(CParser& p) break; case 'C': while(p.IsDouble2()) { - t1 = ReadPoint(p, current, rel); - t2 = ReadPoint(p, current, rel); - current = ReadPoint(p, current, rel); + t1 = ReadPoint(); + t2 = ReadPoint(); + current = ReadPoint(); Cubic(t1, t2, current); done = true; } break; case 'S': while(p.IsDouble2()) { - t2 = ReadPoint(p, current, rel); - current = ReadPoint(p, current, rel); + t2 = ReadPoint(); + current = ReadPoint(); Cubic(t2, current); done = true; } break; case 'Q': while(p.IsDouble2()) { - t1 = ReadPoint(p, current, rel); - current = ReadPoint(p, current, rel); + t1 = ReadPoint(); + current = ReadPoint(); Quadratic(t1, current); done = true; } break; case 'T': while(p.IsDouble2()) { - current = ReadPoint(p, current, rel); + current = ReadPoint(); Quadratic(current); done = true; } break; case 'A': while(p.IsDouble2()) { - t1 = ReadPoint(p, Pointf(0, 0), false); - double xangle = ReadDouble(p); - bool large = ReadBool(p); - bool sweep = ReadBool(p); - current = ReadPoint(p, current, rel); + t1 = ReadPointP(Pointf(0, 0), false); + double xangle = ReadDouble(); + auto ReadBool = [&] { + while(p.Char(',')); + if(p.Char('1')) return true; + p.Char('0'); + return false; + }; + bool large = ReadBool(); + bool sweep = ReadBool(); + current = ReadPoint(); SvgArc(t1, xangle * M_PI / 180.0, large, sweep, current); done = true; } diff --git a/uppsrc/Painter/Path.cpp b/uppsrc/Painter/Path.cpp index 72d667cfd..f65432f62 100644 --- a/uppsrc/Painter/Path.cpp +++ b/uppsrc/Painter/Path.cpp @@ -68,7 +68,6 @@ void BufferPainter::DoMove0() void BufferPainter::LineOp(const Pointf& p, bool rel) { - LLOG("@ LineOp " << p << ", " << rel); DoMove0(); LinearData h; PathAdd(LINE).p = ccontrol = qcontrol = EndPoint(p, rel); diff --git a/uppsrc/Painter/SvgArc.cpp b/uppsrc/Painter/SvgArc.cpp index 25950145e..78b366a7d 100644 --- a/uppsrc/Painter/SvgArc.cpp +++ b/uppsrc/Painter/SvgArc.cpp @@ -32,7 +32,7 @@ void Painter::DoSvgArc(const Pointf& rr, double xangle, int large, int sweep, Pointf r(fabs(rr.x), fabs(rr.y)); Xform2D m = Xform2D::Rotation(-xangle); Pointf d1 = m.Transform(0.5 * (p0 - p1)); - Pointf pr = r * r; + Pointf pr = r * r; Pointf p = d1 * d1; double check = p.x / pr.x + p.y / pr.y; if(check > 1) diff --git a/uppsrc/Painter/SvgBounds.cpp b/uppsrc/Painter/SvgBounds.cpp index 261982dc5..c9fe87f84 100644 --- a/uppsrc/Painter/SvgBounds.cpp +++ b/uppsrc/Painter/SvgBounds.cpp @@ -17,15 +17,15 @@ void BoundsPainter::Bounds(Pointf p) boundingbox.Union(p); } -void BoundsPainter::MoveOp(const Pointf& p, bool) +void BoundsPainter::MoveOp(const Pointf& p, bool rel) { - sw.Move(p); + sw.Move(p, rel); qcontrol = ccontrol = current = p; } -void BoundsPainter::LineOp(const Pointf& p, bool) +void BoundsPainter::LineOp(const Pointf& p, bool rel) { - sw.Line(p); + sw.Line(p, rel); Bounds(current); Bounds(p); ccontrol = qcontrol = p; @@ -161,6 +161,11 @@ void BoundsPainter::DivOp() sw.Div(); } +void BoundsPainter::ClipOp() +{ + sw.Clip(); +} + void BoundsPainter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const double *dx) { Painter::TextOp(p, text, fnt, n, dx); diff --git a/uppsrc/Painter/SvgInternal.h b/uppsrc/Painter/SvgInternal.h index d211f564e..601429adc 100644 --- a/uppsrc/Painter/SvgInternal.h +++ b/uppsrc/Painter/SvgInternal.h @@ -10,8 +10,10 @@ struct BoundsPainter : public NilPainter { const Pointf& p, bool rel); virtual void CloseOp(); virtual void DivOp(); + + virtual void ClipOp(); - virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1, + virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1, const double *dx = NULL); virtual void CharacterOp(const Pointf& p, int ch, Font fnt); diff --git a/uppsrc/Painter/SvgParser.cpp b/uppsrc/Painter/SvgParser.cpp index a412408cc..8299e0b79 100644 --- a/uppsrc/Painter/SvgParser.cpp +++ b/uppsrc/Painter/SvgParser.cpp @@ -286,7 +286,7 @@ Rectf GetSvgViewBox(const String& v) r.left = ReadNumber(p); r.top = ReadNumber(p); r.right = r.left + ReadNumber(p); - r.bottom = r.right + ReadNumber(p); + r.bottom = r.top + ReadNumber(p); } catch(CParser::Error) { r = Null; @@ -456,9 +456,17 @@ void SvgParser::Element(const XmlNode& n, int depth, bool dosymbols) const XmlNode *idn = idmap.Get(Nvl(n.Attr("href"), n.Attr("xlink:href")), NULL); if(idn) { StartElement(n); + Rectf vr = GetSvgViewBox(*idn); + Sizef sz = GetSvgSize(*idn); bp.Translate(Dbl("x"), Dbl("y")); + if(!IsNull(vr) && !IsNull(sz)) { + bp.Rectangle(0, 0, sz.cx, sz.cy).Clip(); + sz /= vr.GetSize(); + bp.Scale(sz.cx, sz.cy); + bp.Translate(-vr.left, -vr.top); + } Element(*idn, depth + 1, true); - FinishElement(); + EndElement(); } } else @@ -589,6 +597,7 @@ Image RenderSVGImage(Size sz, const char *svg, Event resloader) Size isz((int)ceil(iszf.cx), (int)ceil(iszf.cy)); if(isz.cx <= 0 || isz.cy <= 0) return Null; + RLOG("===================== PAINT"); ImageBuffer ib(isz); BufferPainter sw(ib); sw.Clear(White()); diff --git a/uppsrc/Painter/SvgUtil.cpp b/uppsrc/Painter/SvgUtil.cpp index e77e22c95..fe9a5f03b 100644 --- a/uppsrc/Painter/SvgUtil.cpp +++ b/uppsrc/Painter/SvgUtil.cpp @@ -9,146 +9,146 @@ Color SvgParser::GetTextColor(const String& color) { const char *name; byte r, g, b; } colors[] = { - {"aliceblue", 240, 248, 255}, - {"antiquewhite", 250, 235, 215}, - {"aqua", 0, 255, 255}, - {"aquamarine", 127, 255, 212}, - {"azure", 240, 255, 255}, - {"beige", 245, 245, 220}, - {"bisque", 255, 228, 196}, - {"black", 0, 0, 0}, - {"blanchedalmond", 255, 235, 205}, - {"blue", 0, 0, 255}, - {"blueviolet", 138, 43, 226}, - {"brown", 165, 42, 42}, - {"burlywood", 222, 184, 135}, - {"cadetblue", 95, 158, 160}, - {"chartreuse", 127, 255, 0}, - {"chocolate", 210, 105, 30}, - {"coral", 255, 127, 80}, - {"cornflowerblue", 100, 149, 237}, - {"cornsilk", 255, 248, 220}, - {"crimson", 237, 164, 61}, - {"cyan", 0, 255, 255}, - {"darkblue", 0, 0, 139}, - {"darkcyan", 0, 139, 139}, - {"darkgoldenrod", 184, 134, 11}, - {"darkgray", 169, 169, 169}, - {"darkgreen", 0, 100, 0}, - {"darkkhaki", 189, 183, 107}, - {"darkmagenta", 139, 0, 139}, - {"darkolivegreen", 85, 107, 47}, - {"darkorange", 255, 140, 0}, - {"darkorchid", 153, 50, 204}, - {"darkred", 139, 0, 0}, - {"darksalmon", 233, 150, 122}, - {"darkseagreen", 143, 188, 143}, - {"darkslateblue", 72, 61, 139}, - {"darkslategray", 47, 79, 79}, - {"darkturquoise", 0, 206, 209}, - {"darkviolet", 148, 0, 211}, - {"deeppink", 255, 20, 147}, - {"deepskyblue", 0, 191, 255}, - {"dimgray", 105, 105, 105}, - {"dodgerblue", 30, 144, 255}, - {"firebrick", 178, 34, 34}, - {"floralwhite", 255, 250, 240}, - {"forestgreen", 34, 139, 34}, - {"fuchsia", 255, 0, 255}, - {"gainsboro", 220, 220, 220}, - {"ghostwhite", 248, 248, 255}, - {"gold", 255, 215, 0}, - {"goldenrod", 218, 165, 32}, - {"gray", 128, 128, 128}, - {"green", 0, 128, 0}, - {"greenyellow", 173, 255, 47}, - {"honeydew", 240, 255, 240}, - {"hotpink", 255, 105, 180}, - {"indianred", 205, 92, 92}, - {"indigo", 75, 0, 130}, - {"ivory", 255, 255, 240}, - {"khaki", 240, 230, 140}, - {"lavender", 230, 230, 250}, - {"lavenderblush", 255, 240, 245}, - {"lawngreen", 124, 252, 0}, - {"lemonchiffon", 255, 250, 205}, - {"lightblue", 173, 216, 230}, - {"lightcoral", 240, 128, 128}, - {"lightcyan", 224, 255, 255}, - {"lightgoldenrodyellow", 250, 250, 210}, - {"lightgrey", 211, 211, 211}, - {"lightgreen", 144, 238, 144}, - {"lightpink", 255, 182, 193}, - {"lightsalmon", 255, 160, 122}, - {"lightseagreen", 32, 178, 170}, - {"lightskyblue", 135, 206, 250}, - {"lightslategray", 119, 136, 153}, - {"lightsteelblue", 176, 196, 222}, - {"lightyellow", 255, 255, 224}, - {"lime", 0, 255, 0}, - {"limegreen", 50, 205, 50}, - {"linen", 250, 240, 230}, - {"magenta", 255, 0, 255}, - {"maroon", 128, 0, 0}, - {"mediumaquamarine", 102, 205, 170}, - {"mediumblue", 0, 0, 205}, - {"mediumorchid", 186, 85, 211}, - {"mediumpurple", 147, 112, 219}, - {"mediumseagreen", 60, 179, 113}, - {"mediumslateblue", 123, 104, 238}, - {"mediumspringgreen", 0, 250, 154}, - {"mediumturquoise", 72, 209, 204}, - {"mediumvioletred", 199, 21, 133}, - {"midnightblue", 25, 25, 112}, - {"mintcream", 245, 255, 250}, - {"mistyrose", 255, 228, 225}, - {"moccasin", 255, 228, 181}, - {"navajowhite", 255, 222, 173}, - {"navy", 0, 0, 128}, - {"oldlace", 253, 245, 230}, - {"olive", 128, 128, 0}, - {"olivedrab", 107, 142, 35}, - {"orange", 255, 165, 0}, - {"orangered", 255, 69, 0}, - {"orchid", 218, 112, 214}, - {"palegoldenrod", 238, 232, 170}, - {"palegreen", 152, 251, 152}, - {"paleturquoise", 175, 238, 238}, - {"palevioletred", 219, 112, 147}, - {"papayawhip", 255, 239, 213}, - {"peachpuff", 255, 218, 185}, - {"peru", 205, 133, 63}, - {"pink", 255, 192, 203}, - {"plum", 221, 160, 221}, - {"powderblue", 176, 224, 230}, - {"purple", 128, 0, 128}, - {"red", 255, 0, 0}, - {"rosybrown", 188, 143, 143}, - {"royalblue", 65, 105, 225}, - {"saddlebrown", 139, 69, 19}, - {"salmon", 250, 128, 114}, - {"sandybrown", 244, 164, 96}, - {"seagreen", 46, 139, 87}, - {"seashell", 255, 245, 238}, - {"sienna", 160, 82, 45}, - {"silver", 192, 192, 192}, - {"skyblue", 135, 206, 235}, - {"slateblue", 106, 90, 205}, - {"slategray", 112, 128, 144}, - {"snow", 255, 250, 250}, - {"springgreen", 0, 255, 127}, - {"steelblue", 70, 130, 180}, - {"tan", 210, 180, 140}, - {"teal", 0, 128, 128}, - {"thistle", 216, 191, 216}, - {"tomato", 255, 99, 71}, - {"turquoise", 64, 224, 208}, - {"violet", 238, 130, 238}, - {"wheat", 245, 222, 179}, - {"white", 255, 255, 255}, - {"whitesmoke", 245, 245, 245}, - {"yellow", 255, 255, 0}, - {"yellowgreen", 154, 205, 50}, + {"aliceblue", 240, 248, 255}, + {"antiquewhite", 250, 235, 215}, + {"aqua", 0, 255, 255}, + {"aquamarine", 127, 255, 212}, + {"azure", 240, 255, 255}, + {"beige", 245, 245, 220}, + {"bisque", 255, 228, 196}, + {"black", 0, 0, 0}, + {"blanchedalmond", 255, 235, 205}, + {"blue", 0, 0, 255}, + {"blueviolet", 138, 43, 226}, + {"brown", 165, 42, 42}, + {"burlywood", 222, 184, 135}, + {"cadetblue", 95, 158, 160}, + {"chartreuse", 127, 255, 0}, + {"chocolate", 210, 105, 30}, + {"coral", 255, 127, 80}, + {"cornflowerblue", 100, 149, 237}, + {"cornsilk", 255, 248, 220}, + {"crimson", 237, 164, 61}, + {"cyan", 0, 255, 255}, + {"darkblue", 0, 0, 139}, + {"darkcyan", 0, 139, 139}, + {"darkgoldenrod", 184, 134, 11}, + {"darkgray", 169, 169, 169}, + {"darkgreen", 0, 100, 0}, + {"darkkhaki", 189, 183, 107}, + {"darkmagenta", 139, 0, 139}, + {"darkolivegreen", 85, 107, 47}, + {"darkorange", 255, 140, 0}, + {"darkorchid", 153, 50, 204}, + {"darkred", 139, 0, 0}, + {"darksalmon", 233, 150, 122}, + {"darkseagreen", 143, 188, 143}, + {"darkslateblue", 72, 61, 139}, + {"darkslategray", 47, 79, 79}, + {"darkturquoise", 0, 206, 209}, + {"darkviolet", 148, 0, 211}, + {"deeppink", 255, 20, 147}, + {"deepskyblue", 0, 191, 255}, + {"dimgray", 105, 105, 105}, + {"dodgerblue", 30, 144, 255}, + {"firebrick", 178, 34, 34}, + {"floralwhite", 255, 250, 240}, + {"forestgreen", 34, 139, 34}, + {"fuchsia", 255, 0, 255}, + {"gainsboro", 220, 220, 220}, + {"ghostwhite", 248, 248, 255}, + {"gold", 255, 215, 0}, + {"goldenrod", 218, 165, 32}, + {"gray", 128, 128, 128}, + {"green", 0, 128, 0}, + {"greenyellow", 173, 255, 47}, + {"honeydew", 240, 255, 240}, + {"hotpink", 255, 105, 180}, + {"indianred", 205, 92, 92}, + {"indigo", 75, 0, 130}, + {"ivory", 255, 255, 240}, + {"khaki", 240, 230, 140}, + {"lavender", 230, 230, 250}, + {"lavenderblush", 255, 240, 245}, + {"lawngreen", 124, 252, 0}, + {"lemonchiffon", 255, 250, 205}, + {"lightblue", 173, 216, 230}, + {"lightcoral", 240, 128, 128}, + {"lightcyan", 224, 255, 255}, + {"lightgoldenrodyellow", 250, 250, 210}, + {"lightgrey", 211, 211, 211}, + {"lightgreen", 144, 238, 144}, + {"lightpink", 255, 182, 193}, + {"lightsalmon", 255, 160, 122}, + {"lightseagreen", 32, 178, 170}, + {"lightskyblue", 135, 206, 250}, + {"lightslategray", 119, 136, 153}, + {"lightsteelblue", 176, 196, 222}, + {"lightyellow", 255, 255, 224}, + {"lime", 0, 255, 0}, + {"limegreen", 50, 205, 50}, + {"linen", 250, 240, 230}, + {"magenta", 255, 0, 255}, + {"maroon", 128, 0, 0}, + {"mediumaquamarine", 102, 205, 170}, + {"mediumblue", 0, 0, 205}, + {"mediumorchid", 186, 85, 211}, + {"mediumpurple", 147, 112, 219}, + {"mediumseagreen", 60, 179, 113}, + {"mediumslateblue", 123, 104, 238}, + {"mediumspringgreen", 0, 250, 154}, + {"mediumturquoise", 72, 209, 204}, + {"mediumvioletred", 199, 21, 133}, + {"midnightblue", 25, 25, 112}, + {"mintcream", 245, 255, 250}, + {"mistyrose", 255, 228, 225}, + {"moccasin", 255, 228, 181}, + {"navajowhite", 255, 222, 173}, + {"navy", 0, 0, 128}, + {"oldlace", 253, 245, 230}, + {"olive", 128, 128, 0}, + {"olivedrab", 107, 142, 35}, + {"orange", 255, 165, 0}, + {"orangered", 255, 69, 0}, + {"orchid", 218, 112, 214}, + {"palegoldenrod", 238, 232, 170}, + {"palegreen", 152, 251, 152}, + {"paleturquoise", 175, 238, 238}, + {"palevioletred", 219, 112, 147}, + {"papayawhip", 255, 239, 213}, + {"peachpuff", 255, 218, 185}, + {"peru", 205, 133, 63}, + {"pink", 255, 192, 203}, + {"plum", 221, 160, 221}, + {"powderblue", 176, 224, 230}, + {"purple", 128, 0, 128}, + {"red", 255, 0, 0}, + {"rosybrown", 188, 143, 143}, + {"royalblue", 65, 105, 225}, + {"saddlebrown", 139, 69, 19}, + {"salmon", 250, 128, 114}, + {"sandybrown", 244, 164, 96}, + {"seagreen", 46, 139, 87}, + {"seashell", 255, 245, 238}, + {"sienna", 160, 82, 45}, + {"silver", 192, 192, 192}, + {"skyblue", 135, 206, 235}, + {"slateblue", 106, 90, 205}, + {"slategray", 112, 128, 144}, + {"snow", 255, 250, 250}, + {"springgreen", 0, 255, 127}, + {"steelblue", 70, 130, 180}, + {"tan", 210, 180, 140}, + {"teal", 0, 128, 128}, + {"thistle", 216, 191, 216}, + {"tomato", 255, 99, 71}, + {"turquoise", 64, 224, 208}, + {"violet", 238, 130, 238}, + {"wheat", 245, 222, 179}, + {"white", 255, 255, 255}, + {"whitesmoke", 245, 245, 245}, + {"yellow", 255, 255, 0}, + {"yellowgreen", 154, 205, 50}, }; static VectorMap map; @@ -208,20 +208,20 @@ Array GetTransformArgs(String str, const char *command) { Array args; int pos, endpos; - if ((pos = str.Find(command)) < 0) + if((pos = str.Find(command)) < 0) return args; pos += (int)strlen(command); pos = 1 + str.Find('(', pos); - while (true) { - if ((endpos = str.Find(',', pos)) < 0) + while(true) { + if((endpos = str.Find(',', pos)) < 0) break; double &d = args.Add(); d = Atof(str.Mid(pos, endpos-pos)); pos = endpos+1; - } - if (args.GetCount() < 2) { + } + if(args.GetCount() < 2) { if ((endpos = str.Find(')', pos)) >= 0) { double &d = args.Add(); d = Atof(str.Mid(pos, endpos-pos));