f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/0000755000000000000000000000000012506556244016523 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/README.md0000644000000000000000000001741312506556244020010 0ustar rootroot# SCSS Blend Modes CSS doesn't natively support color blending the way that Photoshop does. This library attempts to fake that by allowing you to blend a foreground color with a background color in order to approximate color blending. This is not a dynamic blend; you can't use this to blend a color with an image. This was originally intended for use with the [Compass Photoshop Drop Shadow Plugin](https://github.com/heygrady/compass-photoshop-drop-shadow) but it proved impractical to integrate. ## A Note on Real CSS3 Blend Modes Adobe has been working on a [W3C spec](http://www.w3.org/TR/compositing/) to [add blend modes to CSS3](http://blogs.adobe.com/webplatform/2012/04/04/bringing-blending-to-the-web/). However, CSS blend modes have [extremely limited support in browsers](http://html.adobe.com/webplatform/graphics/blendmodes/browser-support/), as of September 2013. This library is **not** a polyfill for those blend modes. A polyfill for dynamic blend modes will require something like SVG and JavaScript and would likely be quite complicated (or impossible). ## A Note on Color Blending The included functions are based on [blend.js](https://github.com/jseidelin/pixastic/blob/master/actions/blend.js) from the [Pixastic Image Processing Library](http://www.pixastic.com/lib/). I chose this library because JavaScript is easy enough to read and the blend modes seemed to match closely with what Photoshop offered. Additionally, a [detailed explaination of Photoshop blend modes](http://photoblogstop.com/photoshop/photoshop-blend-modes-explained) was used as a reference as well as the [Wikipedia article on blend modes](http://en.wikipedia.org/wiki/Blend_modes). These blend mode functions are not magic. In Photoshop, the blend mode functions are applied dynamically between two layers in order to create a pixel-by-pixel blend. In CSS they can only be used to combine two solid colors together. Blend modes can be useful in times when a Photoshop design implements a blend mode on an element, like a drop shadow, that is over a mostly solid background. Choosing a dominant background color and a solid foreground color may allow for the apearance of a dynamically blended color. ## Installation #### Install the Ruby Gem. ``` gem install compass-blend-modes ``` #### Existing Compass Projects You can include it in any existing Compass project by including the plugin in your config.rb file. ```ruby # Require any additional compass plugins here. require 'compass-blend-modes' ``` #### New Compass Projects You can install the plugin as part of a new Compass project. ``` compass create my_project -r compass-blend-modes ``` ## Usage ```scss @import 'blend-modes'; ``` ### Examples ```scss // make sure the functions are imported @import 'blend-modes'; // Solid background .multiply { background-color: blend-multiply(#7FFFD4, #DEB887); } // RGBa background .multiply { background-color: blend-multiply(rgba(#7FFFD4, 0.5), rgba(#DEB887, 0.5)); } ``` ## Blending Functions All functions expect a color as the `$foreground` and `$background` colors. The colors can be any hex, [rgb](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#rgb-instance_method), [rgba](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#rgba-instance_method), [hsl](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#hsl-instance_method), or [hsla](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#hsla-instance_method) color supported by Sass. Blending functions work by combining the colors from the top-most layer, the `$foreground`, with the lower layer, the `$background`. - **blend-normal(** *$foreground*, *$background* **)** - Normal is used primarily to preserve the opacity after the blending has been applied to the RGB values. - **blend-multiply(** *$foreground*, *$background* **)** - **blend-lighten(** *$foreground*, *$background* **)** - **blend-darken(** *$foreground*, *$background* **)** - **blend-darkercolor(** *$foreground*, *$background* **)** - Not found in Photoshop. - **blend-lightercolor(** *$foreground*, *$background* **)** - Not found in Photoshop. - **blend-lineardodge(** *$foreground*, *$background* **)** - **blend-linearburn(** *$foreground*, *$background* **)** - **blend-difference(** *$foreground*, *$background* **)** - **blend-screen(** *$foreground*, *$background* **)** - **blend-exclusion(** *$foreground*, *$background* **)** - **blend-overlay(** *$foreground*, *$background* **)** - **blend-softlight(** *$foreground*, *$background* **)** - **blend-hardlight(** *$foreground*, *$background* **)** - **blend-colordodge(** *$foreground*, *$background* **)** - **blend-colorburn(** *$foreground*, *$background* **)** - **blend-linearlight(** *$foreground*, *$background* **)** - **blend-vividlight(** *$foreground*, *$background* **)** - **blend-pinlight(** *$foreground*, *$background* **)** - **blend-hardmix(** *$foreground*, *$background* **)** - **blend-colorblend(** *$foreground*, *$background* **)** - **blend-dissolve(** *$foreground*, *$background* **)** - Not implemented. Dissolve treats transparency as a pixel pattern and applies a diffusion dither pattern. - **blend-divide(** *$foreground*, *$background* **)** - **blend-hue(** *$foreground*, *$background* **)** - **blend-luminosity(** *$foreground*, *$background* **)** - **blend-saturation(** *$foreground*, *$background* **)** - **blend-subtract(** *$foreground*, *$background* **)** ## HSV Functions These functions are used to convert between RGB, HSL and HSV color formats. The HSV color format is not natively supported by CSS or Sass. These functions were taken directly from this [Gist](https://gist.github.com/1069204). HSV values are used to calculate the results for the `blend-colorblend`, `blend-hue`, `blend-luminosity` and `blend-saturation` functions. - **hsv-to-hsl(** *$h*, [ *$s: 0*, *$v: 0* ] **)** - Converts a HSV color values into HSL color values. `$h` can be a list of three values representing `$h`, `$s` and `$v`. - **hsl-to-hsv(** *$h*, [ *$ss: 0*, *$ll: 0* ] **)** - Converts a HSL color values into HSV color values. `$h` can be a list of three values representing `$h`, `$ss` and `$ll`. - **color-to-hsv(** *$color* **)** - Converts a [Sass Color](http://sass-lang.com/docs/yardoc/Sass/Script/Color.html) into a [list](http://sass-lang.com/docs/yardoc/Sass/Script/List.html) HSV color values. - **hsv-to-color(** *$h*, [ *$s: 0*, *$v: 0* ] **)** - Converts a list of HSV color values into a Sass Color. `$h` can be a list of three values representing `$h`, `$s` and `$v` ## Internal Functions These functions are used to save redundant code and are not meant to be used directly. These functions perform the blending operation on a single r, g or b value. **NOTE:** These functions are not intended to be used directly. - **blend-lighten-color(** *$foreground*, *$background* **)** - **blend-darken-color(** *$foreground*, *$background* **)** - **blend-lineardodge-color(** *$foreground*, *$background* **)** - **blend-linearburn-color(** *$foreground*, *$background* **)** - **blend-screen-color(** *$foreground*, *$background* **)** - **blend-exclusion-color(** *$foreground*, *$background* **)** - **blend-overlay-color(** *$foreground*, *$background* **)** - **blend-softlight-color(** *$foreground*, *$background* **)** - **blend-hardlight-color(** *$foreground*, *$background* **)** - **blend-colordodge-color(** *$foreground*, *$background* **)** - **blend-colorburn-color(** *$foreground*, *$background* **)** - **blend-linearlight-color(** *$foreground*, *$background* **)** - **blend-vividlight-color(** *$foreground*, *$background* **)** - **blend-pinlight-color(** *$foreground*, *$background* **)** - **blend-hardmix-color(** *$foreground*, *$background* **)** - **blend-divide-color(** *$foreground*, *$background* **)** f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/lib/0000755000000000000000000000000012506556244017271 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/lib/compass-blend-modes.rb0000644000000000000000000000010012506556244023441 0ustar rootrootrequire 'compass' # Ensure Compass require 'compass/blend-modes'f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/lib/compass/0000755000000000000000000000000012506556244020736 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/lib/compass/blend-modes.rb0000644000000000000000000000026512506556244023457 0ustar rootrootrequire 'compass/blend-modes/version' module Compass module BlendModes Compass::Frameworks.register('blend-modes', :path => "#{File.dirname(__FILE__)}/../..") end endf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/lib/compass/blend-modes/0000755000000000000000000000000012506556244023127 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/lib/compass/blend-modes/version.rb0000644000000000000000000000010612506556244025136 0ustar rootrootmodule Compass module BlendModes VERSION = '0.0.3' end endf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/.gitignore0000644000000000000000000000004712506556244020514 0ustar rootroot.sass-cache styles.css node_modules f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/templates/0000755000000000000000000000000012506556244020521 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/templates/project/0000755000000000000000000000000012506556244022167 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/templates/project/manifest.rb0000644000000000000000000000020312506556244024315 0ustar rootroot# Make sure you list all the project template files here in the manifest. stylesheet 'screen.scss', :media => 'screen, projection' f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/templates/project/screen.scss0000644000000000000000000000032212506556244024340 0ustar rootroot@import 'blend-modes'; // Solid background .multiply { background-color: blend-multiply(#7FFFD4, #DEB887); } // RGBa background .multiply { background-color: blend-multiply(rgba(#7FFFD4, 0.5), #DEB887); }f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/LICENSE0000644000000000000000000000210312506556244017524 0ustar rootrootCopyright (c) 2013 Grady Kuhnline MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/0000755000000000000000000000000012506556244020156 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/config.rb0000644000000000000000000000152112506556244021747 0ustar rootroot# Require any additional compass plugins here. require 'compass-blend-modes' # Set this to the root of your project when deployed: http_path = "/" css_dir = "css" sass_dir = "scss" images_dir = "i" javascripts_dir = "js" # You can select your preferred output style here (can be overridden via the command line): output_style = :compact # To enable relative paths to assets via compass helper functions. Uncomment: relative_assets = true # To disable debugging comments that display the original location of your selectors. Uncomment: line_comments = false # If you prefer the indented syntax, you might want to regenerate this # project again passing --syntax sass, or you can uncomment this: # preferred_syntax = :sass # and then run: # sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/i/0000755000000000000000000000000013024256553020402 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/js/0000755000000000000000000000000012506556244020572 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/js/blend-modes.js0000644000000000000000000003041212506556244023321 0ustar rootroot/* * Pixastic Lib - Blend - v0.1.1 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ * License: [http://www.pixastic.com/lib/license.txt] */ // NOTE: modified to blend 2 single pixels // color conversions function hex2rgba(h) {return [hexToR(h), hexToG(h),hexToB(h), 255]} function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)} function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)} function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)} function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h} function rgba2hex(color) {return '#' + (1 << 24 | color[0] << 16 | color[1] << 8 | color[2]).toString(16).substr(1);} function blend(mode, foregroundColor, backgroundColor) { var data = hex2rgba(backgroundColor); var w = 1; var h = 1; var data2 = hex2rgba(foregroundColor); var p = w*h; var pix = p*4; var pix1, pix2; var r1, g1, b1; var r2, g2, b2; var r3, g3, b3; var r4, g4, b4; var dataChanged = false; switch (mode) { case "normal" : //while (p--) { // data2[pix-=4] = data2[pix]; // data2[pix1=pix+1] = data2[pix1]; // data2[pix2=pix+2] = data2[pix2]; //} break; case "multiply" : while (p--) { data2[pix-=4] = data[pix] * data2[pix] / 255; data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255; data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255; } dataChanged = true; break; case "lighten" : while (p--) { if ((r1 = data[pix-=4]) > data2[pix]) data2[pix] = r1; if ((g1 = data[pix1=pix+1]) > data2[pix1]) data2[pix1] = g1; if ((b1 = data[pix2=pix+2]) > data2[pix2]) data2[pix2] = b1; } dataChanged = true; break; case "darken" : while (p--) { if ((r1 = data[pix-=4]) < data2[pix]) data2[pix] = r1; if ((g1 = data[pix1=pix+1]) < data2[pix1]) data2[pix1] = g1; if ((b1 = data[pix2=pix+2]) < data2[pix2]) data2[pix2] = b1; } dataChanged = true; break; case "darkercolor" : while (p--) { if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) <= (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) { data2[pix] = r1; data2[pix1] = g1; data2[pix2] = b1; } } dataChanged = true; break; case "lightercolor" : while (p--) { if (((r1 = data[pix-=4])*0.3+(g1 = data[pix1=pix+1])*0.59+(b1 = data[pix2=pix+2])*0.11) > (data2[pix]*0.3+data2[pix1]*0.59+data2[pix2]*0.11)) { data2[pix] = r1; data2[pix1] = g1; data2[pix2] = b1; } } dataChanged = true; break; case "lineardodge" : /* otherCtx.globalCompositeOperation = "source-over"; otherCtx.drawImage(params.canvas, 0, 0); otherCtx.globalCompositeOperation = "lighter"; otherCtx.drawImage(image, 0, 0); */ while (p--) { if ((r3 = data[pix-=4] + data2[pix]) > 255) data2[pix] = 255; else data2[pix] = r3; if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255) data2[pix1] = 255; else data2[pix1] = g3; if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255) data2[pix2] = 255; else data2[pix2] = b3; } dataChanged = true; break; case "linearburn" : while (p--) { if ((r3 = data[pix-=4] + data2[pix]) < 255) data2[pix] = 0; else data2[pix] = (r3 - 255); if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255) data2[pix1] = 0; else data2[pix1] = (g3 - 255); if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255) data2[pix2] = 0; else data2[pix2] = (b3 - 255); } dataChanged = true; break; case "difference" : while (p--) { if ((r3 = data[pix-=4] - data2[pix]) < 0) data2[pix] = -r3; else data2[pix] = r3; if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0) data2[pix1] = -g3; else data2[pix1] = g3; if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0) data2[pix2] = -b3; else data2[pix2] = b3; } dataChanged = true; break; case "screen" : while (p--) { data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8)); data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8)); data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8)); } dataChanged = true; break; case "exclusion" : var div_2_255 = 2 / 255; while (p--) { data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix]; data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1]; data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2]; } dataChanged = true; break; case "overlay" : var div_2_255 = 2 / 255; while (p--) { if ((r1 = data[pix-=4]) < 128) data2[pix] = data2[pix]*r1*div_2_255; else data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255; if ((g1 = data[pix1=pix+1]) < 128) data2[pix1] = data2[pix1]*g1*div_2_255; else data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255; if ((b1 = data[pix2=pix+2]) < 128) data2[pix2] = data2[pix2]*b1*div_2_255; else data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255; } dataChanged = true; break; case "softlight" : var div_2_255 = 2 / 255; while (p--) { if ((r1 = data[pix-=4]) < 128) data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255; else data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255; if ((g1 = data[pix1=pix+1]) < 128) data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255; else data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255; if ((b1 = data[pix2=pix+2]) < 128) data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255; else data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255; } dataChanged = true; break; case "hardlight" : var div_2_255 = 2 / 255; while (p--) { if ((r2 = data2[pix-=4]) < 128) data2[pix] = data[pix] * r2 * div_2_255; else data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255; if ((g2 = data2[pix1=pix+1]) < 128) data2[pix1] = data[pix1] * g2 * div_2_255; else data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255; if ((b2 = data2[pix2=pix+2]) < 128) data2[pix2] = data[pix2] * b2 * div_2_255; else data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255; } dataChanged = true; break; case "colordodge" : while (p--) { if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255) data2[pix] = 255; else data2[pix] = r3; if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255) data2[pix1] = 255; else data2[pix1] = g3; if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255) data2[pix2] = 255; else data2[pix2] = b3; } dataChanged = true; break; case "colorburn" : while (p--) { if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0) data2[pix] = 0; else data2[pix] = r3; if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0) data2[pix1] = 0; else data2[pix1] = g3; if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0) data2[pix2] = 0; else data2[pix2] = b3; } dataChanged = true; break; case "linearlight" : while (p--) { if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) { data2[pix] = 0 } else { if (r3 > 255) data2[pix] = 255; else data2[pix] = r3; } if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) { data2[pix1] = 0 } else { if (g3 > 255) data2[pix1] = 255; else data2[pix1] = g3; } if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) { data2[pix2] = 0 } else { if (b3 > 255) data2[pix2] = 255; else data2[pix2] = b3; } } dataChanged = true; break; case "vividlight" : while (p--) { if ((r2=data2[pix-=4]) < 128) { if (r2) { if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0) data2[pix] = 0; else data2[pix] = r3 } else { data2[pix] = 0; } } else if ((r3 = (r4=2*r2-256)) < 255) { if ((r3 = (data[pix]<<8)/(255-r4)) > 255) data2[pix] = 255; else data2[pix] = r3; } else { if (r3 < 0) data2[pix] = 0; else data2[pix] = r3 } if ((g2=data2[pix1=pix+1]) < 128) { if (g2) { if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0) data2[pix1] = 0; else data2[pix1] = g3; } else { data2[pix1] = 0; } } else if ((g3 = (g4=2*g2-256)) < 255) { if ((g3 = (data[pix1]<<8)/(255-g4)) > 255) data2[pix1] = 255; else data2[pix1] = g3; } else { if (g3 < 0) data2[pix1] = 0; else data2[pix1] = g3; } if ((b2=data2[pix2=pix+2]) < 128) { if (b2) { if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0) data2[pix2] = 0; else data2[pix2] = b3; } else { data2[pix2] = 0; } } else if ((b3 = (b4=2*b2-256)) < 255) { if ((b3 = (data[pix2]<<8)/(255-b4)) > 255) data2[pix2] = 255; else data2[pix2] = b3; } else { if (b3 < 0) data2[pix2] = 0; else data2[pix2] = b3; } } dataChanged = true; break; case "pinlight" : while (p--) { if ((r2=data2[pix-=4]) < 128) if ((r1=data[pix]) < (r4=2*r2)) data2[pix] = r1; else data2[pix] = r4; else if ((r1=data[pix]) > (r4=2*r2-256)) data2[pix] = r1; else data2[pix] = r4; if ((g2=data2[pix1=pix+1]) < 128) if ((g1=data[pix1]) < (g4=2*g2)) data2[pix1] = g1; else data2[pix1] = g4; else if ((g1=data[pix1]) > (g4=2*g2-256)) data2[pix1] = g1; else data2[pix1] = g4; if ((r2=data2[pix2=pix+2]) < 128) if ((r1=data[pix2]) < (r4=2*r2)) data2[pix2] = r1; else data2[pix2] = r4; else if ((r1=data[pix2]) > (r4=2*r2-256)) data2[pix2] = r1; else data2[pix2] = r4; } dataChanged = true; break; case "hardmix" : while (p--) { if ((r2 = data2[pix-=4]) < 128) if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0) data2[pix] = 0; else data2[pix] = 255; else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128) data2[pix] = 0; else data2[pix] = 255; if ((g2 = data2[pix1=pix+1]) < 128) if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0) data2[pix1] = 0; else data2[pix1] = 255; else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128) data2[pix1] = 0; else data2[pix1] = 255; if ((b2 = data2[pix2=pix+2]) < 128) if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0) data2[pix2] = 0; else data2[pix2] = 255; else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128) data2[pix2] = 0; else data2[pix2] = 255; } dataChanged = true; break; } return rgba2hex(data2); }f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/index.html0000644000000000000000000000665212506556244022164 0ustar rootroot
foreground
background

