10cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org/* 20cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org * Copyright 2012 The Android Open Source Project 30cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org * 40cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 50cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org * found in the LICENSE file. 60cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org */ 70cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 80cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org#include "SkMergeImageFilter.h" 90cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org#include "SkCanvas.h" 100cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org#include "SkDevice.h" 110cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org#include "SkFlattenableBuffers.h" 123218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org#include "SkValidationUtils.h" 130cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 140cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org/////////////////////////////////////////////////////////////////////////////// 150cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 160cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgvoid SkMergeImageFilter::initAllocModes() { 170cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org int inputCount = countInputs(); 180cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (inputCount) { 190cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org size_t size = sizeof(uint8_t) * inputCount; 200cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (size <= sizeof(fStorage)) { 210cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org fModes = SkTCast<uint8_t*>(fStorage); 220cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 230cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org fModes = SkTCast<uint8_t*>(sk_malloc_throw(size)); 240cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 250cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 260cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org fModes = NULL; 270cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 280cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 290cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 300cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgvoid SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) { 310cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (modes) { 320cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org this->initAllocModes(); 330cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org int inputCount = countInputs(); 340cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org for (int i = 0; i < inputCount; ++i) { 350cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org fModes[i] = SkToU8(modes[i]); 360cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 370cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 380cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org fModes = NULL; 390cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 400cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 410cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 420cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgSkMergeImageFilter::SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second, 433822393952bf5e8aa60fb69ceb21300be37819dfsenorblanco@chromium.org SkXfermode::Mode mode, 44a308293b09f3e34492eac153a1c3ddd3e639831asenorblanco@chromium.org const CropRect* cropRect) : INHERITED(first, second, cropRect) { 450cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (SkXfermode::kSrcOver_Mode != mode) { 460cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkXfermode::Mode modes[] = { mode, mode }; 470cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org this->initModes(modes); 480cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 490cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org fModes = NULL; 500cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 510cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 520cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 530cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgSkMergeImageFilter::SkMergeImageFilter(SkImageFilter* filters[], int count, 543822393952bf5e8aa60fb69ceb21300be37819dfsenorblanco@chromium.org const SkXfermode::Mode modes[], 55a308293b09f3e34492eac153a1c3ddd3e639831asenorblanco@chromium.org const CropRect* cropRect) : INHERITED(count, filters, cropRect) { 56ca21698b7babb16f59c516ecb59ef7de4b15e412commit-bot@chromium.org SkASSERT(count >= 0); 570cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org this->initModes(modes); 580cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 590cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 600cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgSkMergeImageFilter::~SkMergeImageFilter() { 610cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 620cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (fModes != SkTCast<uint8_t*>(fStorage)) { 630cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org sk_free(fModes); 640cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 650cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 660cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 670cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgbool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 680cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkIRect* dst) { 690cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (countInputs() < 1) { 700cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return false; 710cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 720cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 730cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkIRect totalBounds; 740cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 750cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org int inputCount = countInputs(); 760cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org for (int i = 0; i < inputCount; ++i) { 770cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkImageFilter* filter = getInput(i); 780cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkIRect r; 790cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (filter) { 800cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (!filter->filterBounds(src, ctm, &r)) { 810cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return false; 820cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 830cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 840cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org r = src; 850cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 860cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (0 == i) { 870cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org totalBounds = r; 880cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 890cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org totalBounds.join(r); 900cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 910cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 920cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 930cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org // don't modify dst until now, so we don't accidentally change it in the 940cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org // loop, but then return false on the next filter. 950cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org *dst = totalBounds; 960cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return true; 970cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 980cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 990cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgbool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, 1000cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org const SkMatrix& ctm, 1010cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkBitmap* result, SkIPoint* loc) { 1020cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (countInputs() < 1) { 1030cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return false; 1040cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1050cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1060cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkIRect bounds; 1073822393952bf5e8aa60fb69ceb21300be37819dfsenorblanco@chromium.org src.getBounds(&bounds); 1083822393952bf5e8aa60fb69ceb21300be37819dfsenorblanco@chromium.org if (!this->applyCropRect(&bounds, ctm)) { 1090cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return false; 1100cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1110cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1120cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org const int x0 = bounds.left(); 1130cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org const int y0 = bounds.top(); 1140cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1152fd2390b98908719dd1e94662706ffe6b0dfc659robertphillips@google.com SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height())); 1160cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (NULL == dst) { 1170cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return false; 1180cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1190cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkCanvas canvas(dst); 1200cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkPaint paint; 1210cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1220cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org int inputCount = countInputs(); 1230cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org for (int i = 0; i < inputCount; ++i) { 1240cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkBitmap tmp; 1250cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org const SkBitmap* srcPtr; 1263822393952bf5e8aa60fb69ceb21300be37819dfsenorblanco@chromium.org SkIPoint pos = SkIPoint::Make(0, 0); 1270cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org SkImageFilter* filter = getInput(i); 1280cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (filter) { 1290cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) { 1300cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return false; 1310cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1320cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org srcPtr = &tmp; 1330cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 1340cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org srcPtr = &src; 1350cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1360cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1370cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (fModes) { 1380cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); 1390cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 1400cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org paint.setXfermode(NULL); 1410cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1420cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint); 1430cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1440cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1453822393952bf5e8aa60fb69ceb21300be37819dfsenorblanco@chromium.org loc->fX += bounds.left(); 1463822393952bf5e8aa60fb69ceb21300be37819dfsenorblanco@chromium.org loc->fY += bounds.top(); 1470cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org *result = dst->accessBitmap(false); 1480cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org return true; 1490cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 1500cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1510cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.orgvoid SkMergeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 1520cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org this->INHERITED::flatten(buffer); 1530cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1540cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org buffer.writeBool(fModes != NULL); 1550cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (fModes) { 1560cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0])); 1570cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1580cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 1590cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org 1603c6b25d019f8a2f79ad09934c85dc5ec55ceeaaccommit-bot@chromium.orgSkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) 161ca21698b7babb16f59c516ecb59ef7de4b15e412commit-bot@chromium.org : INHERITED(-1, buffer) { 1620cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org bool hasModes = buffer.readBool(); 1630cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org if (hasModes) { 1640cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org this->initAllocModes(); 1653218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org int nbInputs = countInputs(); 166863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org size_t size = nbInputs * sizeof(fModes[0]); 167863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org SkASSERT(buffer.getArrayCount() == size); 168ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.org if (buffer.readByteArray(fModes, size)) { 169ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.org for (int i = 0; i < nbInputs; ++i) { 170ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.org buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i])); 171ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.org } 1723218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org } 1730cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } else { 1740cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org fModes = 0; 1750cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org } 1760cef3808fc44c7a4e5eef30f9604517776e61975senorblanco@chromium.org} 177