starmath/inc/error.hxx                    |    3 
 starmath/inc/parse.hxx                    |    3 
 starmath/inc/strings.hrc                  |    5 
 starmath/inc/strings.hxx                  |    2 
 starmath/inc/token.hxx                    |   28 -
 starmath/source/ElementsDockingWindow.cxx |    7 
 starmath/source/node.cxx                  |   41 --
 starmath/source/parse.cxx                 |  601 +++++++++++++++++++-----------
 starmath/source/visitors.cxx              |   34 +
 9 files changed, 463 insertions(+), 261 deletions(-)

New commits:
commit 351f620baa64ecabd4f7f93ec0139724766c7c59
Author:     Dante DM <dante19031...@gmail.com>
AuthorDate: Wed Oct 21 15:43:30 2020 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Tue Nov 3 20:57:12 2020 +0100

    Added hexadecimal number and color  support for starmath.
    
    Adds hidden command on guy hex number wich allows to use numbers of
    base 16 and also 0-9-A-Z.
    Added support for custom RGB colors on hexadecimal on starmath
    via command color hex colornumber.
    Improved RGB color handle on starmath.
    Changed the way the color is handled on starmath. Colors keywords
    won't give errors. They have been moved to an independent tokens list
    so starmath will load tokens faster.
    Changed the way the font size is handeled on starmath. This won't
    change anything, just related with the structural change.
    Implemented premature support for rgba colors on math. This change
    only adds the possibility on the parser, node and node visitors. For
    now end-user can not access it since in a future there'll be work
    to do on the renderer to add full support.
    Added hex entrie on the docking window.
    Changes made on Color.hxx, will save some nanoseconds on build.
    
    If you are interested on allowing rgba and do the job on the renderer
    (and all the other stuff than there are a lot of .GetRGBColor()),
    you may find usefull color hex colnum. Since transparency setting is
    ignored, the hexadecimal color has hidden support for it since did
    not instore the max value (255 + 255*256 + 255*256*256) and everything
    is loaded into the sal_uInt32.
    
    Change-Id: Iafb38b142fffa329ca468e3d62643154fcdd2bbf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104630
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/starmath/inc/error.hxx b/starmath/inc/error.hxx
index a05123d6e080..d8179da593d5 100644
--- a/starmath/inc/error.hxx
+++ b/starmath/inc/error.hxx
@@ -39,7 +39,8 @@ enum class SmParseError
     FontExpected,
     SizeExpected,
     DoubleAlign,
-    DoubleSubsupscript
+    DoubleSubsupscript,
+    NumberExpected
 };
 
 
diff --git a/starmath/inc/parse.hxx b/starmath/inc/parse.hxx
index 519a90041f65..4f1e3024ccb3 100644
--- a/starmath/inc/parse.hxx
+++ b/starmath/inc/parse.hxx
@@ -83,6 +83,8 @@ class SmParser
     SmParser& operator=(const SmParser&) = delete;
 
     void            NextToken();
+    void            NextTokenColor();
+    void            NextTokenFontSize();
     sal_Int32       GetTokenIndex() const   { return m_nTokenIndex; }
     void            Replace( sal_Int32 nPos, sal_Int32 nLen, const OUString 
&rText );
 
@@ -140,7 +142,6 @@ public:
     const SmErrorDesc*  NextError();
     const SmErrorDesc*  PrevError();
     const SmErrorDesc*  GetError();
-    static const SmTokenTableEntry* GetTokenTableEntry( const OUString &rName 
);
     const std::set< OUString >&   GetUsedSymbols() const      { return 
m_aUsedSymbols; }
 };
 
diff --git a/starmath/inc/strings.hrc b/starmath/inc/strings.hrc
index 64144759f5cc..50adc4a3e042 100644
--- a/starmath/inc/strings.hrc
+++ b/starmath/inc/strings.hrc
@@ -195,6 +195,8 @@
 #define RID_COLORX_TEAL_HELP                NC_("RID_COLORX_TEAL_HELP", "Color 
Teal" )
 #define RID_COLORX_YELLOW_HELP              NC_("RID_COLORX_YELLOW_HELP", 
"Color Yellow" )
 #define RID_COLORX_RGB_HELP                 NC_("RID_COLORX_RGB_HELP", "Color 
RGB" )
+#define RID_COLORX_RGBA_HELP                NC_("RID_COLORX_RGBA_HELP", "Color 
RGBA" )
+#define RID_COLORX_HEX_HELP                 NC_("RID_COLORX_HEX_HELP", "Color 
hexadecimal" )
 #define RID_LRGROUPX_HELP                   NC_("RID_LRGROUPX_HELP", "Group 
Brackets" )
 #define RID_LRPARENTX_HELP                  NC_("RID_LRPARENTX_HELP", "Round 
Brackets" )
 #define RID_LRBRACKETX_HELP                 NC_("RID_LRBRACKETX_HELP", "Square 
Brackets" )
@@ -317,6 +319,8 @@
 #define STR_TEAL                            NC_("STR_TEAL", "teal" )
 #define STR_YELLOW                          NC_("STR_YELLOW", "yellow" )
 #define STR_RGB                             NC_("STR_RGB", "rgb" )
+#define STR_RGBA                            NC_("STR_RGBA", "rgba" )
+#define STR_HEX                             NC_("STR_HEX", "hex" )
 #define STR_HIDE                            NC_("STR_HIDE", "hide" )
 #define STR_SIZE                            NC_("STR_SIZE", "size" )
 #define STR_FONT                            NC_("STR_FONT", "font" )
@@ -339,6 +343,7 @@
 #define RID_ERR_SIZEEXPECTED                NC_("RID_ERR_SIZEEXPECTED", 
"'size' followed by an unexpected token" )
 #define RID_ERR_DOUBLEALIGN                 NC_("RID_ERR_DOUBLEALIGN", "Double 
aligning is not allowed" )
 #define RID_ERR_DOUBLESUBSUPSCRIPT          NC_("RID_ERR_DOUBLESUBSUPSCRIPT", 
"Double sub/superscripts is not allowed" )
+#define RID_ERR_NUMBEREXPECTED              NC_("RID_ERR_NUMBEREXPECTED", 
"Expected number" )
 #define RID_ERR_POUNDEXPECTED               NC_("RID_ERR_POUNDEXPECTED", "'#' 
expected" )
 #define RID_ERR_COLOREXPECTED               NC_("RID_ERR_COLOREXPECTED", 
"Color required" )
 #define RID_ERR_RIGHTEXPECTED               NC_("RID_ERR_RIGHTEXPECTED", 
"'RIGHT' expected" )
diff --git a/starmath/inc/strings.hxx b/starmath/inc/strings.hxx
index fb00ac2f4782..2daf463afd25 100644
--- a/starmath/inc/strings.hxx
+++ b/starmath/inc/strings.hxx
@@ -188,6 +188,8 @@
 #define RID_COLORX_TEAL     "color teal {<?>} "
 #define RID_COLORX_YELLOW   "color yellow {<?>} "
 #define RID_COLORX_RGB      "color rgb 0 0 0 {<?>} "
+#define RID_COLORX_RGBA     "color rgba 0 0 0 0 {<?>} "
+#define RID_COLORX_HEX      "color hex 000000 {<?>} "
 #define RID_LRGROUPX        "{<?>} "
 #define RID_LRPARENTX       "(<?>) "
 #define RID_LRBRACKETX      "[<?>] "
