| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) | 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) |
| 3 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. | 3 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 intrinsicTileSize.setWidth(scaledTileSize.width()); | 98 intrinsicTileSize.setWidth(scaledTileSize.width()); |
| 99 intrinsicTileSize.setHeight(scaledTileSize.height()); | 99 intrinsicTileSize.setHeight(scaledTileSize.height()); |
| 100 } | 100 } |
| 101 | 101 |
| 102 FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), | 102 FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(), |
| 103 scaledTileSize.height() / intrinsicTileSize.height()); | 103 scaledTileSize.height() / intrinsicTileSize.height()); |
| 104 | 104 |
| 105 const FloatRect oneTileRect = computeTileContaining( | 105 const FloatRect oneTileRect = computeTileContaining( |
| 106 destRect.location(), scaledTileSize, srcPoint, repeatSpacing); | 106 destRect.location(), scaledTileSize, srcPoint, repeatSpacing); |
| 107 | 107 |
| 108 // Check and see if a single draw of the image can cover the entire area we ar
e supposed to tile. | 108 // Check and see if a single draw of the image can cover the entire area we |
| 109 // are supposed to tile. |
| 109 if (oneTileRect.contains(destRect)) { | 110 if (oneTileRect.contains(destRect)) { |
| 110 const FloatRect visibleSrcRect = | 111 const FloatRect visibleSrcRect = |
| 111 computeSubsetForTile(oneTileRect, destRect, intrinsicTileSize); | 112 computeSubsetForTile(oneTileRect, destRect, intrinsicTileSize); |
| 112 ctxt.drawImage(this, destRect, &visibleSrcRect, op, | 113 ctxt.drawImage(this, destRect, &visibleSrcRect, op, |
| 113 DoNotRespectImageOrientation); | 114 DoNotRespectImageOrientation); |
| 114 return; | 115 return; |
| 115 } | 116 } |
| 116 | 117 |
| 117 FloatRect tileRect(FloatPoint(), intrinsicTileSize); | 118 FloatRect tileRect(FloatPoint(), intrinsicTileSize); |
| 118 drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, | 119 drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, |
| 119 repeatSpacing); | 120 repeatSpacing); |
| 120 | 121 |
| 121 startAnimation(); | 122 startAnimation(); |
| 122 } | 123 } |
| 123 | 124 |
| 124 // FIXME: Merge with the other drawTiled eventually, since we need a combination
of both for some things. | 125 // FIXME: Merge with the other drawTiled() function eventually, since we need a |
| 126 // combination of both for some things. |
| 125 void Image::drawTiled(GraphicsContext& ctxt, | 127 void Image::drawTiled(GraphicsContext& ctxt, |
| 126 const FloatRect& dstRect, | 128 const FloatRect& dstRect, |
| 127 const FloatRect& srcRect, | 129 const FloatRect& srcRect, |
| 128 const FloatSize& providedTileScaleFactor, | 130 const FloatSize& providedTileScaleFactor, |
| 129 TileRule hRule, | 131 TileRule hRule, |
| 130 TileRule vRule, | 132 TileRule vRule, |
| 131 SkXfermode::Mode op) { | 133 SkXfermode::Mode op) { |
| 132 // FIXME: We do not support 'space' yet. For now just map it to 'repeat'. | 134 // FIXME: We do not support 'space' yet. For now just map it to 'repeat'. |
| 133 if (hRule == SpaceTile) | 135 if (hRule == SpaceTile) |
| 134 hRule = RepeatTile; | 136 hRule = RepeatTile; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 148 (srcRect.width() * hRepetitions)); | 150 (srcRect.width() * hRepetitions)); |
| 149 } | 151 } |
| 150 if (vRule == RoundTile) { | 152 if (vRule == RoundTile) { |
| 151 float vRepetitions = | 153 float vRepetitions = |
| 152 std::max(1.0f, roundf(dstRect.height() / | 154 std::max(1.0f, roundf(dstRect.height() / |
| 153 (tileScaleFactor.height() * srcRect.height()))); | 155 (tileScaleFactor.height() * srcRect.height()))); |
| 154 tileScaleFactor.setHeight(dstRect.height() / | 156 tileScaleFactor.setHeight(dstRect.height() / |
| 155 (srcRect.height() * vRepetitions)); | 157 (srcRect.height() * vRepetitions)); |
| 156 } | 158 } |
| 157 if (hRule == RoundTile || vRule == RoundTile) { | 159 if (hRule == RoundTile || vRule == RoundTile) { |
| 158 // High interpolation quality rounds the scaled tile to an integer size (see
Image::drawPattern). | 160 // High quality interpolation rounds the scaled tile to an integer size (see |
| 159 // To avoid causing a visual problem, linear interpolation must be used inst
ead. | 161 // Image::drawPattern). To avoid causing a visual problem, linear |
| 162 // interpolation must be used instead. |
| 160 // FIXME: Allow using high-quality interpolation in this case, too. | 163 // FIXME: Allow using high-quality interpolation in this case, too. |
| 161 useLowInterpolationQuality = true; | 164 useLowInterpolationQuality = true; |
| 162 } | 165 } |
| 163 | 166 |
| 164 // We want to construct the phase such that the pattern is centered (when stre
tch is not | 167 // We want to construct the phase such that the pattern is centered (when |
| 165 // set for a particular rule). | 168 // stretch is not set for a particular rule). |
| 166 float hPhase = tileScaleFactor.width() * srcRect.x(); | 169 float hPhase = tileScaleFactor.width() * srcRect.x(); |
| 167 float vPhase = tileScaleFactor.height() * srcRect.y(); | 170 float vPhase = tileScaleFactor.height() * srcRect.y(); |
| 168 float scaledTileWidth = tileScaleFactor.width() * srcRect.width(); | 171 float scaledTileWidth = tileScaleFactor.width() * srcRect.width(); |
| 169 float scaledTileHeight = tileScaleFactor.height() * srcRect.height(); | 172 float scaledTileHeight = tileScaleFactor.height() * srcRect.height(); |
| 170 if (hRule == Image::RepeatTile) | 173 if (hRule == Image::RepeatTile) |
| 171 hPhase -= (dstRect.width() - scaledTileWidth) / 2; | 174 hPhase -= (dstRect.width() - scaledTileWidth) / 2; |
| 172 if (vRule == Image::RepeatTile) | 175 if (vRule == Image::RepeatTile) |
| 173 vPhase -= (dstRect.height() - scaledTileHeight) / 2; | 176 vPhase -= (dstRect.height() - scaledTileHeight) / 2; |
| 174 FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase); | 177 FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase); |
| 175 | 178 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 189 namespace { | 192 namespace { |
| 190 | 193 |
| 191 sk_sp<SkShader> createPatternShader(const SkImage* image, | 194 sk_sp<SkShader> createPatternShader(const SkImage* image, |
| 192 const SkMatrix& shaderMatrix, | 195 const SkMatrix& shaderMatrix, |
| 193 const SkPaint& paint, | 196 const SkPaint& paint, |
| 194 const FloatSize& spacing) { | 197 const FloatSize& spacing) { |
| 195 if (spacing.isZero()) | 198 if (spacing.isZero()) |
| 196 return image->makeShader(SkShader::kRepeat_TileMode, | 199 return image->makeShader(SkShader::kRepeat_TileMode, |
| 197 SkShader::kRepeat_TileMode, &shaderMatrix); | 200 SkShader::kRepeat_TileMode, &shaderMatrix); |
| 198 | 201 |
| 199 // Arbitrary tiling is currently only supported for SkPictureShader - so we us
e it instead | 202 // Arbitrary tiling is currently only supported for SkPictureShader, so we use |
| 200 // of a plain bitmap shader to implement spacing. | 203 // that instead of a plain bitmap shader to implement spacing. |
| 201 const SkRect tileRect = SkRect::MakeWH(image->width() + spacing.width(), | 204 const SkRect tileRect = SkRect::MakeWH(image->width() + spacing.width(), |
| 202 image->height() + spacing.height()); | 205 image->height() + spacing.height()); |
| 203 | 206 |
| 204 SkPictureRecorder recorder; | 207 SkPictureRecorder recorder; |
| 205 SkCanvas* canvas = recorder.beginRecording(tileRect); | 208 SkCanvas* canvas = recorder.beginRecording(tileRect); |
| 206 canvas->drawImage(image, 0, 0, &paint); | 209 canvas->drawImage(image, 0, 0, &paint); |
| 207 | 210 |
| 208 return SkShader::MakePictureShader( | 211 return SkShader::MakePictureShader( |
| 209 recorder.finishRecordingAsPicture(), SkShader::kRepeat_TileMode, | 212 recorder.finishRecordingAsPicture(), SkShader::kRepeat_TileMode, |
| 210 SkShader::kRepeat_TileMode, &shaderMatrix, nullptr); | 213 SkShader::kRepeat_TileMode, &shaderMatrix, nullptr); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 | 278 |
| 276 return image.release(); | 279 return image.release(); |
| 277 } | 280 } |
| 278 | 281 |
| 279 bool Image::isTextureBacked() { | 282 bool Image::isTextureBacked() { |
| 280 sk_sp<SkImage> image = imageForCurrentFrame(); | 283 sk_sp<SkImage> image = imageForCurrentFrame(); |
| 281 return image ? image->isTextureBacked() : false; | 284 return image ? image->isTextureBacked() : false; |
| 282 } | 285 } |
| 283 | 286 |
| 284 bool Image::applyShader(SkPaint& paint, const SkMatrix& localMatrix) { | 287 bool Image::applyShader(SkPaint& paint, const SkMatrix& localMatrix) { |
| 285 // Default shader impl: attempt to build a shader based on the current frame S
kImage. | 288 // Default shader impl: attempt to build a shader based on the current frame |
| 289 // SkImage. |
| 286 sk_sp<SkImage> image = imageForCurrentFrame(); | 290 sk_sp<SkImage> image = imageForCurrentFrame(); |
| 287 if (!image) | 291 if (!image) |
| 288 return false; | 292 return false; |
| 289 | 293 |
| 290 paint.setShader(image->makeShader(SkShader::kRepeat_TileMode, | 294 paint.setShader(image->makeShader(SkShader::kRepeat_TileMode, |
| 291 SkShader::kRepeat_TileMode, &localMatrix)); | 295 SkShader::kRepeat_TileMode, &localMatrix)); |
| 292 | 296 |
| 293 // Animation is normally refreshed in draw() impls, which we don't call when p
ainting via shaders. | 297 // Animation is normally refreshed in draw() impls, which we don't call when |
| 298 // painting via shaders. |
| 294 startAnimation(); | 299 startAnimation(); |
| 295 | 300 |
| 296 return true; | 301 return true; |
| 297 } | 302 } |
| 298 | 303 |
| 299 FloatRect Image::computeTileContaining(const FloatPoint& point, | 304 FloatRect Image::computeTileContaining(const FloatPoint& point, |
| 300 const FloatSize& tileSize, | 305 const FloatSize& tileSize, |
| 301 const FloatPoint& tilePhase, | 306 const FloatPoint& tilePhase, |
| 302 const FloatSize& tileSpacing) { | 307 const FloatSize& tileSpacing) { |
| 303 const FloatSize actualTileSize(tileSize + tileSpacing); | 308 const FloatSize actualTileSize(tileSize + tileSpacing); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 323 FloatRect subset = dest; | 328 FloatRect subset = dest; |
| 324 subset.setX((dest.x() - tile.x()) / scale.width()); | 329 subset.setX((dest.x() - tile.x()) / scale.width()); |
| 325 subset.setY((dest.y() - tile.y()) / scale.height()); | 330 subset.setY((dest.y() - tile.y()) / scale.height()); |
| 326 subset.setWidth(dest.width() / scale.width()); | 331 subset.setWidth(dest.width() / scale.width()); |
| 327 subset.setHeight(dest.height() / scale.height()); | 332 subset.setHeight(dest.height() / scale.height()); |
| 328 | 333 |
| 329 return subset; | 334 return subset; |
| 330 } | 335 } |
| 331 | 336 |
| 332 } // namespace blink | 337 } // namespace blink |
| OLD | NEW |