Ejemplo n.º 1
0
def test_rgba():
    # four args (css-style)
    assert calc('rgba(128, 192, 224, 0.5)') == Color.from_rgb(128/255, 192/255, 224/255, 0.5)
    assert calc('rgba(20%, 40%, 60%, 0.7)') == Color.from_rgb(0.2, 0.4, 0.6, 0.7)

    # two args (modify alpha of existing color)
    assert calc('rgba(red, 0.4)') == Color.from_rgb(1., 0., 0., 0.4)
Ejemplo n.º 2
0
def test_rgba(calc):
    # four args (css-style)
    assert calc('rgba(128, 192, 224, 0.5)') == Color.from_rgb(128/255, 192/255, 224/255, 0.5)
    assert calc('rgba(20%, 40%, 60%, 0.7)') == Color.from_rgb(0.2, 0.4, 0.6, 0.7)

    # two args (modify alpha of existing color)
    assert calc('rgba(red, 0.4)') == Color.from_rgb(1., 0., 0., 0.4)
Ejemplo n.º 3
0
def test_reference_operations():
    """Test the example expressions in the reference document:

    http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#operations
    """
    # TODO: break this into its own file and add the entire reference guide

    # Need to build the calculator manually to get at its namespace, and need
    # to use calculate() instead of evaluate_expression() so interpolation
    # works
    ns = CoreExtension.namespace.derive()
    calc = Calculator(ns).calculate

    # Simple example
    assert calc('1in + 8pt') == Number(1.1111111111111112, "in")

    # Division
    ns.set_variable('$width', Number(1000, "px"))
    ns.set_variable('$font-size', Number(12, "px"))
    ns.set_variable('$line-height', Number(30, "px"))
    assert calc('10px/8px') == String('10px / 8px')  # plain CSS; no division
    assert calc('$width/2') == Number(500,
                                      "px")  # uses a variable; does division
    assert calc('(500px/2)') == Number(250, "px")  # uses parens; does division
    assert calc('5px + 8px/2px') == Number(9, "px")  # uses +; does division
    # TODO, again: Ruby Sass correctly renders this without spaces
    assert calc('#{$font-size}/#{$line-height}') == String('12px / 30px')
    # uses #{}; does no division

    # Color operations
    ns.set_variable('$translucent-red', Color.from_rgb(1, 0, 0, 0.5))
    ns.set_variable('$green', Color.from_name('lime'))
    assert calc('#010203 + #040506') == Color.from_hex('#050709')
    assert calc('#010203 * 2') == Color.from_hex('#020406')
    assert calc(
        'rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75)') == Color.from_rgb(
            1, 1, 0, 0.75)
    assert calc('opacify($translucent-red, 0.3)') == Color.from_rgb(
        1, 0, 0, 0.8)
    assert calc('transparentize($translucent-red, 0.25)') == Color.from_rgb(
        1, 0, 0, 0.25)
    assert calc(
        "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}')"
    ).render(
    ) == "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#FF00FF00', endColorstr='#80FF0000')"

    # String operations
    ns.set_variable('$value', Null())
    assert_strict_string_eq(calc('e + -resize'), String('e-resize',
                                                        quotes=None))
    assert_strict_string_eq(calc('"Foo " + Bar'), String('Foo Bar',
                                                         quotes='"'))
    assert_strict_string_eq(calc('sans- + "serif"'),
                            String('sans-serif', quotes=None))
    assert calc('3px + 4px auto') == List(
        [Number(7, "px"), String('auto', quotes=None)])
    assert_strict_string_eq(calc('"I ate #{5 + 10} pies!"'),
                            String('I ate 15 pies!', quotes='"'))
    assert_strict_string_eq(calc('"I ate #{$value} pies!"'),
                            String('I ate  pies!', quotes='"'))