diff --git a/starmath/inc/token.hxx b/starmath/inc/token.hxx
index 1403e96987a2..a58e28d42be8 100644
--- a/starmath/inc/token.hxx
+++ b/starmath/inc/token.hxx
@@ -64,14 +64,12 @@ enum SmTokenType
     TDOTSDIAG,      TDOTSUP,        TDOTSDOWN,      TACUTE,         TBAR,
     TBREVE,         TCHECK,         TCIRCLE,        TDOT,           TDDOT,
     TDDDOT,         TGRAVE,         THAT,           TTILDE,         TVEC,
-    THARPOON,
     TUNDERLINE,     TOVERLINE,      TOVERSTRIKE,    TITALIC,        TNITALIC,
     TBOLD,          TNBOLD,         TPHANTOM,       TFONT,          TSIZE,
     TCOLOR,         TALIGNL,        TALIGNC,        TALIGNR,        TLEFT,
     TRIGHT,         TLANGLE,        TLBRACE,        TLLINE,         TLDLINE,
     TLCEIL,         TLFLOOR,        TNONE,          TMLINE,         TRANGLE,
     TRBRACE,        TRLINE,         TRDLINE,        TRCEIL,         TRFLOOR,
-    TSIN,           TCOS,           TTAN,           TCOT,           TFUNC,
     TSTACK,         TMATRIX,        TDPOUND,        TPLACE,
     TTEXT,          TNUMBER,        TCHARACTER,     TIDENT,         TNEQ,
     TEQUIV,         TDEF,           TPROP,          TSIM,           TSIMEQ,
@@ -81,12 +79,7 @@ enum SmTokenType
     TODIVIDE,       TTRANSL,        TTRANSR,        TIINT,          TIIINT,
     TLINT,          TLLINT,         TLLLINT,        TPROD,          TCOPROD,
     TFORALL,        TEXISTS,        TNOTEXISTS,     TLIM,           TNABLA,
-    TTOWARD,        TSINH,          TCOSH,          TTANH,          TCOTH,
-    TASIN,          TACOS,          TATAN,          TLN,            TLOG,
-    TUOPER,         TBOPER,         TBLACK,         TWHITE,         TRED,
-    TGREEN,         TBLUE,          TCYAN,          TMAGENTA,       TYELLOW,
-    TFIXED,         TSANS,          TSERIF,         TASINH,
-    TACOSH,         TATANH,         TACOTH,         TACOT,          TEXP,
+    TUOPER,         TBOPER,         TFIXED,         TSANS,          TSERIF,
     TCDOT,          TODOT,          TLESLANT,       TGESLANT,       TNSUBSET,
     TNSUPSET,       TNSUBSETEQ,     TNSUPSETEQ,     TPARTIAL,       TNEG,
     TNI,            TBACKEPSILON,   TALEPH,         TIM,            TRE,
@@ -96,13 +89,22 @@ enum SmTokenType
     TLAMBDABAR,     TLEFTARROW,     TRIGHTARROW,    TUPARROW,       TDOWNARROW,
     TDIVIDES,       TSETN,          TSETZ,          TSETQ,
     TSETR,          TSETC,          TWIDEVEC,       TWIDEHARPOON,   TWIDETILDE,
-    TWIDEHAT,
     TWIDESLASH,     TWIDEBACKSLASH, TLDBRACKET,     TRDBRACKET,     TNOSPACE,
     TUNKNOWN,       TPRECEDES,      TSUCCEEDS,      TPRECEDESEQUAL, 
TSUCCEEDSEQUAL,
-    TPRECEDESEQUIV, TSUCCEEDSEQUIV, TNOTPRECEDES,   TNOTSUCCEEDS,   TSILVER,
-    TGRAY,          TMAROON,        TPURPLE,        TLIME,          TOLIVE,
-    TNAVY,          TTEAL,          TAQUA,          TFUCHSIA,       TINTD,
-    TRGB,           TLAPLACE,       TFOURIER
+    TPRECEDESEQUIV, TSUCCEEDSEQUIV, TNOTPRECEDES,   TNOTSUCCEEDS,   THARPOON,
+    TINTD,          TLAPLACE,       TFOURIER,       TTOWARD,        TWIDEHAT,
+    // Function
+    TFUNC,          TLN,            TLOG,           TEXP,           // Exp - 
Log
+    TSIN,           TCOS,           TTAN,           TCOT,           // Trigo
+    TSINH,          TCOSH,          TTANH,          TCOTH,          // Trigo 
hyperbolic
+    TASIN,          TACOS,          TATAN,          TACOT,          // Arctrigo
+    TASINH,         TACOSH,         TATANH,         TACOTH,         // 
Arctrigo hyperbolic
+    // Color
+    TRGB,           TRGBA,          THEX,
+    TAQUA,          TBLACK,         TBLUE,          TCYAN,          TFUCHSIA,
+    TGRAY,          TGREEN,         TLIME,          TMAGENTA,       TMAROON,
+    TNAVY,          TOLIVE,         TPURPLE,        TRED,           TSILVER,
+    TTEAL,          TWHITE,         TYELLOW
 };
 
 struct SmToken
diff --git a/starmath/source/ElementsDockingWindow.cxx 
b/starmath/source/ElementsDockingWindow.cxx
index 516f424f0107..053c7e04dc06 100644
--- a/starmath/source/ElementsDockingWindow.cxx
+++ b/starmath/source/ElementsDockingWindow.cxx
@@ -189,7 +189,8 @@ const SmElementDescr SmElementsControl::m_aAttributesList[] 
=
     {RID_COLORX_LIME, RID_COLORX_LIME_HELP}, {RID_COLORX_MAROON, 
RID_COLORX_MAROON_HELP},
     {RID_COLORX_NAVY, RID_COLORX_NAVY_HELP}, {RID_COLORX_OLIVE, 
RID_COLORX_OLIVE_HELP},
     {RID_COLORX_PURPLE, RID_COLORX_PURPLE_HELP}, {RID_COLORX_SILVER, 
RID_COLORX_SILVER_HELP},
-    {RID_COLORX_TEAL, RID_COLORX_TEAL_HELP},{RID_COLORX_RGB, 
RID_COLORX_RGB_HELP}
+    {RID_COLORX_TEAL, RID_COLORX_TEAL_HELP},{RID_COLORX_RGB, 
RID_COLORX_RGB_HELP},
+    {RID_COLORX_HEX, RID_COLORX_HEX_HELP}
 };
 
 const SmElementDescr SmElementsControl::m_aBracketsList[] =
