123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * Copyright 2012 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/effects/SkColorFilterImageFilter.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkColorFilter.h"
- #include "src/core/SkImageFilterPriv.h"
- #include "src/core/SkReadBuffer.h"
- #include "src/core/SkSpecialImage.h"
- #include "src/core/SkSpecialSurface.h"
- #include "src/core/SkWriteBuffer.h"
- sk_sp<SkImageFilter> SkColorFilterImageFilter::Make(sk_sp<SkColorFilter> cf,
- sk_sp<SkImageFilter> input,
- const CropRect* cropRect) {
- if (!cf) {
- return nullptr;
- }
- SkColorFilter* inputCF;
- if (input && input->isColorFilterNode(&inputCF)) {
- // This is an optimization, as it collapses the hierarchy by just combining the two
- // colorfilters into a single one, which the new imagefilter will wrap.
- sk_sp<SkColorFilter> newCF = cf->makeComposed(sk_sp<SkColorFilter>(inputCF));
- if (newCF) {
- return sk_sp<SkImageFilter>(new SkColorFilterImageFilter(std::move(newCF),
- sk_ref_sp(input->getInput(0)),
- cropRect));
- }
- }
- return sk_sp<SkImageFilter>(new SkColorFilterImageFilter(std::move(cf),
- std::move(input),
- cropRect));
- }
- SkColorFilterImageFilter::SkColorFilterImageFilter(sk_sp<SkColorFilter> cf,
- sk_sp<SkImageFilter> input,
- const CropRect* cropRect)
- : INHERITED(&input, 1, cropRect)
- , fColorFilter(std::move(cf)) {
- }
- sk_sp<SkFlattenable> SkColorFilterImageFilter::CreateProc(SkReadBuffer& buffer) {
- SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
- sk_sp<SkColorFilter> cf(buffer.readColorFilter());
- return Make(std::move(cf), common.getInput(0), &common.cropRect());
- }
- void SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
- buffer.writeFlattenable(fColorFilter.get());
- }
- sk_sp<SkSpecialImage> SkColorFilterImageFilter::onFilterImage(SkSpecialImage* source,
- const Context& ctx,
- SkIPoint* offset) const {
- SkIPoint inputOffset = SkIPoint::Make(0, 0);
- sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
- SkIRect inputBounds;
- if (fColorFilter->affectsTransparentBlack()) {
- // If the color filter affects transparent black, the bounds are the entire clip.
- inputBounds = ctx.clipBounds();
- } else if (!input) {
- return nullptr;
- } else {
- inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
- input->width(), input->height());
- }
- SkIRect bounds;
- if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
- return nullptr;
- }
- sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
- if (!surf) {
- return nullptr;
- }
- SkCanvas* canvas = surf->getCanvas();
- SkASSERT(canvas);
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- paint.setColorFilter(fColorFilter);
- // TODO: it may not be necessary to clear or drawPaint inside the input bounds
- // (see skbug.com/5075)
- if (fColorFilter->affectsTransparentBlack()) {
- // The subsequent input->draw() call may not fill the entire canvas. For filters which
- // affect transparent black, ensure that the filter is applied everywhere.
- paint.setColor(SK_ColorTRANSPARENT);
- canvas->drawPaint(paint);
- paint.setColor(SK_ColorBLACK);
- } else {
- canvas->clear(0x0);
- }
- if (input) {
- input->draw(canvas,
- SkIntToScalar(inputOffset.fX - bounds.fLeft),
- SkIntToScalar(inputOffset.fY - bounds.fTop),
- &paint);
- }
- offset->fX = bounds.fLeft;
- offset->fY = bounds.fTop;
- return surf->makeImageSnapshot();
- }
- bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const {
- SkASSERT(1 == this->countInputs());
- if (!this->cropRectIsSet()) {
- if (filter) {
- *filter = SkRef(fColorFilter.get());
- }
- return true;
- }
- return false;
- }
- bool SkColorFilterImageFilter::affectsTransparentBlack() const {
- return fColorFilter->affectsTransparentBlack();
- }
|