Ejemplo n.º 4
0
def test_hsl(calc):
    # Examples from the CSS 3 color spec, which Sass uses
    # (http://www.w3.org/TR/css3-color/#hsl-color)
    assert calc('hsl(0, 100%, 50%)') == Color.from_rgb(1., 0., 0.)
    assert calc('hsl(120, 100%, 50%)') == Color.from_rgb(0., 1., 0.)
    assert calc('hsl(120, 100%, 25%)') == Color.from_rgb(0., 0.5, 0.)
    assert calc('hsl(120, 100%, 75%)') == Color.from_rgb(0.5, 1., 0.5)
    assert calc('hsl(120, 75%, 75%)') == Color.from_rgb(0.5625, 0.9375, 0.5625)
Ejemplo n.º 5
0
def test_hsl():
    # Examples from the CSS 3 color spec, which Sass uses
    # (http://www.w3.org/TR/css3-color/#hsl-color)
    assert calc('hsl(0, 100%, 50%)') == Color.from_rgb(1., 0., 0.)
    assert calc('hsl(120, 100%, 50%)') == Color.from_rgb(0., 1., 0.)
    assert calc('hsl(120, 100%, 25%)') == Color.from_rgb(0., 0.5, 0.)
    assert calc('hsl(120, 100%, 75%)') == Color.from_rgb(0.5, 1., 0.5)
    assert calc('hsl(120, 75%, 75%)') == Color.from_rgb(0.5625, 0.9375, 0.5625)
Ejemplo n.º 6
0
def test_hsla():
    # Examples from the CSS 3 color spec
    assert calc('hsla(120, 100%, 50%, 1)') == Color.from_rgb(
        0.,
        1.,
        0.,
    )
    assert calc('hsla(240, 100%, 50%, 0.5)') == Color.from_rgb(0., 0., 1., 0.5)
    assert calc('hsla(30, 100%, 50%, 0.1)') == Color.from_rgb(1., 0.5, 0., 0.1)
Ejemplo n.º 7
0
def test_reference_operations():
    """Test the example expressions in the reference document:

    http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#operations
    """
    # TODO: break this into its own file and add the entire reference guide

    # Need to build the calculator manually to get at its namespace, and need
    # to use calculate() instead of evaluate_expression() so interpolation
    # works
    ns = CoreExtension.namespace.derive()
    calc = Calculator(ns).calculate

    # Simple example
    assert calc('1in + 8pt') == Number(1.1111111111111112, "in")

    # Division
    ns.set_variable('$width', Number(1000, "px"))
    ns.set_variable('$font-size', Number(12, "px"))
    ns.set_variable('$line-height', Number(30, "px"))
    assert calc('10px/8px') == String('10px / 8px')   # plain CSS; no division
    assert calc('$width/2') == Number(500, "px")      # uses a variable; does division
    assert calc('(500px/2)') == Number(250, "px")     # uses parens; does division
    assert calc('5px + 8px/2px') == Number(9, "px")   # uses +; does division
    # TODO, again: Ruby Sass correctly renders this without spaces
    assert calc('#{$font-size}/#{$line-height}') == String('12px / 30px')
                                            # uses #{}; does no division

    # Modulo
    assert calc('29 % 12') == Number(5)
    assert calc('29px % 12') == Number(5, 'px')
    assert calc('29px % 12px') == Number(5, 'px')

    # Color operations
    ns.set_variable('$translucent-red', Color.from_rgb(1, 0, 0, 0.5))
    ns.set_variable('$green', Color.from_name('lime'))
    assert calc('#010203 + #040506') == Color.from_hex('#050709')
    assert calc('#010203 * 2') == Color.from_hex('#020406')
    assert calc('rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75)') == Color.from_rgb(1, 1, 0, 0.75)
    assert calc('opacify($translucent-red, 0.3)') == Color.from_rgb(1, 0, 0, 0.8)
    assert calc('transparentize($translucent-red, 0.25)') == Color.from_rgb(1, 0, 0, 0.25)
    assert calc("progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}')"
                ).render() == "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#FF00FF00', endColorstr='#80FF0000')"

    # String operations
    ns.set_variable('$value', Null())
    assert_strict_string_eq(calc('e + -resize'), String('e-resize', quotes=None))
    assert_strict_string_eq(calc('"Foo " + Bar'), String('Foo Bar', quotes='"'))
    assert_strict_string_eq(calc('sans- + "serif"'), String('sans-serif', quotes=None))
    assert calc('3px + 4px auto') == List([Number(7, "px"), String('auto', quotes=None)])
    assert_strict_string_eq(calc('"I ate #{5 + 10} pies!"'), String('I ate 15 pies!', quotes='"'))
    assert_strict_string_eq(calc('"I ate #{$value} pies!"'), String('I ate  pies!', quotes='"'))
