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]];
451 return [[
CPColor alloc] _initWithPatternImage:anImage];
462 return [[
CPColor alloc] _initWithCSSString: aString];
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) &&
739 var description = [
super description],
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}";
814 var CPColorComponentsKey =
@"CPColorComponentsKey",
815 CPColorPatternImageKey =
@"CPColorPatternImageKey";
826 if ([aCoder containsValueForKey:CPColorPatternImageKey])
827 return [
self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
829 return [
self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
839 [aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
841 [aCoder encodeObject:_components forKey:CPColorComponentsKey];
848 var hexCharacters =
"0123456789ABCDEF";
854 var hexToRGB =
function(hex)
857 hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
862 hex = hex.toUpperCase();
864 for (var i = 0; i < hex.length; i++)
865 if (hexCharacters.indexOf(hex.charAt(i)) == -1)
868 var red = (hexCharacters.indexOf(hex.charAt(0)) * 16 + hexCharacters.indexOf(hex.charAt(1))) / 255.0,
869 green = (hexCharacters.indexOf(hex.charAt(2)) * 16 + hexCharacters.indexOf(hex.charAt(3))) / 255.0,
870 blue = (hexCharacters.indexOf(hex.charAt(4)) * 16 + hexCharacters.indexOf(hex.charAt(5))) / 255.0;
872 return [red, green, blue, 1.0];
875 var rgbToHex =
function(r,g,b)
877 return byteToHex(r) + byteToHex(g) + byteToHex(b);
880 var byteToHex =
function(n)
885 n = FLOOR(MIN(255, MAX(0, 256 * n)));
887 return hexCharacters.charAt((n - n % 16) / 16) +
888 hexCharacters.charAt(n % 16);
1110 function CPColorWithImages()
1116 args = Array.prototype.slice.apply(arguments);
1118 if (typeof(args[args.length - 1]) ===
"function")
1119 imageFactory = args.pop();
1121 switch (args.length)
1124 return imageFromSlices(args[0], isVertical, imageFactory);
1128 if (typeof(args[0]) ===
"string")
1129 return patternColorsFromPattern.call(
this, args[0], args[1], imageFactory);
1131 return imageFromSlices(args[0], args[1], imageFactory);
1138 throw(
"ERROR: Invalid argument count: " + args.length);
1142 var imageFromSlices =
function(slices, isVertical, imageFactory)
1144 var imageSlices = [];
1146 for (var i = 0; i < slices.length; ++i)
1148 var slice = slices[i];
1150 imageSlices.push(slice ? imageFactory(slice[0], slice[1], slice[2], slice[3]) : nil);
1153 switch (slices.length)
1162 throw(
"ERROR: Invalid number of image slices: " + slices.length);
1166 var patternColorsFromPattern =
function(pattern, attributes, imageFactory)
1168 if (pattern.match(/^.*\{[^}]+\}/))
1170 var
width = attributes["width"],
1171 height = attributes["height"],
1172 separator = attributes["separator"] ||
"-",
1173 orientation = attributes["orientation"],
1181 if (pattern.indexOf(
"{position}") < 0)
1182 throw(
"ERROR: Pattern strings must have a {position} placeholder (\"" + pattern +
"\")");
1184 if (orientation === undefined)
1188 if (attributes[
"centerIsNil"] !== undefined)
1189 centerIsNil = attributes["centerIsNil"];
1194 isVertical = orientation === PatternIsVertical;
1198 if (attributes[
"centerHeight"])
1199 centerWidthHeight = attributes["centerHeight"];
1203 if (attributes[
"centerWidth"])
1204 centerWidthHeight = attributes["centerWidth"];
1208 if (attributes[
"rightWidth"])
1209 rightWidth = attributes["rightWidth"];
1211 if (attributes[
"bottomHeight"])
1212 bottomHeight = attributes["bottomHeight"];
1214 var positions = attributes["positions"] ||
"@",
1220 if (positions ===
"@")
1223 positions = ["top", "center", "bottom"];
1225 positions = ["left", "center", "right"];
1227 else if (positions ===
"#")
1228 positions = ["0", "1", "2"];
1230 throw(
"ERROR: Invalid positions: " + positions)
1234 if (positions ===
"@" || positions ===
"abbrev")
1235 positions = ["top-left", "top", "top-right", "left", "center", "right", "bottom-left", "bottom", "bottom-right"];
1236 else if (positions ===
"full")
1237 positions = ["top-left", "top-center", "top-right", "center-left", "center-center", "center-right", "bottom-left", "bottom-center", "bottom-right"];
1238 else if (positions ===
"#")
1239 positions = ["0", "1", "2", "3", "4", "5", "6", "7", "8"];
1241 throw(
"ERROR: Invalid positions: " + positions)
1245 if (pattern.indexOf(
"{state}") >= 0)
1247 states = attributes["states"];
1250 throw(
"ERROR: {state} placeholder in the pattern (\"" + pattern +
"\") but no states item in the attributes");
1254 if (pattern.indexOf(
"{style}") >= 0)
1256 styles = attributes["styles"];
1259 throw(
"ERROR: {style} placeholder in the pattern (\"" + pattern +
"\") but no styles item in the attributes");
1263 var placeholder =
"{position}",
1264 pos = pattern.indexOf(placeholder),
1267 for (i = 0; i < positions.length; ++i)
1268 positions[i] = pattern.replace(placeholder, pos === 0 ? positions[i] + separator : separator + positions[i]);
1270 var slices = positions,
1277 placeholder =
"{state}";
1278 pos = pattern.indexOf(placeholder);
1281 for (i = 0; i < states.length; ++i)
1283 var state = states[i];
1285 sep = state ? separator :
"";
1287 object[key] = slices.slice(0);
1288 replacePlaceholderInArray(
object[key], placeholder, pos === 0 ? state + sep : sep + state);
1294 placeholder =
"{style}";
1295 pos = pattern.indexOf(placeholder);
1297 var styleObject = {};
1299 for (i = 0; i < styles.length; ++i)
1301 var style = styles[i];
1303 sep = style ? separator :
"";
1307 styleObject[key] = cloneObject(
object);
1308 replacePlaceholderInObject(styleObject[key], placeholder, pos === 0 ? style + sep : sep + style);
1312 styleObject[key] = slices.slice(0);
1313 replacePlaceholderInArray(styleObject[key], placeholder, pos === 0 ? style + sep : sep + style);
1317 object = styleObject;
1320 if (styles || states)
1323 makeThreePartSlicesFromObject(
object, width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1325 makeNinePartSlicesFromObject(
object, width, height, rightWidth, bottomHeight, centerIsNil);
1327 makeImagesFromObject(
object, isVertical, imageFactory);
1333 makeThreePartSlicesFromArray(
object, width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1335 makeNinePartSlicesFromArray(
object, width, height, rightWidth, bottomHeight, centerIsNil);
1337 return imageFromSlices(
object, isVertical, imageFactory);
1341 throw(
"ERROR: No placeholders in slice pattern (\"" + pattern +
"\")");
1344 var replacePlaceholderInArray =
function(array, find, replacement)
1346 for (var i = 0; i < array.length; ++i)
1347 array[i] = array[i].replace(find, replacement);
1350 var replacePlaceholderInObject =
function(object, find, replacement)
1352 for (var key in
object)
1353 if (
object.hasOwnProperty(key))
1354 if (
object[key].constructor === Array)
1355 replacePlaceholderInArray(
object[key], find, replacement);
1357 replacePlaceholderInObject(
object[key], find, replacement);
1360 var cloneObject =
function(object)
1364 for (var key in
object)
1365 if (
object.hasOwnProperty(key))
1366 if (
object[key].constructor === Array)
1367 clone[key] =
object[key].slice(0);
1368 else if (typeof(
object[key]) ===
"object")
1369 clone[key] = cloneObject(
object[key]);
1371 clone[key] =
object[key];
1376 var makeThreePartSlicesFromObject =
function(object,
width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical)
1378 for (var key in
object)
1379 if (
object.hasOwnProperty(key))
1380 if (
object[key].constructor === Array)
1381 makeThreePartSlicesFromArray(
object[key], width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1383 makeThreePartSlicesFromObject(
object[key], width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical);
1386 var makeThreePartSlicesFromArray =
function(array,
width, height, centerWidthHeight, rightWidth, bottomHeight, isVertical)
1388 array[0] = [array[0], width, height];
1392 array[1] = [array[1], width, centerWidthHeight ? centerWidthHeight : 1.0];
1393 array[2] = [array[2], width, bottomHeight ? bottomHeight : height];
1397 array[1] = [array[1], centerWidthHeight ? centerWidthHeight : 1.0, height];
1398 array[2] = [array[2], rightWidth ? rightWidth : width, height];
1402 var makeNinePartSlicesFromObject =
function(object,
width, height, rightWidth, bottomHeight, centerIsNil)
1404 for (var key in
object)
1405 if (
object.hasOwnProperty(key))
1406 if (
object[key].constructor === Array)
1407 makeNinePartSlicesFromArray(
object[key], width, height, rightWidth, bottomHeight, centerIsNil);
1409 makeNinePartSlicesFromObject(
object[key], width, height, rightWidth, bottomHeight, centerIsNil);
1412 var makeNinePartSlicesFromArray =
function(array,
width, height, rightWidth, bottomHeight, centerIsNil)
1414 rightWidth = rightWidth ? rightWidth :
width;
1415 bottomHeight = bottomHeight ? bottomHeight : height;
1417 array[0] = [array[0], width, height];
1418 array[1] = [array[1], 1.0, height];
1419 array[2] = [array[2], rightWidth, height];
1420 array[3] = [array[3], width, 1.0];
1421 array[4] = centerIsNil ? nil : [array[4], 1.0, 1.0];
1422 array[5] = [array[5], rightWidth, 1.0];
1423 array[6] = [array[6], width, bottomHeight];
1424 array[7] = [array[7], 1.0, bottomHeight];
1425 array[8] = [array[8], rightWidth, bottomHeight];
1428 var makeImagesFromObject =
function(object, isVertical, imageFactory)
1430 for (var key in
object)
1431 if (
object.hasOwnProperty(key))
1432 if (
object[key].constructor === Array)
1433 object[key] = imageFromSlices(
object[key], isVertical, imageFactory);
1435 makeImagesFromObject(
object[key], isVertical, imageFactory);