1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27 28#if USE(ACCELERATED_COMPOSITING) 29#if ENABLE(CSS_FILTERS) 30 31#import "PlatformCAFilters.h" 32 33#import "BlockExceptions.h" 34#import "FloatConversion.h" 35#import "LengthFunctions.h" // This is a layering violation. 36#import "PlatformCALayer.h" 37#import <QuartzCore/QuartzCore.h> 38 39using namespace WebCore; 40 41#if USE_CA_FILTERS 42struct CAColorMatrix 43{ 44 float m11, m12, m13, m14, m15; 45 float m21, m22, m23, m24, m25; 46 float m31, m32, m33, m34, m35; 47 float m41, m42, m43, m44, m45; 48}; 49 50typedef struct CAColorMatrix CAColorMatrix; 51 52@interface NSValue (Details) 53+ (NSValue *)valueWithCAColorMatrix:(CAColorMatrix)t; 54@end 55 56@interface CAFilter : NSObject <NSCopying, NSMutableCopying, NSCoding> 57@end 58 59@interface CAFilter (Details) 60@property(copy) NSString *name; 61+ (CAFilter *)filterWithType:(NSString *)type; 62@end 63 64extern NSString * const kCAFilterColorMatrix; 65extern NSString * const kCAFilterColorMonochrome; 66extern NSString * const kCAFilterColorHueRotate; 67extern NSString * const kCAFilterColorSaturate; 68extern NSString * const kCAFilterGaussianBlur; 69#endif 70 71// FIXME: Should share these values with FilterEffectRenderer::build() (https://bugs.webkit.org/show_bug.cgi?id=76008). 72static double sepiaFullConstants[3][3] = { 73 { 0.393, 0.769, 0.189 }, 74 { 0.349, 0.686, 0.168 }, 75 { 0.272, 0.534, 0.131 } 76}; 77 78static double sepiaNoneConstants[3][3] = { 79 { 1, 0, 0 }, 80 { 0, 1, 0 }, 81 { 0, 0, 1 } 82}; 83 84void PlatformCAFilters::setFiltersOnLayer(PlatformCALayer* platformCALayer, const FilterOperations& filters) 85{ 86 CALayer* layer = platformCALayer->platformLayer(); 87 88 if (!filters.size()) { 89 BEGIN_BLOCK_OBJC_EXCEPTIONS 90 [layer setFilters:nil]; 91 // FIXME: this adds shadow properties to the layer even when it had none. 92 [layer setShadowOffset:CGSizeZero]; 93 [layer setShadowColor:nil]; 94 [layer setShadowRadius:0]; 95 [layer setShadowOpacity:0]; 96 END_BLOCK_OBJC_EXCEPTIONS 97 return; 98 } 99 100 // Assume filtersCanBeComposited was called and it returned true. 101 ASSERT(platformCALayer->filtersCanBeComposited(filters)); 102 103 BEGIN_BLOCK_OBJC_EXCEPTIONS 104 105 RetainPtr<NSMutableArray> array = adoptNS([[NSMutableArray alloc] init]); 106 107 for (unsigned i = 0; i < filters.size(); ++i) { 108 String filterName = String::format("filter_%d", i); 109 const FilterOperation* filterOperation = filters.at(i); 110 switch (filterOperation->getOperationType()) { 111 case FilterOperation::DEFAULT: 112 ASSERT_NOT_REACHED(); 113 break; 114 case FilterOperation::DROP_SHADOW: { 115 // FIXME: For now assume drop shadow is the last filter, put it on the layer. 116 // <rdar://problem/10959969> Handle case where drop-shadow is not the last filter. 117 const DropShadowFilterOperation* op = toDropShadowFilterOperation(filterOperation); 118 [layer setShadowOffset:CGSizeMake(op->x(), op->y())]; 119 120 CGFloat components[4]; 121 op->color().getRGBA(components[0], components[1], components[2], components[3]); 122 RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB()); 123 RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components)); 124 [layer setShadowColor:color.get()]; 125 [layer setShadowRadius:op->stdDeviation()]; 126 [layer setShadowOpacity:1]; 127 break; 128 } 129#if USE_CA_FILTERS 130 case FilterOperation::GRAYSCALE: { 131 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(filterOperation); 132 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorMonochrome]; 133 [filter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputAmount"]; 134 [filter setName:filterName]; 135 [array.get() addObject:filter]; 136 break; 137 } 138 case FilterOperation::SEPIA: { 139 RetainPtr<NSValue> colorMatrixValue = PlatformCAFilters::colorMatrixValueForFilter(filterOperation->getOperationType(), filterOperation); 140 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorMatrix]; 141 [filter setValue:colorMatrixValue.get() forKey:@"inputColorMatrix"]; 142 [filter setName:filterName]; 143 [array.get() addObject:filter]; 144 break; 145 } 146 case FilterOperation::SATURATE: { 147 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(filterOperation); 148 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorSaturate]; 149 [filter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputAmount"]; 150 [filter setName:filterName]; 151 [array.get() addObject:filter]; 152 break; 153 } 154 case FilterOperation::HUE_ROTATE: { 155 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(filterOperation); 156 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorHueRotate]; 157 [filter setValue:[NSNumber numberWithFloat:deg2rad(op->amount())] forKey:@"inputAngle"]; 158 [filter setName:@"hueRotate"]; 159 [filter setName:filterName]; 160 [array.get() addObject:filter]; 161 break; 162 } 163 case FilterOperation::INVERT: { 164 RetainPtr<NSValue> colorMatrixValue = PlatformCAFilters::colorMatrixValueForFilter(filterOperation->getOperationType(), filterOperation); 165 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorMatrix]; 166 [filter setValue:colorMatrixValue.get() forKey:@"inputColorMatrix"]; 167 [filter setName:filterName]; 168 [array.get() addObject:filter]; 169 break; 170 } 171 case FilterOperation::OPACITY: { 172 RetainPtr<NSValue> colorMatrixValue = PlatformCAFilters::colorMatrixValueForFilter(filterOperation->getOperationType(), filterOperation); 173 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorMatrix]; 174 [filter setValue:colorMatrixValue.get() forKey:@"inputColorMatrix"]; 175 [filter setName:filterName]; 176 [array.get() addObject:filter]; 177 break; 178 } 179 case FilterOperation::BRIGHTNESS: { 180 RetainPtr<NSValue> colorMatrixValue = PlatformCAFilters::colorMatrixValueForFilter(filterOperation->getOperationType(), filterOperation); 181 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorMatrix]; 182 [filter setValue:colorMatrixValue.get() forKey:@"inputColorMatrix"]; 183 [filter setName:filterName]; 184 [array.get() addObject:filter]; 185 break; 186 } 187 case FilterOperation::CONTRAST: { 188 RetainPtr<NSValue> colorMatrixValue = PlatformCAFilters::colorMatrixValueForFilter(filterOperation->getOperationType(), filterOperation); 189 CAFilter *filter = [CAFilter filterWithType:kCAFilterColorMatrix]; 190 [filter setValue:colorMatrixValue.get() forKey:@"inputColorMatrix"]; 191 [filter setName:filterName]; 192 [array.get() addObject:filter]; 193 break; 194 } 195 case FilterOperation::BLUR: { 196 const BlurFilterOperation* op = toBlurFilterOperation(filterOperation); 197 CAFilter *filter = [CAFilter filterWithType:kCAFilterGaussianBlur]; 198 [filter setValue:[NSNumber numberWithFloat:floatValueForLength(op->stdDeviation(), 0)] forKey:@"inputRadius"]; 199 [filter setName:filterName]; 200 [array.get() addObject:filter]; 201 break; 202 } 203#else 204 case FilterOperation::GRAYSCALE: { 205 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(filterOperation); 206 CIFilter* filter = [CIFilter filterWithName:@"CIColorMonochrome"]; 207 [filter setDefaults]; 208 [filter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputIntensity"]; 209 [filter setValue:[CIColor colorWithRed:0.67 green:0.67 blue:0.67] forKey:@"inputColor"]; // Color derived empirically to match zero saturation levels. 210 [filter setName:filterName]; 211 [array.get() addObject:filter]; 212 break; 213 } 214 case FilterOperation::SEPIA: { 215 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(filterOperation); 216 CIFilter* filter = [CIFilter filterWithName:@"CIColorMatrix"]; 217 [filter setDefaults]; 218 219 double t = op->amount(); 220 t = std::min(std::max(0.0, t), 1.0); 221 // FIXME: results don't match the software filter. 222 [filter setValue:[CIVector vectorWithX:WebCore::blend(sepiaNoneConstants[0][0], sepiaFullConstants[0][0], t) 223 Y:WebCore::blend(sepiaNoneConstants[0][1], sepiaFullConstants[0][1], t) 224 Z:WebCore::blend(sepiaNoneConstants[0][2], sepiaFullConstants[0][2], t) W:0] forKey:@"inputRVector"]; 225 [filter setValue:[CIVector vectorWithX:WebCore::blend(sepiaNoneConstants[1][0], sepiaFullConstants[1][0], t) 226 Y:WebCore::blend(sepiaNoneConstants[1][1], sepiaFullConstants[1][1], t) 227 Z:WebCore::blend(sepiaNoneConstants[1][2], sepiaFullConstants[1][2], t) W:0] forKey:@"inputGVector"]; 228 [filter setValue:[CIVector vectorWithX:WebCore::blend(sepiaNoneConstants[2][0], sepiaFullConstants[2][0], t) 229 Y:WebCore::blend(sepiaNoneConstants[2][1], sepiaFullConstants[2][1], t) 230 Z:WebCore::blend(sepiaNoneConstants[2][2], sepiaFullConstants[2][2], t) W:0] forKey:@"inputBVector"]; 231 [filter setName:filterName]; 232 [array.get() addObject:filter]; 233 break; 234 } 235 case FilterOperation::SATURATE: { 236 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(filterOperation); 237 CIFilter* filter = [CIFilter filterWithName:@"CIColorControls"]; 238 [filter setDefaults]; 239 [filter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputSaturation"]; 240 [filter setName:filterName]; 241 [array.get() addObject:filter]; 242 break; 243 } 244 case FilterOperation::HUE_ROTATE: { 245 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(filterOperation); 246 CIFilter* filter = [CIFilter filterWithName:@"CIHueAdjust"]; 247 [filter setDefaults]; 248 249 [filter setValue:[NSNumber numberWithFloat:deg2rad(op->amount())] forKey:@"inputAngle"]; 250 [filter setName:filterName]; 251 [array.get() addObject:filter]; 252 break; 253 } 254 case FilterOperation::INVERT: { 255 const BasicComponentTransferFilterOperation* op = toBasicComponentTransferFilterOperation(filterOperation); 256 CIFilter* filter = [CIFilter filterWithName:@"CIColorMatrix"]; 257 [filter setDefaults]; 258 259 double multiplier = 1 - op->amount() * 2; 260 261 // FIXME: the results of this filter look wrong. 262 [filter setValue:[CIVector vectorWithX:multiplier Y:0 Z:0 W:0] forKey:@"inputRVector"]; 263 [filter setValue:[CIVector vectorWithX:0 Y:multiplier Z:0 W:0] forKey:@"inputGVector"]; 264 [filter setValue:[CIVector vectorWithX:0 Y:0 Z:multiplier W:0] forKey:@"inputBVector"]; 265 [filter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:1] forKey:@"inputAVector"]; 266 [filter setValue:[CIVector vectorWithX:op->amount() Y:op->amount() Z:op->amount() W:0] forKey:@"inputBiasVector"]; 267 [filter setName:filterName]; 268 [array.get() addObject:filter]; 269 break; 270 } 271 case FilterOperation::OPACITY: { 272 const BasicComponentTransferFilterOperation* op = toBasicComponentTransferFilterOperation(filterOperation); 273 CIFilter* filter = [CIFilter filterWithName:@"CIColorMatrix"]; 274 [filter setDefaults]; 275 276 [filter setValue:[CIVector vectorWithX:1 Y:0 Z:0 W:0] forKey:@"inputRVector"]; 277 [filter setValue:[CIVector vectorWithX:0 Y:1 Z:0 W:0] forKey:@"inputGVector"]; 278 [filter setValue:[CIVector vectorWithX:0 Y:0 Z:1 W:0] forKey:@"inputBVector"]; 279 [filter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:op->amount()] forKey:@"inputAVector"]; 280 [filter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:0] forKey:@"inputBiasVector"]; 281 [filter setName:filterName]; 282 [array.get() addObject:filter]; 283 break; 284 } 285 case FilterOperation::BRIGHTNESS: { 286 const BasicComponentTransferFilterOperation* op = toBasicComponentTransferFilterOperation(filterOperation); 287 CIFilter* filter = [CIFilter filterWithName:@"CIColorMatrix"]; 288 [filter setDefaults]; 289 double amount = op->amount(); 290 291 [filter setValue:[CIVector vectorWithX:amount Y:0 Z:0 W:0] forKey:@"inputRVector"]; 292 [filter setValue:[CIVector vectorWithX:0 Y:amount Z:0 W:0] forKey:@"inputGVector"]; 293 [filter setValue:[CIVector vectorWithX:0 Y:0 Z:amount W:0] forKey:@"inputBVector"]; 294 [filter setName:filterName]; 295 [array.get() addObject:filter]; 296 break; 297 } 298 case FilterOperation::CONTRAST: { 299 const BasicComponentTransferFilterOperation* op = toBasicComponentTransferFilterOperation(filterOperation); 300 CIFilter* filter = [CIFilter filterWithName:@"CIColorControls"]; 301 [filter setDefaults]; 302 [filter setValue:[NSNumber numberWithFloat:op->amount()] forKey:@"inputContrast"]; 303 [filter setName:filterName]; 304 [array.get() addObject:filter]; 305 break; 306 } 307 case FilterOperation::BLUR: { 308 // FIXME: For now we ignore stdDeviationY. 309 const BlurFilterOperation* op = toBlurFilterOperation(filterOperation); 310 CIFilter* filter = [CIFilter filterWithName:@"CIGaussianBlur"]; 311 [filter setDefaults]; 312 [filter setValue:[NSNumber numberWithFloat:floatValueForLength(op->stdDeviation(), 0)] forKey:@"inputRadius"]; 313 [filter setName:filterName]; 314 [array.get() addObject:filter]; 315 break; 316 } 317#endif 318 case FilterOperation::PASSTHROUGH: 319 break; 320 default: 321 ASSERT(0); 322 break; 323 } 324 } 325 326 if ([array.get() count] > 0) 327 [layer setFilters:array.get()]; 328 329 END_BLOCK_OBJC_EXCEPTIONS 330} 331 332RetainPtr<NSValue> PlatformCAFilters::filterValueForOperation(const FilterOperation* operation, int internalFilterPropertyIndex) 333{ 334#if USE_CA_FILTERS 335 UNUSED_PARAM(internalFilterPropertyIndex); 336#endif 337 FilterOperation::OperationType type = operation->getOperationType(); 338 RetainPtr<id> value; 339 340 if (type == FilterOperation::DEFAULT) { 341 type = toDefaultFilterOperation(operation)->representedType(); 342 operation = nullptr; 343 } 344 345 switch (type) { 346 case FilterOperation::DEFAULT: 347 ASSERT_NOT_REACHED(); 348 break; 349 case FilterOperation::GRAYSCALE: { 350 // CIFilter: inputIntensity 351 // CAFilter: inputAmount 352 double amount = 0; 353 if (operation) 354 amount = toBasicColorMatrixFilterOperation(operation)->amount(); 355 356 value = [NSNumber numberWithDouble:amount]; 357 break; 358 } 359 case FilterOperation::SEPIA: { 360#if USE_CA_FILTERS 361 // CAFilter: inputColorMatrix 362 value = PlatformCAFilters::colorMatrixValueForFilter(type, operation); 363#else 364 // CIFilter: inputRVector, inputGVector, inputBVector 365 double amount = 0; 366 if (operation) { 367 const BasicColorMatrixFilterOperation* op = toBasicColorMatrixFilterOperation(operation); 368 amount = op->amount(); 369 } 370 371 CIVector* rowVector = 0; 372 switch (internalFilterPropertyIndex) { 373 case 0: rowVector = [[CIVector alloc] initWithX:WebCore::blend(sepiaNoneConstants[0][0], sepiaFullConstants[0][0], amount) 374 Y:WebCore::blend(sepiaNoneConstants[0][1], sepiaFullConstants[0][1], amount) 375 Z:WebCore::blend(sepiaNoneConstants[0][2], sepiaFullConstants[0][2], amount) W:0]; break; // inputRVector 376 case 1: rowVector = [[CIVector alloc] initWithX:WebCore::blend(sepiaNoneConstants[1][0], sepiaFullConstants[1][0], amount) 377 Y:WebCore::blend(sepiaNoneConstants[1][1], sepiaFullConstants[1][1], amount) 378 Z:WebCore::blend(sepiaNoneConstants[1][2], sepiaFullConstants[1][2], amount) W:0]; break; // inputGVector 379 case 2: rowVector = [[CIVector alloc] initWithX:WebCore::blend(sepiaNoneConstants[2][0], sepiaFullConstants[2][0], amount) 380 Y:WebCore::blend(sepiaNoneConstants[2][1], sepiaFullConstants[2][1], amount) 381 Z:WebCore::blend(sepiaNoneConstants[2][2], sepiaFullConstants[2][2], amount) W:0]; break; // inputBVector 382 } 383 value = adoptNS(rowVector); 384#endif 385 break; 386 } 387 case FilterOperation::SATURATE: { 388 // CIFilter: inputSaturation 389 // CAFilter: inputAmount 390 double amount = 1; 391 if (operation) 392 amount = toBasicColorMatrixFilterOperation(operation)->amount(); 393 394 value = [NSNumber numberWithDouble:amount]; 395 break; 396 } 397 case FilterOperation::HUE_ROTATE: { 398 // Hue rotate CIFilter: inputAngle 399 // Hue rotate CAFilter: inputAngle 400 double amount = 0; 401 if (operation) 402 amount = toBasicColorMatrixFilterOperation(operation)->amount(); 403 404 amount = deg2rad(amount); 405 value = [NSNumber numberWithDouble:amount]; 406 break; 407 } 408 case FilterOperation::INVERT: { 409#if USE_CA_FILTERS 410 // CAFilter: inputColorMatrix 411 value = PlatformCAFilters::colorMatrixValueForFilter(type, operation); 412#else 413 // CIFilter: inputRVector, inputGVector, inputBVector, inputBiasVector 414 double amount = 0; 415 if (operation) 416 amount = toBasicComponentTransferFilterOperation(operation)->amount(); 417 418 double multiplier = 1 - amount * 2; 419 420 // The color matrix animation for invert does a scale of each color component by a value that goes from 421 // 1 (when amount is 0) to -1 (when amount is 1). Then the color values are offset by amount. This has the 422 // effect of performing the operation: c' = c * -1 + 1, which inverts the color. 423 CIVector* rowVector = 0; 424 switch (internalFilterPropertyIndex) { 425 case 0: rowVector = [[CIVector alloc] initWithX:multiplier Y:0 Z:0 W:0]; break; // inputRVector 426 case 1: rowVector = [[CIVector alloc] initWithX:0 Y:multiplier Z:0 W:0]; break; // inputGVector 427 case 2: rowVector = [[CIVector alloc] initWithX:0 Y:0 Z:multiplier W:0]; break; // inputBVector 428 case 3: rowVector = [[CIVector alloc] initWithX:amount Y:amount Z:amount W:0]; break; // inputBiasVector 429 } 430 value = adoptNS(rowVector); 431#endif 432 break; 433 } 434 case FilterOperation::OPACITY: { 435#if USE_CA_FILTERS 436 // Opacity CAFilter: inputColorMatrix 437 value = PlatformCAFilters::colorMatrixValueForFilter(type, operation); 438#else 439 // Opacity CIFilter: inputAVector 440 double amount = 1; 441 if (operation) 442 amount = toBasicComponentTransferFilterOperation(operation)->amount(); 443 444 value = adoptNS([[CIVector alloc] initWithX:0 Y:0 Z:0 W:amount]); 445#endif 446 break; 447 } 448 449 case FilterOperation::BRIGHTNESS: { 450#if USE_CA_FILTERS 451 // Brightness CAFilter: inputColorMatrix 452 value = PlatformCAFilters::colorMatrixValueForFilter(type, operation); 453#else 454 // Brightness CIFilter: inputColorMatrix 455 double amount = 1; 456 if (operation) 457 amount = toBasicComponentTransferFilterOperation(operation)->amount(); 458 459 CIVector* rowVector = 0; 460 switch (internalFilterPropertyIndex) { 461 case 0: rowVector = [[CIVector alloc] initWithX:amount Y:0 Z:0 W:0]; break; // inputRVector 462 case 1: rowVector = [[CIVector alloc] initWithX:0 Y:amount Z:0 W:0]; break; // inputGVector 463 case 2: rowVector = [[CIVector alloc] initWithX:0 Y:0 Z:amount W:0]; break; // inputBVector 464 } 465 value = adoptNS(rowVector); 466#endif 467 break; 468 } 469 470 case FilterOperation::CONTRAST: { 471#if USE_CA_FILTERS 472 // Contrast CAFilter: inputColorMatrix 473 value = PlatformCAFilters::colorMatrixValueForFilter(type, operation); 474#else 475 // Contrast CIFilter: inputContrast 476 double amount = 1; 477 if (operation) 478 amount = toBasicComponentTransferFilterOperation(operation)->amount(); 479 480 value = [NSNumber numberWithDouble:amount]; 481#endif 482 break; 483 } 484 case FilterOperation::BLUR: { 485 // CIFilter: inputRadius 486 // CAFilter: inputRadius 487 double amount = 0; 488 if (operation) 489 amount = floatValueForLength(toBlurFilterOperation(operation)->stdDeviation(), 0); 490 491 value = [NSNumber numberWithDouble:amount]; 492 break; 493 } 494 default: 495 break; 496 } 497 498 return value; 499} 500 501#if USE_CA_FILTERS 502RetainPtr<NSValue> PlatformCAFilters::colorMatrixValueForFilter(FilterOperation::OperationType type, const FilterOperation* filterOperation) 503{ 504 switch (type) { 505 case FilterOperation::SEPIA: { 506 double t = filterOperation ? toBasicColorMatrixFilterOperation(filterOperation)->amount() : 0; 507 t = std::min(std::max(0.0, t), 1.0); 508 CAColorMatrix colorMatrix = { 509 static_cast<float>(WebCore::blend(sepiaNoneConstants[0][0], sepiaFullConstants[0][0], t)), 510 static_cast<float>(WebCore::blend(sepiaNoneConstants[0][1], sepiaFullConstants[0][1], t)), 511 static_cast<float>(WebCore::blend(sepiaNoneConstants[0][2], sepiaFullConstants[0][2], t)), 0, 0, 512 513 static_cast<float>(WebCore::blend(sepiaNoneConstants[1][0], sepiaFullConstants[1][0], t)), 514 static_cast<float>(WebCore::blend(sepiaNoneConstants[1][1], sepiaFullConstants[1][1], t)), 515 static_cast<float>(WebCore::blend(sepiaNoneConstants[1][2], sepiaFullConstants[1][2], t)), 0, 0, 516 517 static_cast<float>(WebCore::blend(sepiaNoneConstants[2][0], sepiaFullConstants[2][0], t)), 518 static_cast<float>(WebCore::blend(sepiaNoneConstants[2][1], sepiaFullConstants[2][1], t)), 519 static_cast<float>(WebCore::blend(sepiaNoneConstants[2][2], sepiaFullConstants[2][2], t)), 0, 0, 520 0, 0, 0, 1, 0 521 }; 522 return [NSValue valueWithCAColorMatrix:colorMatrix]; 523 } 524 case FilterOperation::INVERT: { 525 float amount = filterOperation ? toBasicComponentTransferFilterOperation(filterOperation)->amount() : 0; 526 float multiplier = 1 - amount * 2; 527 CAColorMatrix colorMatrix = { 528 multiplier, 0, 0, 0, amount, 529 0, multiplier, 0, 0, amount, 530 0, 0, multiplier, 0, amount, 531 0, 0, 0, 1, 0 532 }; 533 return [NSValue valueWithCAColorMatrix:colorMatrix]; 534 } 535 case FilterOperation::OPACITY: { 536 float amount = filterOperation ? toBasicComponentTransferFilterOperation(filterOperation)->amount() : 1; 537 CAColorMatrix colorMatrix = { 538 1, 0, 0, 0, 0, 539 0, 1, 0, 0, 0, 540 0, 0, 1, 0, 0, 541 0, 0, 0, amount, 0 542 }; 543 return [NSValue valueWithCAColorMatrix:colorMatrix]; 544 } 545 case FilterOperation::CONTRAST: { 546 float amount = filterOperation ? toBasicComponentTransferFilterOperation(filterOperation)->amount() : 1; 547 float intercept = -0.5 * amount + 0.5; 548 CAColorMatrix colorMatrix = { 549 amount, 0, 0, 0, intercept, 550 0, amount, 0, 0, intercept, 551 0, 0, amount, 0, intercept, 552 0, 0, 0, 1, 0 553 }; 554 return [NSValue valueWithCAColorMatrix:colorMatrix]; 555 } 556 case FilterOperation::BRIGHTNESS: { 557 float amount = filterOperation ? toBasicComponentTransferFilterOperation(filterOperation)->amount() : 1; 558 CAColorMatrix colorMatrix = { 559 amount, 0, 0, 0, 0, 560 0, amount, 0, 0, 0, 561 0, 0, amount, 0, 0, 562 0, 0, 0, 1, 0 563 }; 564 return [NSValue valueWithCAColorMatrix:colorMatrix]; 565 } 566 default: 567 ASSERT_NOT_REACHED(); 568 return 0; 569 } 570} 571#endif 572 573int PlatformCAFilters::numAnimatedFilterProperties(FilterOperation::OperationType type) 574{ 575#if USE_CA_FILTERS 576 switch (type) { 577 case FilterOperation::GRAYSCALE: return 1; 578 case FilterOperation::SEPIA: return 1; 579 case FilterOperation::SATURATE: return 1; 580 case FilterOperation::HUE_ROTATE: return 1; 581 case FilterOperation::INVERT: return 1; 582 case FilterOperation::OPACITY: return 1; 583 case FilterOperation::BRIGHTNESS: return 1; 584 case FilterOperation::CONTRAST: return 1; 585 case FilterOperation::BLUR: return 1; 586 default: return 0; 587 } 588#else 589 switch (type) { 590 case FilterOperation::GRAYSCALE: return 1; 591 case FilterOperation::SEPIA: return 3; 592 case FilterOperation::SATURATE: return 1; 593 case FilterOperation::HUE_ROTATE: return 1; 594 case FilterOperation::INVERT: return 4; 595 case FilterOperation::OPACITY: return 1; 596 case FilterOperation::BRIGHTNESS: return 3; 597 case FilterOperation::CONTRAST: return 1; 598 case FilterOperation::BLUR: return 1; 599 default: return 0; 600 } 601#endif 602} 603 604const char* PlatformCAFilters::animatedFilterPropertyName(FilterOperation::OperationType type, int internalFilterPropertyIndex) 605{ 606#if USE_CA_FILTERS 607 UNUSED_PARAM(internalFilterPropertyIndex); 608 switch (type) { 609 case FilterOperation::GRAYSCALE: return "inputAmount"; 610 case FilterOperation::SEPIA:return "inputColorMatrix"; 611 case FilterOperation::SATURATE: return "inputAmount"; 612 case FilterOperation::HUE_ROTATE: return "inputAngle"; 613 case FilterOperation::INVERT: return "inputColorMatrix"; 614 case FilterOperation::OPACITY: return "inputColorMatrix"; 615 case FilterOperation::BRIGHTNESS: return "inputColorMatrix"; 616 case FilterOperation::CONTRAST: return "inputColorMatrix"; 617 case FilterOperation::BLUR: return "inputRadius"; 618 default: return ""; 619 } 620#else 621 switch (type) { 622 case FilterOperation::GRAYSCALE: return "inputIntensity"; 623 case FilterOperation::SEPIA: 624 case FilterOperation::BRIGHTNESS: 625 switch (internalFilterPropertyIndex) { 626 case 0: return "inputRVector"; 627 case 1: return "inputGVector"; 628 case 2: return "inputBVector"; 629 default: return ""; 630 } 631 case FilterOperation::SATURATE: return "inputSaturation"; 632 case FilterOperation::HUE_ROTATE: return "inputAngle"; 633 case FilterOperation::INVERT: 634 switch (internalFilterPropertyIndex) { 635 case 0: return "inputRVector"; 636 case 1: return "inputGVector"; 637 case 2: return "inputBVector"; 638 case 3: return "inputBiasVector"; 639 default: return ""; 640 } 641 case FilterOperation::OPACITY: return "inputAVector"; 642 case FilterOperation::CONTRAST: return "inputContrast"; 643 case FilterOperation::BLUR: return "inputRadius"; 644 default: return ""; 645 } 646#endif 647} 648 649#endif // ENABLE(CSS_FILTERS) 650#endif // USE(ACCELERATED_COMPOSITING) 651