Ejemplo n.º 8
0
def transparentize(color, amount):
    r, g, b, a = color.rgba
    if amount.is_simple_unit('%'):
        amt = amount.value / 100
    else:
        amt = amount.value
    return Color.from_rgb(r, g, b, alpha=a - amt)
Ejemplo n.º 9
0
def opacify(color, amount):
    r, g, b, a = color.rgba
    if amount.is_simple_unit('%'):
        amt = amount.value / 100
    else:
        amt = amount.value
    return Color.from_rgb(r, g, b, alpha=a + amt)
Ejemplo n.º 10
0
def transparentize(color, amount):
    r, g, b, a = color.rgba
    if amount.is_simple_unit("%"):
        amt = amount.value / 100
    else:
        amt = amount.value
    return Color.from_rgb(r, g, b, alpha=a - amt)
Ejemplo n.º 11
0
def opacify(color, amount):
    r, g, b, a = color.rgba
    if amount.is_simple_unit("%"):
        amt = amount.value / 100
    else:
        amt = amount.value
    return Color.from_rgb(r, g, b, alpha=a + amt)
Ejemplo n.º 12
0
def change_color(color, red=None, green=None, blue=None, hue=None, saturation=None, lightness=None, alpha=None):
    do_rgb = red or green or blue
    do_hsl = hue or saturation or lightness
    if do_rgb and do_hsl:
        raise ValueError("Can't change both RGB and HSL channels at the same time")

    if alpha is None:
        alpha = color.alpha
    else:
        alpha = alpha.value

    if do_rgb:
        channels = list(color.rgba[:3])
        if red:
            channels[0] = _interpret_percentage(red, relto=255)
        if green:
            channels[1] = _interpret_percentage(green, relto=255)
        if blue:
            channels[2] = _interpret_percentage(blue, relto=255)

        return Color.from_rgb(*channels, alpha=alpha)

    else:
        channels = list(color.hsl)
        if hue:
            expect_type(hue, Number, unit=None)
            channels[0] = (hue.value / 360) % 1
        # Ruby sass treats plain numbers for saturation and lightness as though
        # they were percentages, just without the %
        if saturation:
            channels[1] = _interpret_percentage(saturation, relto=100)
        if lightness:
            channels[2] = _interpret_percentage(lightness, relto=100)

        return Color.from_hsl(*channels, alpha=alpha)
Ejemplo n.º 13
0
def rgba(r, g, b, a):
    r = _interpret_percentage(r, relto=255)
    g = _interpret_percentage(g, relto=255)
    b = _interpret_percentage(b, relto=255)
    a = _interpret_percentage(a, relto=1)

    return Color.from_rgb(r, g, b, a)
Ejemplo n.º 14
0
def adjust_color(
        color, red=None, green=None, blue=None,
        hue=None, saturation=None, lightness=None, alpha=None):
    do_rgb = red or green or blue
    do_hsl = hue or saturation or lightness
    if do_rgb and do_hsl:
        raise ValueError(
            "Can't adjust both RGB and HSL channels at the same time")

    zero = Number(0)
    a = color.alpha + (alpha or zero).value

    if do_rgb:
        r, g, b = color.rgba[:3]
        channels = [
            current + (adjustment or zero).value / 255
            for (current, adjustment) in zip(color.rgba, (red, green, blue))]
        return Color.from_rgb(*channels, alpha=a)

    else:
        h, s, l = color.hsl
        h = (h + (hue or zero).value / 360) % 1
        s += _interpret_percentage(saturation or zero, relto=100, clamp=False)
        l += _interpret_percentage(lightness or zero, relto=100, clamp=False)
        return Color.from_hsl(h, s, l, a)