@@ -924,6 +925,10 @@ void SmElementsControl::addElements(const SmElementDescr 
aElementsArray[], sal_u
                 addElement(aParser, "color teal { \"" + SmResId(STR_TEAL) + 
"\" }", aElement, SmResId(pElementHelp));
             else if (aElement == RID_COLORX_RGB)
                 addElement(aParser, "color rgb 0 0 0 { \"" + SmResId(STR_RGB) 
+ "\" }", aElement, SmResId(pElementHelp));
+            else if (aElement == RID_COLORX_RGBA)
+                addElement(aParser, "color rgba 0 0 0 0 { \"" + 
SmResId(STR_RGBA) + "\" }", aElement, SmResId(pElementHelp));
+            else if (aElement == RID_COLORX_HEX)
+                addElement(aParser, "color hex 000000 { \"" + SmResId(STR_HEX) 
+ "\" }", aElement, SmResId(pElementHelp));
             else if (aElement == RID_ALIGNLX)
                 addElement(aParser, "\"" + SmResId(STR_ALIGN_LEFT) + "\"", 
aElement, SmResId(pElementHelp));
             else if (aElement == RID_ALIGNCX)
diff --git a/starmath/source/node.cxx b/starmath/source/node.cxx
index e252b83ee308..957c91cb33c6 100644
--- a/starmath/source/node.cxx
+++ b/starmath/source/node.cxx
@@ -1607,8 +1607,7 @@ void SmFontNode::Arrange(OutputDevice &rDev, const 
SmFormat &rFormat)
 {
     SmNode *pNode = GetSubNode(1);
     assert(pNode);
-    sal_Int32 nc;
-    Color col_perso_rgb_color = COL_AUTO;
+    sal_uInt32 nc;
 
     switch (GetToken().eType)
     {   case TSIZE :
@@ -1646,13 +1645,10 @@ void SmFontNode::Arrange(OutputDevice &rDev, const 
SmFormat &rFormat)
         case TAQUA :    SetColor(COL_LIGHTCYAN);     break;
         case TFUCHSIA : SetColor(COL_LIGHTMAGENTA);  break;
         case TRGB :
-            nc = GetToken().aText.toInt32();
-            col_perso_rgb_color.SetBlue(nc % 256);
-            nc /= 256;
-            col_perso_rgb_color.SetGreen(nc % 256);
-            nc /= 256;
-            col_perso_rgb_color.SetRed(nc % 256);
-            SetColor(col_perso_rgb_color);
+        case TRGBA :
+        case THEX :
+            nc = GetToken().aText.toUInt32();
+            SetColor(Color(nc));
             break;
 
         default:
@@ -1855,28 +1851,13 @@ void SmTextNode::GetAccessibleText( OUStringBuffer 
&rText ) const
 
 void SmTextNode::AdjustFontDesc()
 {
-    if (GetToken().eType == TTEXT)
-        mnFontDesc = FNT_TEXT;
-    else if(GetToken().eType == TFUNC)
-        mnFontDesc = FNT_FUNCTION;
+    if (GetToken().nGroup == TG::Function) mnFontDesc = FNT_FUNCTION;
+    else if (GetToken().eType == TTEXT) mnFontDesc = FNT_TEXT;
     else {
-        const SmTokenTableEntry *pEntry = SmParser::GetTokenTableEntry( maText 
);
-        if (pEntry && pEntry->nGroup == TG::Function) {
-            GetToken().eType = pEntry->eType;
-            mnFontDesc = FNT_FUNCTION;
-        } else {
-            sal_Unicode firstChar = maText[0];
-            if( ('0' <= firstChar && firstChar <= '9') || firstChar == '.' || 
firstChar == ',') {
-                mnFontDesc = FNT_NUMBER;
-                GetToken().eType = TNUMBER;
-            } else if (maText.getLength() > 1) {
-                mnFontDesc = FNT_VARIABLE;
-                GetToken().eType = TIDENT;
-            } else {
-                mnFontDesc = FNT_VARIABLE;
-                GetToken().eType = TCHARACTER;
-            }
-        }
+        sal_Unicode firstChar = maText[0];
+        if( ('0' <= firstChar && firstChar <= '9') || firstChar == '.' || 
firstChar == ',')
+            mnFontDesc = FNT_NUMBER;
+        else mnFontDesc = FNT_VARIABLE;
     }
 }
 
diff --git a/starmath/source/parse.cxx b/starmath/source/parse.cxx
index a5872f9e9118..6d7e1891b762 100644
--- a/starmath/source/parse.cxx
+++ b/starmath/source/parse.cxx
@@ -78,7 +78,6 @@ const SmTokenTableEntry aTokenTable[] =
     { "alignt", TALIGNC, '\0', TG::Align, 0},
     { "and", TAND, MS_AND, TG::Product, 0},
     { "approx", TAPPROX, MS_APPROX, TG::Relation, 0},
-    { "aqua", TAQUA, '\0', TG::Color, 0},
     { "arccos", TACOS, '\0', TG::Function, 5},
     { "arccot", TACOT, '\0', TG::Function, 5},
     { "arcosh", TACOSH, '\0', TG::Function, 5 },
@@ -90,8 +89,6 @@ const SmTokenTableEntry aTokenTable[] =
     { "backepsilon" , TBACKEPSILON, MS_BACKEPSILON, TG::Standalone, 5},
     { "bar", TBAR, MS_BAR, TG::Attribute, 5},
     { "binom", TBINOM, '\0', TG::NONE, 5 },
-    { "black", TBLACK, '\0', TG::Color, 0},
-    { "blue", TBLUE, '\0', TG::Color, 0},
     { "bold", TBOLD, '\0', TG::FontAttr, 5},
     { "boper", TBOPER, '\0', TG::Product, 0},
     { "breve", TBREVE, MS_BREVE, TG::Attribute, 5},
@@ -108,7 +105,6 @@ const SmTokenTableEntry aTokenTable[] =
     { "coth", TCOTH, '\0', TG::Function, 5},
     { "csub", TCSUB, '\0', TG::Power, 0},
     { "csup", TCSUP, '\0', TG::Power, 0},
-    { "cyan", TCYAN, '\0', TG::Color, 0},
     { "dddot", TDDDOT, MS_DDDOT, TG::Attribute, 5},
     { "ddot", TDDOT, MS_DDOT, TG::Attribute, 5},
     { "def", TDEF, MS_DEF, TG::Relation, 0},
@@ -135,14 +131,11 @@ const SmTokenTableEntry aTokenTable[] =
     { "forall", TFORALL, MS_FORALL, TG::Standalone, 5},
     { "fourier", TFOURIER, MS_FOURIER, TG::Standalone, 5},
     { "from", TFROM, '\0', TG::Limit, 0},
-    { "fuchsia", TFUCHSIA, '\0', TG::Color, 0},
     { "func", TFUNC, '\0', TG::Function, 5},
     { "ge", TGE, MS_GE, TG::Relation, 0},
     { "geslant", TGESLANT, MS_GESLANT, TG::Relation, 0 },
     { "gg", TGG, MS_GG, TG::Relation, 0},
     { "grave", TGRAVE, MS_GRAVE, TG::Attribute, 5},
-    { "gray", TGRAY, '\0', TG::Color, 0},
-    { "green", TGREEN, '\0', TG::Color, 0},
     { "gt", TGT, MS_GT, TG::Relation, 0},
     { "harpoon", THARPOON, MS_HARPOON, TG::Attribute, 5},
     { "hat", THAT, MS_HAT, TG::Attribute, 5},
@@ -171,7 +164,6 @@ const SmTokenTableEntry aTokenTable[] =
     { "leslant", TLESLANT, MS_LESLANT, TG::Relation, 0 },
     { "lfloor", TLFLOOR, MS_LFLOOR, TG::LBrace, 5},
     { "lim", TLIM, '\0', TG::Oper, 5},
-    { "lime", TLIME, '\0', TG::Color, 0},
     { "liminf", TLIMINF, '\0', TG::Oper, 5},
     { "limsup", TLIMSUP, '\0', TG::Oper, 5},
     { "lint", TLINT, MS_LINT, TG::Oper, 5},
@@ -184,13 +176,10 @@ const SmTokenTableEntry aTokenTable[] =
     { "lsub", TLSUB, '\0', TG::Power, 0},
     { "lsup", TLSUP, '\0', TG::Power, 0},
     { "lt", TLT, MS_LT, TG::Relation, 0},
-    { "magenta", TMAGENTA, '\0', TG::Color, 0},
-    { "maroon", TMAROON, '\0', TG::Color, 0},
     { "matrix", TMATRIX, '\0', TG::NONE, 5},
     { "minusplus", TMINUSPLUS, MS_MINUSPLUS, TG::UnOper | TG::Sum, 5},
     { "mline", TMLINE, MS_VERTLINE, TG::NONE, 0},      //! not in TG::RBrace, 
Level 0
     { "nabla", TNABLA, MS_NABLA, TG::Standalone, 5},
-    { "navy", TNAVY, '\0', TG::Color, 0},
     { "nbold", TNBOLD, '\0', TG::FontAttr, 5},
     { "ndivides", TNDIVIDES, MS_NDIVIDES, TG::Relation, 0},
     { "neg", TNEG, MS_NEG, TG::UnOper, 5 },
@@ -211,7 +200,6 @@ const SmTokenTableEntry aTokenTable[] =
     { "nsupseteq", TNSUPSETEQ, MS_NSUPSETEQ, TG::Relation, 0 },
     { "odivide", TODIVIDE, MS_ODIVIDE, TG::Product, 0},
     { "odot", TODOT, MS_ODOT, TG::Product, 0},
-    { "olive", TOLIVE, '\0', TG::Color, 0},
     { "ominus", TOMINUS, MS_OMINUS, TG::Sum, 0},
     { "oper", TOPER, '\0', TG::Oper, 5},
     { "oplus", TOPLUS, MS_OPLUS, TG::Sum, 0},
@@ -232,16 +220,13 @@ const SmTokenTableEntry aTokenTable[] =
     { "precsim", TPRECEDESEQUIV, MS_PRECEDESEQUIV, TG::Relation, 0 },
     { "prod", TPROD, MS_PROD, TG::Oper, 5},
     { "prop", TPROP, MS_PROP, TG::Relation, 0},
-    { "purple", TPURPLE, '\0', TG::Color, 0},
     { "rangle", TRANGLE, MS_RMATHANGLE, TG::RBrace, 0},  //! 0 to terminate 
expression
     { "rbrace", TRBRACE, MS_RBRACE, TG::RBrace, 0},
     { "rceil", TRCEIL, MS_RCEIL, TG::RBrace, 0},
     { "rdbracket", TRDBRACKET, MS_RDBRACKET, TG::RBrace, 0},
     { "rdline", TRDLINE, MS_DVERTLINE, TG::RBrace, 0},
     { "re" , TRE, MS_RE, TG::Standalone, 5 },
-    { "red", TRED, '\0', TG::Color, 0},
     { "rfloor", TRFLOOR, MS_RFLOOR, TG::RBrace, 0},  //! 0 to terminate 
expression
-    { "rgb", TRGB, '\0', TG::Color, 0},
     { "right", TRIGHT, '\0', TG::NONE, 0},
     { "rightarrow" , TRIGHTARROW, MS_RIGHTARROW, TG::Standalone, 5},
     { "rline", TRLINE, MS_VERTLINE, TG::RBrace, 0},  //! 0 to terminate 
expression
@@ -255,7 +240,6 @@ const SmTokenTableEntry aTokenTable[] =
     { "setQ" , TSETQ, MS_SETQ, TG::Standalone, 5},
     { "setR" , TSETR, MS_SETR, TG::Standalone, 5},
     { "setZ" , TSETZ, MS_SETZ, TG::Standalone, 5},
-    { "silver", TSILVER, '\0', TG::Color, 0},
     { "sim", TSIM, MS_SIM, TG::Relation, 0},
     { "simeq", TSIMEQ, MS_SIMEQ, TG::Relation, 0},
     { "sin", TSIN, '\0', TG::Function, 5},
@@ -276,7 +260,6 @@ const SmTokenTableEntry aTokenTable[] =
     { "supseteq", TSUPSETEQ, MS_SUPSETEQ, TG::Relation, 0},
     { "tan", TTAN, '\0', TG::Function, 5},
     { "tanh", TTANH, '\0', TG::Function, 5},
-    { "teal", TTEAL, '\0', TG::Color, 0},
     { "tilde", TTILDE, MS_TILDE, TG::Attribute, 5},
     { "times", TTIMES, MS_TIMES, TG::Product, 0},
     { "to", TTO, '\0', TG::Limit, 0},
@@ -289,59 +272,103 @@ const SmTokenTableEntry aTokenTable[] =
     { "uoper", TUOPER, '\0', TG::UnOper, 5},
     { "uparrow" , TUPARROW, MS_UPARROW, TG::Standalone, 5},
     { "vec", TVEC, MS_VEC, TG::Attribute, 5},
-    { "white", TWHITE, '\0', TG::Color, 0},
     { "widebslash", TWIDEBACKSLASH, MS_BACKSLASH, TG::Product, 0 },
     { "wideharpoon", TWIDEHARPOON, MS_HARPOON, TG::Attribute, 5},
     { "widehat", TWIDEHAT, MS_HAT, TG::Attribute, 5},
     { "wideslash", TWIDESLASH, MS_SLASH, TG::Product, 0 },
     { "widetilde", TWIDETILDE, MS_TILDE, TG::Attribute, 5},
     { "widevec", TWIDEVEC, MS_VEC, TG::Attribute, 5},
-    { "wp" , TWP, MS_WP, TG::Standalone, 5},
-    { "yellow", TYELLOW, '\0', TG::Color, 0}
+    { "wp" , TWP, MS_WP, TG::Standalone, 5}
 };
 
-//Checks if keyword is in the list by SmTokenTableEntry.
-#if !defined NDEBUG
-static bool sortCompare(const SmTokenTableEntry & lhs, const SmTokenTableEntry 
& rhs)
+//Definition of color keywords
+const SmTokenTableEntry aColorTokenTable[] =
 {
-    return 
OUString::createFromAscii(lhs.pIdent).compareToIgnoreAsciiCase(OUString::createFromAscii(rhs.pIdent))
 < 0;
-}
-#endif
+    { "aqua", TAQUA, '\0', TG::Color, 0},
+    { "black", TBLACK, '\0', TG::Color, 0},
+    { "blue", TBLUE, '\0', TG::Color, 0},
+    { "cyan", TCYAN, '\0', TG::Color, 0},
+    { "fuchsia", TFUCHSIA, '\0', TG::Color, 0},
+    { "gray", TGRAY, '\0', TG::Color, 0},
+    { "green", TGREEN, '\0', TG::Color, 0},
+    { "hex" , THEX, '\0', TG::Color, 0},
+    { "lime", TLIME, '\0', TG::Color, 0},
+    { "magenta", TMAGENTA, '\0', TG::Color, 0},
+    { "maroon", TMAROON, '\0', TG::Color, 0},
+    { "navy", TNAVY, '\0', TG::Color, 0},
+    { "olive", TOLIVE, '\0', TG::Color, 0},
+    { "purple", TPURPLE, '\0', TG::Color, 0},
+    { "red", TRED, '\0', TG::Color, 0},
+    { "rgb", TRGB, '\0', TG::Color, 0},
+    //{ "rgba", TRGBA, '\0', TG::Color, 0},
+    { "silver", TSILVER, '\0', TG::Color, 0},
+    { "teal", TTEAL, '\0', TG::Color, 0},
+    { "white", TWHITE, '\0', TG::Color, 0},
+    { "yellow", TYELLOW, '\0', TG::Color, 0}
+};
+
+// First character may be any alphabetic
+const sal_Int32 coStartFlags = KParseTokens::ANY_LETTER | 
KParseTokens::IGNORE_LEADING_WS;
+
+// Continuing characters may be any alphabetic
+const sal_Int32 coContFlags = (coStartFlags & ~KParseTokens::IGNORE_LEADING_WS)
+                              | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING;
+// First character for numbers, may be any numeric or dot
+const sal_Int32 coNumStartFlags = KParseTokens::ASC_DIGIT | 
KParseTokens::ASC_DOT
+                                  | KParseTokens::IGNORE_LEADING_WS;
+// Continuing characters for numbers, may be any numeric or dot or comma.
+// tdf#127873: additionally accept ',' comma group separator as too many
+// existing documents unwittingly may have used that as decimal separator
+// in such locales (though it never was as this is always the en-US locale
+// and the group separator is only parsed away).
+const sal_Int32 coNumContFlags = (coNumStartFlags & 
~KParseTokens::IGNORE_LEADING_WS)
+                                 | KParseTokens::GROUP_SEPARATOR_IN_NUMBER;
+// First character for numbers hexadecimal
+const sal_Int32 coNum16StartFlags = KParseTokens::ASC_DIGIT | 
KParseTokens::ASC_UPALPHA
+                                    | KParseTokens::IGNORE_LEADING_WS;
+
+// Continuing characters for numbers hexadecimal
+const sal_Int32 coNum16ContFlags = (coNum16StartFlags & 
~KParseTokens::IGNORE_LEADING_WS);
+// user-defined char continuing characters may be any alphanumeric or dot.
+const sal_Int32 coUserDefinedCharContFlags = KParseTokens::ANY_LETTER_OR_NUMBER
+                                             | KParseTokens::ASC_DOT
+                                             | 
KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING;
 
 //Checks if keyword is in the list.
-static bool findCompare(const SmTokenTableEntry & lhs, const OUString & s)
+static inline bool findCompare(const SmTokenTableEntry & lhs, const OUString & 
s)
 {
     return s.compareToIgnoreAsciiCaseAscii(lhs.pIdent) > 0;
 }
 
 //Returns the SmTokenTableEntry for a keyword
-const SmTokenTableEntry * SmParser::GetTokenTableEntry( const OUString &rName )
+static const SmTokenTableEntry * GetTokenTableEntry( const OUString &rName )
 {
-    static bool bSortKeyWords = false; // Flag: RTF-token table has been 
sorted.
-    if( !bSortKeyWords ) //First time sorts it.
-    {
-        assert( std::is_sorted( std::begin(aTokenTable), 
std::end(aTokenTable), sortCompare ) );
-        bSortKeyWords = true;
-    }
-
     if (rName.isEmpty())return nullptr; //avoid null pointer exceptions
-
     //Looks for the first keyword after or equal to rName in alphabetical 
order.
-    auto findIter = std::lower_bound( std::begin(aTokenTable), 
std::end(aTokenTable), rName, findCompare );
-    if ( findIter != std::end(aTokenTable) && 
rName.equalsIgnoreAsciiCaseAscii( findIter->pIdent ))return &*findIter; //check 
is equal
-
+    auto findIter = std::lower_bound( std::begin(aTokenTable),
+                                      std::end(aTokenTable), rName, 
findCompare );
+    if ( findIter != std::end(aTokenTable) && 
rName.equalsIgnoreAsciiCaseAscii( findIter->pIdent ))
+        return &*findIter; //check is equal
     return nullptr; //not found
 }
 
-namespace {
-
-bool IsDelimiter( const OUString &rTxt, sal_Int32 nPos )
-    // returns 'true' iff cChar is '\0' or a delimiter
+//Returns the SmTokenTableEntry for a keyword
+static const SmTokenTableEntry * GetColorTokenTableEntry( const OUString 
&rName )
 {
-    assert(nPos <= rTxt.getLength()); //index out of range
+    if (rName.isEmpty())return nullptr; //avoid null pointer exceptions
+    //Looks for the first keyword after or equal to rName in alphabetical 
order.
+    auto findIter = std::lower_bound( std::begin(aColorTokenTable),
+                                      std::end(aColorTokenTable), rName, 
findCompare );
+    if ( findIter != std::end(aColorTokenTable)
+                     && rName.equalsIgnoreAsciiCaseAscii( findIter->pIdent ))
+        return &*findIter; //check is equal
+    return nullptr; //not found
+}
+static bool IsDelimiter( const OUString &rTxt, sal_Int32 nPos )
+{   // returns 'true' iff cChar is '\0' or a delimiter
 
+    assert(nPos <= rTxt.getLength()); //index out of range
     if (nPos == rTxt.getLength())return true; //This is EOF
-
     sal_Unicode cChar = rTxt[nPos];
 
     // check if 'cChar' is in the delimiter table
@@ -364,7 +391,42 @@ bool IsDelimiter( const OUString &rTxt, sal_Int32 nPos )
              nTypJp == css::i18n::UnicodeType::CONTROL);
 }
 
-}//end namespace
+// checks number used as arguments in Math formulas (e.g. 'size' command)
+// Format: no negative numbers, must start with a digit, no exponent notation, 
...
+static bool lcl_IsNumber(const OUString& rText)
+{
+    bool bPoint = false;
+    const sal_Unicode* pBuffer = rText.getStr();
+    for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++)
+    {
+        const sal_Unicode cChar = *pBuffer;
+        if(cChar == '.')
+        {
+            if(bPoint) return false;
+            else bPoint = true;
+        }
+        else if ( !rtl::isAsciiDigit( cChar ) ) return false;
+    }
+    return true;
+}
+// checks number used as arguments in Math formulas (e.g. 'size' command)
+// Format: no negative numbers, must start with a digit, no exponent notation, 
...
+static bool lcl_IsNotWholeNumber(const OUString& rText)
+{
+    const sal_Unicode* pBuffer = rText.getStr();
+    for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++)
+        if ( !rtl::isAsciiDigit( *pBuffer ) ) return true;
+    return false;
+}
+// checks hex number used as arguments in Math formulas (e.g. 'hex' command)
+// Format: no negative numbers, must start with a digit, no exponent notation, 
...
+static bool lcl_IsNotWholeNumber16(const OUString& rText)
+{
+    const sal_Unicode* pBuffer = rText.getStr();
+    for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++)
+        if ( !rtl::isAsciiCanonicHexDigit( *pBuffer ) ) return true;
+    return false;
+}
 
 //Text replace onto m_aBufferString
 void SmParser::Replace( sal_Int32 nPos, sal_Int32 nLen, const OUString &rText )