SCSS Blend Modes

normal
multiply
lighten
darken
darkercolor
lightercolor
lineardodge
linearburn
difference
screen
exclusion
overlay
softlight
hardlight
colordodge
colorburn
linearlight
vividlight
pinlight
hardmix

Photoshop

colorblend
dissolve
divide
hue
luminosity
saturation
subtract
f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/scss/0000755000000000000000000000000012506556244021131 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/example/scss/styles.scss0000644000000000000000000000512112506556244023350 0ustar rootroot// Import the Compass Plugin @import "blend-modes"; // Plain Colors $foreground-color: #7FFFD4; $background-color: #DEB887; .foreground { background-color: $foreground-color; } .background { background-color: $background-color; } // Blended Colors .normal { background-color: blend-normal($foreground-color, $background-color); } .multiply { background-color: blend-multiply($foreground-color, $background-color); } .lighten { background-color: blend-lighten($foreground-color, $background-color); } .darken { background-color: blend-darken($foreground-color, $background-color); } .darkercolor { background-color: blend-darkercolor($foreground-color, $background-color); } .lightercolor { background-color: blend-lightercolor($foreground-color, $background-color); } .lineardodge { background-color: blend-lineardodge($foreground-color, $background-color); } .linearburn { background-color: blend-linearburn($foreground-color, $background-color); } .difference { background-color: blend-difference($foreground-color, $background-color); } .screen { background-color: blend-screen($foreground-color, $background-color); } .exclusion { background-color: blend-exclusion($foreground-color, $background-color); } .overlay { background-color: blend-overlay($foreground-color, $background-color); } .softlight { background-color: blend-softlight($foreground-color, $background-color); } .hardlight { background-color: blend-hardlight($foreground-color, $background-color); } .colordodge { background-color: blend-colordodge($foreground-color, $background-color); } .colorburn { background-color: blend-colorburn($foreground-color, $background-color); } .linearlight { background-color: blend-linearlight($foreground-color, $background-color); } .vividlight { background-color: blend-vividlight($foreground-color, $background-color); } .pinlight { background-color: blend-pinlight($foreground-color, $background-color); } .hardmix { background-color: blend-hardmix($foreground-color, $background-color); } .colorblend { background-color: blend-colorblend($foreground-color, $background-color); } .dissolve { background-color: blend-dissolve($foreground-color, $background-color); } .divide { background-color: blend-divide($foreground-color, $background-color); } .hue { background-color: blend-hue($foreground-color, $background-color); } .luminosity { background-color: blend-luminosity($foreground-color, $background-color); } .saturation { background-color: blend-saturation($foreground-color, $background-color); } .subtract { background-color: blend-subtract($foreground-color, $background-color); }f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/stylesheets/0000755000000000000000000000000012506556244021077 5ustar rootrootf5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/stylesheets/_blend-modes.scss0000644000000000000000000004310712506556244024331 0ustar rootroot// Import the Compass Plugin //-------------------------------- // Normal //-------------------------------- @function blend-normal ($foreground, $background) { $opacity: opacity($foreground); $background-opacity: opacity($background); // calculate opacity $bm-red: red($foreground) * $opacity + red($background) * $background-opacity * (1 - $opacity); $bm-green: green($foreground) * $opacity + green($background) * $background-opacity * (1 - $opacity); $bm-blue: blue($foreground) * $opacity + blue($background) * $background-opacity * (1 - $opacity); @return rgb($bm-red, $bm-green, $bm-blue); } //-------------------------------- // Multiply //-------------------------------- @function blend-multiply ($foreground, $background) { $bm-red: red($background) * red($foreground) / 255; $bm-green: green($background) * green($foreground) / 255; $bm-blue: blue($background) * blue($foreground) / 255; @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } //-------------------------------- // Lighten //-------------------------------- @function blend-lighten ($foreground, $background) { $bm-red: blend-lighten-color(red($foreground), red($background)); $bm-green: blend-lighten-color(green($foreground), green($background)); $bm-blue: blend-lighten-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-lighten-color($foreground, $background) { @if $background > $foreground { $foreground: $background; } @return $foreground; } //-------------------------------- // Darken //-------------------------------- @function blend-darken ($foreground, $background) { $bm-red: blend-darken-color(red($foreground), red($background)); $bm-green: blend-darken-color(green($foreground), green($background)); $bm-blue: blend-darken-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-darken-color($foreground, $background) { @if $background < $foreground { $foreground: $background; } @return $foreground; } //-------------------------------- // Darker Color //-------------------------------- @function blend-darkercolor ($foreground, $background) { $bm-red: red($foreground); $bm-green: green($foreground); $bm-blue: blue($foreground); $background-red: red($background); $background-green: green($background); $background-blue: blue($background); @if $background-red * 0.3 + $background-green * 0.59 + $background-blue * 0.11 <= $bm-red * 0.3 + $bm-green * 0.59 + $bm-blue * 0.11 { $bm-red: $background-red; $bm-green: $background-green; $bm-blue: $background-blue; } @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } //-------------------------------- // Lighter Color //-------------------------------- @function blend-lightercolor ($foreground, $background) { $bm-red: red($foreground); $bm-green: green($foreground); $bm-blue: blue($foreground); $background-red: red($background); $background-green: green($background); $background-blue: blue($background); @if $background-red * 0.3 + $background-green * 0.59 + $background-blue * 0.11 > $bm-red * 0.3 + $bm-green * 0.59 + $bm-blue * 0.11 { $bm-red: $background-red; $bm-green: $background-green; $bm-blue: $background-blue; } @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } //-------------------------------- // Linear Dodge //-------------------------------- @function blend-lineardodge ($foreground, $background) { $bm-red: blend-lineardodge-color(red($foreground), red($background)); $bm-green: blend-lineardodge-color(green($foreground), green($background)); $bm-blue: blend-lineardodge-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-lineardodge-color($foreground, $background) { @if $background + $foreground > 255 { $foreground: 255; } @else { $foreground: $background + $foreground; } @return $foreground; } //-------------------------------- // Linear Burn //-------------------------------- @function blend-linearburn ($foreground, $background) { $bm-red: blend-linearburn-color(red($foreground), red($background)); $bm-green: blend-linearburn-color(green($foreground), green($background)); $bm-blue: blend-linearburn-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-linearburn-color($foreground, $background) { @if $background + $foreground < 255 { $foreground: 0; } @else { $foreground: $background + $foreground - 255; } @return $foreground; } //-------------------------------- // Difference //-------------------------------- @function blend-difference ($foreground, $background) { $bm-red: abs(red($background) - red($foreground)); $bm-green: abs(green($background) - green($foreground)); $bm-blue: abs(blue($background) - blue($foreground)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } //-------------------------------- // Screen //-------------------------------- @function blend-screen ($foreground, $background) { $bm-red: blend-screen-color(red($foreground), red($background)); $bm-green: blend-screen-color(green($foreground), green($background)); $bm-blue: blend-screen-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-screen-color($foreground, $background) { @return (255 - ( ( (255 - $foreground) * (255 - $background)) / 256)); } //-------------------------------- // Exclusion //-------------------------------- @function blend-exclusion ($foreground, $background) { $bm-red: blend-exclusion-color(red($foreground), red($background)); $bm-green: blend-exclusion-color(green($foreground), green($background)); $bm-blue: blend-exclusion-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-exclusion-color($foreground, $background) { @return $background - ($background * (2 / 255) - 1) * $foreground; } //-------------------------------- // Overlay //-------------------------------- @function blend-overlay ($foreground, $background) { $bm-red: blend-overlay-color(red($foreground), red($background)); $bm-green: blend-overlay-color(green($foreground), green($background)); $bm-blue: blend-overlay-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-overlay-color($foreground, $background) { @if $background <= 255 / 2 { $foreground: (2 * $background * $foreground) / 255; } @else { $foreground: 255 - (255 - 2 * ($background - (255 / 2))) * (255 - $foreground) / 255; } @return $foreground; } //-------------------------------- // Soft Light //-------------------------------- @function blend-softlight ($foreground, $background) { $bm-red: blend-softlight-color(red($foreground), red($background)); $bm-green: blend-softlight-color(green($foreground), green($background)); $bm-blue: blend-softlight-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-softlight-color($foreground, $background) { @if $background < 128 { $foreground: (($foreground / 2) + 64) * $background * (2 / 255); } @else { $foreground: 255 - (191 - ($foreground / 2)) * (255 - $background) * (2 / 255); } @return $foreground; } //-------------------------------- // Hard Light //-------------------------------- @function blend-hardlight ($foreground, $background) { $bm-red: blend-hardlight-color(red($foreground), red($background)); $bm-green: blend-hardlight-color(green($foreground), green($background)); $bm-blue: blend-hardlight-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-hardlight-color($foreground, $background) { $tmp-blend: $foreground; @if $tmp-blend < 128 { $foreground: $background * $tmp-blend * (2 / 255); } @else { $foreground: 255 - (255-$background) * (255-$tmp-blend) * (2 / 255); } @return $foreground; } //-------------------------------- // Color Dodge //-------------------------------- @function blend-colordodge ($foreground, $background) { $bm-red: blend-colordodge-color(red($foreground), red($background)); $bm-green: blend-colordodge-color(green($foreground), green($background)); $bm-blue: blend-colordodge-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-colordodge-color($foreground, $background) { $tmp: $background * 256 / (255 - $foreground); @if $tmp > 255 or $foreground == 255 { $foreground: 255; } @else { $foreground: $tmp; } @return $foreground; } //-------------------------------- // Color Burn //-------------------------------- @function blend-colorburn ($foreground, $background) { $bm-red: blend-colorburn-color(red($foreground), red($background)); $bm-green: blend-colorburn-color(green($foreground), green($background)); $bm-blue: blend-colorburn-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-colorburn-color($foreground, $background) { $tmp: (255 - ((255 - $background) * 255) / $foreground); // TODO: hacked to replicate photoshop @if $foreground == 0 { $foreground: 255; } @elseif $tmp < 0 { $foreground: 0; } @else { $foreground: $tmp; } @return $foreground; } //-------------------------------- // Linear Light //-------------------------------- @function blend-linearlight ($foreground, $background) { $bm-red: blend-linearlight-color(red($foreground), red($background)); $bm-green: blend-linearlight-color(green($foreground), green($background)); $bm-blue: blend-linearlight-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-linearlight-color($foreground, $background) { @if $foreground < 128 { $foreground: blend-linearburn-color($background, 2 * $foreground); } @else { $foreground: blend-lineardodge-color($background, 2 * ($foreground - 128)); } @return $foreground; } //-------------------------------- // Vivid Light //-------------------------------- @function blend-vividlight ($foreground, $background) { $bm-red: blend-vividlight-color(red($foreground), red($background)); $bm-green: blend-vividlight-color(green($foreground), green($background)); $bm-blue: blend-vividlight-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-vividlight-color($foreground, $background) { @if $foreground < 128 { $foreground: blend-colorburn-color(2 * $foreground, $background); } @else { $foreground: blend-colordodge-color(2 * ($foreground - 128), $background); } @return $foreground; } //-------------------------------- // Pin Light //-------------------------------- @function blend-pinlight ($foreground, $background) { $bm-red: blend-pinlight-color(red($foreground), red($background)); $bm-green: blend-pinlight-color(green($foreground), green($background)); $bm-blue: blend-pinlight-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-pinlight-color($foreground, $background) { @if $foreground < 128 { $foreground: blend-darken-color($background, 2 * $foreground); } @else { $foreground: blend-lighten-color($background, 2 * ($foreground - 128)); } @return $foreground; } //-------------------------------- // Hard Mix //-------------------------------- @function blend-hardmix ($foreground, $background) { $bm-red: blend-hardmix-color(red($foreground), red($background)); $bm-green: blend-hardmix-color(green($foreground), green($background)); $bm-blue: blend-hardmix-color(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-hardmix-color($foreground, $background) { $tmp: blend-vividlight-color($foreground, $background); @if $tmp < 128 { $foreground: 0; } @else { $foreground: 255; } @return $foreground; } // Unique to Photoshop //-------------------------------- // Color Blend //-------------------------------- @function blend-colorblend ($foreground, $background) { $foreground-hsv: color-to-hsv($foreground); $background-hsv: color-to-hsv($background); $bm-hsv: nth($foreground-hsv, 1), nth($foreground-hsv, 2), nth($background-hsv, 3); $bm-color: hsv-to-color($bm-hsv); @return blend-normal(rgba(red($bm-color), green($bm-color), blue($bm-color), opacity($foreground)), $background); } //-------------------------------- // Dissolve //-------------------------------- @function blend-dissolve ($foreground, $background) { // The Dissolve blend mode acts on transparent and partially transparent pixels // it treats transparency as a pixel pattern and applies a diffusion dither pattern. // @see http://photoblogstop.com/photoshop/photoshop-blend-modes-explained @return $foreground; } //-------------------------------- // Divide //-------------------------------- @function blend-divide ($foreground, $background) { $bm-red: blend-divide-colors(red($foreground), red($background)); $bm-green: blend-divide-colors(green($foreground), green($background)); $bm-blue:blend-divide-colors(blue($foreground), blue($background)); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } @function blend-divide-colors($foreground, $background) { @return min((($background / 255) / ($foreground / 255)) * 255, 255); } //-------------------------------- // Hue //-------------------------------- @function blend-hue ($foreground, $background) { $foreground-hsv: color-to-hsv($foreground); $background-hsv: color-to-hsv($background); $bm-hsv: nth($foreground-hsv, 1), nth($background-hsv, 2), nth($background-hsv, 3); $bm-color: hsv-to-color($bm-hsv); @return blend-normal(rgba(red($bm-color), green($bm-color), blue($bm-color), opacity($foreground)), $background); } //-------------------------------- // Luminosity //-------------------------------- @function blend-luminosity ($foreground, $background) { $foreground-hsv: color-to-hsv($foreground); $background-hsv: color-to-hsv($background); $bm-hsv: nth($background-hsv, 1), nth($background-hsv, 2), nth($foreground-hsv, 3); $bm-color: hsv-to-color($bm-hsv); @return blend-normal(rgba(red($bm-color), green($bm-color), blue($bm-color), opacity($foreground)), $background); } //-------------------------------- // Saturation //-------------------------------- @function blend-saturation ($foreground, $background) { $foreground-hsv: color-to-hsv($foreground); $background-hsv: color-to-hsv($background); $bm-hsv: nth($background-hsv, 1), nth($foreground-hsv, 2), nth($background-hsv, 3); $bm-color: hsv-to-color($bm-hsv); @return blend-normal(rgba(red($bm-color), green($bm-color), blue($bm-color), opacity($foreground)), $background); } //-------------------------------- // Subtract //-------------------------------- @function blend-subtract ($foreground, $background) { $bm-red: max(red($background) - red($foreground), 0); $bm-green: max(green($background) - green($foreground), 0); $bm-blue: max(blue($background) - blue($foreground), 0); @return blend-normal(rgba($bm-red, $bm-green, $bm-blue, opacity($foreground)), $background); } //-------------------------------- // HSL and HSV //-------------------------------- // @see https://gist.github.com/1069204 @function hsv-to-hsl($h, $s: 0, $v: 0) { @if type-of($h) == 'list' { $v: nth($h, 3); $s: nth($h, 2); $h: nth($h, 1); } @if unit($h) == 'deg' { $h: 3.1415 * 2 * ($h / 360deg); } @if unit($s) == '%' { $s: 0 + ($s / 100%); } @if unit($v) == '%' { $v: 0 + ($v / 100%); } $ss: $s * $v; $ll: (2 - $s) * $v; @if $ll <= 1 and $ll != 0 { $ss: $ss / $ll; } @else if ($ll == 2) { $ss: 0; } @else { $ss: $ss / (2 - $ll); } $ll: $ll / 2; @return 360deg * $h / (3.1415 * 2), percentage(max(0, min(1, $ss))), percentage(max(0, min(1, $ll))); } @function hsl-to-hsv($h, $ss: 0, $ll: 0) { @if type-of($h) == 'list' { $ll: nth($h, 3); $ss: nth($h, 2); $h: nth($h, 1); } @else if type-of($h) == 'color' { $ll: lightness($h); $ss: saturation($h); $h: hue($h); } @if unit($h) == 'deg' { $h: 3.1415 * 2 * ($h / 360deg); } @if unit($ss) == '%' { $ss: 0 + ($ss / 100%); } @if unit($ll) == '%' { $ll: 0 + ($ll / 100%); } $ll: $ll * 2; @if $ll <= 1 { $ss: $ss * $ll; } @else { $ss: $ss * (2 - $ll); } $v: ($ll + $ss) / 2; $s: if($ll + $ss == 0, 0, (2 * $ss) / ($ll + $ss)); @return 360deg * $h / (3.1415 * 2), percentage(max(0, min(1, $s))), percentage(max(0, min(1, $v))); } @function color-to-hsv($color) { @return hsl-to-hsv($color); } @function hsv-to-color($h, $s: 0, $v: 0) { $hsl: hsv-to-hsl($h, $s, $v); @return hsl(nth($hsl, 1), nth($hsl, 2), nth($hsl, 3)); }f5b77d3d8e71223afb89597ba6fa4ea4ade0c962~dfsg/compass-blend-modes.gemspec0000644000000000000000000000156212506556244023730 0ustar rootroot# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "compass/blend-modes/version" Gem::Specification.new do |s| s.name = 'compass-blend-modes' s.version = Compass::BlendModes::VERSION s.platform = Gem::Platform::RUBY s.summary = "Using standard color blending functions in Sass." s.description = "Using standard color blending functions in Sass." s.homepage = "https://github.com/heygrady/scss-blend-modes" s.authors = ["Grady Kuhnline"] s.email = ["github@heygrady.net"] s.license = 'MIT' s.has_rdoc = false s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] s.add_dependency("compass") end