Ejemplo n.º 15
0
def rgba_(color, a=None):
    if a is None:
        alpha = 1
    else:
        alpha = _interpret_percentage(a)

    return Color.from_rgb(*color.rgba[:3], alpha=alpha)
Ejemplo n.º 16
0
def rgba_(color, a=None):
    if a is None:
        alpha = 1
    else:
        alpha = _interpret_percentage(a)

    return Color.from_rgb(*color.rgba[:3], alpha=alpha)
Ejemplo n.º 17
0
def adjust_color(
        color, red=None, green=None, blue=None,
        hue=None, saturation=None, lightness=None, alpha=None):
    do_rgb = red or green or blue
    do_hsl = hue or saturation or lightness
    if do_rgb and do_hsl:
        raise ValueError(
            "Can't adjust both RGB and HSL channels at the same time")

    zero = Number(0)
    a = color.alpha + (alpha or zero).value

    if do_rgb:
        r, g, b = color.rgba[:3]
        channels = [
            current + (adjustment or zero).value / 255
            for (current, adjustment) in zip(color.rgba, (red, green, blue))]
        return Color.from_rgb(*channels, alpha=a)

    else:
        h, s, l = color.hsl
        h = (h + (hue or zero).value / 360) % 1
        s += _interpret_percentage(saturation or zero, relto=100, clamp=False)
        l += _interpret_percentage(lightness or zero, relto=100, clamp=False)
        return Color.from_hsl(h, s, l, a)
Ejemplo n.º 18
0
def scale_color(color,
                red=None,
                green=None,
                blue=None,
                saturation=None,
                lightness=None,
                alpha=None):
    do_rgb = red or green or blue
    do_hsl = saturation or lightness
    if do_rgb and do_hsl:
        raise ValueError(
            "Can't scale both RGB and HSL channels at the same time")

    scaled_alpha = _scale_channel(color.alpha, alpha)

    if do_rgb:
        channels = [
            _scale_channel(channel, scaleby)
            for channel, scaleby in zip(color.rgba, (red, green, blue))
        ]
        return Color.from_rgb(*channels, alpha=scaled_alpha)

    else:
        channels = [
            _scale_channel(channel, scaleby)
            for channel, scaleby in zip(color.hsl, (None, saturation,
                                                    lightness))
        ]
        return Color.from_hsl(*channels, alpha=scaled_alpha)
Ejemplo n.º 19
0
def rgba(r, g, b, a):
    r = _interpret_percentage(r, relto=255)
    g = _interpret_percentage(g, relto=255)
    b = _interpret_percentage(b, relto=255)
    a = _interpret_percentage(a, relto=1)

    return Color.from_rgb(r, g, b, a)
Ejemplo n.º 20
0
def invert(color):
    """
    Returns the inverse (negative) of a color.
    The red, green, and blue values are inverted, while the opacity is left alone.
    """
    r, g, b, a = color.rgba
    return Color.from_rgb(1 - r, 1 - g, 1 - b, alpha=a)
Ejemplo n.º 21
0
def change_color(color, red=None, green=None, blue=None, hue=None, saturation=None, lightness=None, alpha=None):
    do_rgb = red or green or blue
    do_hsl = hue or saturation or lightness
    if do_rgb and do_hsl:
        raise ValueError("Can't change both RGB and HSL channels at the same time")

    if alpha is None:
        alpha = color.alpha
    else:
        alpha = alpha.value

    if do_rgb:
        channels = list(color.rgba[:3])
        if red:
            channels[0] = _interpret_percentage(red, relto=255)
        if green:
            channels[1] = _interpret_percentage(green, relto=255)
        if blue:
            channels[2] = _interpret_percentage(blue, relto=255)

        return Color.from_rgb(*channels, alpha=alpha)

    else:
        channels = list(color.hsl)
        if hue:
            expect_type(hue, Number, unit=None)
            channels[0] = (hue.value / 360) % 1
        # Ruby sass treats plain numbers for saturation and lightness as though
        # they were percentages, just without the %
        if saturation:
            channels[1] = _interpret_percentage(saturation, relto=100)
        if lightness:
            channels[2] = _interpret_percentage(lightness, relto=100)

        return Color.from_hsl(*channels, alpha=alpha)