@@ -379,36 +441,6 @@ void SmParser::Replace( sal_Int32 nPos, sal_Int32 nLen, 
const OUString &rText )
 
 void SmParser::NextToken() //Central part of the parser
 {
-    // First character may be any alphabetic
-    static const sal_Int32 coStartFlags =
-        KParseTokens::ANY_LETTER |
-        KParseTokens::IGNORE_LEADING_WS;
-
-    // Continuing characters may be any alphabetic
-    static const sal_Int32 coContFlags =
-        (coStartFlags & ~KParseTokens::IGNORE_LEADING_WS)
-        | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING;
-
-    // user-defined char continuing characters may be any alphanumeric or dot.
-    static const sal_Int32 coUserDefinedCharContFlags =
-        KParseTokens::ANY_LETTER_OR_NUMBER |
-        KParseTokens::ASC_DOT |
-        KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING;
-
-    // First character for numbers, may be any numeric or dot
-    static const sal_Int32 coNumStartFlags =
-        KParseTokens::ASC_DIGIT |
-        KParseTokens::ASC_DOT |
-        KParseTokens::IGNORE_LEADING_WS;
-
-    // Continuing characters for numbers, may be any numeric or dot.
-    // tdf#127873: additionally accept ',' comma group separator as too many
-    // existing documents unwittingly may have used that as decimal separator
-    // in such locales (though it never was as this is always the en-US locale
-    // and the group separator is only parsed away).
-    static const sal_Int32 coNumContFlags =
-        (coNumStartFlags & ~KParseTokens::IGNORE_LEADING_WS) |
-        KParseTokens::GROUP_SEPARATOR_IN_NUMBER;
 
     sal_Int32   nBufLen = m_aBufferString.getLength();
     ParseResult aRes;
@@ -979,6 +1011,186 @@ void SmParser::NextToken() //Central part of the parser
         m_nBufferIndex = aRes.EndPos;
 }
 
