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* filters[], int count, 44962c8864e4cf0cfbaf8ea3d17eda83261733362asenorblanco@chromium.org const SkXfermode::Mode modes[], 455e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco const CropRect* cropRect, 465e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco uint32_t uniqueID) 475e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco : INHERITED(count, filters, cropRect, uniqueID) { 48c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org SkASSERT(count >= 0); 494a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->initModes(modes); 504a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 514a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 524a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgSkMergeImageFilter::~SkMergeImageFilter() { 534a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 544a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (fModes != SkTCast<uint8_t*>(fStorage)) { 554a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org sk_free(fModes); 564a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 574a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 584a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 594a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.orgbool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, 604cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org const Context& ctx, 61ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org SkBitmap* result, SkIPoint* offset) const { 624a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (countInputs() < 1) { 634a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 644a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 654a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 664a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkIRect bounds; 67118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org if (!this->applyCropRect(ctx, src, SkIPoint::Make(0, 0), &bounds)) { 684a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 694a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 704a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 714a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org const int x0 = bounds.left(); 724a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org const int y0 = bounds.top(); 734a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 741f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height())); 754a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (NULL == dst) { 764a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 774a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 784a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkCanvas canvas(dst); 794a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkPaint paint; 804a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 814a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org int inputCount = countInputs(); 824a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org for (int i = 0; i < inputCount; ++i) { 834a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkBitmap tmp; 844a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org const SkBitmap* srcPtr; 85962c8864e4cf0cfbaf8ea3d17eda83261733362asenorblanco@chromium.org SkIPoint pos = SkIPoint::Make(0, 0); 864a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org SkImageFilter* filter = getInput(i); 874a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (filter) { 884cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org if (!filter->filterImage(proxy, src, ctx, &tmp, &pos)) { 894a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return false; 904a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 914a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org srcPtr = &tmp; 924a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 934a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org srcPtr = &src; 944a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 954a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 964a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (fModes) { 974a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); 984a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 994a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org paint.setXfermode(NULL); 1004a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1014a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint); 1024a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1034a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1046776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = bounds.left(); 1056776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fY = bounds.top(); 1064a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org *result = dst->accessBitmap(false); 1074a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org return true; 1084a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 1094a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1109fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkMergeImageFilter::CreateProc(SkReadBuffer& buffer) { 1119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed Common common; 1129fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!common.unflatten(buffer, -1)) { 1139fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 1149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 1159fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 1169fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const int count = common.inputCount(); 1179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed bool hasModes = buffer.readBool(); 1189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (hasModes) { 1199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkAutoSTArray<4, SkXfermode::Mode> modes(count); 1209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkAutoSTArray<4, uint8_t> modes8(count); 1219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!buffer.readByteArray(modes8.get(), count)) { 1229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 1239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 1249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed for (int i = 0; i < count; ++i) { 1259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed modes[i] = (SkXfermode::Mode)modes8[i]; 1269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.validate(SkIsValidMode(modes[i])); 1279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 1289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!buffer.isValid()) { 1299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 1309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 1315e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco return Create(common.inputs(), count, modes.get(), &common.cropRect(), common.uniqueID()); 1329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 1335e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco return Create(common.inputs(), count, NULL, &common.cropRect(), common.uniqueID()); 1349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 1359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 1368b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const { 1374a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->INHERITED::flatten(buffer); 1384a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org buffer.writeBool(fModes != NULL); 1394a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (fModes) { 1404a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0])); 1414a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1424a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 1434a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org 1449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 1458b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkMergeImageFilter::SkMergeImageFilter(SkReadBuffer& buffer) 146c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org : INHERITED(-1, buffer) { 1474a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org bool hasModes = buffer.readBool(); 1484a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org if (hasModes) { 1494a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org this->initAllocModes(); 150c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org int nbInputs = countInputs(); 151025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org size_t size = nbInputs * sizeof(fModes[0]); 152025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org SkASSERT(buffer.getArrayCount() == size); 153ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org if (buffer.validate(buffer.getArrayCount() == size) && 154ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org buffer.readByteArray(fModes, size)) { 155c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org for (int i = 0; i < nbInputs; ++i) { 156c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i])); 157c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org } 158c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org } 1594a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } else { 1604a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org fModes = 0; 1614a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org } 1624a9a612b5200597cca0bda0a356250835cbdc7d6senorblanco@chromium.org} 1639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif 164