Ejemplo n.º 22
0
def invert(color):
    """
    Returns the inverse (negative) of a color.
    The red, green, and blue values are inverted, while the opacity is left alone.
    """
    r, g, b, a = color.rgba
    return Color.from_rgb(1 - r, 1 - g, 1 - b, alpha=a)
Ejemplo n.º 23
0
def test_adjust_hue():
    # Examples from the Ruby docs
    assert calc('adjust-hue(hsl(120, 30%, 90%), 60deg)') == calc(
        'hsl(180, 30%, 90%)')
    assert calc('adjust-hue(hsl(120, 30%, 90%), -60deg)') == calc(
        'hsl(60, 30%, 90%)')
    assert calc('adjust-hue(#811, 45deg)') == Color.from_rgb(
        136 / 255, 106.25 / 255, 17 / 255)
Ejemplo n.º 24
0
def test_functions(calc):
    calc = Calculator(CoreExtension.namespace).calculate

    assert calc('grayscale(red)') == Color.from_rgb(0.5, 0.5, 0.5)
    assert calc('grayscale(1)') == String('grayscale(1)', quotes=None)  # Misusing css built-in functions (with scss counterpart)
    assert calc('skew(1)') == String('skew(1)', quotes=None)  # Missing css-only built-in functions
    with pytest.raises(SassEvaluationError):
        calc('unitless("X")')  # Misusing non-css built-in scss funtions
Ejemplo n.º 25
0
def test_functions(calc):
    ns = Namespace(functions=CORE_LIBRARY)
    calc = Calculator(ns).calculate

    assert calc('grayscale(red)') == Color.from_rgb(0.5, 0.5, 0.5)
    assert calc('grayscale(1)') == String('grayscale(1)', quotes=None)  # Misusing css built-in functions (with scss counterpart)
    assert calc('skew(1)') == String('skew(1)', quotes=None)  # Missing css-only built-in functions
    with pytest.raises(TypeError):
        calc('unitless("X")')  # Misusing non-css built-in scss funtions
Ejemplo n.º 26
0
def test_functions(calc):
    calc = Calculator(CoreExtension.namespace).calculate

    assert calc('grayscale(red)') == Color.from_rgb(0.5, 0.5, 0.5)
    assert calc('grayscale(1)') == String(
        'grayscale(1)',
        quotes=None)  # Misusing css built-in functions (with scss counterpart)
    assert calc('skew(1)') == String(
        'skew(1)', quotes=None)  # Missing css-only built-in functions
    with pytest.raises(SassEvaluationError):
        calc('unitless("X")')  # Misusing non-css built-in scss funtions
Ejemplo n.º 27
0
def invert(color):
    """Returns the inverse (negative) of a color.  The red, green, and blue
    values are inverted, while the opacity is left alone.
    """
    if isinstance(color, Number):
        # invert(n) and invert(n%) are CSS3 filters and should be left
        # intact
        return String.unquoted("invert(%s)" % (color.render(),))

    expect_type(color, Color)
    r, g, b, a = color.rgba
    return Color.from_rgb(1 - r, 1 - g, 1 - b, alpha=a)
Ejemplo n.º 28
0
def invert(color):
    """Returns the inverse (negative) of a color.  The red, green, and blue
    values are inverted, while the opacity is left alone.
    """
    if isinstance(color, Number):
        # invert(n) and invert(n%) are CSS3 filters and should be left
        # intact
        return String.unquoted("invert(%s)" % (color.render(), ))

    expect_type(color, Color)
    r, g, b, a = color.rgba
    return Color.from_rgb(1 - r, 1 - g, 1 - b, alpha=a)