+void SmParser::NextTokenColor()
+{
+
+    sal_Int32   nBufLen = m_aBufferString.getLength();
+    ParseResult aRes;
+    sal_Int32   nRealStart;
+    bool        bCont;
+
+    do
+    {
+        // skip white spaces
+        while (UnicodeType::SPACE_SEPARATOR ==
+                        m_pSysCC->getType( m_aBufferString, m_nBufferIndex ))
+           ++m_nBufferIndex;
+        //parse, there are few options, so less strict.
+        aRes = m_pSysCC->parseAnyToken(m_aBufferString, m_nBufferIndex,
+                                       coStartFlags, "", coContFlags, "");
+        nRealStart = m_nBufferIndex + aRes.LeadingWhiteSpace;
+        m_nBufferIndex = nRealStart;
+        bCont = false;
+        if ( aRes.TokenType == 0  &&
+                nRealStart < nBufLen &&
+                '\n' == m_aBufferString[ nRealStart ] )
+        {
+            // keep data needed for tokens row and col entry up to date
+            ++m_nRow;
+            m_nBufferIndex = m_nColOff = nRealStart + 1;
+            bCont = true;
+        }
+        else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR)
+        {
+            if (nRealStart + 2 <= nBufLen && m_aBufferString.match("%%", 
nRealStart))
+            {
+                //SkipComment
+                m_nBufferIndex = nRealStart + 2;
+                while (m_nBufferIndex < nBufLen  &&
+                    '\n' != m_aBufferString[ m_nBufferIndex ])
+                    ++m_nBufferIndex;
+                bCont = true;
+            }
+        }
+    } while (bCont);
+
+    // set index of current token
+    m_nTokenIndex    = m_nBufferIndex;
+    m_aCurToken.nRow = m_nRow;
+    m_aCurToken.nCol = nRealStart - m_nColOff + 1;
+    if (nRealStart >= nBufLen) m_aCurToken.eType = TEND;
+    else if (aRes.TokenType & KParseType::IDENTNAME)
+    {
+        sal_Int32 n = aRes.EndPos - nRealStart;
+        assert(n >= 0);
+        OUString aName( m_aBufferString.copy( nRealStart, n ) );
+        const SmTokenTableEntry *pEntry = GetColorTokenTableEntry( aName );
+        if (pEntry)
+        {
+            m_aCurToken.eType      = pEntry->eType;
+            m_aCurToken.cMathChar  = pEntry->cMathChar;
+            m_aCurToken.nGroup     = pEntry->nGroup;
+            m_aCurToken.nLevel     = pEntry->nLevel;
+            m_aCurToken.aText      = OUString::createFromAscii( pEntry->pIdent 
);
+        }
+        else m_aCurToken.eType     = TNONE;
+    }
+    else m_aCurToken.eType         = TNONE;
+    if (TEND != m_aCurToken.eType) m_nBufferIndex = aRes.EndPos;
+}
+
+void SmParser::NextTokenFontSize()
+{
+
+    sal_Int32   nBufLen = m_aBufferString.getLength();
+    ParseResult aRes;
+    sal_Int32   nRealStart;
+    bool        bCont;
+    bool        hex = false;
+
+    do
+    {
+        // skip white spaces
+        while (UnicodeType::SPACE_SEPARATOR ==
+                    m_pSysCC->getType( m_aBufferString, m_nBufferIndex ))
+           ++m_nBufferIndex;
+        //hexadecimal parser
+        aRes = m_pSysCC->parseAnyToken(m_aBufferString, m_nBufferIndex,
+                                       coNum16StartFlags, ".", 
coNum16ContFlags, ".,");
+        if (aRes.TokenType == 0)
+        {
+            // Try again with the default token parsing.
+            aRes = m_pSysCC->parseAnyToken(m_aBufferString, m_nBufferIndex,
+                                     coStartFlags, "", coContFlags, "");
+        }
+        else hex = true;
+        nRealStart = m_nBufferIndex + aRes.LeadingWhiteSpace;
+        m_nBufferIndex = nRealStart;
+        bCont = false;
+        if ( aRes.TokenType == 0  &&
+                nRealStart < nBufLen &&
+                '\n' == m_aBufferString[ nRealStart ] )
+        {
+            // keep data needed for tokens row and col entry up to date
+            ++m_nRow;
+            m_nBufferIndex = m_nColOff = nRealStart + 1;
+            bCont = true;
+        }
+        else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR)
+        {
+            if (nRealStart + 2 <= nBufLen && m_aBufferString.match("%%", 
nRealStart))
+            {
+                //SkipComment
+                m_nBufferIndex = nRealStart + 2;
+                while (m_nBufferIndex < nBufLen  &&
+                    '\n' != m_aBufferString[ m_nBufferIndex ])
+                    ++m_nBufferIndex;
+                bCont = true;
+            }
+        }
+    } while (bCont);
+
+    // set index of current token
+    m_nTokenIndex      = m_nBufferIndex;
+    m_aCurToken.nRow   = m_nRow;
+    m_aCurToken.nCol   = nRealStart - m_nColOff + 1;
+    if (nRealStart >= nBufLen) m_aCurToken.eType    = TEND;
+    else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR)
+    {
+        if ( aRes.EndPos - nRealStart == 1 )
+        {
+            switch ( m_aBufferString[ nRealStart ] )
+            {
+                case '*':
+                    m_aCurToken.eType     = TMULTIPLY;
+                    m_aCurToken.cMathChar = MS_MULTIPLY;
+                    m_aCurToken.nGroup    = TG::Product;
+                    m_aCurToken.nLevel    = 0;
+                    m_aCurToken.aText     = "*";
+                    break;
+                case '+':
+                    m_aCurToken.eType     = TPLUS;
+                    m_aCurToken.cMathChar = MS_PLUS;
+                    m_aCurToken.nGroup    = TG::UnOper | TG::Sum;
+                    m_aCurToken.nLevel    = 5;
+                    m_aCurToken.aText     = "+";
+                    break;
+                case '-':
+                    m_aCurToken.eType     = TMINUS;
+                    m_aCurToken.cMathChar = MS_MINUS;
+                    m_aCurToken.nGroup    = TG::UnOper | TG::Sum;
+                    m_aCurToken.nLevel    = 5;
+                    m_aCurToken.aText     = "-";
+                    break;
+                case '/':
+                    m_aCurToken.eType     = TDIVIDEBY;
+                    m_aCurToken.cMathChar = MS_SLASH;
+                    m_aCurToken.nGroup    = TG::Product;
+                    m_aCurToken.nLevel    = 0;
+                    m_aCurToken.aText     = "/";
+                    break;
+                default:
+                    m_aCurToken.eType     = TNONE;
+                    break;
+            }
+        }
+        else m_aCurToken.eType = TNONE;
+    }
+    else if(hex)
+    {
+        assert(aRes.EndPos > 0);
+        sal_Int32 n = aRes.EndPos - nRealStart;
+        assert(n >= 0);
+        m_aCurToken.eType      = THEX;
+        m_aCurToken.cMathChar  = '\0';
+        m_aCurToken.nGroup     = TG::NONE;
+        m_aCurToken.nLevel     = 5;
+        m_aCurToken.aText      = m_aBufferString.copy( nRealStart, n );
+    }
+    else m_aCurToken.eType     = TNONE;
+    if (TEND != m_aCurToken.eType) m_nBufferIndex = aRes.EndPos;
+}
+
 namespace
 {
     SmNodeArray buildNodeArray(std::vector<std::unique_ptr<SmNode>>& rSubNodes)
@@ -991,6 +1203,7 @@ namespace
 } //end namespace
 
 // grammar
