39 var _redComponent = 0,
44 var _hueComponent = 0,
45 _saturationComponent = 1,
46 _brightnessComponent = 2;
97 + (
CPColor)colorWithRed:(
float)red green:(
float)green blue:(
float)blue alpha:(
float)alpha
99 return [[
CPColor alloc] _initWithRGBA:[MAX(0.0, MIN(1.0, red)), MAX(0.0, MIN(1.0, green)), MAX(0.0, MIN(1.0, blue)), MAX(0.0, MIN(1.0, alpha))]];
117 + (
CPColor)colorWithCalibratedRed:(
float)red green:(
float)green blue:(
float)blue alpha:(
float)alpha
132 + (
CPColor)colorWithWhite:(
float)white alpha:(
float)alpha
134 return [[
CPColor alloc] _initWithRGBA:[white, white, white, alpha]];
148 + (
CPColor)colorWithCalibratedWhite:(
float)white alpha:(
float)alpha
166 + (
CPColor)colorWithHue:(
float)hue saturation:(
float)saturation brightness:(
float)brightness
176 + (
CPColor)colorWithCalibratedHue:(
float)hue saturation:(
float)saturation brightness:(
float)brightness alpha:(
float)alpha
195 + (
CPColor)colorWithHue:(
float)hue saturation:(
float)saturation brightness:(
float)brightness alpha:(
float)alpha
198 hue = MAX(MIN(hue, 1.0), 0.0);
199 saturation = MAX(MIN(saturation, 1.0), 0.0);
200 brightness = MAX(MIN(brightness, 1.0), 0.0);
202 if (saturation === 0.0)
205 var f = (hue * 360) % 60,
206 p = (brightness * (1 - saturation)),
207 q = (brightness * (60 - saturation * f)) / 60,
208 t = (brightness * (60 - saturation * (60 - f))) / 60,
211 switch (FLOOR(hue * 6))
241 var rgba = hexToRGB(hex);
242 return rgba ? [[
CPColor alloc] _initWithRGBA: rgba] : null;
249 + (
CPColor)colorWithSRGBRed:(
float)red green:(
float)green blue:(
float)blue alpha:(
float)alpha
261 if (!cachedBlackColor)
262 cachedBlackColor = [[
CPColor alloc] _initWithRGBA:[0.0, 0.0, 0.0, 1.0]];
264 return cachedBlackColor;
272 if (!cachedBlueColor)
273 cachedBlueColor = [[
CPColor alloc] _initWithRGBA:[0.0, 0.0, 1.0, 1.0]];
275 return cachedBlueColor;
283 if (!cachedDarkGrayColor)
286 return cachedDarkGrayColor;
294 if (!cachedGrayColor)
297 return cachedGrayColor;
305 if (!cachedGreenColor)
306 cachedGreenColor = [[
CPColor alloc] _initWithRGBA:[0.0, 1.0, 0.0, 1.0]];
308 return cachedGreenColor;
316 if (!cachedLightGrayColor)
319 return cachedLightGrayColor;
328 cachedRedColor = [[
CPColor alloc] _initWithRGBA:[1.0, 0.0, 0.0, 1.0]];
330 return cachedRedColor;
338 if (!cachedWhiteColor)
339 cachedWhiteColor = [[
CPColor alloc] _initWithRGBA:[1.0, 1.0, 1.0, 1.0]];
341 return cachedWhiteColor;
349 if (!cachedYellowColor)
350 cachedYellowColor = [[
CPColor alloc] _initWithRGBA:[1.0, 1.0, 0.0, 1.0]];
352 return cachedYellowColor;
360 if (!cachedBrownColor)
361 cachedBrownColor = [[
CPColor alloc] _initWithRGBA:[0.6, 0.4, 0.2, 1.0]];
363 return cachedBrownColor;
371 if (!cachedCyanColor)
372 cachedCyanColor = [[
CPColor alloc] _initWithRGBA:[0.0, 1.0, 1.0, 1.0]];
374 return cachedCyanColor;
382 if (!cachedMagentaColor)
383 cachedMagentaColor = [[
CPColor alloc] _initWithRGBA:[1.0, 0.0, 1.0, 1.0]];
385 return cachedMagentaColor;
393 if (!cachedOrangeColor)
394 cachedOrangeColor = [[
CPColor alloc] _initWithRGBA:[1.0, 0.5, 0.0, 1.0]];
396 return cachedOrangeColor;
404 if (!cachedPurpleColor)
405 cachedPurpleColor = [[
CPColor alloc] _initWithRGBA:[0.5, 0.0, 0.5, 1.0]];
407 return cachedPurpleColor;
416 if (!cachedShadowColor)
417 cachedShadowColor = [[
CPColor alloc] _initWithRGBA:[0.0, 0.0, 0.0, 1.0 / 3.0]];
419 return cachedShadowColor;
428 if (!cachedClearColor)
431 return cachedClearColor;
436 return [[
CPColor alloc] _initWithRGBA:[0.22, 0.46, 0.84, 1.0]];
441 return [[
CPColor alloc] _initWithRGBA:[0.83, 0.83, 0.83, 1.0]];
466 - (id)_initWithCSSString:(
CPString)aString
473 var startingIndex = aString.indexOf(
"("),
474 parts = aString.substring(startingIndex + 1).split(
',');
477 parseInt(parts[0], 10) / 255.0,
478 parseInt(parts[1], 10) / 255.0,
479 parseInt(parts[2], 10) / 255.0,
480 parts[3] ? parseFloat(parts[3], 10) : 1.0
485 [
self _initCSSStringFromComponents];
491 - (id)_initWithRGBA:(CPArray)components
497 _components = components;
499 [
self _initCSSStringFromComponents];
505 - (void)_initCSSStringFromComponents
509 _cssString = (hasAlpha ?
"rgba(" :
"rgb(") +
510 parseInt(_components[0] * 255.0) + ", " +
511 parseInt(_components[1] * 255.0) + ", " +
512 parseInt(_components[2] * 255.0) +
513 (hasAlpha ? (", " + _components[3]) : "") + ")";
517 - (id)_initWithPatternImage:(
CPImage)anImage
523 _patternImage = anImage;
524 _cssString =
"url(\"" + [_patternImage filename] + "\")";
525 _components = [0.0, 0.0, 0.0, 1.0];
536 return _patternImage;
542 - (float)alphaComponent
544 return _components[3];
550 - (float)blueComponent
552 return _components[2];
558 - (float)greenComponent
560 return _components[1];
566 - (float)redComponent
568 return _components[0];
582 - (CPArray)components
594 - (
CPColor)colorWithAlphaComponent:(
float)anAlphaComponent
596 var components = _components.slice();
598 components[components.length - 1] = anAlphaComponent;
600 return [[[
self class] alloc] _initWithRGBA:components];
606 - (
CPColor)colorUsingColorSpaceName:(
id)aColorSpaceName
624 - (CPArray)hsbComponents
626 var red = ROUND(_components[_redComponent] * 255.0),
627 green = ROUND(_components[_greenComponent] * 255.0),
628 blue = ROUND(_components[_blueComponent] * 255.0);
630 var max = MAX(red, green, blue),
631 min = MIN(red, green, blue),
634 var brightness = max / 255.0,
635 saturation = (max != 0) ? delta / max : 0;
645 var rr = (max - red) / delta,
646 gr = (max - green) / delta,
647 br = (max - blue) / delta;
651 else if (green == max)
671 - (float)hueComponent
679 - (float)saturationComponent
687 - (float)brightnessComponent
711 return rgbToHex([
self redComponent], [
self greenComponent], [
self blueComponent]);
722 if (![aColor isKindOfClass:
CPColor])
725 if (_patternImage || [aColor patternImage])
731 return ROUND([
self redComponent] * 255.0) == ROUND([aColor redComponent] * 255.0) &&
732 ROUND([
self greenComponent] * 255.0) == ROUND([aColor greenComponent] * 255.0) &&
733 ROUND([
self blueComponent] * 255.0) == ROUND([aColor blueComponent] * 255.0) &&
743 return description +
" " + [
self cssString];
745 description +=
" {\n";
747 if ([patternImage isThreePartImage] || [patternImage isNinePartImage])
751 if ([patternImage isThreePartImage])
752 description +=
" orientation: " + ([
patternImage isVertical] ?
"vertical" :
"horizontal") +
",\n";
754 description +=
" patternImage (" + slices.
length +
" part): [\n";
756 for (var i = 0; i < slices.length; ++i)
758 var imgDescription = [slices[i] description] ||
"nil";
760 description += imgDescription.replace(/^/mg,
" ") +
",\n";
763 description = description.substr(0, description.length - 2) +
"\n ]\n}";
820 var CPColorComponentsKey =
@"CPColorComponentsKey",
821 CPColorPatternImageKey =
@"CPColorPatternImageKey";
832 if ([aCoder containsValueForKey:CPColorPatternImageKey])
833 return [
self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
835 return [
self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
845 [aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
847 [aCoder encodeObject:_components forKey:CPColorComponentsKey];
854 var hexCharacters =
"0123456789ABCDEF";
860 var hexToRGB =
function(hex)
863 hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
868 hex = hex.toUpperCase();
870 for (var i = 0; i < hex.length; i++)
871 if (hexCharacters.indexOf(hex.charAt(i)) == -1)
874 var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0,
875 green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0,
876 blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
878 return [red, green, blue, 1.0];
881 var rgbToHex =
function(r,g,b)
883 return byteToHex(r) + byteToHex(g) + byteToHex(b);
886 var byteToHex =
function(n)
891 n = FLOOR(MIN(255, MAX(0, 256 * n)));
893 return hexCharacters.charAt((n - n % 16) / 16) +
894 hexCharacters.charAt(n % 16);
1116 function CPColorWithImages()
1122 args = Array.prototype.slice.apply(arguments);
1124 if (typeof(args[args.length - 1]) ===
"function")
1125 imageFactory = args.pop();
1127 switch (args.length)
1130 return imageFromSlices(args[0], isVertical, imageFactory);
1134 if (typeof(args[0]) ===
"string")
1135 return patternColorsFromPattern.call(
this, args[0], args[1], imageFactory);
1137 return imageFromSlices(args[0], args[1], imageFactory);
1144 throw(
"ERROR: Invalid argument count: " + args.length);
1148 var imageFromSlices =
function(slices, isVertical, imageFactory)
1150 var imageSlices = [];
1152 for (var i = 0; i < slices.length; ++i)
1154 var slice = slices[i];
1156 imageSlices.push(slice ? imageFactory(slice[0], slice[1], slice[2], slice[3]) : nil);
1159 switch (slices.length)
1168 throw(
"ERROR: Invalid number of image slices: " + slices.length);
1172 var patternColorsFromPattern =
function(pattern, attributes, imageFactory)
1174 if (pattern.match(/^.*\{[^}]+\}/))
1176 var
width = attributes["width"],
1177 height = attributes["height"],
1178 separator = attributes["separator"] ||
"-",
1179 orientation = attributes["orientation"],
1187 if (pattern.indexOf(
"{position}") < 0)
1188 throw(
"ERROR: Pattern strings must have a {position} placeholder (\"" + pattern +
"\")");
1190 if (orientation === undefined)
1194 if (attributes[
"centerIsNil"] !== undefined)
1195 centerIsNil = attributes["centerIsNil"];
1200 isVertical = orientation === PatternIsVertical;
1204 if (attributes[
"centerHeight"])
1205 centerWidthHeight = attributes["centerHeight"];
1209 if (attributes[
"centerWidth"])
1210 centerWidthHeight = attributes["centerWidth"];
1214 if (attributes[
"rightWidth"])
1215 rightWidth = attributes["rightWidth"];
1217 if (attributes[
"bottomHeight"])
1218 bottomHeight = attributes["bottomHeight"];
1220 var positions = attributes["positions"] ||
"@",
1226 if (positions ===
"@")
1229 positions = ["top", "center", "bottom"];
1231 positions = ["left", "center", "right"];
1233 else if (positions ===
"#")
1234 positions = ["0", "1", "2"];
1236 throw(
"ERROR: Invalid positions: " + positions)
1240 if (positions ===
"@" || positions ===
"abbrev")
1241 positions = ["top-left", "top", "top-right", "left", "center", "right", "bottom-left", "bottom", "bottom-right"];
1242 else if (positions ===
"full")
1243 positions = ["top-left", "top-center", "top-right", "center-left", "center-center", "center-right", "bottom-left", "bottom-center", "bottom-right"];
1244 else if (positions ===
"#")
1245 positions = ["0", "1", "2", "3", "4", "5", "6", "7", "8"];
1247 throw(
"ERROR: Invalid positions: " + positions)
1251 if (pattern.indexOf(
"{state}") >= 0)
1253 states = attributes["states"];
1256 throw(
"ERROR: {state} placeholder in the pattern (\"" + pattern +
"\") but no states item in the attributes");
1260 if (pattern.indexOf(
"{style}") >= 0)
1262 styles = attributes["styles"];
1265 throw(
"ERROR: {style} placeholder in the pattern (\"" + pattern +
"\") but no styles item in the attributes");
1269 var placeholder =
"{position}",
1270 pos = pattern.indexOf(placeholder),
1273 for (i = 0; i < positions.length; ++i)
1274 positions[i] = pattern.replace(placeholder, pos === 0 ? positions[i] + separator : separator + positions[i]);
1276 var slices = positions,
1283 placeholder =
"{state}";
1284 pos = pattern.indexOf(placeholder);
1287 for (i = 0; i < states.length; ++i)
1289 var state = states[i];
1291 sep = state ? separator :
"";
1293 object[key] = slices.slice(0);
1294 replacePlaceholderInArray(
object[key], placeholder, pos === 0 ? state + sep : sep + state);
1300 placeholder =
"{style}";
1301 pos = pattern.indexOf(placeholder);
1303 var styleObject = {};
1305 for (i = 0; i < styles.length; ++i)
1307 var style = styles[i];
1309 sep = style ? separator :
"";
1313 styleObject[key] = cloneObject(
object);
1314 replacePlaceholderInObject(styleObject[key], placeholder, pos === 0 ? style + sep : sep + style);
1318 styleObject[key] = slices.slice(0);
1319 replacePlaceholderInArray(styleObject[key], placeholder, pos === 0 ? style + sep : sep + style);
1323 object = styleObject;
1326 if (styles || states)
1329 makeThreePartSlicesFromObject(
object, width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1331 makeNinePartSlicesFromObject(
object, width, height, rightWidth, bottomHeight, centerIsNil);
1333 makeImagesFromObject(
object, isVertical, imageFactory);
1339 makeThreePartSlicesFromArray(
object, width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1341 makeNinePartSlicesFromArray(
object, width, height, rightWidth, bottomHeight, centerIsNil);
1343 return imageFromSlices(
object, isVertical, imageFactory);
1347 throw(
"ERROR: No placeholders in slice pattern (\"" + pattern +
"\")");
1350 var replacePlaceholderInArray =
function(array, find, replacement)
1352 for (var i = 0; i < array.length; ++i)
1353 array[i] = array[i].replace(find, replacement);
1356 var replacePlaceholderInObject =
function(object, find, replacement)
1358 for (var key in
object)
1359 if (
object.hasOwnProperty(key))
1360 if (
object[key].constructor === Array)
1361 replacePlaceholderInArray(
object[key], find, replacement);
1363 replacePlaceholderInObject(
object[key], find, replacement);
1366 var cloneObject =
function(object)
1370 for (var key in
object)
1371 if (
object.hasOwnProperty(key))
1372 if (
object[key].constructor === Array)
1373 clone[key] =
object[key].slice(0);
1374 else if (typeof(
object[key]) ===
"object")
1375 clone[key] = cloneObject(
object[key]);
1377 clone[key] =
object[key];
1382 var makeThreePartSlicesFromObject =
function(object,
width, height, centerWidthHeight, rightWidth,
bottomHeight, isVertical)
1384 for (var key in
object)
1385 if (
object.hasOwnProperty(key))
1386 if (
object[key].constructor === Array)
1387 makeThreePartSlicesFromArray(
object[key], width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1389 makeThreePartSlicesFromObject(
object[key], width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1392 var makeThreePartSlicesFromArray =
function(array,
width, height, centerWidthHeight, rightWidth,
bottomHeight, isVertical)
1394 array[0] = [array[0], width, height];
1398 array[1] = [array[1], width, centerWidthHeight ? centerWidthHeight : 1.0];
1399 array[2] = [array[2], width, bottomHeight ? bottomHeight : height];
1403 array[1] = [array[1], centerWidthHeight ? centerWidthHeight : 1.0, height];
1404 array[2] = [array[2], rightWidth ? rightWidth : width, height];
1408 var makeNinePartSlicesFromObject =
function(object,
width, height, rightWidth,
bottomHeight, centerIsNil)
1410 for (var key in
object)
1411 if (
object.hasOwnProperty(key))
1412 if (
object[key].constructor === Array)
1413 makeNinePartSlicesFromArray(
object[key], width, height, rightWidth, bottomHeight, centerIsNil);
1415 makeNinePartSlicesFromObject(
object[key], width, height, rightWidth, bottomHeight, centerIsNil);
1418 var makeNinePartSlicesFromArray =
function(array,
width, height, rightWidth,
bottomHeight, centerIsNil)
1420 rightWidth = rightWidth ? rightWidth :
width;
1421 bottomHeight = bottomHeight ? bottomHeight : height;
1423 array[0] = [array[0], width, height];
1424 array[1] = [array[1], 1.0, height];
1425 array[2] = [array[2], rightWidth, height];
1426 array[3] = [array[3], width, 1.0];
1427 array[4] = centerIsNil ? nil : [array[4], 1.0, 1.0];
1428 array[5] = [array[5], rightWidth, 1.0];
1429 array[6] = [array[6], width, bottomHeight];
1430 array[7] = [array[7], 1.0, bottomHeight];
1431 array[8] = [array[8], rightWidth, bottomHeight];
1434 var makeImagesFromObject =
function(object, isVertical, imageFactory)
1436 for (var key in
object)
1437 if (
object.hasOwnProperty(key))
1438 if (
object[key].constructor === Array)
1439 object[key] = imageFromSlices(
object[key], isVertical, imageFactory);
1441 makeImagesFromObject(
object[key], isVertical, imageFactory);