14a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org/* 24a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org * Copyright 2012 The Android Open Source Project 34a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org * 44a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 54a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org * found in the LICENSE file. 64a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org */ 74a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 84a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org#include "SkMergeImageFilter.h" 94a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org#include "SkCanvas.h" 104a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org#include "SkDevice.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 13c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h" 144a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 154a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org/////////////////////////////////////////////////////////////////////////////// 164a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 174a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgvoid SkMergeImageFilter::initAllocModes() { 184a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org int inputCount = countInputs(); 194a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (inputCount) { 204a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org size_t size = sizeof(uint8_t) * inputCount; 214a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (size <= sizeof(fStorage)) { 224a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes = SkTCast<uint8_t*>(fStorage); 234a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 244a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes = SkTCast<uint8_t*>(sk_malloc_throw(size)); 254a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 264a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 274a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes = NULL; 284a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 294a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 304a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 314a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgvoid SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) { 324a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (modes) { 334a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->initAllocModes(); 344a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org int inputCount = countInputs(); 354a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org for (int i = 0; i < inputCount; ++i) { 364a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes[i] = SkToU8(modes[i]); 374a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 384a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 394a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes = NULL; 404a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 414a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 424a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 434a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgSkMergeImageFilter::SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second, 44962c8864e4cf0cfbaf8ea3d17eda83261733362asenorblanco@chromium.org SkXfermode::Mode mode, 45b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org const CropRect* cropRect) : INHERITED(first, second, cropRect) { 464a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (SkXfermode::kSrcOver_Mode != mode) { 474a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkXfermode::Mode modes[] = { mode, mode }; 484a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->initModes(modes); 494a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 504a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes = NULL; 514a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 524a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 534a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 544a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgSkMergeImageFilter::SkMergeImageFilter(SkImageFilter* filters[], int count, 55962c8864e4cf0cfbaf8ea3d17eda83261733362asenorblanco@chromium.org const SkXfermode::Mode modes[], 56b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org const CropRect* cropRect) : INHERITED(count, filters, cropRect) { 57c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org SkASSERT(count >= 0); 584a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->initModes(modes); 594a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 604a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 614a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgSkMergeImageFilter::~SkMergeImageFilter() { 624a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 634a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (fModes != SkTCast<uint8_t*>(fStorage)) { 644a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org sk_free(fModes); 654a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 664a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 674a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 684a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgbool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, 694cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org const Context& ctx, 70ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org SkBitmap* result, SkIPoint* offset) const { 714a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (countInputs() < 1) { 724a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 734a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 744a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 754a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkIRect bounds; 76118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org if (!this->applyCropRect(ctx, src, SkIPoint::Make(0, 0), &bounds)) { 774a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 784a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 794a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 804a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org const int x0 = bounds.left(); 814a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org const int y0 = bounds.top(); 824a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 831f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height())); 844a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (NULL == dst) { 854a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 864a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 874a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkCanvas canvas(dst); 884a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkPaint paint; 894a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 904a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org int inputCount = countInputs(); 914a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org for (int i = 0; i < inputCount; ++i) { 924a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkBitmap tmp; 934a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org const SkBitmap* srcPtr; 94962c8864e4cf0cfbaf8ea3d17eda83261733362asenorblanco@chromium.org SkIPoint pos = SkIPoint::Make(0, 0); 954a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkImageFilter* filter = getInput(i); 964a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (filter) { 974cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org if (!filter->filterImage(proxy, src, ctx, &tmp, &pos)) { 984a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 994a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1004a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org srcPtr = &tmp; 1014a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 1024a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org srcPtr = &src; 1034a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1044a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1054a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (fModes) { 1064a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); 1074a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 1084a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org paint.setXfermode(NULL); 1094a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1104a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint); 1114a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1124a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1136776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = bounds.left(); 1146776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fY = bounds.top(); 1154a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org *result = dst->accessBitmap(false); 1164a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return true; 1174a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 1184a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1198b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const { 1204a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->INHERITED::flatten(buffer); 1214a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1224a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org buffer.writeBool(fModes != NULL); 1234a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (fModes) { 1244a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0])); 1254a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1264a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 1274a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1288b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkMergeImageFilter::SkMergeImageFilter(SkReadBuffer& buffer) 129c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org : INHERITED(-1, buffer) { 1304a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org bool hasModes = buffer.readBool(); 1314a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (hasModes) { 1324a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->initAllocModes(); 133c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org int nbInputs = countInputs(); 134025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org size_t size = nbInputs * sizeof(fModes[0]); 135025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org SkASSERT(buffer.getArrayCount() == size); 136ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org if (buffer.validate(buffer.getArrayCount() == size) && 137ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org buffer.readByteArray(fModes, size)) { 138c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org for (int i = 0; i < nbInputs; ++i) { 139c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i])); 140c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org } 141c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org } 1424a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 1434a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes = 0; 1444a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1454a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 146