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 |