| 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 "SkDither.h" | 8 #include "SkDither.h" |
| 9 #include "SkPerlinNoiseShader.h" | 9 #include "SkPerlinNoiseShader.h" |
| 10 #include "SkColorFilter.h" | 10 #include "SkColorFilter.h" |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 const SkISize* tileSize) | 271 const SkISize* tileSize) |
| 272 : fType(type) | 272 : fType(type) |
| 273 , fBaseFrequencyX(baseFrequencyX) | 273 , fBaseFrequencyX(baseFrequencyX) |
| 274 , fBaseFrequencyY(baseFrequencyY) | 274 , fBaseFrequencyY(baseFrequencyY) |
| 275 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) | 275 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) |
| 276 , fSeed(seed) | 276 , fSeed(seed) |
| 277 , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize) | 277 , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize) |
| 278 , fStitchTiles(!fTileSize.isEmpty()) | 278 , fStitchTiles(!fTileSize.isEmpty()) |
| 279 { | 279 { |
| 280 SkASSERT(numOctaves >= 0 && numOctaves < 256); | 280 SkASSERT(numOctaves >= 0 && numOctaves < 256); |
| 281 fMatrix.reset(); |
| 281 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX,
fBaseFrequencyY)); | 282 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX,
fBaseFrequencyY)); |
| 282 } | 283 } |
| 283 | 284 |
| 284 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) | 285 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) |
| 285 : INHERITED(buffer) | 286 : INHERITED(buffer) |
| 286 { | 287 { |
| 287 fType = (SkPerlinNoiseShader::Type) buffer.readInt(); | 288 fType = (SkPerlinNoiseShader::Type) buffer.readInt(); |
| 288 fBaseFrequencyX = buffer.readScalar(); | 289 fBaseFrequencyX = buffer.readScalar(); |
| 289 fBaseFrequencyY = buffer.readScalar(); | 290 fBaseFrequencyY = buffer.readScalar(); |
| 290 fNumOctaves = buffer.readInt(); | 291 fNumOctaves = buffer.readInt(); |
| 291 fSeed = buffer.readScalar(); | 292 fSeed = buffer.readScalar(); |
| 292 fStitchTiles = buffer.readBool(); | 293 fStitchTiles = buffer.readBool(); |
| 293 fTileSize.fWidth = buffer.readInt(); | 294 fTileSize.fWidth = buffer.readInt(); |
| 294 fTileSize.fHeight = buffer.readInt(); | 295 fTileSize.fHeight = buffer.readInt(); |
| 296 fMatrix.reset(); |
| 295 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX,
fBaseFrequencyY)); | 297 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX,
fBaseFrequencyY)); |
| 296 buffer.validate(perlin_noise_type_is_valid(fType) && | 298 buffer.validate(perlin_noise_type_is_valid(fType) && |
| 297 (fNumOctaves >= 0) && (fNumOctaves <= 255) && | 299 (fNumOctaves >= 0) && (fNumOctaves <= 255) && |
| 298 (fStitchTiles != fTileSize.isEmpty())); | 300 (fStitchTiles != fTileSize.isEmpty())); |
| 299 } | 301 } |
| 300 | 302 |
| 301 SkPerlinNoiseShader::~SkPerlinNoiseShader() { | 303 SkPerlinNoiseShader::~SkPerlinNoiseShader() { |
| 302 // Safety, should have been done in endContext() | 304 // Safety, should have been done in endContext() |
| 303 SkDELETE(fPaintingData); | 305 SkDELETE(fPaintingData); |
| 304 } | 306 } |
| 305 | 307 |
| 306 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { | 308 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { |
| 307 this->INHERITED::flatten(buffer); | 309 this->INHERITED::flatten(buffer); |
| 308 buffer.writeInt((int) fType); | 310 buffer.writeInt((int) fType); |
| 309 buffer.writeScalar(fBaseFrequencyX); | 311 buffer.writeScalar(fBaseFrequencyX); |
| 310 buffer.writeScalar(fBaseFrequencyY); | 312 buffer.writeScalar(fBaseFrequencyY); |
| 311 buffer.writeInt(fNumOctaves); | 313 buffer.writeInt(fNumOctaves); |
| 312 buffer.writeScalar(fSeed); | 314 buffer.writeScalar(fSeed); |
| 313 buffer.writeBool(fStitchTiles); | 315 buffer.writeBool(fStitchTiles); |
| 314 buffer.writeInt(fTileSize.fWidth); | 316 buffer.writeInt(fTileSize.fWidth); |
| 315 buffer.writeInt(fTileSize.fHeight); | 317 buffer.writeInt(fTileSize.fHeight); |
| 316 } | 318 } |
| 317 | 319 |
| 318 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( | 320 SkScalar SkPerlinNoiseShader::noise2D(int channel, const PaintingData& paintingD
ata, |
| 319 int channel, const PaintingData& paintingData, | 321 const StitchData& stitchData, |
| 320 const StitchData& stitchData, const SkPoint& noiseVector) const { | 322 const SkPoint& noiseVector) const { |
| 321 struct Noise { | 323 struct Noise { |
| 322 int noisePositionIntegerValue; | 324 int noisePositionIntegerValue; |
| 323 SkScalar noisePositionFractionValue; | 325 SkScalar noisePositionFractionValue; |
| 324 Noise(SkScalar component) | 326 Noise(SkScalar component) |
| 325 { | 327 { |
| 326 SkScalar position = component + kPerlinNoise; | 328 SkScalar position = component + kPerlinNoise; |
| 327 noisePositionIntegerValue = SkScalarFloorToInt(position); | 329 noisePositionIntegerValue = SkScalarFloorToInt(position); |
| 328 noisePositionFractionValue = position - SkIntToScalar(noisePositionI
ntegerValue); | 330 noisePositionFractionValue = position - SkIntToScalar(noisePositionI
ntegerValue); |
| 329 } | 331 } |
| 330 }; | 332 }; |
| 331 Noise noiseX(noiseVector.x()); | 333 Noise noiseX(noiseVector.x()); |
| 332 Noise noiseY(noiseVector.y()); | 334 Noise noiseY(noiseVector.y()); |
| 333 SkScalar u, v; | 335 SkScalar u, v; |
| 334 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi
seShader&>(fShader); | |
| 335 // If stitching, adjust lattice points accordingly. | 336 // If stitching, adjust lattice points accordingly. |
| 336 if (perlinNoiseShader.fStitchTiles) { | 337 if (fStitchTiles) { |
| 337 noiseX.noisePositionIntegerValue = | 338 noiseX.noisePositionIntegerValue = |
| 338 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit
chData.fWidth); | 339 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit
chData.fWidth); |
| 339 noiseY.noisePositionIntegerValue = | 340 noiseY.noisePositionIntegerValue = |
| 340 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit
chData.fHeight); | 341 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit
chData.fHeight); |
| 341 } | 342 } |
| 342 noiseX.noisePositionIntegerValue &= kBlockMask; | 343 noiseX.noisePositionIntegerValue &= kBlockMask; |
| 343 noiseY.noisePositionIntegerValue &= kBlockMask; | 344 noiseY.noisePositionIntegerValue &= kBlockMask; |
| 344 int latticeIndex = | 345 int latticeIndex = |
| 345 paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] + | 346 paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] + |
| 346 noiseY.noisePositionIntegerValue; | 347 noiseY.noisePositionIntegerValue; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 357 v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fract
ionValue); | 358 v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fract
ionValue); |
| 358 SkScalar a = SkScalarInterp(u, v, sx); | 359 SkScalar a = SkScalarInterp(u, v, sx); |
| 359 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) | 360 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) |
| 360 v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot
(fractionValue); | 361 v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot
(fractionValue); |
| 361 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) | 362 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) |
| 362 u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fra
ctionValue); | 363 u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fra
ctionValue); |
| 363 SkScalar b = SkScalarInterp(u, v, sx); | 364 SkScalar b = SkScalarInterp(u, v, sx); |
| 364 return SkScalarInterp(a, b, sy); | 365 return SkScalarInterp(a, b, sy); |
| 365 } | 366 } |
| 366 | 367 |
| 367 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValue
ForPoint( | 368 SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(int channel, |
| 368 int channel, const PaintingData& paintingData, | 369 const PaintingDat
a& paintingData, |
| 369 StitchData& stitchData, const SkPoint& point) const { | 370 StitchData& stitc
hData, |
| 370 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi
seShader&>(fShader); | 371 const SkPoint& po
int) const { |
| 371 if (perlinNoiseShader.fStitchTiles) { | 372 if (fStitchTiles) { |
| 372 // Set up TurbulenceInitial stitch values. | 373 // Set up TurbulenceInitial stitch values. |
| 373 stitchData = paintingData.fStitchDataInit; | 374 stitchData = paintingData.fStitchDataInit; |
| 374 } | 375 } |
| 375 SkScalar turbulenceFunctionResult = 0; | 376 SkScalar turbulenceFunctionResult = 0; |
| 376 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseF
requency.fX), | 377 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseF
requency.fX), |
| 377 SkScalarMul(point.y(), paintingData.fBaseF
requency.fY))); | 378 SkScalarMul(point.y(), paintingData.fBaseF
requency.fY))); |
| 378 SkScalar ratio = SK_Scalar1; | 379 SkScalar ratio = SK_Scalar1; |
| 379 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { | 380 for (int octave = 0; octave < fNumOctaves; ++octave) { |
| 380 SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector)
; | 381 SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector)
; |
| 381 turbulenceFunctionResult += SkScalarDiv( | 382 turbulenceFunctionResult += SkScalarDiv( |
| 382 (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAb
s(noise), ratio); | 383 (fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio); |
| 383 noiseVector.fX *= 2; | 384 noiseVector.fX *= 2; |
| 384 noiseVector.fY *= 2; | 385 noiseVector.fY *= 2; |
| 385 ratio *= 2; | 386 ratio *= 2; |
| 386 if (perlinNoiseShader.fStitchTiles) { | 387 if (fStitchTiles) { |
| 387 // Update stitch values | 388 // Update stitch values |
| 388 stitchData.fWidth *= 2; | 389 stitchData.fWidth *= 2; |
| 389 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; | 390 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; |
| 390 stitchData.fHeight *= 2; | 391 stitchData.fHeight *= 2; |
| 391 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; | 392 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; |
| 392 } | 393 } |
| 393 } | 394 } |
| 394 | 395 |
| 395 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResu
lt) + 1) / 2 | 396 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResu
lt) + 1) / 2 |
| 396 // by fractalNoise and (turbulenceFunctionResult) by turbulence. | 397 // by fractalNoise and (turbulenceFunctionResult) by turbulence. |
| 397 if (perlinNoiseShader.fType == kFractalNoise_Type) { | 398 if (fType == kFractalNoise_Type) { |
| 398 turbulenceFunctionResult = | 399 turbulenceFunctionResult = |
| 399 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf
; | 400 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf
; |
| 400 } | 401 } |
| 401 | 402 |
| 402 if (channel == 3) { // Scale alpha by paint value | 403 if (channel == 3) { // Scale alpha by paint value |
| 403 turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, | 404 turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, |
| 404 SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255))); | 405 SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255))); |
| 405 } | 406 } |
| 406 | 407 |
| 407 // Clamp result | 408 // Clamp result |
| 408 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); | 409 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); |
| 409 } | 410 } |
| 410 | 411 |
| 411 SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( | 412 SkPMColor SkPerlinNoiseShader::shade(const SkPoint& point, StitchData& stitchDat
a) const { |
| 412 const SkPoint& point, StitchData& stitchData) const { | |
| 413 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi
seShader&>(fShader); | |
| 414 SkPoint newPoint; | 413 SkPoint newPoint; |
| 415 fMatrix.mapPoints(&newPoint, &point, 1); | 414 fMatrix.mapPoints(&newPoint, &point, 1); |
| 416 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); | 415 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); |
| 417 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); | 416 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); |
| 418 | 417 |
| 419 U8CPU rgba[4]; | 418 U8CPU rgba[4]; |
| 420 for (int channel = 3; channel >= 0; --channel) { | 419 for (int channel = 3; channel >= 0; --channel) { |
| 421 rgba[channel] = SkScalarFloorToInt(255 * | 420 rgba[channel] = SkScalarFloorToInt(255 * |
| 422 calculateTurbulenceValueForPoint(channel, *perlinNoiseShader.fPainti
ngData, | 421 calculateTurbulenceValueForPoint(channel, *fPaintingData, stitchData
, newPoint)); |
| 423 stitchData, newPoint)); | |
| 424 } | 422 } |
| 425 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); | 423 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); |
| 426 } | 424 } |
| 427 | 425 |
| 428 SkShader::Context* SkPerlinNoiseShader::createContext(const SkBitmap& device, co
nst SkPaint& paint, | 426 bool SkPerlinNoiseShader::setContext(const SkBitmap& device, const SkPaint& pain
t, |
| 429 const SkMatrix& matrix, vo
id* storage) const { | 427 const SkMatrix& matrix) { |
| 430 if (!this->validContext(device, paint, matrix)) { | |
| 431 return NULL; | |
| 432 } | |
| 433 | |
| 434 return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, devic
e, paint, matrix)); | |
| 435 } | |
| 436 | |
| 437 size_t SkPerlinNoiseShader::contextSize() const { | |
| 438 return sizeof(PerlinNoiseShaderContext); | |
| 439 } | |
| 440 | |
| 441 SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( | |
| 442 const SkPerlinNoiseShader& shader, const SkBitmap& device, | |
| 443 const SkPaint& paint, const SkMatrix& matrix) | |
| 444 : INHERITED(shader, device, paint, matrix) | |
| 445 { | |
| 446 SkMatrix newMatrix = matrix; | 428 SkMatrix newMatrix = matrix; |
| 447 newMatrix.postConcat(shader.getLocalMatrix()); | 429 newMatrix.postConcat(getLocalMatrix()); |
| 448 SkMatrix invMatrix; | 430 SkMatrix invMatrix; |
| 449 if (!newMatrix.invert(&invMatrix)) { | 431 if (!newMatrix.invert(&invMatrix)) { |
| 450 invMatrix.reset(); | 432 invMatrix.reset(); |
| 451 } | 433 } |
| 452 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi
se | 434 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi
se |
| 453 // (as opposed to 0 based, usually). The same adjustment is in the setData()
function. | 435 // (as opposed to 0 based, usually). The same adjustment is in the setData()
function. |
| 454 newMatrix.postTranslate(SK_Scalar1, SK_Scalar1); | 436 newMatrix.postTranslate(SK_Scalar1, SK_Scalar1); |
| 455 newMatrix.postConcat(invMatrix); | 437 newMatrix.postConcat(invMatrix); |
| 456 newMatrix.postConcat(invMatrix); | 438 newMatrix.postConcat(invMatrix); |
| 457 fMatrix = newMatrix; | 439 fMatrix = newMatrix; |
| 440 return INHERITED::setContext(device, paint, matrix); |
| 458 } | 441 } |
| 459 | 442 |
| 460 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan( | 443 void SkPerlinNoiseShader::shadeSpan(int x, int y, SkPMColor result[], int count)
{ |
| 461 int x, int y, SkPMColor result[], int count) { | |
| 462 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); | 444 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); |
| 463 StitchData stitchData; | 445 StitchData stitchData; |
| 464 for (int i = 0; i < count; ++i) { | 446 for (int i = 0; i < count; ++i) { |
| 465 result[i] = shade(point, stitchData); | 447 result[i] = shade(point, stitchData); |
| 466 point.fX += SK_Scalar1; | 448 point.fX += SK_Scalar1; |
| 467 } | 449 } |
| 468 } | 450 } |
| 469 | 451 |
| 470 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16( | 452 void SkPerlinNoiseShader::shadeSpan16(int x, int y, uint16_t result[], int count
) { |
| 471 int x, int y, uint16_t result[], int count) { | |
| 472 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); | 453 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); |
| 473 StitchData stitchData; | 454 StitchData stitchData; |
| 474 DITHER_565_SCAN(y); | 455 DITHER_565_SCAN(y); |
| 475 for (int i = 0; i < count; ++i) { | 456 for (int i = 0; i < count; ++i) { |
| 476 unsigned dither = DITHER_VALUE(x); | 457 unsigned dither = DITHER_VALUE(x); |
| 477 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither); | 458 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither); |
| 478 DITHER_INC_X(x); | 459 DITHER_INC_X(x); |
| 479 point.fX += SK_Scalar1; | 460 point.fX += SK_Scalar1; |
| 480 } | 461 } |
| 481 } | 462 } |
| (...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1365 str->append(" seed: "); | 1346 str->append(" seed: "); |
| 1366 str->appendScalar(fSeed); | 1347 str->appendScalar(fSeed); |
| 1367 str->append(" stitch tiles: "); | 1348 str->append(" stitch tiles: "); |
| 1368 str->append(fStitchTiles ? "true " : "false "); | 1349 str->append(fStitchTiles ? "true " : "false "); |
| 1369 | 1350 |
| 1370 this->INHERITED::toString(str); | 1351 this->INHERITED::toString(str); |
| 1371 | 1352 |
| 1372 str->append(")"); | 1353 str->append(")"); |
| 1373 } | 1354 } |
| 1374 #endif | 1355 #endif |
| OLD | NEW |