OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "platform/graphics/ImagePattern.h" | 6 #include "platform/graphics/ImagePattern.h" |
7 | 7 |
| 8 #include "platform/graphics/BitmapImage.h" |
| 9 #include "platform/graphics/ColorSpaceFilter.h" |
| 10 #include "platform/graphics/ColorSpaceProfile.h" |
| 11 #include "platform/graphics/GraphicsScreen.h" |
8 #include "platform/graphics/Image.h" | 12 #include "platform/graphics/Image.h" |
9 #include "platform/graphics/skia/SkiaUtils.h" | 13 #include "platform/graphics/skia/SkiaUtils.h" |
10 #include "third_party/skia/include/core/SkCanvas.h" | 14 #include "third_party/skia/include/core/SkCanvas.h" |
| 15 #include "third_party/skia/include/core/SkColorFilter.h" |
11 #include "third_party/skia/include/core/SkImage.h" | 16 #include "third_party/skia/include/core/SkImage.h" |
12 #include "third_party/skia/include/core/SkShader.h" | 17 #include "third_party/skia/include/core/SkShader.h" |
13 #include "third_party/skia/include/core/SkSurface.h" | 18 #include "third_party/skia/include/core/SkSurface.h" |
14 | 19 |
15 namespace blink { | 20 namespace blink { |
16 | 21 |
17 PassRefPtr<ImagePattern> ImagePattern::create(PassRefPtr<Image> image, RepeatMod
e repeatMode) | 22 PassRefPtr<ImagePattern> ImagePattern::create(PassRefPtr<Image> image, RepeatMod
e repeatMode) |
18 { | 23 { |
19 return adoptRef(new ImagePattern(image, repeatMode)); | 24 return adoptRef(new ImagePattern(image, repeatMode)); |
20 } | 25 } |
21 | 26 |
22 ImagePattern::ImagePattern(PassRefPtr<Image> image, RepeatMode repeatMode) | 27 ImagePattern::ImagePattern(PassRefPtr<Image> image, RepeatMode repeatMode) |
23 : Pattern(repeatMode) | 28 : Pattern(repeatMode) |
24 , m_tileImage(image->imageForCurrentFrame()) | 29 , m_tileImage(image->imageForCurrentFrame()) |
| 30 , m_image(image) |
25 { | 31 { |
26 if (m_tileImage) { | 32 if (m_tileImage) { |
27 // TODO(fmalita): mechanism to extract the actual SkImageInfo from an Sk
Image? | 33 // TODO(fmalita): mechanism to extract the actual SkImageInfo from an Sk
Image? |
28 const SkImageInfo info = | 34 const SkImageInfo info = |
29 SkImageInfo::MakeN32Premul(m_tileImage->width(), m_tileImage->height
()); | 35 SkImageInfo::MakeN32Premul(m_tileImage->width(), m_tileImage->height
()); |
30 adjustExternalMemoryAllocated(info.getSafeSize(info.minRowBytes())); | 36 adjustExternalMemoryAllocated(info.getSafeSize(info.minRowBytes())); |
31 } | 37 } |
32 } | 38 } |
33 | 39 |
| 40 inline PassRefPtr<ColorSpaceProfile> sourceColorProfile(Image* image) |
| 41 { |
| 42 return image->isBitmapImage() ? toBitmapImage(image)->colorProfile() : nullp
tr; |
| 43 } |
| 44 |
34 PassRefPtr<SkShader> ImagePattern::createShader() | 45 PassRefPtr<SkShader> ImagePattern::createShader() |
35 { | 46 { |
36 if (!m_tileImage) | 47 if (!m_tileImage) |
37 return adoptRef(SkShader::CreateColorShader(SK_ColorTRANSPARENT)); | 48 return adoptRef(SkShader::CreateColorShader(SK_ColorTRANSPARENT)); |
38 | 49 |
| 50 // Patterns of tagged images (those that have a color profile) are drawn to
sRGB |
| 51 // on supported platforms. Note the only allowed caller is the <canvas> elem
ent. |
| 52 RefPtr<SkColorFilter> colorTransform; |
| 53 if (RefPtr<ColorSpaceProfile> source = sourceColorProfile(m_image.get())) { |
| 54 RefPtr<ColorSpaceProfile> screen = screenColorProfile(currentScreenId())
; |
| 55 colorTransform = createColorSpaceFilter(source.get(), screen.get()); |
| 56 |
| 57 if (currentScreenId()) { |
| 58 fprintf(stderr, "ImagePattern::createShader has a non-zero page %ld\
n", (long int)currentScreenId()); |
| 59 fflush(stderr); |
| 60 } |
| 61 |
| 62 RELEASE_ASSERT(!currentScreenId()); // Check caller is an HTML <canvas>. |
| 63 } |
| 64 |
39 SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformatio
n); | 65 SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformatio
n); |
40 | 66 |
41 if (isRepeatXY()) { | 67 if (isRepeatXY() && !colorTransform.get()) { |
42 // Fast path: for repeatXY we just return a shader from the original ima
ge. | 68 // Fast path: for repeatXY we just return a shader from the original ima
ge. |
43 return adoptRef(m_tileImage->newShader(SkShader::kRepeat_TileMode, | 69 return adoptRef(m_tileImage->newShader(SkShader::kRepeat_TileMode, |
44 SkShader::kRepeat_TileMode, &localMatrix)); | 70 SkShader::kRepeat_TileMode, &localMatrix)); |
45 } | 71 } |
46 | 72 |
47 // Skia does not have a "draw the tile only once" option. Clamp_TileMode | 73 // Skia does not have a "draw the tile only once" option. Clamp_TileMode |
48 // repeats the last line of the image after drawing one tile. To avoid | 74 // repeats the last line of the image after drawing one tile. To avoid |
49 // filling the space with arbitrary pixels, this workaround forces the | 75 // filling the space with arbitrary pixels, this workaround forces the |
50 // image to have a line of transparent pixels on the "repeated" edge(s), | 76 // image to have a line of transparent pixels on the "repeated" edge(s), |
51 // thus causing extra space to be transparent filled. | 77 // thus causing extra space to be transparent filled. |
52 SkShader::TileMode tileModeX = isRepeatX() | 78 SkShader::TileMode tileModeX = isRepeatX() |
53 ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode; | 79 ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode; |
54 SkShader::TileMode tileModeY = isRepeatY() | 80 SkShader::TileMode tileModeY = isRepeatY() |
55 ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode; | 81 ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode; |
56 int expandW = isRepeatX() ? 0 : 1; | 82 int expandW = isRepeatX() ? 0 : 1; |
57 int expandH = isRepeatY() ? 0 : 1; | 83 int expandH = isRepeatY() ? 0 : 1; |
58 | 84 |
59 // Create a transparent image 1 pixel wider and/or taller than the | 85 // Create a transparent image 1 pixel wider and/or taller than the |
60 // original, then copy the orignal into it. | 86 // original, then copy the orignal into it. |
61 // FIXME: Is there a better way to pad (not scale) an image in skia? | 87 // FIXME: Is there a better way to pad (not scale) an image in skia? |
| 88 // since the drawing is noticably pixelated compared to drawing the |
| 89 // same tiled image with Image:drawTiled (which is used to draw CSS |
| 90 // background-image repeat tiles). |
62 RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul( | 91 RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul( |
63 m_tileImage->width() + expandW, m_tileImage->height() + expandH)); | 92 m_tileImage->width() + expandW, m_tileImage->height() + expandH)); |
64 if (!surface) | 93 if (!surface) |
65 return adoptRef(SkShader::CreateColorShader(SK_ColorTRANSPARENT)); | 94 return adoptRef(SkShader::CreateColorShader(SK_ColorTRANSPARENT)); |
| 95 surface->getCanvas()->clear(SK_ColorTRANSPARENT); |
66 | 96 |
67 surface->getCanvas()->clear(SK_ColorTRANSPARENT); | |
68 SkPaint paint; | 97 SkPaint paint; |
| 98 paint.setColorFilter(colorTransform.get()); |
69 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 99 paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
70 surface->getCanvas()->drawImage(m_tileImage.get(), 0, 0, &paint); | 100 surface->getCanvas()->drawImage(m_tileImage.get(), 0, 0, &paint); |
71 RefPtr<SkImage> expandedImage = adoptRef(surface->newImageSnapshot()); | |
72 | 101 |
73 return adoptRef(expandedImage->newShader(tileModeX, tileModeY, &localMatrix)
); | 102 RefPtr<SkImage> image = adoptRef(surface->newImageSnapshot()); |
| 103 return adoptRef(image->newShader(tileModeX, tileModeY, &localMatrix)); |
74 } | 104 } |
75 | 105 |
76 bool ImagePattern::isTextureBacked() const | 106 bool ImagePattern::isTextureBacked() const |
77 { | 107 { |
78 return m_tileImage && m_tileImage->isTextureBacked(); | 108 return m_tileImage && m_tileImage->isTextureBacked(); |
79 } | 109 } |
80 | 110 |
81 } // namespace | 111 } // namespace |
OLD | NEW |