+/*************************************************************************************************/
 
 std::unique_ptr<SmTableNode> SmParser::DoTable()
 {
@@ -1537,15 +1750,20 @@ std::unique_ptr<SmNode> SmParser::DoTerm(bool 
bGroupNumberIdent)
         case TMATRIX:
             return DoMatrix();
 
+        case THEX:
+            NextTokenFontSize();
+            if( m_aCurToken.eType == THEX )
+            {
+                auto pTextNode = std::make_unique<SmTextNode>(m_aCurToken, 
FNT_NUMBER );
+                NextToken();
+                return pTextNode;
+            }
+            else return DoError(SmParseError::NumberExpected);
         default:
-            if (TokenInGroup(TG::LBrace))
-                return DoBrace();
-            if (TokenInGroup(TG::Oper))
-                return DoOperator();
-            if (TokenInGroup(TG::UnOper))
-                return DoUnOper();
-            if ( TokenInGroup(TG::Attribute) ||
-                 TokenInGroup(TG::FontAttr) )
+            if (TokenInGroup(TG::LBrace)) return DoBrace();
+            if (TokenInGroup(TG::Oper)) return DoOperator();
+            if (TokenInGroup(TG::UnOper)) return DoUnOper();
+            if ( TokenInGroup(TG::Attribute) || TokenInGroup(TG::FontAttr) )
             {
                 std::stack<std::unique_ptr<SmStructureNode>> aStack;
                 bool    bIsAttr;
@@ -1862,51 +2080,76 @@ std::unique_ptr<SmStructureNode> 
SmParser::DoFontAttribut()
 std::unique_ptr<SmStructureNode> SmParser::DoColor()
 {
     DepthProtect aDepthGuard(m_nParseDepth);
-    if (aDepthGuard.TooDeep())
-        throw std::range_error("parser depth limit");
+    if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit");
 
     assert(m_aCurToken.eType == TCOLOR);
-
-    std::unique_ptr<SmStructureNode> xNode;
-    // last color rules, get that one
+    NextTokenColor();
     SmToken  aToken;
-    do
-    {
-
-        NextToken();
 
-        if (TokenInGroup(TG::Color))
+    if (TokenInGroup(TG::Color))
+    {
+        aToken = m_aCurToken;
+        if( m_aCurToken.eType == TRGB ) //loads r, g and b
         {
-            aToken = m_aCurToken;
-            if(m_aCurToken.eType==TRGB){
-                SmToken r,g,b;
-                sal_Int32 nr, ng, nb, nc;
-                NextToken();
-                if(m_aCurToken.eType!=TNUMBER)return 
DoError(SmParseError::ColorExpected);
-                r = m_aCurToken;
-                NextToken();
-                if(m_aCurToken.eType!=TNUMBER)return 
DoError(SmParseError::ColorExpected);
-                g = m_aCurToken;
-                NextToken();
-                if(m_aCurToken.eType!=TNUMBER)return 
DoError(SmParseError::ColorExpected);
-                b = m_aCurToken;
-                nr = r.aText.toInt32();
-                if( nr < 0 || nr > 255 )return 
DoError(SmParseError::ColorExpected);
-                ng = g.aText.toInt32();
-                if( ng < 0 || ng > 255 )return 
DoError(SmParseError::ColorExpected);
-                nb = b.aText.toInt32();
-                if( nb < 0 || nb > 255 )return 
DoError(SmParseError::ColorExpected);
-                nc = nb + 256 * ( ng + nr*256 );
-                aToken.aText = OUString::number(nc);
-            }
-            NextToken();
+            sal_uInt32 nr, ng, nb, nc;
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            nr = m_aCurToken.aText.toUInt32();
+            if( nr > 255 )return DoError(SmParseError::ColorExpected);
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            ng = m_aCurToken.aText.toUInt32();
+            if( ng > 255 )return DoError(SmParseError::ColorExpected);
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            nb = m_aCurToken.aText.toUInt32();
+            if( nb > 255 )return DoError(SmParseError::ColorExpected);
+            nc = nb | ng << 8 | nr << 16 | sal_uInt32(0) << 24;
+            aToken.aText = OUString::number(nc);
         }
-        else
+        else if( m_aCurToken.eType == TRGBA ) //loads r, g and b
+        {
+            sal_uInt32 nr, na, ng, nb, nc;
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            nr = m_aCurToken.aText.toUInt32();
+            if( nr > 255 )return DoError(SmParseError::ColorExpected);
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            ng = m_aCurToken.aText.toUInt32();
+            if( ng > 255 )return DoError(SmParseError::ColorExpected);
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            nb = m_aCurToken.aText.toUInt32();
+            if( nb > 255 )return DoError(SmParseError::ColorExpected);
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            na = m_aCurToken.aText.toUInt32();
+            if( na > 255 )return DoError(SmParseError::ColorExpected);
+            nc = nb | ng << 8 | nr << 16 | na << 24;
+            aToken.aText = OUString::number(nc);
+        }
+        else if( m_aCurToken.eType == THEX ) //loads hex code
         {
-            return DoError(SmParseError::ColorExpected);
+            sal_uInt32 nc;
+            NextTokenFontSize();
+            if( lcl_IsNotWholeNumber16(m_aCurToken.aText) )
+                return DoError(SmParseError::ColorExpected);
+            nc = m_aCurToken.aText.toUInt32(16);
+            aToken.aText = OUString::number(nc);
         }
-    } while (m_aCurToken.eType == TCOLOR);
+        NextToken();
+    }
+    else return DoError(SmParseError::ColorExpected);
 
+    std::unique_ptr<SmStructureNode> xNode;
     xNode.reset(new SmFontNode(aToken));
     return xNode;
 }
@@ -1939,45 +2182,17 @@ std::unique_ptr<SmStructureNode> SmParser::DoFont()
     return xNode;
 }
 
-
-// gets number used as arguments in Math formulas (e.g. 'size' command)
-// Format: no negative numbers, must start with a digit, no exponent notation, 
...
-static bool lcl_IsNumber(const OUString& rText)
-{
-    bool bPoint = false;
-    const sal_Unicode* pBuffer = rText.getStr();
-    for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++)
-    {
-        const sal_Unicode cChar = *pBuffer;
-        if(cChar == '.')
-        {
-            if(bPoint)
-                return false;
-            else
-                bPoint = true;
-        }
-        else if ( !rtl::isAsciiDigit( cChar ) )
-            return false;
-    }
-    return true;
-}
-
 std::unique_ptr<SmStructureNode> SmParser::DoFontSize()
 {
     DepthProtect aDepthGuard(m_nParseDepth);
-    if (aDepthGuard.TooDeep())
-        throw std::range_error("parser depth limit");
-
-    assert(m_aCurToken.eType == TSIZE);
-
-    FontSizeType   Type;
+    if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit");
     std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(m_aCurToken));
