1 // sass.hpp must go before all system headers to get the 2 // __EXTENSIONS__ fix on Solaris. 3 #include "sass.hpp" 4 5 #include <iomanip> 6 #include "ast.hpp" 7 #include "fn_utils.hpp" 8 #include "fn_colors.hpp" 9 #include "util.hpp" 10 #include "util_string.hpp" 11 12 namespace Sass { 13 14 namespace Functions { 15 string_argument(AST_Node_Obj obj)16 bool string_argument(AST_Node_Obj obj) { 17 String_Constant* s = Cast<String_Constant>(obj); 18 if (s == nullptr) return false; 19 const sass::string& str = s->value(); 20 return starts_with(str, "calc(") || 21 starts_with(str, "var("); 22 } 23 hsla_alpha_percent_deprecation(const SourceSpan & pstate,const sass::string val)24 void hsla_alpha_percent_deprecation(const SourceSpan& pstate, const sass::string val) 25 { 26 27 sass::string msg("Passing a percentage as the alpha value to hsla() will be interpreted"); 28 sass::string tail("differently in future versions of Sass. For now, use " + val + " instead."); 29 30 deprecated(msg, tail, false, pstate); 31 32 } 33 34 Signature rgb_sig = "rgb($red, $green, $blue)"; BUILT_IN(rgb)35 BUILT_IN(rgb) 36 { 37 if ( 38 string_argument(env["$red"]) || 39 string_argument(env["$green"]) || 40 string_argument(env["$blue"]) 41 ) { 42 return SASS_MEMORY_NEW(String_Constant, pstate, "rgb(" 43 + env["$red"]->to_string() 44 + ", " 45 + env["$green"]->to_string() 46 + ", " 47 + env["$blue"]->to_string() 48 + ")" 49 ); 50 } 51 52 return SASS_MEMORY_NEW(Color_RGBA, 53 pstate, 54 COLOR_NUM("$red"), 55 COLOR_NUM("$green"), 56 COLOR_NUM("$blue")); 57 } 58 59 Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)"; BUILT_IN(rgba_4)60 BUILT_IN(rgba_4) 61 { 62 if ( 63 string_argument(env["$red"]) || 64 string_argument(env["$green"]) || 65 string_argument(env["$blue"]) || 66 string_argument(env["$alpha"]) 67 ) { 68 return SASS_MEMORY_NEW(String_Constant, pstate, "rgba(" 69 + env["$red"]->to_string() 70 + ", " 71 + env["$green"]->to_string() 72 + ", " 73 + env["$blue"]->to_string() 74 + ", " 75 + env["$alpha"]->to_string() 76 + ")" 77 ); 78 } 79 80 return SASS_MEMORY_NEW(Color_RGBA, 81 pstate, 82 COLOR_NUM("$red"), 83 COLOR_NUM("$green"), 84 COLOR_NUM("$blue"), 85 ALPHA_NUM("$alpha")); 86 } 87 88 Signature rgba_2_sig = "rgba($color, $alpha)"; BUILT_IN(rgba_2)89 BUILT_IN(rgba_2) 90 { 91 if ( 92 string_argument(env["$color"]) 93 ) { 94 return SASS_MEMORY_NEW(String_Constant, pstate, "rgba(" 95 + env["$color"]->to_string() 96 + ", " 97 + env["$alpha"]->to_string() 98 + ")" 99 ); 100 } 101 102 Color_RGBA_Obj c_arg = ARG("$color", Color)->toRGBA(); 103 104 if ( 105 string_argument(env["$alpha"]) 106 ) { 107 sass::ostream strm; 108 strm << "rgba(" 109 << (int)c_arg->r() << ", " 110 << (int)c_arg->g() << ", " 111 << (int)c_arg->b() << ", " 112 << env["$alpha"]->to_string() 113 << ")"; 114 return SASS_MEMORY_NEW(String_Constant, pstate, strm.str()); 115 } 116 117 Color_RGBA_Obj new_c = SASS_MEMORY_COPY(c_arg); 118 new_c->a(ALPHA_NUM("$alpha")); 119 new_c->disp(""); 120 return new_c.detach(); 121 } 122 123 //////////////// 124 // RGB FUNCTIONS 125 //////////////// 126 127 Signature red_sig = "red($color)"; BUILT_IN(red)128 BUILT_IN(red) 129 { 130 Color_RGBA_Obj color = ARG("$color", Color)->toRGBA(); 131 return SASS_MEMORY_NEW(Number, pstate, color->r()); 132 } 133 134 Signature green_sig = "green($color)"; BUILT_IN(green)135 BUILT_IN(green) 136 { 137 Color_RGBA_Obj color = ARG("$color", Color)->toRGBA(); 138 return SASS_MEMORY_NEW(Number, pstate, color->g()); 139 } 140 141 Signature blue_sig = "blue($color)"; BUILT_IN(blue)142 BUILT_IN(blue) 143 { 144 Color_RGBA_Obj color = ARG("$color", Color)->toRGBA(); 145 return SASS_MEMORY_NEW(Number, pstate, color->b()); 146 } 147 colormix(Context & ctx,SourceSpan & pstate,Color * color1,Color * color2,double weight)148 Color_RGBA* colormix(Context& ctx, SourceSpan& pstate, Color* color1, Color* color2, double weight) { 149 Color_RGBA_Obj c1 = color1->toRGBA(); 150 Color_RGBA_Obj c2 = color2->toRGBA(); 151 double p = weight/100; 152 double w = 2*p - 1; 153 double a = c1->a() - c2->a(); 154 155 double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0; 156 double w2 = 1 - w1; 157 158 return SASS_MEMORY_NEW(Color_RGBA, 159 pstate, 160 Sass::round(w1*c1->r() + w2*c2->r(), ctx.c_options.precision), 161 Sass::round(w1*c1->g() + w2*c2->g(), ctx.c_options.precision), 162 Sass::round(w1*c1->b() + w2*c2->b(), ctx.c_options.precision), 163 c1->a()*p + c2->a()*(1-p)); 164 } 165 166 Signature mix_sig = "mix($color1, $color2, $weight: 50%)"; BUILT_IN(mix)167 BUILT_IN(mix) 168 { 169 Color_Obj color1 = ARG("$color1", Color); 170 Color_Obj color2 = ARG("$color2", Color); 171 double weight = DARG_U_PRCT("$weight"); 172 return colormix(ctx, pstate, color1, color2, weight); 173 174 } 175 176 //////////////// 177 // HSL FUNCTIONS 178 //////////////// 179 180 Signature hsl_sig = "hsl($hue, $saturation, $lightness)"; BUILT_IN(hsl)181 BUILT_IN(hsl) 182 { 183 if ( 184 string_argument(env["$hue"]) || 185 string_argument(env["$saturation"]) || 186 string_argument(env["$lightness"]) 187 ) { 188 return SASS_MEMORY_NEW(String_Constant, pstate, "hsl(" 189 + env["$hue"]->to_string() 190 + ", " 191 + env["$saturation"]->to_string() 192 + ", " 193 + env["$lightness"]->to_string() 194 + ")" 195 ); 196 } 197 198 return SASS_MEMORY_NEW(Color_HSLA, 199 pstate, 200 ARGVAL("$hue"), 201 ARGVAL("$saturation"), 202 ARGVAL("$lightness"), 203 1.0); 204 205 } 206 207 Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)"; BUILT_IN(hsla)208 BUILT_IN(hsla) 209 { 210 if ( 211 string_argument(env["$hue"]) || 212 string_argument(env["$saturation"]) || 213 string_argument(env["$lightness"]) || 214 string_argument(env["$alpha"]) 215 ) { 216 return SASS_MEMORY_NEW(String_Constant, pstate, "hsla(" 217 + env["$hue"]->to_string() 218 + ", " 219 + env["$saturation"]->to_string() 220 + ", " 221 + env["$lightness"]->to_string() 222 + ", " 223 + env["$alpha"]->to_string() 224 + ")" 225 ); 226 } 227 228 Number* alpha = ARG("$alpha", Number); 229 if (alpha && alpha->unit() == "%") { 230 Number_Obj val = SASS_MEMORY_COPY(alpha); 231 val->numerators.clear(); // convert 232 val->value(val->value() / 100.0); 233 sass::string nr(val->to_string(ctx.c_options)); 234 hsla_alpha_percent_deprecation(pstate, nr); 235 } 236 237 return SASS_MEMORY_NEW(Color_HSLA, 238 pstate, 239 ARGVAL("$hue"), 240 ARGVAL("$saturation"), 241 ARGVAL("$lightness"), 242 ARGVAL("$alpha")); 243 244 } 245 246 ///////////////////////////////////////////////////////////////////////// 247 // Query functions 248 ///////////////////////////////////////////////////////////////////////// 249 250 Signature hue_sig = "hue($color)"; BUILT_IN(hue)251 BUILT_IN(hue) 252 { 253 Color_HSLA_Obj col = ARG("$color", Color)->toHSLA(); 254 return SASS_MEMORY_NEW(Number, pstate, col->h(), "deg"); 255 } 256 257 Signature saturation_sig = "saturation($color)"; BUILT_IN(saturation)258 BUILT_IN(saturation) 259 { 260 Color_HSLA_Obj col = ARG("$color", Color)->toHSLA(); 261 return SASS_MEMORY_NEW(Number, pstate, col->s(), "%"); 262 } 263 264 Signature lightness_sig = "lightness($color)"; BUILT_IN(lightness)265 BUILT_IN(lightness) 266 { 267 Color_HSLA_Obj col = ARG("$color", Color)->toHSLA(); 268 return SASS_MEMORY_NEW(Number, pstate, col->l(), "%"); 269 } 270 271 ///////////////////////////////////////////////////////////////////////// 272 // HSL manipulation functions 273 ///////////////////////////////////////////////////////////////////////// 274 275 Signature adjust_hue_sig = "adjust-hue($color, $degrees)"; BUILT_IN(adjust_hue)276 BUILT_IN(adjust_hue) 277 { 278 Color* col = ARG("$color", Color); 279 double degrees = ARGVAL("$degrees"); 280 Color_HSLA_Obj copy = col->copyAsHSLA(); 281 copy->h(absmod(copy->h() + degrees, 360.0)); 282 return copy.detach(); 283 } 284 285 Signature lighten_sig = "lighten($color, $amount)"; BUILT_IN(lighten)286 BUILT_IN(lighten) 287 { 288 Color* col = ARG("$color", Color); 289 double amount = DARG_U_PRCT("$amount"); 290 Color_HSLA_Obj copy = col->copyAsHSLA(); 291 copy->l(clip(copy->l() + amount, 0.0, 100.0)); 292 return copy.detach(); 293 294 } 295 296 Signature darken_sig = "darken($color, $amount)"; BUILT_IN(darken)297 BUILT_IN(darken) 298 { 299 Color* col = ARG("$color", Color); 300 double amount = DARG_U_PRCT("$amount"); 301 Color_HSLA_Obj copy = col->copyAsHSLA(); 302 copy->l(clip(copy->l() - amount, 0.0, 100.0)); 303 return copy.detach(); 304 } 305 306 Signature saturate_sig = "saturate($color, $amount: false)"; BUILT_IN(saturate)307 BUILT_IN(saturate) 308 { 309 // CSS3 filter function overload: pass literal through directly 310 if (!Cast<Number>(env["$amount"])) { 311 return SASS_MEMORY_NEW(String_Quoted, pstate, "saturate(" + env["$color"]->to_string(ctx.c_options) + ")"); 312 } 313 314 Color* col = ARG("$color", Color); 315 double amount = DARG_U_PRCT("$amount"); 316 Color_HSLA_Obj copy = col->copyAsHSLA(); 317 copy->s(clip(copy->s() + amount, 0.0, 100.0)); 318 return copy.detach(); 319 } 320 321 Signature desaturate_sig = "desaturate($color, $amount)"; BUILT_IN(desaturate)322 BUILT_IN(desaturate) 323 { 324 Color* col = ARG("$color", Color); 325 double amount = DARG_U_PRCT("$amount"); 326 Color_HSLA_Obj copy = col->copyAsHSLA(); 327 copy->s(clip(copy->s() - amount, 0.0, 100.0)); 328 return copy.detach(); 329 } 330 331 Signature grayscale_sig = "grayscale($color)"; BUILT_IN(grayscale)332 BUILT_IN(grayscale) 333 { 334 // CSS3 filter function overload: pass literal through directly 335 Number* amount = Cast<Number>(env["$color"]); 336 if (amount) { 337 return SASS_MEMORY_NEW(String_Quoted, pstate, "grayscale(" + amount->to_string(ctx.c_options) + ")"); 338 } 339 340 Color* col = ARG("$color", Color); 341 Color_HSLA_Obj copy = col->copyAsHSLA(); 342 copy->s(0.0); // just reset saturation 343 return copy.detach(); 344 } 345 346 ///////////////////////////////////////////////////////////////////////// 347 // Misc manipulation functions 348 ///////////////////////////////////////////////////////////////////////// 349 350 Signature complement_sig = "complement($color)"; BUILT_IN(complement)351 BUILT_IN(complement) 352 { 353 Color* col = ARG("$color", Color); 354 Color_HSLA_Obj copy = col->copyAsHSLA(); 355 copy->h(absmod(copy->h() - 180.0, 360.0)); 356 return copy.detach(); 357 } 358 359 Signature invert_sig = "invert($color, $weight: 100%)"; BUILT_IN(invert)360 BUILT_IN(invert) 361 { 362 // CSS3 filter function overload: pass literal through directly 363 Number* amount = Cast<Number>(env["$color"]); 364 double weight = DARG_U_PRCT("$weight"); 365 if (amount) { 366 // TODO: does not throw on 100% manually passed as value 367 if (weight < 100.0) { 368 error("Only one argument may be passed to the plain-CSS invert() function.", pstate, traces); 369 } 370 return SASS_MEMORY_NEW(String_Quoted, pstate, "invert(" + amount->to_string(ctx.c_options) + ")"); 371 } 372 373 Color* col = ARG("$color", Color); 374 Color_RGBA_Obj inv = col->copyAsRGBA(); 375 inv->r(clip(255.0 - inv->r(), 0.0, 255.0)); 376 inv->g(clip(255.0 - inv->g(), 0.0, 255.0)); 377 inv->b(clip(255.0 - inv->b(), 0.0, 255.0)); 378 return colormix(ctx, pstate, inv, col, weight); 379 } 380 381 ///////////////////////////////////////////////////////////////////////// 382 // Opacity functions 383 ///////////////////////////////////////////////////////////////////////// 384 385 Signature alpha_sig = "alpha($color)"; 386 Signature opacity_sig = "opacity($color)"; BUILT_IN(alpha)387 BUILT_IN(alpha) 388 { 389 String_Constant* ie_kwd = Cast<String_Constant>(env["$color"]); 390 if (ie_kwd) { 391 return SASS_MEMORY_NEW(String_Quoted, pstate, "alpha(" + ie_kwd->value() + ")"); 392 } 393 394 // CSS3 filter function overload: pass literal through directly 395 Number* amount = Cast<Number>(env["$color"]); 396 if (amount) { 397 return SASS_MEMORY_NEW(String_Quoted, pstate, "opacity(" + amount->to_string(ctx.c_options) + ")"); 398 } 399 400 return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->a()); 401 } 402 403 Signature opacify_sig = "opacify($color, $amount)"; 404 Signature fade_in_sig = "fade-in($color, $amount)"; BUILT_IN(opacify)405 BUILT_IN(opacify) 406 { 407 Color* col = ARG("$color", Color); 408 double amount = DARG_U_FACT("$amount"); 409 Color_Obj copy = SASS_MEMORY_COPY(col); 410 copy->a(clip(col->a() + amount, 0.0, 1.0)); 411 return copy.detach(); 412 } 413 414 Signature transparentize_sig = "transparentize($color, $amount)"; 415 Signature fade_out_sig = "fade-out($color, $amount)"; BUILT_IN(transparentize)416 BUILT_IN(transparentize) 417 { 418 Color* col = ARG("$color", Color); 419 double amount = DARG_U_FACT("$amount"); 420 Color_Obj copy = SASS_MEMORY_COPY(col); 421 copy->a(std::max(col->a() - amount, 0.0)); 422 return copy.detach(); 423 } 424 425 //////////////////////// 426 // OTHER COLOR FUNCTIONS 427 //////////////////////// 428 429 Signature adjust_color_sig = "adjust-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)"; BUILT_IN(adjust_color)430 BUILT_IN(adjust_color) 431 { 432 Color* col = ARG("$color", Color); 433 Number* r = Cast<Number>(env["$red"]); 434 Number* g = Cast<Number>(env["$green"]); 435 Number* b = Cast<Number>(env["$blue"]); 436 Number* h = Cast<Number>(env["$hue"]); 437 Number* s = Cast<Number>(env["$saturation"]); 438 Number* l = Cast<Number>(env["$lightness"]); 439 Number* a = Cast<Number>(env["$alpha"]); 440 441 bool rgb = r || g || b; 442 bool hsl = h || s || l; 443 444 if (rgb && hsl) { 445 error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate, traces); 446 } 447 else if (rgb) { 448 Color_RGBA_Obj c = col->copyAsRGBA(); 449 if (r) c->r(c->r() + DARG_R_BYTE("$red")); 450 if (g) c->g(c->g() + DARG_R_BYTE("$green")); 451 if (b) c->b(c->b() + DARG_R_BYTE("$blue")); 452 if (a) c->a(c->a() + DARG_R_FACT("$alpha")); 453 return c.detach(); 454 } 455 else if (hsl) { 456 Color_HSLA_Obj c = col->copyAsHSLA(); 457 if (h) c->h(c->h() + absmod(h->value(), 360.0)); 458 if (s) c->s(c->s() + DARG_R_PRCT("$saturation")); 459 if (l) c->l(c->l() + DARG_R_PRCT("$lightness")); 460 if (a) c->a(c->a() + DARG_R_FACT("$alpha")); 461 return c.detach(); 462 } 463 else if (a) { 464 Color_Obj c = SASS_MEMORY_COPY(col); 465 c->a(c->a() + DARG_R_FACT("$alpha")); 466 c->a(clip(c->a(), 0.0, 1.0)); 467 return c.detach(); 468 } 469 error("not enough arguments for `adjust-color'", pstate, traces); 470 // unreachable 471 return col; 472 } 473 474 Signature scale_color_sig = "scale-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)"; BUILT_IN(scale_color)475 BUILT_IN(scale_color) 476 { 477 Color* col = ARG("$color", Color); 478 Number* r = Cast<Number>(env["$red"]); 479 Number* g = Cast<Number>(env["$green"]); 480 Number* b = Cast<Number>(env["$blue"]); 481 Number* h = Cast<Number>(env["$hue"]); 482 Number* s = Cast<Number>(env["$saturation"]); 483 Number* l = Cast<Number>(env["$lightness"]); 484 Number* a = Cast<Number>(env["$alpha"]); 485 486 bool rgb = r || g || b; 487 bool hsl = h || s || l; 488 489 if (rgb && hsl) { 490 error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate, traces); 491 } 492 else if (rgb) { 493 Color_RGBA_Obj c = col->copyAsRGBA(); 494 double rscale = (r ? DARG_R_PRCT("$red") : 0.0) / 100.0; 495 double gscale = (g ? DARG_R_PRCT("$green") : 0.0) / 100.0; 496 double bscale = (b ? DARG_R_PRCT("$blue") : 0.0) / 100.0; 497 double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0; 498 if (rscale) c->r(c->r() + rscale * (rscale > 0.0 ? 255.0 - c->r() : c->r())); 499 if (gscale) c->g(c->g() + gscale * (gscale > 0.0 ? 255.0 - c->g() : c->g())); 500 if (bscale) c->b(c->b() + bscale * (bscale > 0.0 ? 255.0 - c->b() : c->b())); 501 if (ascale) c->a(c->a() + ascale * (ascale > 0.0 ? 1.0 - c->a() : c->a())); 502 return c.detach(); 503 } 504 else if (hsl) { 505 Color_HSLA_Obj c = col->copyAsHSLA(); 506 double hscale = (h ? DARG_R_PRCT("$hue") : 0.0) / 100.0; 507 double sscale = (s ? DARG_R_PRCT("$saturation") : 0.0) / 100.0; 508 double lscale = (l ? DARG_R_PRCT("$lightness") : 0.0) / 100.0; 509 double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0; 510 if (hscale) c->h(c->h() + hscale * (hscale > 0.0 ? 360.0 - c->h() : c->h())); 511 if (sscale) c->s(c->s() + sscale * (sscale > 0.0 ? 100.0 - c->s() : c->s())); 512 if (lscale) c->l(c->l() + lscale * (lscale > 0.0 ? 100.0 - c->l() : c->l())); 513 if (ascale) c->a(c->a() + ascale * (ascale > 0.0 ? 1.0 - c->a() : c->a())); 514 return c.detach(); 515 } 516 else if (a) { 517 Color_Obj c = SASS_MEMORY_COPY(col); 518 double ascale = DARG_R_PRCT("$alpha") / 100.0; 519 c->a(c->a() + ascale * (ascale > 0.0 ? 1.0 - c->a() : c->a())); 520 c->a(clip(c->a(), 0.0, 1.0)); 521 return c.detach(); 522 } 523 error("not enough arguments for `scale-color'", pstate, traces); 524 // unreachable 525 return col; 526 } 527 528 Signature change_color_sig = "change-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)"; BUILT_IN(change_color)529 BUILT_IN(change_color) 530 { 531 Color* col = ARG("$color", Color); 532 Number* r = Cast<Number>(env["$red"]); 533 Number* g = Cast<Number>(env["$green"]); 534 Number* b = Cast<Number>(env["$blue"]); 535 Number* h = Cast<Number>(env["$hue"]); 536 Number* s = Cast<Number>(env["$saturation"]); 537 Number* l = Cast<Number>(env["$lightness"]); 538 Number* a = Cast<Number>(env["$alpha"]); 539 540 bool rgb = r || g || b; 541 bool hsl = h || s || l; 542 543 if (rgb && hsl) { 544 error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate, traces); 545 } 546 else if (rgb) { 547 Color_RGBA_Obj c = col->copyAsRGBA(); 548 if (r) c->r(DARG_U_BYTE("$red")); 549 if (g) c->g(DARG_U_BYTE("$green")); 550 if (b) c->b(DARG_U_BYTE("$blue")); 551 if (a) c->a(DARG_U_FACT("$alpha")); 552 return c.detach(); 553 } 554 else if (hsl) { 555 Color_HSLA_Obj c = col->copyAsHSLA(); 556 if (h) c->h(absmod(h->value(), 360.0)); 557 if (s) c->s(DARG_U_PRCT("$saturation")); 558 if (l) c->l(DARG_U_PRCT("$lightness")); 559 if (a) c->a(DARG_U_FACT("$alpha")); 560 return c.detach(); 561 } 562 else if (a) { 563 Color_Obj c = SASS_MEMORY_COPY(col); 564 c->a(clip(DARG_U_FACT("$alpha"), 0.0, 1.0)); 565 return c.detach(); 566 } 567 error("not enough arguments for `change-color'", pstate, traces); 568 // unreachable 569 return col; 570 } 571 572 Signature ie_hex_str_sig = "ie-hex-str($color)"; BUILT_IN(ie_hex_str)573 BUILT_IN(ie_hex_str) 574 { 575 Color* col = ARG("$color", Color); 576 Color_RGBA_Obj c = col->toRGBA(); 577 double r = clip(c->r(), 0.0, 255.0); 578 double g = clip(c->g(), 0.0, 255.0); 579 double b = clip(c->b(), 0.0, 255.0); 580 double a = clip(c->a(), 0.0, 1.0) * 255.0; 581 582 sass::ostream ss; 583 ss << '#' << std::setw(2) << std::setfill('0'); 584 ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(a, ctx.c_options.precision)); 585 ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(r, ctx.c_options.precision)); 586 ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(g, ctx.c_options.precision)); 587 ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(b, ctx.c_options.precision)); 588 589 sass::string result = ss.str(); 590 Util::ascii_str_toupper(&result); 591 return SASS_MEMORY_NEW(String_Quoted, pstate, result); 592 } 593 594 } 595 596 } 597