commit e5c02058d0cc594292729c6c1e8ef38297e4352d Author: Juergen Spitzmueller <sp...@lyx.org> Date: Sun Feb 23 14:40:28 2025 +0100
tex2lyx: support most xcolor models by converting them to rgb math guys, please double check whether I got this right. from the leftovers: Hsb and tHsb depend on a dynamic (settable) range (\rangeHsb, \rangetHsb) which would need to be taken into account. The wave to rgb algorithm is simply beyond my simple mind. --- src/tex2lyx/Preamble.cpp | 219 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 3 deletions(-) diff --git a/src/tex2lyx/Preamble.cpp b/src/tex2lyx/Preamble.cpp index f453f993b5..f53246ee56 100644 --- a/src/tex2lyx/Preamble.cpp +++ b/src/tex2lyx/Preamble.cpp @@ -462,6 +462,211 @@ string process_keyval_opt(vector<string> & options, string const & name) return ""; } + +string const tripleToString(double const a, double const b, double const c) +{ + return convert<string>(a) + ", " + convert<string>(b) + ", " + convert<string>(c); +} + + +string convert_color_value(string const & model, string const & value) +{ + // we attempt to convert color values to rgb + // for the formulae, cf. the xcolor manual + if (model == "rgb") + // already have it + return value; + vector<string> invals = getVectorFromString(value); + if (model == "RGB") { + if (invals.size() != 3 || !isStrInt(invals[0]) + || !isStrInt(invals[1]) || !isStrInt(invals[2])) { + LYXERR0("Ignoring wrong RGB color value: " << value); + return string(); + } + // r = R / 255 + // g = G / 255 + // b = B / 255 + double const r = convert<double>(invals[0]) / 255.0; + double const g = convert<double>(invals[1]) / 255.0; + double const b = convert<double>(invals[2]) / 255.0; + return tripleToString(r, g, b); + } + if (model == "cmyk") { + if (invals.size() != 4 || !isStrDbl(invals[0]) || !isStrDbl(invals[1]) + || !isStrDbl(invals[2]) || !isStrDbl(invals[3])) { + LYXERR0("Ignoring wrong cmyk color value: " << value); + return string(); + } + // r = (1 - c) * (1 - k) + // g = (1 - m) * (1 - k) + // b = (1 - y) * (1 - k) + double const c = convert<double>(invals[0]); + double const m = convert<double>(invals[1]); + double const y = convert<double>(invals[2]); + double const k = convert<double>(invals[3]); + double const r = (1.0-c) * (1.0-k); + double const g = (1.0-m) * (1.0-k); + double const b = (1.0-y) * (1.0-k); + return tripleToString(r, g, b); + } + if (model == "cmy") { + if (invals.size() != 3 || !isStrDbl(invals[0]) || !isStrDbl(invals[1]) + || !isStrDbl(invals[2])) { + LYXERR0("Ignoring wrong cmy color value: " << value); + return string(); + } + // r = (1 - c) + // g = (1 - m) + // b = (1 - y) + double const c = convert<double>(invals[0]); + double const m = convert<double>(invals[1]); + double const y = convert<double>(invals[2]); + return tripleToString(1 - c, 1 - m, 1 - y); + } + if (model == "gray") { + // we only have a single value, which is + // always r = g = b + if (!isStrDbl(value)) { + LYXERR0("Ignoring wrong cmy color value: " << value); + return string(); + } + ostringstream os; + os << value + << ", " + << value + << ", " + << value; + return os.str(); + } + if (model == "Gray") { + // r = g = b = (gray / 15) + if (!isStrDbl(value)) { + LYXERR0("Ignoring wrong cmy color value: " << value); + return string(); + } + double const gv = convert<double>(value); + double const r = gv / 15.0; + double const g = gv / 15.0; + double const b = gv / 15.0; + return tripleToString(r, g, b); + } + if (model == "hsb") { + // more complex formula + // see xcolor manual + if (invals.size() != 3 || !isStrDbl(invals[0]) || !isStrDbl(invals[1]) + || !isStrDbl(invals[2])) { + LYXERR0("Ignoring wrong hsb color value: " << value); + return string(); + } + double const h = convert<double>(invals[0]); + double const s = convert<double>(invals[1]); + double const b = convert<double>(invals[2]); + int i = (int)(h * 6); + double f = h * 6 - i; + + double f1 = 0.0, f2 = 0.0, f3 = 0.0; + switch (i) { + case 0: + f1 = 0.0; + f2 = 1.0 - f; + f3 = 1.0; + break; + case 1: + f1 = f; + f2 = 0.0; + f3 = 1.0; + break; + case 2: + f1 = 1.0; + f2 = 0.0; + f3 = 1.0 - f; + break; + case 3: + f1 = 1.0; + f2 = f; + f3 = 0.0; + break; + case 4: + f1 = 1.0 - f; + f2 = 1.0; + f3 = 0.0; + break; + case 5: + f1 = 0.0; + f2 = 1.0; + f3 = f; + break; + case 6: + f1 = 0.0; + f2 = 1.0; + f3 = 1.0; + break; + default: + LYXERR0("Something went wrong when converting from hsb to rgb. Input was: " << value); + return string(); + } + return tripleToString((b * (h - s * f1)), (b * (s - s * f2)), (b * (b - s * f3))); + } + if (model == "HSB") { + // same as hsb * 240 + if (invals.size() != 3 || !isStrInt(invals[0]) || !isStrInt(invals[1]) + || !isStrInt(invals[2])) { + LYXERR0("Ignoring wrong hsb color value: " << value); + return string(); + } + double const h = convert<double>(invals[0]) / 240; + double const s = convert<double>(invals[1]) / 240; + double const b = convert<double>(invals[2]) / 240; + int i = (int)(h * 6); + double f = h * 6 - i; + + double f1 = 0.0, f2 = 0.0, f3 = 0.0; + switch (i) { + case 0: + f1 = 0.0; + f2 = 1.0 - f; + f3 = 1.0; + break; + case 1: + f1 = f; + f2 = 0.0; + f3 = 1.0; + break; + case 2: + f1 = 1.0; + f2 = 0.0; + f3 = 1.0 - f; + break; + case 3: + f1 = 1.0; + f2 = f; + f3 = 0.0; + break; + case 4: + f1 = 1.0 - f; + f2 = 1.0; + f3 = 0.0; + break; + case 5: + f1 = 0.0; + f2 = 1.0; + f3 = f; + break; + case 6: + f1 = 0.0; + f2 = 1.0; + f3 = 1.0; + break; + default: + LYXERR0("Something went wrong when converting from hsb to rgb. Input was: " << value); + return string(); + } + return tripleToString((b * (h - s * f1)), (b * (s - s * f2)), (b * (b - s * f3))); + } + // TODO: Hsb, tHsb, wave + return string(); +} + } // anonymous namespace @@ -3217,7 +3422,9 @@ void Preamble::parse(Parser & p, string const & forceclass, string const color = p.getArg('{', '}'); string const space = p.getArg('{', '}'); string const value = p.getArg('{', '}'); - if (space == "rgb") { + // try to convert value to rgb + string const conv_value = convert_color_value(space, value); + if (!conv_value.empty() || space == "HTML") { if (color == "document_fontcolor") h_fontcolor = color; else if (color == "note_fontcolor") @@ -3226,8 +3433,14 @@ void Preamble::parse(Parser & p, string const & forceclass, h_backgroundcolor = color; else if (color == "shadecolor") h_boxbgcolor = color; - RGBColor c(RGBColorFromLaTeX(value)); - h_custom_colors[color] = ltrim(X11hexname(c), "#"); + if (space == "HTML") + // here we already have the (hex) value we want + h_custom_colors[color] = value; + else { + // convert from rgb to hex + RGBColor c(RGBColorFromLaTeX(conv_value)); + h_custom_colors[color] = ltrim(X11hexname(c), "#"); + } } else { h_preamble << "\\definecolor{" << color << "}{" << space << "}{" << value -- lyx-cvs mailing list lyx-cvs@lists.lyx.org https://lists.lyx.org/mailman/listinfo/lyx-cvs