OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 The Android Open Source Project |
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 "SkLightingImageFilter.h" | 8 #include "SkLightingImageFilter.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf), | 178 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf), |
179 surfaceScale); | 179 surfaceScale); |
180 } | 180 } |
181 | 181 |
182 inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) { | 182 inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) { |
183 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds), | 183 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds), |
184 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds), | 184 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds), |
185 surfaceScale); | 185 surfaceScale); |
186 } | 186 } |
187 | 187 |
188 template <class LightingType, class LightType> void lightBitmap(const LightingTy
pe& lightingType, | 188 |
189 const SkImageFil
terLight* light, | 189 class UncheckedPixelFetcher { |
190 const SkBitmap&
src, | 190 public: |
191 SkBitmap* dst, | 191 static inline uint32_t Fetch(const SkBitmap& src, int x, int y, const SkIRec
t& bounds) { |
192 SkScalar surface
Scale, | 192 return SkGetPackedA32(*src.getAddr32(x, y)); |
193 const SkIRect& b
ounds) { | 193 } |
| 194 }; |
| 195 |
| 196 // The DecalPixelFetcher is used when the destination crop rect exceeds the inpu
t bitmap bounds. |
| 197 class DecalPixelFetcher { |
| 198 public: |
| 199 static inline uint32_t Fetch(const SkBitmap& src, int x, int y, const SkIRec
t& bounds) { |
| 200 if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bo
unds.fBottom) { |
| 201 return 0; |
| 202 } else { |
| 203 return SkGetPackedA32(*src.getAddr32(x, y)); |
| 204 } |
| 205 } |
| 206 }; |
| 207 |
| 208 template <class LightingType, class LightType, class PixelFetcher> |
| 209 void lightBitmap(const LightingType& lightingType, |
| 210 const SkImageFilterLight* light, |
| 211 const SkBitmap& src, |
| 212 SkBitmap* dst, |
| 213 SkScalar surfaceScale, |
| 214 const SkIRect& bounds) { |
194 SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height())
; | 215 SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height())
; |
195 const LightType* l = static_cast<const LightType*>(light); | 216 const LightType* l = static_cast<const LightType*>(light); |
196 int left = bounds.left(), right = bounds.right(); | 217 int left = bounds.left(), right = bounds.right(); |
197 int bottom = bounds.bottom(); | 218 int bottom = bounds.bottom(); |
198 int y = bounds.top(); | 219 int y = bounds.top(); |
| 220 SkIRect srcBounds = src.bounds(); |
199 SkPMColor* dptr = dst->getAddr32(0, 0); | 221 SkPMColor* dptr = dst->getAddr32(0, 0); |
200 { | 222 { |
201 int x = left; | 223 int x = left; |
202 const SkPMColor* row1 = src.getAddr32(x, y); | |
203 const SkPMColor* row2 = src.getAddr32(x, y + 1); | |
204 int m[9]; | 224 int m[9]; |
205 m[4] = SkGetPackedA32(*row1++); | 225 m[4] = PixelFetcher::Fetch(src, x, y, srcBounds); |
206 m[5] = SkGetPackedA32(*row1++); | 226 m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds); |
207 m[7] = SkGetPackedA32(*row2++); | 227 m[7] = PixelFetcher::Fetch(src, x, y + 1, srcBounds); |
208 m[8] = SkGetPackedA32(*row2++); | 228 m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds); |
209 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 229 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
210 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLi
ght, | 230 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLi
ght, |
211 l->lightColor(surfaceToLight)); | 231 l->lightColor(surfaceToLight)); |
212 for (++x; x < right - 1; ++x) | 232 for (++x; x < right - 1; ++x) |
213 { | 233 { |
214 shiftMatrixLeft(m); | 234 shiftMatrixLeft(m); |
215 m[5] = SkGetPackedA32(*row1++); | 235 m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds); |
216 m[8] = SkGetPackedA32(*row2++); | 236 m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds); |
217 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 237 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
218 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLi
ght, | 238 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLi
ght, |
219 l->lightColor(surfaceToLight)); | 239 l->lightColor(surfaceToLight)); |
220 } | 240 } |
221 shiftMatrixLeft(m); | 241 shiftMatrixLeft(m); |
222 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 242 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
223 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToL
ight, | 243 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToL
ight, |
224 l->lightColor(surfaceToLight)); | 244 l->lightColor(surfaceToLight)); |
225 } | 245 } |
226 | 246 |
227 for (++y; y < bottom - 1; ++y) { | 247 for (++y; y < bottom - 1; ++y) { |
228 int x = left; | 248 int x = left; |
229 const SkPMColor* row0 = src.getAddr32(x, y - 1); | |
230 const SkPMColor* row1 = src.getAddr32(x, y); | |
231 const SkPMColor* row2 = src.getAddr32(x, y + 1); | |
232 int m[9]; | 249 int m[9]; |
233 m[1] = SkGetPackedA32(*row0++); | 250 m[1] = PixelFetcher::Fetch(src, x, y - 1, srcBounds); |
234 m[2] = SkGetPackedA32(*row0++); | 251 m[2] = PixelFetcher::Fetch(src, x + 1, y - 1, srcBounds); |
235 m[4] = SkGetPackedA32(*row1++); | 252 m[4] = PixelFetcher::Fetch(src, x, y, srcBounds); |
236 m[5] = SkGetPackedA32(*row1++); | 253 m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds); |
237 m[7] = SkGetPackedA32(*row2++); | 254 m[7] = PixelFetcher::Fetch(src, x, y + 1, srcBounds); |
238 m[8] = SkGetPackedA32(*row2++); | 255 m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds); |
239 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 256 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
240 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight
, | 257 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight
, |
241 l->lightColor(surfaceToLight)); | 258 l->lightColor(surfaceToLight)); |
242 for (++x; x < right - 1; ++x) { | 259 for (++x; x < right - 1; ++x) { |
243 shiftMatrixLeft(m); | 260 shiftMatrixLeft(m); |
244 m[2] = SkGetPackedA32(*row0++); | 261 m[2] = PixelFetcher::Fetch(src, x + 1, y - 1, srcBounds); |
245 m[5] = SkGetPackedA32(*row1++); | 262 m[5] = PixelFetcher::Fetch(src, x + 1, y, srcBounds); |
246 m[8] = SkGetPackedA32(*row2++); | 263 m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds); |
247 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 264 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
248 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfac
eToLight, | 265 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfac
eToLight, |
249 l->lightColor(surfaceToLight)); | 266 l->lightColor(surfaceToLight)); |
250 } | 267 } |
251 shiftMatrixLeft(m); | 268 shiftMatrixLeft(m); |
252 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 269 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
253 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLigh
t, | 270 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLigh
t, |
254 l->lightColor(surfaceToLight)); | 271 l->lightColor(surfaceToLight)); |
255 } | 272 } |
256 | 273 |
257 { | 274 { |
258 int x = left; | 275 int x = left; |
259 const SkPMColor* row0 = src.getAddr32(x, bottom - 2); | |
260 const SkPMColor* row1 = src.getAddr32(x, bottom - 1); | |
261 int m[9]; | 276 int m[9]; |
262 m[1] = SkGetPackedA32(*row0++); | 277 m[1] = PixelFetcher::Fetch(src, x, bottom - 2, srcBounds); |
263 m[2] = SkGetPackedA32(*row0++); | 278 m[2] = PixelFetcher::Fetch(src, x + 1, bottom - 2, srcBounds); |
264 m[4] = SkGetPackedA32(*row1++); | 279 m[4] = PixelFetcher::Fetch(src, x, bottom - 1, srcBounds); |
265 m[5] = SkGetPackedA32(*row1++); | 280 m[5] = PixelFetcher::Fetch(src, x + 1, bottom - 1, srcBounds); |
266 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 281 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
267 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceT
oLight, | 282 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceT
oLight, |
268 l->lightColor(surfaceToLight)); | 283 l->lightColor(surfaceToLight)); |
269 for (++x; x < right - 1; ++x) | 284 for (++x; x < right - 1; ++x) |
270 { | 285 { |
271 shiftMatrixLeft(m); | 286 shiftMatrixLeft(m); |
272 m[2] = SkGetPackedA32(*row0++); | 287 m[2] = PixelFetcher::Fetch(src, x + 1, bottom - 2, srcBounds); |
273 m[5] = SkGetPackedA32(*row1++); | 288 m[5] = PixelFetcher::Fetch(src, x + 1, bottom - 1, srcBounds); |
274 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 289 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
275 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceT
oLight, | 290 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceT
oLight, |
276 l->lightColor(surfaceToLight)); | 291 l->lightColor(surfaceToLight)); |
277 } | 292 } |
278 shiftMatrixLeft(m); | 293 shiftMatrixLeft(m); |
279 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); | 294 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); |
280 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surface
ToLight, | 295 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surface
ToLight, |
281 l->lightColor(surfaceToLight)); | 296 l->lightColor(surfaceToLight)); |
282 } | 297 } |
283 } | 298 } |
284 | 299 |
| 300 template <class LightingType, class LightType> |
| 301 void lightBitmap(const LightingType& lightingType, |
| 302 const SkImageFilterLight* light, |
| 303 const SkBitmap& src, |
| 304 SkBitmap* dst, |
| 305 SkScalar surfaceScale, |
| 306 const SkIRect& bounds) { |
| 307 if (src.bounds().contains(bounds)) { |
| 308 lightBitmap<LightingType, LightType, UncheckedPixelFetcher>( |
| 309 lightingType, light, src, dst, surfaceScale, bounds); |
| 310 } else { |
| 311 lightBitmap<LightingType, LightType, DecalPixelFetcher>( |
| 312 lightingType, light, src, dst, surfaceScale, bounds); |
| 313 } |
| 314 } |
| 315 |
285 SkPoint3 readPoint3(SkReadBuffer& buffer) { | 316 SkPoint3 readPoint3(SkReadBuffer& buffer) { |
286 SkPoint3 point; | 317 SkPoint3 point; |
287 point.fX = buffer.readScalar(); | 318 point.fX = buffer.readScalar(); |
288 point.fY = buffer.readScalar(); | 319 point.fY = buffer.readScalar(); |
289 point.fZ = buffer.readScalar(); | 320 point.fZ = buffer.readScalar(); |
290 buffer.validate(SkScalarIsFinite(point.fX) && | 321 buffer.validate(SkScalarIsFinite(point.fX) && |
291 SkScalarIsFinite(point.fY) && | 322 SkScalarIsFinite(point.fY) && |
292 SkScalarIsFinite(point.fZ)); | 323 SkScalarIsFinite(point.fZ)); |
293 return point; | 324 return point; |
294 }; | 325 }; |
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1180 SkIPoint* offset) const { | 1211 SkIPoint* offset) const { |
1181 SkBitmap src = source; | 1212 SkBitmap src = source; |
1182 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 1213 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
1183 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) { | 1214 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) { |
1184 return false; | 1215 return false; |
1185 } | 1216 } |
1186 | 1217 |
1187 if (src.colorType() != kN32_SkColorType) { | 1218 if (src.colorType() != kN32_SkColorType) { |
1188 return false; | 1219 return false; |
1189 } | 1220 } |
| 1221 SkIRect srcBounds = src.bounds(); |
| 1222 srcBounds.offset(srcOffset); |
1190 SkIRect bounds; | 1223 SkIRect bounds; |
1191 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { | 1224 if (!this->applyCropRect(ctx, srcBounds, &bounds)) { |
1192 return false; | 1225 return false; |
1193 } | 1226 } |
1194 | 1227 |
1195 if (bounds.width() < 2 || bounds.height() < 2) { | 1228 if (bounds.width() < 2 || bounds.height() < 2) { |
1196 return false; | 1229 return false; |
1197 } | 1230 } |
1198 | 1231 |
1199 SkAutoLockPixels alp(src); | 1232 SkAutoLockPixels alp(src); |
1200 if (!src.getPixels()) { | 1233 if (!src.getPixels()) { |
1201 return false; | 1234 return false; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 SkBitmap src = source; | 1357 SkBitmap src = source; |
1325 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 1358 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
1326 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) { | 1359 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) { |
1327 return false; | 1360 return false; |
1328 } | 1361 } |
1329 | 1362 |
1330 if (src.colorType() != kN32_SkColorType) { | 1363 if (src.colorType() != kN32_SkColorType) { |
1331 return false; | 1364 return false; |
1332 } | 1365 } |
1333 | 1366 |
| 1367 SkIRect srcBounds = src.bounds(); |
| 1368 srcBounds.offset(srcOffset); |
1334 SkIRect bounds; | 1369 SkIRect bounds; |
1335 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { | 1370 if (!this->applyCropRect(ctx, srcBounds, &bounds)) { |
1336 return false; | 1371 return false; |
1337 } | 1372 } |
1338 | 1373 |
1339 if (bounds.width() < 2 || bounds.height() < 2) { | 1374 if (bounds.width() < 2 || bounds.height() < 2) { |
1340 return false; | 1375 return false; |
1341 } | 1376 } |
1342 | 1377 |
1343 SkAutoLockPixels alp(src); | 1378 SkAutoLockPixels alp(src); |
1344 if (!src.getPixels()) { | 1379 if (!src.getPixels()) { |
1345 return false; | 1380 return false; |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2021 | 2056 |
2022 fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight); | 2057 fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight); |
2023 } | 2058 } |
2024 | 2059 |
2025 #endif | 2060 #endif |
2026 | 2061 |
2027 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter) | 2062 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter) |
2028 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter) | 2063 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter) |
2029 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter) | 2064 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter) |
2030 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 2065 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |