OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkTileImageFilter.h" | 8 #include "SkTileImageFilter.h" |
9 #include "SkBitmap.h" | 9 |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
11 #include "SkDevice.h" | 11 #include "SkImage.h" |
| 12 #include "SkMatrix.h" |
12 #include "SkOffsetImageFilter.h" | 13 #include "SkOffsetImageFilter.h" |
| 14 #include "SkPaint.h" |
13 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
| 16 #include "SkShader.h" |
| 17 #include "SkSpecialImage.h" |
| 18 #include "SkSpecialSurface.h" |
| 19 #include "SkSurface.h" |
| 20 #include "SkValidationUtils.h" |
14 #include "SkWriteBuffer.h" | 21 #include "SkWriteBuffer.h" |
15 #include "SkMatrix.h" | |
16 #include "SkPaint.h" | |
17 #include "SkShader.h" | |
18 #include "SkValidationUtils.h" | |
19 | 22 |
20 SkImageFilter* SkTileImageFilter::Create(const SkRect& srcRect, const SkRect& ds
tRect, | 23 SkImageFilter* SkTileImageFilter::Create(const SkRect& srcRect, const SkRect& ds
tRect, |
21 SkImageFilter* input) { | 24 SkImageFilter* input) { |
22 if (!SkIsValidRect(srcRect) || !SkIsValidRect(dstRect)) { | 25 if (!SkIsValidRect(srcRect) || !SkIsValidRect(dstRect)) { |
23 return nullptr; | 26 return nullptr; |
24 } | 27 } |
25 if (srcRect.width() == dstRect.width() && srcRect.height() == dstRect.height
()) { | 28 if (srcRect.width() == dstRect.width() && srcRect.height() == dstRect.height
()) { |
26 SkRect ir = dstRect; | 29 SkRect ir = dstRect; |
27 if (!ir.intersect(srcRect)) { | 30 if (!ir.intersect(srcRect)) { |
28 return SkSafeRef(input); | 31 return SkSafeRef(input); |
29 } | 32 } |
30 CropRect cropRect(ir); | 33 CropRect cropRect(ir); |
31 return SkOffsetImageFilter::Make(dstRect.x() - srcRect.x(), | 34 return SkOffsetImageFilter::Make(dstRect.x() - srcRect.x(), |
32 dstRect.y() - srcRect.y(), | 35 dstRect.y() - srcRect.y(), |
33 sk_ref_sp<SkImageFilter>(input), | 36 sk_ref_sp<SkImageFilter>(input), |
34 &cropRect).release(); | 37 &cropRect).release(); |
35 } | 38 } |
36 return new SkTileImageFilter(srcRect, dstRect, input); | 39 return new SkTileImageFilter(srcRect, dstRect, input); |
37 } | 40 } |
38 | 41 |
39 bool SkTileImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& sr
c, | 42 sk_sp<SkSpecialImage> SkTileImageFilter::onFilterImage(SkSpecialImage* source, |
40 const Context& ctx, | 43 const Context& ctx, |
41 SkBitmap* dst, SkIPoint* offset)
const { | 44 SkIPoint* offset) const { |
42 SkBitmap source = src; | 45 SkIPoint inputOffset = SkIPoint::Make(0, 0); |
43 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 46 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset))
; |
44 if (!this->filterInputDeprecated(0, proxy, src, ctx, &source, &srcOffset)) { | 47 if (!input) { |
45 return false; | 48 return nullptr; |
46 } | 49 } |
47 | 50 |
48 SkRect dstRect; | 51 SkRect dstRect; |
49 ctx.ctm().mapRect(&dstRect, fDstRect); | 52 ctx.ctm().mapRect(&dstRect, fDstRect); |
50 if (!dstRect.intersect(SkRect::Make(ctx.clipBounds()))) { | 53 if (!dstRect.intersect(SkRect::Make(ctx.clipBounds()))) { |
51 offset->fX = offset->fY = 0; | 54 return nullptr; |
52 return true; | |
53 } | 55 } |
| 56 |
54 const SkIRect dstIRect = dstRect.roundOut(); | 57 const SkIRect dstIRect = dstRect.roundOut(); |
55 int w = dstIRect.width(); | 58 int dstWidth = dstIRect.width(); |
56 int h = dstIRect.height(); | 59 int dstHeight = dstIRect.height(); |
57 if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) { | 60 if (!fSrcRect.width() || !fSrcRect.height() || !dstWidth || !dstHeight) { |
58 return false; | 61 return nullptr; |
59 } | 62 } |
60 | 63 |
61 SkRect srcRect; | 64 SkRect srcRect; |
62 ctx.ctm().mapRect(&srcRect, fSrcRect); | 65 ctx.ctm().mapRect(&srcRect, fSrcRect); |
63 SkIRect srcIRect; | 66 SkIRect srcIRect; |
64 srcRect.roundOut(&srcIRect); | 67 srcRect.roundOut(&srcIRect); |
65 srcIRect.offset(-srcOffset); | 68 srcIRect.offset(-inputOffset); |
66 SkBitmap subset; | 69 const SkIRect inputBounds = SkIRect::MakeWH(input->width(), input->height())
; |
67 SkIRect srcBounds; | |
68 source.getBounds(&srcBounds); | |
69 | 70 |
70 if (!SkIRect::Intersects(srcIRect, srcBounds)) { | 71 if (!SkIRect::Intersects(srcIRect, inputBounds)) { |
71 offset->fX = offset->fY = 0; | 72 return nullptr; |
72 return true; | |
73 } | 73 } |
74 if (srcBounds.contains(srcIRect)) { | 74 |
75 if (!source.extractSubset(&subset, srcIRect)) { | 75 // We create an SkImage here b.c. it needs to be a tight fit for the tiling |
76 return false; | 76 sk_sp<SkImage> subset; |
| 77 if (inputBounds.contains(srcIRect)) { |
| 78 subset = input->makeTightSubset(srcIRect); |
| 79 if (!subset) { |
| 80 return nullptr; |
77 } | 81 } |
78 } else { | 82 } else { |
79 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(srcIRect.width(), | 83 const SkImageInfo info = SkImageInfo::MakeN32(srcIRect.width(), srcIRect
.height(), |
80 srcIRect.height(), | 84 kPremul_SkAlphaType); |
81 kPossible_TileUsag
e)); | 85 sk_sp<SkSurface> surf(input->makeTightSurface(info)); |
82 if (!device) { | 86 if (!surf) { |
83 return false; | 87 return nullptr; |
84 } | 88 } |
85 SkCanvas canvas(device); | 89 |
86 canvas.drawBitmap(source, SkIntToScalar(srcOffset.x()), | 90 SkCanvas* canvas = surf->getCanvas(); |
87 SkIntToScalar(srcOffset.y())); | 91 SkASSERT(canvas); |
88 subset = device->accessBitmap(false); | 92 |
| 93 SkPaint paint; |
| 94 paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
| 95 |
| 96 input->draw(canvas, |
| 97 SkIntToScalar(inputOffset.x()), SkIntToScalar(inputOffset.y(
)), |
| 98 &paint); |
| 99 |
| 100 subset = surf->makeImageSnapshot(); |
89 } | 101 } |
90 SkASSERT(subset.width() == srcIRect.width()); | 102 SkASSERT(subset->width() == srcIRect.width()); |
91 SkASSERT(subset.height() == srcIRect.height()); | 103 SkASSERT(subset->height() == srcIRect.height()); |
92 | 104 |
93 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h)); | 105 const SkImageInfo info = SkImageInfo::MakeN32(dstWidth, dstHeight, kPremul_S
kAlphaType); |
94 if (nullptr == device.get()) { | 106 |
95 return false; | 107 sk_sp<SkSpecialSurface> surf(source->makeSurface(info)); |
| 108 if (!surf) { |
| 109 return nullptr; |
96 } | 110 } |
97 SkCanvas canvas(device); | 111 |
| 112 SkCanvas* canvas = surf->getCanvas(); |
| 113 SkASSERT(canvas); |
| 114 |
98 SkPaint paint; | 115 SkPaint paint; |
99 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 116 paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
100 paint.setShader(SkShader::MakeBitmapShader(subset, SkShader::kRepeat_TileMod
e, | 117 paint.setShader(subset->makeShader(SkShader::kRepeat_TileMode, SkShader::kRe
peat_TileMode)); |
101 SkShader::kRepeat_TileMode)); | 118 canvas->translate(-dstRect.fLeft, -dstRect.fTop); |
102 canvas.translate(-dstRect.fLeft, -dstRect.fTop); | 119 canvas->drawRect(dstRect, paint); |
103 canvas.drawRect(dstRect, paint); | |
104 *dst = device->accessBitmap(false); | |
105 offset->fX = dstIRect.fLeft; | 120 offset->fX = dstIRect.fLeft; |
106 offset->fY = dstIRect.fTop; | 121 offset->fY = dstIRect.fTop; |
107 return true; | 122 return surf->makeImageSnapshot(); |
108 } | 123 } |
109 | 124 |
110 SkIRect SkTileImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix
& ctm, | 125 SkIRect SkTileImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix
& ctm, |
111 MapDirection direction) const { | 126 MapDirection direction) const { |
112 SkRect rect = kReverse_MapDirection == direction ? fSrcRect : fDstRect; | 127 SkRect rect = kReverse_MapDirection == direction ? fSrcRect : fDstRect; |
113 ctm.mapRect(&rect); | 128 ctm.mapRect(&rect); |
114 return rect.roundOut(); | 129 return rect.roundOut(); |
115 } | 130 } |
116 | 131 |
117 SkIRect SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix&, M
apDirection) const { | 132 SkIRect SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix&, M
apDirection) const { |
(...skipping 27 matching lines...) Expand all Loading... |
145 str->appendf(" dst: %.2f %.2f %.2f %.2f", | 160 str->appendf(" dst: %.2f %.2f %.2f %.2f", |
146 fDstRect.fLeft, fDstRect.fTop, fDstRect.fRight, fDstRect.fBotto
m); | 161 fDstRect.fLeft, fDstRect.fTop, fDstRect.fRight, fDstRect.fBotto
m); |
147 if (this->getInput(0)) { | 162 if (this->getInput(0)) { |
148 str->appendf("input: ("); | 163 str->appendf("input: ("); |
149 this->getInput(0)->toString(str); | 164 this->getInput(0)->toString(str); |
150 str->appendf(")"); | 165 str->appendf(")"); |
151 } | 166 } |
152 str->append(")"); | 167 str->append(")"); |
153 } | 168 } |
154 #endif | 169 #endif |
OLD | NEW |