Ejemplo n.º 29
0
def scale_color(color, red=None, green=None, blue=None, saturation=None, lightness=None, alpha=None):
    do_rgb = red or green or blue
    do_hsl = saturation or lightness
    if do_rgb and do_hsl:
        raise ValueError("Can't scale both RGB and HSL channels at the same time")

    scaled_alpha = _scale_channel(color.alpha, alpha)

    if do_rgb:
        channels = [_scale_channel(channel, scaleby) for channel, scaleby in zip(color.rgba, (red, green, blue))]
        return Color.from_rgb(*channels, alpha=scaled_alpha)

    else:
        channels = [
            _scale_channel(channel, scaleby) for channel, scaleby in zip(color.hsl, (None, saturation, lightness))
        ]
        return Color.from_hsl(*channels, alpha=scaled_alpha)
Ejemplo n.º 30
0
def test_grayscale():
    assert calc('grayscale(black)') == Color.from_rgb(0., 0., 0.)
    assert calc('grayscale(white)') == Color.from_rgb(1., 1., 1.)
    assert calc('grayscale(yellow)') == Color.from_rgb(0.5, 0.5, 0.5)
Ejemplo n.º 31
0
def test_saturate():
    # Examples from the Ruby docs
    assert calc('saturate(hsl(120, 30%, 90%), 20%)') == calc(
        'hsl(120, 50%, 90%)')
    assert calc('saturate(#855, 20%)') == Color.from_rgb(
        158.1 / 255, 62.9 / 255, 62.9 / 255)
Ejemplo n.º 32
0
def test_desaturate():
    # Examples from the Ruby docs
    assert calc('desaturate(hsl(120, 30%, 90%), 20%)') == calc(
        'hsl(120, 10%, 90%)')
    assert calc('desaturate(#855, 20%)') == Color.from_rgb(
        113.9 / 255, 107.1 / 255, 107.1 / 255)
Ejemplo n.º 33
0
def test_adjust_hue(calc):
    # Examples from the Ruby docs
    assert calc('adjust-hue(hsl(120, 30%, 90%), 60deg)') == calc('hsl(180, 30%, 90%)')
    assert calc('adjust-hue(hsl(120, 30%, 90%), -60deg)') == calc('hsl(60, 30%, 90%)')
    assert calc('adjust-hue(#811, 45deg)') == Color.from_rgb(136/255, 106.25/255, 17/255)
Ejemplo n.º 34
0
def opacify(color, amount):
    r, g, b, a = color.rgba
    return Color.from_rgb(r, g, b, alpha=color.alpha + amount.value)
Ejemplo n.º 35
0
def mix(color1, color2, weight=Number(50, "%")):
    """
    Mixes together two colors. Specifically, takes the average of each of the
    RGB components, optionally weighted by the given percentage.
    The opacity of the colors is also considered when weighting the components.

    Specifically, takes the average of each of the RGB components,
    optionally weighted by the given percentage.
    The opacity of the colors is also considered when weighting the components.

    The weight specifies the amount of the first color that should be included
    in the returned color.
    50%, means that half the first color
        and half the second color should be used.
    25% means that a quarter of the first color
        and three quarters of the second color should be used.

    For example:

        mix(#f00, #00f) => #7f007f
        mix(#f00, #00f, 25%) => #3f00bf
        mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
    """
    # This algorithm factors in both the user-provided weight
    # and the difference between the alpha values of the two colors
    # to decide how to perform the weighted average of the two RGB values.
    #
    # It works by first normalizing both parameters to be within [-1, 1],
    # where 1 indicates "only use color1", -1 indicates "only use color 0",
    # and all values in between indicated a proportionately weighted average.
    #
    # Once we have the normalized variables w and a,
    # we apply the formula (w + a)/(1 + w*a)
    # to get the combined weight (in [-1, 1]) of color1.
    # This formula has two especially nice properties:
    #
    #   * When either w or a are -1 or 1, the combined weight is also that
    #     number (cases where w * a == -1 are undefined, and handled as a
    #     special case).
    #
    #   * When a is 0, the combined weight is w, and vice versa
    #
    # Finally, the weight of color1 is renormalized to be within [0, 1]
    # and the weight of color2 is given by 1 minus the weight of color1.
    #
    # Algorithm from the Sass project: http://sass-lang.com/

    p = _interpret_percentage(weight)

    # Scale weight to [-1, 1]
    w = p * 2 - 1
    # Compute difference in alpha channels
    a = color1.alpha - color2.alpha

    # Weight of first color
    if w * a == -1:
        # Avoid zero-div case
        scaled_weight1 = w
    else:
        scaled_weight1 = (w + a) / (1 + w * a)

    # Unscale back to [0, 1] and get the weight of the other color
    w1 = (scaled_weight1 + 1) / 2
    w2 = 1 - w1

    # Do the scaling.  Note that alpha isn't scaled by alpha, as that wouldn't
    # make much sense; it uses the original untwiddled weight, p.
    channels = [
        ch1 * w1 + ch2 * w2
        for (ch1, ch2) in zip(color1.rgba[:3], color2.rgba[:3])]
    alpha = color1.alpha * p + color2.alpha * (1 - p)
    return Color.from_rgb(*channels, alpha=alpha)
