OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "skia/ext/platform_canvas.h" | 5 #include "skia/ext/platform_canvas.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
9 #include "skia/ext/platform_device.h" | 9 #include "skia/ext/platform_device.h" |
| 10 #include "skia/ext/layer_allocator.h" |
10 #include "third_party/skia/include/core/SkMetaData.h" | 11 #include "third_party/skia/include/core/SkMetaData.h" |
11 #include "third_party/skia/include/core/SkTypes.h" | 12 #include "third_party/skia/include/core/SkTypes.h" |
12 | 13 |
13 namespace { | 14 namespace { |
14 | 15 |
15 #if defined(OS_MACOSX) | 16 #if defined(OS_MACOSX) |
16 const char kIsPreviewMetafileKey[] = "CrIsPreviewMetafile"; | 17 const char kIsPreviewMetafileKey[] = "CrIsPreviewMetafile"; |
17 | 18 |
18 void SetBoolMetaData(const SkCanvas& canvas, const char* key, bool value) { | 19 void SetBoolMetaData(const SkCanvas& canvas, const char* key, bool value) { |
19 SkMetaData& meta = skia::GetMetaData(canvas); | 20 SkMetaData& meta = skia::GetMetaData(canvas); |
20 meta.setBool(key, value); | 21 meta.setBool(key, value); |
21 } | 22 } |
22 | 23 |
23 bool GetBoolMetaData(const SkCanvas& canvas, const char* key) { | 24 bool GetBoolMetaData(const SkCanvas& canvas, const char* key) { |
24 bool value; | 25 bool value; |
25 SkMetaData& meta = skia::GetMetaData(canvas); | 26 SkMetaData& meta = skia::GetMetaData(canvas); |
26 if (!meta.findBool(key, &value)) | 27 if (!meta.findBool(key, &value)) |
27 value = false; | 28 value = false; |
28 return value; | 29 return value; |
29 } | 30 } |
30 #endif | 31 #endif |
31 | 32 |
32 } // namespace | 33 } // namespace |
33 | 34 |
34 namespace skia { | 35 namespace skia { |
35 | 36 |
| 37 #if defined(WIN32) |
| 38 |
| 39 SkCanvas* CreatePlatformCanvas(int width, |
| 40 int height, |
| 41 bool is_opaque, |
| 42 HANDLE shared_section, |
| 43 OnFailureType failure_type); |
| 44 SkImageInfo info = SkImageInfo::MakeN32(width, height, |
| 45 is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); |
| 46 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| 47 |
| 48 LayerAllocator* allocator = new LayerAllocator; |
| 49 return allocator->createCanvas(info, props, static_cast<void*>(shared_section)
).get(); |
| 50 } |
| 51 |
| 52 #elif defined(__APPLE__) |
| 53 |
| 54 // TODO(fmalita): mac implementations using LayerAllocator |
| 55 |
| 56 /* |
| 57 SkCanvas* CreatePlatformCanvas(CGContextRef context, |
| 58 int width, |
| 59 int height, |
| 60 bool is_opaque, |
| 61 OnFailureType failure_type); |
| 62 |
| 63 SkCanvas* CreatePlatformCanvas(int width, |
| 64 int height, |
| 65 bool is_opaque, |
| 66 uint8_t* context, |
| 67 OnFailureType failure_type); |
| 68 */ |
| 69 |
| 70 #elif defined(USE_OZONE) |
| 71 |
| 72 // Unlike all other linuxy versions, Chromecast doesn't have Cairo underneath; |
| 73 // we give them a plain bitmap-backed canvas. |
| 74 |
| 75 SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque, |
| 76 uint8_t* data, OnFailureType failureType) { |
| 77 SkImageInfo info = SkImageInfo::MakeN32(width, height, |
| 78 is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); |
| 79 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| 80 |
| 81 SkBitmap bitmap; |
| 82 bool success = false; |
| 83 if (data) |
| 84 success = bitmap.installPixels(info, data, info.minRowBytes()); |
| 85 else |
| 86 success = bitmap.tryAllocPixels(info); |
| 87 |
| 88 if (!success && failureType == CRASH_ON_FAILURE) |
| 89 SK_CRASH(); |
| 90 return new SkCanvas(bitmap, props); |
| 91 } |
| 92 |
| 93 #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ |
| 94 defined(__sun) || defined(ANDROID) |
| 95 |
| 96 SkCanvas* CreatePlatformCanvas(int width, int height, bool is_opaque, |
| 97 uint8_t* data, OnFailureType failureType) { |
| 98 SkImageInfo info = SkImageInfo::MakeN32(width, height, |
| 99 is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); |
| 100 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| 101 |
| 102 LayerAllocator* allocator = new LayerAllocator; |
| 103 if (!allocator && failureType == CRASH_ON_FAILURE) |
| 104 SK_CRASH(); |
| 105 |
| 106 return allocator->createCanvas(info, props, data).get(); |
| 107 } |
| 108 |
| 109 #endif |
| 110 |
36 SkBitmap ReadPixels(SkCanvas* canvas) { | 111 SkBitmap ReadPixels(SkCanvas* canvas) { |
37 SkBitmap bitmap; | 112 SkBitmap bitmap; |
38 bitmap.setInfo(canvas->imageInfo()); | 113 bitmap.setInfo(canvas->imageInfo()); |
39 canvas->readPixels(&bitmap, 0, 0); | 114 canvas->readPixels(&bitmap, 0, 0); |
40 return bitmap; | 115 return bitmap; |
41 } | 116 } |
42 | 117 |
43 bool GetWritablePixels(SkCanvas* canvas, SkPixmap* result) { | 118 bool GetWritablePixels(SkCanvas* canvas, SkPixmap* result) { |
44 if (!canvas || !result) { | 119 if (!canvas || !result) { |
45 return false; | 120 return false; |
46 } | 121 } |
47 | 122 |
48 SkImageInfo info; | 123 SkImageInfo info; |
49 size_t row_bytes; | 124 size_t row_bytes; |
50 void* pixels = canvas->accessTopLayerPixels(&info, &row_bytes); | 125 void* pixels = canvas->accessTopLayerPixels(&info, &row_bytes); |
51 if (!pixels) { | 126 if (!pixels) { |
52 result->reset(); | 127 result->reset(); |
53 return false; | 128 return false; |
54 } | 129 } |
55 | 130 |
56 result->reset(info, pixels, row_bytes); | 131 result->reset(info, pixels, row_bytes); |
57 return true; | 132 return true; |
58 } | 133 } |
59 | 134 |
60 bool SupportsPlatformPaint(const SkCanvas* canvas) { | 135 bool SupportsPlatformPaint(const SkCanvas* canvas) { |
61 return GetPlatformDevice(canvas->getTopDevice(true)) != nullptr; | 136 // Fragile: true only as long as Chrome *only* uses layer allocators |
| 137 // to allocate platform-specific raster backings. |
| 138 return canvas->getLayerAllocator() != nullptr; |
62 } | 139 } |
63 | 140 |
64 size_t PlatformCanvasStrideForWidth(unsigned width) { | 141 size_t PlatformCanvasStrideForWidth(unsigned width) { |
65 return 4 * width; | 142 return 4 * width; |
66 } | 143 } |
67 | 144 |
68 SkCanvas* CreateCanvas(const sk_sp<SkBaseDevice>& device, | |
69 OnFailureType failureType) { | |
70 if (!device) { | |
71 if (CRASH_ON_FAILURE == failureType) | |
72 SK_CRASH(); | |
73 return nullptr; | |
74 } | |
75 return new SkCanvas(device.get()); | |
76 } | |
77 | |
78 SkMetaData& GetMetaData(const SkCanvas& canvas) { | 145 SkMetaData& GetMetaData(const SkCanvas& canvas) { |
79 SkBaseDevice* device = canvas.getDevice(); | 146 SkBaseDevice* device = canvas.getDevice(); |
80 DCHECK(device != nullptr); | 147 DCHECK(device != nullptr); |
81 return device->getMetaData(); | 148 return device->getMetaData(); |
82 } | 149 } |
83 | 150 |
84 #if defined(OS_MACOSX) | 151 #if defined(OS_MACOSX) |
85 void SetIsPreviewMetafile(const SkCanvas& canvas, bool is_preview) { | 152 void SetIsPreviewMetafile(const SkCanvas& canvas, bool is_preview) { |
86 SetBoolMetaData(canvas, kIsPreviewMetafileKey, is_preview); | 153 SetBoolMetaData(canvas, kIsPreviewMetafileKey, is_preview); |
87 } | 154 } |
88 | 155 |
89 bool IsPreviewMetafile(const SkCanvas& canvas) { | 156 bool IsPreviewMetafile(const SkCanvas& canvas) { |
90 return GetBoolMetaData(canvas, kIsPreviewMetafileKey); | 157 return GetBoolMetaData(canvas, kIsPreviewMetafileKey); |
91 } | 158 } |
92 | 159 |
93 CGContextRef GetBitmapContext(const SkCanvas& canvas) { | 160 CGContextRef GetBitmapContext(const SkCanvas& canvas) { |
| 161 // TODO(fmalita): mac implementation of LayerAllocator lets us |
| 162 // get rid of this last user of GetPlatformDevice. |
94 PlatformDevice* platform_device = | 163 PlatformDevice* platform_device = |
95 GetPlatformDevice(canvas.getTopDevice(true)); | 164 GetPlatformDevice(canvas.getTopDevice(true)); |
96 SkIRect clip_bounds; | 165 SkIRect clip_bounds; |
97 canvas.getClipDeviceBounds(&clip_bounds); | 166 canvas.getClipDeviceBounds(&clip_bounds); |
98 return platform_device ? | 167 return platform_device ? |
99 platform_device->GetBitmapContext( | 168 platform_device->GetBitmapContext( |
100 canvas.getTotalMatrix(), clip_bounds) : | 169 canvas.getTotalMatrix(), clip_bounds) : |
101 nullptr; | 170 nullptr; |
102 } | 171 } |
103 | 172 |
104 #endif | 173 #endif |
105 | 174 |
106 ScopedPlatformPaint::ScopedPlatformPaint(SkCanvas* canvas) : | 175 ScopedPlatformPaint::ScopedPlatformPaint(SkCanvas* canvas) : |
107 canvas_(canvas), | 176 canvas_(canvas), |
108 platform_surface_(nullptr) { | 177 platform_surface_(nullptr) { |
109 // TODO(tomhudson) we're assuming non-null canvas? | 178 if (!canvas) { |
110 PlatformDevice* platform_device = GetPlatformDevice(canvas->getTopDevice(true)
); | 179 return; |
111 if (platform_device) { | |
112 // Compensate for drawing to a layer rather than the entire canvas | |
113 SkMatrix ctm; | |
114 SkIRect clip_bounds; | |
115 canvas->temporary_internal_describeTopLayer(&ctm, &clip_bounds); | |
116 platform_surface_ = platform_device->BeginPlatformPaint(ctm, clip_bounds); | |
117 } | 180 } |
| 181 |
| 182 SkRasterCanvasLayerAllocator* allocator = canvas->getLayerAllocator(); |
| 183 if (!allocator) { |
| 184 return; |
| 185 } |
| 186 |
| 187 // Need to use CTM & clip bounds to compensate for drawing to a layer |
| 188 // rather than the entire canvas. |
| 189 SkMatrix ctm; |
| 190 SkIRect clip_bounds; |
| 191 canvas->temporary_internal_describeTopLayer(&ctm, &clip_bounds); |
| 192 |
| 193 void* buffer = canvas->accessTopLayerPixels(nullptr, nullptr); |
| 194 platform_surface_ = |
| 195 (PlatformSurface) allocator->getNativeContext(buffer, ctm, clip_bounds); |
118 } | 196 } |
119 | 197 |
120 } // namespace skia | 198 } // namespace skia |
OLD | NEW |