-
-    NextToken();
+    NextTokenFontSize();
+    FontSizeType Type;
 
     switch (m_aCurToken.eType)
     {
-        case TNUMBER:   Type = FontSizeType::ABSOLUT;  break;
+        case THEX:      Type = FontSizeType::ABSOLUT;  break;
         case TPLUS:     Type = FontSizeType::PLUS;     break;
         case TMINUS:    Type = FontSizeType::MINUS;    break;
         case TMULTIPLY: Type = FontSizeType::MULTIPLY; break;
@@ -1989,42 +2204,32 @@ std::unique_ptr<SmStructureNode> SmParser::DoFontSize()
 
     if (Type != FontSizeType::ABSOLUT)
     {
-        NextToken();
-        if (m_aCurToken.eType != TNUMBER)
-            return DoError(SmParseError::SizeExpected);
+        NextTokenFontSize();
+        if (m_aCurToken.eType != THEX) return 
DoError(SmParseError::SizeExpected);
     }
 
     // get number argument
     Fraction  aValue( 1 );
     if (lcl_IsNumber( m_aCurToken.aText ))
     {
-        double fTmp = m_aCurToken.aText.toDouble();
-        if (fTmp != 0.0)
+        aValue = m_aCurToken.aText.toDouble();
+        //!! Reduce values in order to avoid numerical errors
+        if (aValue.GetDenominator() > 1000)
         {
-            aValue = fTmp;
-
-            //!! keep the numerator and denominator from being too large
-            //!! otherwise ongoing multiplications may result in overflows
-            //!! (for example in SmNode::SetFontSize the font size calculated
-            //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 
with Linux
-            //!! or ftmp = 1.11111111111111111... (11/9) on every platform.)
-            if (aValue.GetDenominator() > 1000)
+            tools::Long nNum   = aValue.GetNumerator();
+            tools::Long nDenom = aValue.GetDenominator();
+            while ( nDenom > 1000 ) //remove big denominator
             {
-                tools::Long nNum   = aValue.GetNumerator();
-                tools::Long nDenom = aValue.GetDenominator();
-                while (nDenom > 1000)
-                {
-                    nNum    /= 10;
-                    nDenom  /= 10;
-                }
-                aValue = Fraction( nNum, nDenom );
+                nNum    /= 10;
+                nDenom  /= 10;
             }
+            aValue = Fraction( nNum, nDenom );
         }
     }
-
-    NextToken();
+    else return DoError(SmParseError::SizeExpected);
 
     pFontNode->SetSizeParameter(aValue, Type);
+    NextToken();
     return pFontNode;
 }
 