Ejemplo n.º 36
0
def test_hsla(calc):
    # Examples from the CSS 3 color spec
    assert calc('hsla(120, 100%, 50%, 1)') == Color.from_rgb(0., 1., 0.,)
    assert calc('hsla(240, 100%, 50%, 0.5)') == Color.from_rgb(0., 0., 1., 0.5)
    assert calc('hsla(30, 100%, 50%, 0.1)') == Color.from_rgb(1., 0.5, 0., 0.1)
Ejemplo n.º 37
0
def test_rgb(calc):
    assert calc('rgb(128, 192, 224)') == Color.from_rgb(128/255, 192/255, 224/255)
    assert calc('rgb(20%, 40%, 60%)') == Color.from_rgb(0.2, 0.4, 0.6)
Ejemplo n.º 38
0
def test_rgb():
    assert calc('rgb(128, 192, 224)') == Color.from_rgb(
        128 / 255, 192 / 255, 224 / 255)
    assert calc('rgb(20%, 40%, 60%)') == Color.from_rgb(0.2, 0.4, 0.6)
Ejemplo n.º 39
0
def test_complement(calc):
    assert calc('complement(black)') == Color.from_rgb(0., 0., 0.)
    assert calc('complement(white)') == Color.from_rgb(1., 1., 1.)
    assert calc('complement(yellow)') == Color.from_rgb(0., 0., 1.)
Ejemplo n.º 40
0
def test_invert(calc):
    assert calc('invert(black)') == Color.from_rgb(1., 1., 1.)
    assert calc('invert(white)') == Color.from_rgb(0., 0., 0.)
    assert calc('invert(yellow)') == Color.from_rgb(0., 0., 1.)
Ejemplo n.º 41
0
def test_grayscale(calc):
    assert calc('grayscale(black)') == Color.from_rgb(0., 0., 0.)
    assert calc('grayscale(white)') == Color.from_rgb(1., 1., 1.)
    assert calc('grayscale(yellow)') == Color.from_rgb(0.5, 0.5, 0.5)
Ejemplo n.º 42
0
def test_desaturate(calc):
    # Examples from the Ruby docs
    assert calc('desaturate(hsl(120, 30%, 90%), 20%)') == calc('hsl(120, 10%, 90%)')
    assert calc('desaturate(#855, 20%)') == Color.from_rgb(113.9/255, 107.1/255, 107.1/255)
Ejemplo n.º 43
0
def transparentize(color, amount):
    r, g, b, a = color.rgba
    return Color.from_rgb(r, g, b, alpha=color.alpha - amount.value)
Ejemplo n.º 44
0
def test_complement():
    assert calc('complement(black)') == Color.from_rgb(0., 0., 0.)
    assert calc('complement(white)') == Color.from_rgb(1., 1., 1.)
    assert calc('complement(yellow)') == Color.from_rgb(0., 0., 1.)
