RESOLVED FIXED 215956
CoreImage Implementation of CSS Filters invert(), opacity(), brightness(), contrast()
https://bugs.webkit.org/show_bug.cgi?id=215956
Summary CoreImage Implementation of CSS Filters invert(), opacity(), brightness(), co...
frankhome61
Reported 2020-08-28 16:28:35 PDT
Implementing invert(), opacity(), brightness(), contrast(), which are based on FEComponentTransfer using CoreImage
Attachments
Patch (16.49 KB, patch)
2020-08-31 13:52 PDT, frankhome61
no flags
Patch (16.50 KB, patch)
2020-08-31 14:11 PDT, frankhome61
no flags
Patch (8.04 KB, patch)
2020-09-03 15:23 PDT, frankhome61
no flags
Patch (15.69 KB, patch)
2020-09-03 16:08 PDT, frankhome61
no flags
Patch (14.96 KB, patch)
2020-09-04 11:37 PDT, frankhome61
darin: review+
Ready for commit (14.90 KB, patch)
2020-09-04 13:39 PDT, frankhome61
no flags
Ready for commit (14.92 KB, patch)
2020-09-04 14:16 PDT, frankhome61
no flags
Patch (missing reviewer name) (14.93 KB, patch)
2020-09-04 14:48 PDT, frankhome61
no flags
Ready for Commit (14.92 KB, patch)
2020-09-08 11:46 PDT, frankhome61
no flags
Radar WebKit Bug Importer
Comment 1 2020-08-28 16:29:01 PDT
frankhome61
Comment 2 2020-08-31 13:52:52 PDT
frankhome61
Comment 3 2020-08-31 13:55:11 PDT
This patch depends on path 213673, so it will temporarily contain changes already introduced in 213673. Once 213673 is landed, the only changes in this patch should only be the two additional functions, - feComponentTransferLinearFunctionImage - componentTransferLinearFunctionOnly
frankhome61
Comment 4 2020-08-31 14:11:34 PDT
frankhome61
Comment 5 2020-09-03 15:23:08 PDT
Darin Adler
Comment 6 2020-09-03 16:03:16 PDT
Comment on attachment 407920 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=407920&action=review > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.h:31 > +#import "FEComponentTransfer.h" Could forward declare this instead of including it in the header. Nothing in the header requires the full definition. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.h:62 > + static bool isNullOrLinearComponentTransferFunction(const FEComponentTransfer&); Could just make this a free function in the .cpp file instead of a static member function. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:72 > + if (effect.redFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > + && effect.redFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > + return false; > + if (effect.greenFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > + && effect.greenFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > + return false; > + if (effect.blueFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > + && effect.blueFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > + return false; > + if (effect.alphaFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > + && effect.alphaFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > + return false; > + return true; This very wordy thing could be cut down to size with a lambda: auto isNullOrLinear = [] (const ComponentTransferFunction& function) { return function.type == FECOMPONENTTRANSFER_TYPE_UNKNOWN || function.type == FECOMPONENTTRANSFER_TYPE_LINEAR; }; return isNullOrLinear(effect.redFunction()) && isNullOrLinear(effect.greenFunction()) && isNullOrLinear(effect.blueFunction()) && isNullOrLinear(effect.alphaFunction()); I think the && is also easier to read than the backwards logic and early returns. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:243 > + if (!isNullOrLinearComponentTransferFunction(effect)) > + return nullptr; Seems like this should be an assertion instead of a "return null" thing. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:245 > + > + Extra blank line here. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:247 > + CIFilter* componentTransferFilter = [CIFilter filterWithName:@"CIColorPolynomial"]; auto Also how about using a shorter local variable name, like "filter"? The function is a narrow enough scope that the meaning of the name is clear enough, I think. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:252 > + ComponentTransferFunction redFunction = effect.redFunction(); > + ComponentTransferFunction greenFunction = effect.greenFunction(); > + ComponentTransferFunction blueFunction = effect.blueFunction(); > + ComponentTransferFunction alphaFunction = effect.alphaFunction(); auto& There is no need to copy these functions out of the effect object. Could also consider shorter names. I think we could call the locals just red, green, blue, alpha given the scope of a short function like this. No real ambiguity about what they mean. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:263 > + if (redFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > + [componentTransferFilter setValue:[CIVector vectorWithX:redFunction.intercept Y:redFunction.slope Z:0 W:0] forKey:@"inputRedCoefficients"]; > + if (greenFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > + [componentTransferFilter setValue:[CIVector vectorWithX:greenFunction.intercept Y:greenFunction.slope Z:0 W:0] forKey:@"inputGreenCoefficients"]; > + if (blueFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > + [componentTransferFilter setValue:[CIVector vectorWithX:blueFunction.intercept Y:blueFunction.slope Z:0 W:0] forKey:@"inputBlueCoefficients"]; > + if (alphaFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > + [componentTransferFilter setValue:[CIVector vectorWithX:alphaFunction.intercept Y:alphaFunction.slope Z:0 W:0] forKey:@"inputAlphaCoefficients"]; Code can be simplified with a lambda: auto setCoefficients = [&] (NSString *key, const ComponentFunction& function) { if (function.type == FECOMPONENTTRANSFER_TYPE_LINEAR) [componentTransferFilter setValue:[CIVector vectorWithX:function.intercept Y:function.slope Z:0 W:0] forKey:key]; }; setCoefficients(@"inputRedCoefficients", effect.redFunction()); setCoefficients(@"inputGreenCoefficients", effect.greenFunction()); setCoefficients(@"inputBlueCoefficients", effect.blueFunction()); setCoefficients(@"inputAlphaCoefficients", effect.alphaFunction()); This replaces 12 lines of more hard-to-read code.
frankhome61
Comment 7 2020-09-03 16:08:18 PDT
Darin Adler
Comment 8 2020-09-03 16:10:29 PDT
Comment on attachment 407926 [details] Patch Please check out my comments on the earlier version of the patch.
frankhome61
Comment 9 2020-09-03 16:11:57 PDT
(In reply to Darin Adler from comment #8) > Comment on attachment 407926 [details] > Patch > > Please check out my comments on the earlier version of the patch. Oh whoops just saw the comments, I immediately obsoleted the one you commented on because I forgot to include the test files. Working on it right now.
frankhome61
Comment 10 2020-09-04 10:24:28 PDT
(In reply to Darin Adler from comment #6) > Comment on attachment 407920 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=407920&action=review > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.h:31 > > +#import "FEComponentTransfer.h" > > Could forward declare this instead of including it in the header. Nothing in > the header requires the full definition. > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.h:62 > > + static bool isNullOrLinearComponentTransferFunction(const FEComponentTransfer&); > > Could just make this a free function in the .cpp file instead of a static > member function. > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:72 > > + if (effect.redFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > > + && effect.redFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > > + return false; > > + if (effect.greenFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > > + && effect.greenFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > > + return false; > > + if (effect.blueFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > > + && effect.blueFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > > + return false; > > + if (effect.alphaFunction().type != FECOMPONENTTRANSFER_TYPE_UNKNOWN > > + && effect.alphaFunction().type != FECOMPONENTTRANSFER_TYPE_LINEAR) > > + return false; > > + return true; > > This very wordy thing could be cut down to size with a lambda: > > auto isNullOrLinear = [] (const ComponentTransferFunction& function) { > return function.type == FECOMPONENTTRANSFER_TYPE_UNKNOWN || > function.type == FECOMPONENTTRANSFER_TYPE_LINEAR; > }; > return isNullOrLinear(effect.redFunction()) && > isNullOrLinear(effect.greenFunction()) > && isNullOrLinear(effect.blueFunction()) && > isNullOrLinear(effect.alphaFunction()); > > I think the && is also easier to read than the backwards logic and early > returns. > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:243 > > + if (!isNullOrLinearComponentTransferFunction(effect)) > > + return nullptr; > > Seems like this should be an assertion instead of a "return null" thing. > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:245 > > + > > + > > Extra blank line here. > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:247 > > + CIFilter* componentTransferFilter = [CIFilter filterWithName:@"CIColorPolynomial"]; > > auto > > Also how about using a shorter local variable name, like "filter"? The > function is a narrow enough scope that the meaning of the name is clear > enough, I think. > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:252 > > + ComponentTransferFunction redFunction = effect.redFunction(); > > + ComponentTransferFunction greenFunction = effect.greenFunction(); > > + ComponentTransferFunction blueFunction = effect.blueFunction(); > > + ComponentTransferFunction alphaFunction = effect.alphaFunction(); > > auto& since redFunction(), and those function are all marked const, we need "const auto&" > > There is no need to copy these functions out of the effect object. > > Could also consider shorter names. I think we could call the locals just > red, green, blue, alpha given the scope of a short function like this. No > real ambiguity about what they mean. > > > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:263 > > + if (redFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > > + [componentTransferFilter setValue:[CIVector vectorWithX:redFunction.intercept Y:redFunction.slope Z:0 W:0] forKey:@"inputRedCoefficients"]; > > + if (greenFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > > + [componentTransferFilter setValue:[CIVector vectorWithX:greenFunction.intercept Y:greenFunction.slope Z:0 W:0] forKey:@"inputGreenCoefficients"]; > > + if (blueFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > > + [componentTransferFilter setValue:[CIVector vectorWithX:blueFunction.intercept Y:blueFunction.slope Z:0 W:0] forKey:@"inputBlueCoefficients"]; > > + if (alphaFunction.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > > + [componentTransferFilter setValue:[CIVector vectorWithX:alphaFunction.intercept Y:alphaFunction.slope Z:0 W:0] forKey:@"inputAlphaCoefficients"]; > > Code can be simplified with a lambda: > > auto setCoefficients = [&] (NSString *key, const ComponentFunction& > function) { > if (function.type == FECOMPONENTTRANSFER_TYPE_LINEAR) > [componentTransferFilter setValue:[CIVector > vectorWithX:function.intercept Y:function.slope Z:0 W:0] forKey:key]; > }; > setCoefficients(@"inputRedCoefficients", effect.redFunction()); > setCoefficients(@"inputGreenCoefficients", effect.greenFunction()); > setCoefficients(@"inputBlueCoefficients", effect.blueFunction()); > setCoefficients(@"inputAlphaCoefficients", effect.alphaFunction()); > > This replaces 12 lines of more hard-to-read code.
frankhome61
Comment 11 2020-09-04 11:37:03 PDT
Darin Adler
Comment 12 2020-09-04 12:14:43 PDT
Comment on attachment 408006 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=408006&action=review > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:68 > + return isNullOrLinear(effect.redFunction()) && isNullOrLinear(effect.greenFunction()) > + && isNullOrLinear(effect.blueFunction()) && isNullOrLinear(effect.alphaFunction()); This is indented too much. > Source/WebCore/platform/graphics/coreimage/FilterEffectRendererCoreImage.mm:241 > + CIFilter* filter = [CIFilter filterWithName:@"CIColorPolynomial"]; I suggest auto here.
frankhome61
Comment 13 2020-09-04 13:39:47 PDT
Created attachment 408019 [details] Ready for commit
frankhome61
Comment 14 2020-09-04 14:16:20 PDT
Created attachment 408024 [details] Ready for commit
frankhome61
Comment 15 2020-09-04 14:48:57 PDT
Created attachment 408026 [details] Patch (missing reviewer name)
frankhome61
Comment 16 2020-09-08 11:46:02 PDT
Created attachment 408247 [details] Ready for Commit
EWS
Comment 17 2020-09-08 12:25:18 PDT
Committed r266740: <https://trac.webkit.org/changeset/266740> All reviewed patches have been landed. Closing bug and clearing flags on attachment 408247 [details].
Note You need to log in before you can comment on or make changes to this bug.