@@ -2169,45 +2374,16 @@ std::unique_ptr<SmBracebodyNode> 
SmParser::DoBracebody(bool bIsLeftRight)
 std::unique_ptr<SmTextNode> SmParser::DoFunction()
 {
     DepthProtect aDepthGuard(m_nParseDepth);
-    if (aDepthGuard.TooDeep())
-        throw std::range_error("parser depth limit");
-
-    switch (m_aCurToken.eType)
+    if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit");
+    if( m_aCurToken.eType == TFUNC )
     {
-        case TFUNC:
-            NextToken();    // skip "FUNC"-statement
-            m_aCurToken.eType = TFUNC;
-            [[fallthrough]];
-
-        case TSIN :
-        case TCOS :
-        case TTAN :
-        case TCOT :
-        case TASIN :
-        case TACOS :
-        case TATAN :
-        case TACOT :
-        case TSINH :
-        case TCOSH :
-        case TTANH :
-        case TCOTH :
-        case TASINH :
-        case TACOSH :
-        case TATANH :
-        case TACOTH :
-        case TLN :
-        case TLOG :
-        case TEXP :
-            {
-                auto pNode = std::make_unique<SmTextNode>(m_aCurToken, 
FNT_FUNCTION);
-                NextToken();
-                return pNode;
-            }
-
-        default:
-            assert(false);
-            return nullptr;
+        NextToken();    // skip "FUNC"-statement
+        m_aCurToken.eType = TFUNC;
+        m_aCurToken.nGroup = TG::Function;
     }
+    auto pNode = std::make_unique<SmTextNode>(m_aCurToken, FNT_FUNCTION);
+    NextToken();
+    return pNode;
 }
 
 std::unique_ptr<SmTableNode> SmParser::DoBinom()
@@ -2459,6 +2635,7 @@ void SmParser::AddError(SmParseError Type, SmNode *pNode)
         case SmParseError::SizeExpected:       pRID = RID_ERR_SIZEEXPECTED;    
    break;
         case SmParseError::DoubleAlign:        pRID = RID_ERR_DOUBLEALIGN;     
    break;
         case SmParseError::DoubleSubsupscript: pRID = 
RID_ERR_DOUBLESUBSUPSCRIPT;  break;
+        case SmParseError::NumberExpected:     pRID = RID_ERR_NUMBEREXPECTED;  
    break;
         default:
             assert(false);
             return;
diff --git a/starmath/source/visitors.cxx b/starmath/source/visitors.cxx
index 3704abc18c32..f6e030b298d7 100644
--- a/starmath/source/visitors.cxx
+++ b/starmath/source/visitors.cxx
@@ -2077,8 +2077,8 @@ void SmNodeToTextVisitor::Visit( SmAttributNode* pNode )
 
 void SmNodeToTextVisitor::Visit( SmFontNode* pNode )
 {
-    sal_Int32 nc;
-    sal_Int16 nr, ng, nb;
+    sal_uInt32 nc;
+    sal_uInt8  nr, ng, nb;
     switch ( pNode->GetToken( ).eType )
     {
         case TBOLD:
@@ -2180,7 +2180,7 @@ void SmNodeToTextVisitor::Visit( SmFontNode* pNode )
             break;
         case TRGB:
             Append( "color rgb " );
-            nc = pNode->GetToken().aText.toInt32();
+            nc = pNode->GetToken().aText.toUInt32();
             nb = nc % 256;
             nc /= 256;
             ng = nc % 256;
@@ -2193,6 +2193,30 @@ void SmNodeToTextVisitor::Visit( SmFontNode* pNode )
             Append(OUString::number(nb));
             Separate();
             break;
+        case TRGBA:
+            Append( "color rgba " );
+            nc = pNode->GetToken().aText.toUInt32();
+            nb = nc % 256;
+            nc /= 256;
+            ng = nc % 256;
+            nc /= 256;
+            nr = nc % 256;
+            nc /= 256;
+            Append(OUString::number(nr));
+            Separate();
+            Append(OUString::number(ng));
+            Separate();
+            Append(OUString::number(nb));
+            Separate();
+            Append(OUString::number(nc));
+            Separate();
+            break;
+        case THEX:
+            Append( "color hex " );
+            nc = pNode->GetToken().aText.toUInt32();
+            Append(OUString::number(nc,16));
+            Separate();
+            break;
         case TSANS:
             Append( "font sans " );
             break;
@@ -2370,6 +2394,10 @@ void SmNodeToTextVisitor::Visit( SmTextNode* pNode )
             Append("func ");
             Append( pNode->GetToken().aText );
             break;
+        case THEX:
+            Append("hex ");
+            Append( pNode->GetToken().aText );
+            break;
         default:
             Append( pNode->GetToken().aText );
     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to