Ejemplo n.º 45
0
def opacify(color, amount):
    r, g, b, a = color.rgba
    return Color.from_rgb(
        r, g, b,
        alpha=color.alpha + amount.value)
Ejemplo n.º 46
0
def test_invert():
    assert calc('invert(black)') == Color.from_rgb(1., 1., 1.)
    assert calc('invert(white)') == Color.from_rgb(0., 0., 0.)
    assert calc('invert(yellow)') == Color.from_rgb(0., 0., 1.)
Ejemplo n.º 47
0
def mix(color1, color2, weight=Number(50, "%")):
    """
    Mixes together two colors. Specifically, takes the average of each of the
    RGB components, optionally weighted by the given percentage.
    The opacity of the colors is also considered when weighting the components.

    Specifically, takes the average of each of the RGB components,
    optionally weighted by the given percentage.
    The opacity of the colors is also considered when weighting the components.

    The weight specifies the amount of the first color that should be included
    in the returned color.
    50%, means that half the first color
        and half the second color should be used.
    25% means that a quarter of the first color
        and three quarters of the second color should be used.

    For example:

        mix(#f00, #00f) => #7f007f
        mix(#f00, #00f, 25%) => #3f00bf
        mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
    """
    # This algorithm factors in both the user-provided weight
    # and the difference between the alpha values of the two colors
    # to decide how to perform the weighted average of the two RGB values.
    #
    # It works by first normalizing both parameters to be within [-1, 1],
    # where 1 indicates "only use color1", -1 indicates "only use color 0",
    # and all values in between indicated a proportionately weighted average.
    #
    # Once we have the normalized variables w and a,
    # we apply the formula (w + a)/(1 + w*a)
    # to get the combined weight (in [-1, 1]) of color1.
    # This formula has two especially nice properties:
    #
    #   * When either w or a are -1 or 1, the combined weight is also that
    #     number (cases where w * a == -1 are undefined, and handled as a
    #     special case).
    #
    #   * When a is 0, the combined weight is w, and vice versa
    #
    # Finally, the weight of color1 is renormalized to be within [0, 1]
    # and the weight of color2 is given by 1 minus the weight of color1.
    #
    # Algorithm from the Sass project: http://sass-lang.com/

    p = _interpret_percentage(weight)

    # Scale weight to [-1, 1]
    w = p * 2 - 1
    # Compute difference in alpha channels
    a = color1.alpha - color2.alpha

    # Weight of first color
    if w * a == -1:
        # Avoid zero-div case
        scaled_weight1 = w
    else:
        scaled_weight1 = (w + a) / (1 + w * a)

    # Unscale back to [0, 1] and get the weight of the other color
    w1 = (scaled_weight1 + 1) / 2
    w2 = 1 - w1

    # Do the scaling.  Note that alpha isn't scaled by alpha, as that wouldn't
    # make much sense; it uses the original untwiddled weight, p.
    channels = [
        ch1 * w1 + ch2 * w2
        for (ch1, ch2) in zip(color1.rgba[:3], color2.rgba[:3])]
    alpha = color1.alpha * p + color2.alpha * (1 - p)
    return Color.from_rgb(*channels, alpha=alpha)
Ejemplo n.º 48
0
def test_image_color():
    libextra.image_color(Color.from_rgb(1, 1, 0))
    assert True
Ejemplo n.º 49
0
def transparentize(color, amount):
    r, g, b, a = color.rgba
    return Color.from_rgb(
        r, g, b,
        alpha=color.alpha - amount.value)
Ejemplo n.º 50
0
def test_saturate(calc):
    # Examples from the Ruby docs
    assert calc('saturate(hsl(120, 30%, 90%), 20%)') == calc('hsl(120, 50%, 90%)')
    assert calc('saturate(#855, 20%)') == Color.from_rgb(158.1/255, 62.9/255, 62.9/255)
Ejemplo n.º 51
0
def test_image_color():
    libextra.image_color(Color.from_rgb(1, 1, 0))
    assert True