OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2008, Google Inc. All rights reserved. | 2 * Copyright (c) 2008, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 | 137 |
138 return LinearResampling; | 138 return LinearResampling; |
139 } | 139 } |
140 | 140 |
141 static ResamplingMode limitResamplingMode(GraphicsContext* context, ResamplingMo
de resampling) | 141 static ResamplingMode limitResamplingMode(GraphicsContext* context, ResamplingMo
de resampling) |
142 { | 142 { |
143 switch (context->imageInterpolationQuality()) { | 143 switch (context->imageInterpolationQuality()) { |
144 case InterpolationNone: | 144 case InterpolationNone: |
145 return NoResampling; | 145 return NoResampling; |
146 case InterpolationMedium: | 146 case InterpolationMedium: |
147 // For now we treat InterpolationMedium and InterpolationLow the same. | 147 if (resampling == AwesomeResampling) |
| 148 return LinearWithMipmapsResampling; |
| 149 break; |
148 case InterpolationLow: | 150 case InterpolationLow: |
149 if (resampling == AwesomeResampling) | 151 if (resampling == AwesomeResampling || resampling == LinearWithMipmapsRe
sampling) |
150 return LinearResampling; | 152 return LinearResampling; |
151 break; | 153 break; |
152 case InterpolationHigh: | 154 case InterpolationHigh: |
153 case InterpolationDefault: | |
154 break; | 155 break; |
155 } | 156 } |
156 | 157 |
157 return resampling; | 158 return resampling; |
158 } | 159 } |
159 | 160 |
| 161 static SkPaint::FilterLevel convertToSkiaFilterLevel(bool useBicubicFilter, Resa
mplingMode resampling) |
| 162 { |
| 163 if (useBicubicFilter) |
| 164 return SkPaint::kHigh_FilterLevel; |
| 165 |
| 166 switch (resampling) { |
| 167 case LinearWithMipmapsResampling: |
| 168 return SkPaint::kMedium_FilterLevel; |
| 169 case LinearResampling: |
| 170 return SkPaint::kLow_FilterLevel; |
| 171 // AwesomeResampling if useBicubicFilter is false means that we do |
| 172 // a manual high quality resampling before drawing to Skia. |
| 173 case AwesomeResampling: |
| 174 default: |
| 175 return SkPaint::kNone_FilterLevel; |
| 176 } |
| 177 } |
| 178 |
160 // This function is used to scale an image and extract a scaled fragment. | 179 // This function is used to scale an image and extract a scaled fragment. |
161 // | 180 // |
162 // ALGORITHM | 181 // ALGORITHM |
163 // | 182 // |
164 // Because the scaled image size has to be integers, we approximate the real | 183 // Because the scaled image size has to be integers, we approximate the real |
165 // scale with the following formula (only X direction is shown): | 184 // scale with the following formula (only X direction is shown): |
166 // | 185 // |
167 // scaledImageWidth = round(scaleX * imageRect.width()) | 186 // scaledImageWidth = round(scaleX * imageRect.width()) |
168 // approximateScaleX = scaledImageWidth / imageRect.width() | 187 // approximateScaleX = scaledImageWidth / imageRect.width() |
169 // | 188 // |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTar
get.height())); | 365 SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTar
get.height())); |
347 } | 366 } |
348 | 367 |
349 if (resampling == NoResampling) { | 368 if (resampling == NoResampling) { |
350 // FIXME: This is to not break tests (it results in the filter bitmap fl
ag | 369 // FIXME: This is to not break tests (it results in the filter bitmap fl
ag |
351 // being set to true). We need to decide if we respect NoResampling | 370 // being set to true). We need to decide if we respect NoResampling |
352 // being returned from computeResamplingMode. | 371 // being returned from computeResamplingMode. |
353 resampling = LinearResampling; | 372 resampling = LinearResampling; |
354 } | 373 } |
355 resampling = limitResamplingMode(context, resampling); | 374 resampling = limitResamplingMode(context, resampling); |
356 paint.setFilterBitmap(resampling == LinearResampling); | |
357 | 375 |
358 bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap()); | 376 bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap()); |
359 // FIXME: Bicubic filtering in Skia is only applied to defer-decoded images | 377 // FIXME: Bicubic filtering in Skia is only applied to defer-decoded images |
360 // as an experiment. Once this filtering code path becomes stable we should | 378 // as an experiment. Once this filtering code path becomes stable we should |
361 // turn this on for all cases, including non-defer-decoded images. | 379 // turn this on for all cases, including non-defer-decoded images. |
362 bool useBicubicFilter = resampling == AwesomeResampling && isLazyDecoded; | 380 bool useBicubicFilter = resampling == AwesomeResampling && isLazyDecoded; |
363 | 381 |
364 if (useBicubicFilter) | 382 paint.setFilterLevel(convertToSkiaFilterLevel(useBicubicFilter, resampling))
; |
365 paint.setFilterLevel(SkPaint::kHigh_FilterLevel); | |
366 | 383 |
367 if (resampling == AwesomeResampling && !useBicubicFilter) { | 384 if (resampling == AwesomeResampling && !useBicubicFilter) { |
368 // Resample the image and then draw the result to canvas with bilinear | 385 // Resample the image and then draw the result to canvas with bilinear |
369 // filtering. | 386 // filtering. |
370 drawResampledBitmap(context, paint, srcRect, destRect); | 387 drawResampledBitmap(context, paint, srcRect, destRect); |
371 } else { | 388 } else { |
372 // We want to filter it if we decided to do interpolation above, or if | 389 // We want to filter it if we decided to do interpolation above, or if |
373 // there is something interesting going on with the matrix (like a rotat
ion). | 390 // there is something interesting going on with the matrix (like a rotat
ion). |
374 // Note: for serialization, we will want to subset the bitmap first so w
e | 391 // Note: for serialization, we will want to subset the bitmap first so w
e |
375 // don't send extra pixels. | 392 // don't send extra pixels. |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 // a shifted image, it will shift it from there using the shaderTransform. | 506 // a shifted image, it will shift it from there using the shaderTransform. |
490 float adjustedX = phase.x() + normSrcRect.x() * scale.width(); | 507 float adjustedX = phase.x() + normSrcRect.x() * scale.width(); |
491 float adjustedY = phase.y() + normSrcRect.y() * scale.height(); | 508 float adjustedY = phase.y() + normSrcRect.y() * scale.height(); |
492 shaderTransform.postTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(ad
justedY)); | 509 shaderTransform.postTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(ad
justedY)); |
493 shader->setLocalMatrix(shaderTransform); | 510 shader->setLocalMatrix(shaderTransform); |
494 | 511 |
495 SkPaint paint; | 512 SkPaint paint; |
496 paint.setShader(shader.get()); | 513 paint.setShader(shader.get()); |
497 paint.setXfermode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode).ge
t()); | 514 paint.setXfermode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode).ge
t()); |
498 paint.setColorFilter(context->colorFilter()); | 515 paint.setColorFilter(context->colorFilter()); |
| 516 paint.setFilterLevel(convertToSkiaFilterLevel(useBicubicFilter, resampling))
; |
499 | 517 |
500 paint.setFilterBitmap(resampling == LinearResampling); | |
501 if (useBicubicFilter) | |
502 paint.setFilterLevel(SkPaint::kHigh_FilterLevel); | |
503 if (isLazyDecoded) | 518 if (isLazyDecoded) |
504 PlatformInstrumentation::didDrawLazyPixelRef(bitmap().getGenerationID())
; | 519 PlatformInstrumentation::didDrawLazyPixelRef(bitmap().getGenerationID())
; |
505 | 520 |
506 context->drawRect(destRect, paint); | 521 context->drawRect(destRect, paint); |
507 } | 522 } |
508 | 523 |
509 bool NativeImageSkia::shouldCacheResampling(const SkISize& scaledImageSize, cons
t SkIRect& scaledImageSubset) const | 524 bool NativeImageSkia::shouldCacheResampling(const SkISize& scaledImageSize, cons
t SkIRect& scaledImageSubset) const |
510 { | 525 { |
511 // Check whether the requested dimensions match previous request. | 526 // Check whether the requested dimensions match previous request. |
512 bool matchesPreviousRequest = m_cachedImageInfo.isEqual(scaledImageSize, sca
ledImageSubset); | 527 bool matchesPreviousRequest = m_cachedImageInfo.isEqual(scaledImageSize, sca
ledImageSubset); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 SkIRect NativeImageSkia::ImageResourceInfo::rectInSubset(const SkIRect& otherSca
ledImageSubset) | 587 SkIRect NativeImageSkia::ImageResourceInfo::rectInSubset(const SkIRect& otherSca
ledImageSubset) |
573 { | 588 { |
574 if (!scaledImageSubset.contains(otherScaledImageSubset)) | 589 if (!scaledImageSubset.contains(otherScaledImageSubset)) |
575 return SkIRect::MakeEmpty(); | 590 return SkIRect::MakeEmpty(); |
576 SkIRect subsetRect = otherScaledImageSubset; | 591 SkIRect subsetRect = otherScaledImageSubset; |
577 subsetRect.offset(-scaledImageSubset.x(), -scaledImageSubset.y()); | 592 subsetRect.offset(-scaledImageSubset.x(), -scaledImageSubset.y()); |
578 return subsetRect; | 593 return subsetRect; |
579 } | 594 } |
580 | 595 |
581 } // namespace WebCore | 596 } // namespace WebCore |
OLD | NEW |