Changeset 58078 in webkit
- Timestamp:
- Apr 22, 2010 2:38:29 AM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r58072 r58078 1 2010-04-22 Stephan Aßmus <superstippi@gmx.de> 2 3 Reviewed by David Levin. 4 5 [Haiku] Implement ImageBuffer support 6 https://bugs.webkit.org/show_bug.cgi?id=35288 7 8 Covered by existing tests. 9 10 Complete implementation of ImageBuffer for Haiku. Uses StillImage 11 class to export a WebCore::Image and associated GraphicsContext 12 to perform arbitrary drawing in the offscreen BBitmap buffer. 13 14 * platform/graphics/haiku/ImageBufferData.h: 15 * platform/graphics/haiku/ImageBufferHaiku.cpp, 16 (WebCore::ImageBufferData::ImageBufferData), 17 (WebCore::ImageBufferData::~ImageBufferData), 18 (WebCore::ImageBuffer::ImageBuffer), 19 (WebCore::ImageBuffer::~ImageBuffer), 20 (WebCore::ImageBuffer::context), 21 (WebCore::ImageBuffer::image): 22 Implementation uses offscreen BBitmap and BView, wraps StillImage 23 around those to provide WebCore::Image interface. 24 (WebCore::ImageBuffer::platformTransformColorSpace): 25 (WebCore::convertFromData): 26 Method just performs BGRA <-> RGBA conversion. 27 (WebCore::convertFromInternalData): 28 Method just performs BGRA <-> RGBA conversion and handles 29 pre-multiplying the color values if requested. 30 (WebCore::convertToInternalData): 31 Method just performs BGRA <-> RGBA conversion and handles 32 de.multiplying the color values if requested. 33 (WebCore::getImageData): 34 Common code for the next two methods. 35 (WebCore::ImageBuffer::getUnmultipliedImageData), 36 (WebCore::ImageBuffer::getPremultipliedImageData): 37 Implemented. 38 (WebCore::putImageData): 39 Common code for the next two methods. 40 (WebCore::ImageBuffer::putUnmultipliedImageData), 41 (WebCore::ImageBuffer::putPremultipliedImageData): 42 Implemented. 43 (WebCore::ImageBuffer::toDataURL): 44 Uses Haiku "Translation Kit" to convert image data to data 45 of the requested mime type. 46 1 47 2010-04-22 Adam Barth <abarth@webkit.org> 2 48 -
trunk/WebCore/platform/graphics/haiku/ImageBufferData.h
r47463 r58078 1 1 /* 2 * Copyright (C) 20 09 Maxime Simon <simon.maxime@gmail.com>2 * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> 3 3 * 4 4 * All rights reserved. … … 29 29 #define ImageBufferData_h 30 30 31 #include <Bitmap.h> 32 #include <View.h> 33 31 34 namespace WebCore { 32 35 33 36 class IntSize; 34 37 35 36 37 38 };38 class ImageBufferData { 39 public: 40 ImageBufferData(const IntSize&); 41 ~ImageBufferData(); 39 42 40 } // namespace WebCore 43 BBitmap m_bitmap; 44 BView m_view; 45 }; 41 46 42 #endif // ImageBufferData_h 47 } // namespace WebCore 43 48 49 #endif // ImageBufferData_h 50 -
trunk/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
r47463 r58078 1 1 /* 2 * Copyright (C) 20 09 Maxime Simon <simon.maxime@gmail.com>2 * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 … … 27 27 #include "ImageBuffer.h" 28 28 29 #include "Base64.h" 29 30 #include "GraphicsContext.h" 30 31 #include "ImageData.h" 31 #include "NotImplemented.h" 32 32 #include "MIMETypeRegistry.h" 33 #include "StillImageHaiku.h" 34 #include <wtf/text/CString.h> 35 #include <BitmapStream.h> 36 #include <String.h> 37 #include <TranslatorRoster.h> 33 38 34 39 namespace WebCore { 35 40 36 ImageBufferData::ImageBufferData(const IntSize&) 37 { 38 } 39 40 ImageBuffer::ImageBuffer(const IntSize&, ImageColorSpace imageColorSpace, bool& success) 41 : m_data(IntSize()) 42 { 43 notImplemented(); 44 success = false; 41 ImageBufferData::ImageBufferData(const IntSize& size) 42 : m_bitmap(BRect(0, 0, size.width() - 1, size.height() - 1), B_RGBA32, true) 43 , m_view(m_bitmap.Bounds(), "WebKit ImageBufferData", 0, 0) 44 { 45 // Always keep the bitmap locked, we are the only client. 46 m_bitmap.Lock(); 47 m_bitmap.AddChild(&m_view); 48 49 // Fill with completely transparent color. 50 memset(m_bitmap.Bits(), 0, m_bitmap.BitsLength()); 51 52 // Since ImageBuffer is used mainly for Canvas, explicitly initialize 53 // its view's graphics state with the corresponding canvas defaults 54 // NOTE: keep in sync with CanvasRenderingContext2D::State 55 m_view.SetLineMode(B_BUTT_CAP, B_MITER_JOIN, 10); 56 m_view.SetDrawingMode(B_OP_ALPHA); 57 m_view.SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); 58 } 59 60 ImageBufferData::~ImageBufferData() 61 { 62 // Remove the view from the bitmap, keeping it from being free'd twice. 63 m_view.RemoveSelf(); 64 m_bitmap.Unlock(); 65 } 66 67 ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success) 68 : m_data(size) 69 , m_size(size) 70 { 71 m_context.set(new GraphicsContext(&m_data.m_view)); 72 success = true; 45 73 } 46 74 … … 51 79 GraphicsContext* ImageBuffer::context() const 52 80 { 53 notImplemented(); 54 return 0; 55 } 81 ASSERT(m_data.m_view.Window()); 82 83 return m_context.get(); 84 } 85 86 Image* ImageBuffer::image() const 87 { 88 if (!m_image) { 89 // It's assumed that if image() is called, the actual rendering to the 90 // GraphicsContext must be done. 91 ASSERT(context()); 92 m_data.m_view.Sync(); 93 m_image = StillImage::create(m_data.m_bitmap); 94 } 95 96 return m_image.get(); 97 } 98 99 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) 100 { 101 uint8* rowData = reinterpret_cast<uint8*>(m_data.m_bitmap.Bits()); 102 unsigned bytesPerRow = m_data.m_bitmap.BytesPerRow(); 103 unsigned rows = m_size.height(); 104 unsigned columns = m_size.width(); 105 for (unsigned y = 0; y < rows; y++) { 106 uint8* pixel = rowData; 107 for (unsigned x = 0; x < columns; x++) { 108 // lookUpTable doesn't seem to support a LUT for each color channel 109 // separately (judging from the other ports). We don't need to 110 // convert from/to pre-multiplied color space since BBitmap storage 111 // is not pre-multiplied. 112 pixel[0] = lookUpTable[pixel[0]]; 113 pixel[1] = lookUpTable[pixel[1]]; 114 pixel[2] = lookUpTable[pixel[2]]; 115 // alpha stays unmodified. 116 pixel += 4; 117 } 118 rowData += bytesPerRow; 119 } 120 } 121 122 static inline void convertFromData(const uint8* sourceRows, unsigned sourceBytesPerRow, 123 uint8* destRows, unsigned destBytesPerRow, 124 unsigned rows, unsigned columns) 125 { 126 for (unsigned y = 0; y < rows; y++) { 127 const uint8* sourcePixel = sourceRows; 128 uint8* destPixel = destRows; 129 for (unsigned x = 0; x < columns; x++) { 130 // RGBA -> BGRA or BGRA -> RGBA 131 destPixel[0] = sourcePixel[2]; 132 destPixel[1] = sourcePixel[1]; 133 destPixel[2] = sourcePixel[0]; 134 destPixel[3] = sourcePixel[3]; 135 destPixel += 4; 136 sourcePixel += 4; 137 } 138 sourceRows += sourceBytesPerRow; 139 destRows += destBytesPerRow; 140 } 141 } 142 143 static inline void convertFromInternalData(const uint8* sourceRows, unsigned sourceBytesPerRow, 144 uint8* destRows, unsigned destBytesPerRow, 145 unsigned rows, unsigned columns, 146 bool premultiplied) 147 { 148 if (premultiplied) { 149 // Internal storage is not pre-multiplied, pre-multiply on the fly. 150 for (unsigned y = 0; y < rows; y++) { 151 const uint8* sourcePixel = sourceRows; 152 uint8* destPixel = destRows; 153 for (unsigned x = 0; x < columns; x++) { 154 // RGBA -> BGRA or BGRA -> RGBA 155 destPixel[0] = static_cast<uint16>(sourcePixel[2]) * sourcePixel[3] / 255; 156 destPixel[1] = static_cast<uint16>(sourcePixel[1]) * sourcePixel[3] / 255; 157 destPixel[2] = static_cast<uint16>(sourcePixel[0]) * sourcePixel[3] / 255; 158 destPixel[3] = sourcePixel[3]; 159 destPixel += 4; 160 sourcePixel += 4; 161 } 162 sourceRows += sourceBytesPerRow; 163 destRows += destBytesPerRow; 164 } 165 } else { 166 convertFromData(sourceRows, sourceBytesPerRow, 167 destRows, destBytesPerRow, 168 rows, columns); 169 } 170 } 171 172 static inline void convertToInternalData(const uint8* sourceRows, unsigned sourceBytesPerRow, 173 uint8* destRows, unsigned destBytesPerRow, 174 unsigned rows, unsigned columns, 175 bool premultiplied) 176 { 177 if (premultiplied) { 178 // Internal storage is not pre-multiplied, de-multiply source data. 179 for (unsigned y = 0; y < rows; y++) { 180 const uint8* sourcePixel = sourceRows; 181 uint8* destPixel = destRows; 182 for (unsigned x = 0; x < columns; x++) { 183 // RGBA -> BGRA or BGRA -> RGBA 184 if (sourcePixel[3]) { 185 destPixel[0] = static_cast<uint16>(sourcePixel[2]) * 255 / sourcePixel[3]; 186 destPixel[1] = static_cast<uint16>(sourcePixel[1]) * 255 / sourcePixel[3]; 187 destPixel[2] = static_cast<uint16>(sourcePixel[0]) * 255 / sourcePixel[3]; 188 destPixel[3] = sourcePixel[3]; 189 } else { 190 destPixel[0] = 0; 191 destPixel[1] = 0; 192 destPixel[2] = 0; 193 destPixel[3] = 0; 194 } 195 destPixel += 4; 196 sourcePixel += 4; 197 } 198 sourceRows += sourceBytesPerRow; 199 destRows += destBytesPerRow; 200 } 201 } else { 202 convertFromData(sourceRows, sourceBytesPerRow, 203 destRows, destBytesPerRow, 204 rows, columns); 205 } 206 } 207 208 static PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size, bool premultiplied) 209 { 210 PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height()); 211 unsigned char* data = result->data()->data()->data(); 212 213 // If the destination image is larger than the source image, the outside 214 // regions need to be transparent. This way is simply, although with a 215 // a slight overhead for the inside region. 216 if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height()) 217 memset(data, 0, result->data()->length()); 218 219 // If the requested image is outside the source image, we can return at 220 // this point. 221 if (rect.x() > size.width() || rect.y() > size.height() || rect.right() < 0 || rect.bottom() < 0) 222 return result; 223 224 // Now we know there must be an intersection rect which we need to extract. 225 BRect sourceRect(0, 0, size.width() - 1, size.height() - 1); 226 sourceRect = BRect(rect) & sourceRect; 227 228 unsigned destBytesPerRow = 4 * rect.width(); 229 unsigned char* destRows = data; 230 // Offset the destination pointer to point at the first pixel of the 231 // intersection rect. 232 destRows += (rect.x() - static_cast<int>(sourceRect.left)) * 4 233 + (rect.y() - static_cast<int>(sourceRect.top)) * destBytesPerRow; 234 235 const uint8* sourceRows = reinterpret_cast<const uint8*>(imageData.m_bitmap.Bits()); 236 uint32 sourceBytesPerRow = imageData.m_bitmap.BytesPerRow(); 237 // Offset the source pointer to point at the first pixel of the 238 // intersection rect. 239 sourceRows += static_cast<int>(sourceRect.left) * 4 240 + static_cast<int>(sourceRect.top) * sourceBytesPerRow; 241 242 unsigned rows = sourceRect.IntegerHeight() + 1; 243 unsigned columns = sourceRect.IntegerWidth() + 1; 244 convertFromInternalData(sourceRows, sourceBytesPerRow, destRows, destBytesPerRow, 245 rows, columns, premultiplied); 246 247 return result; 248 } 249 56 250 57 251 PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const 58 252 { 59 notImplemented(); 60 return 0; 253 // Make sure all asynchronous drawing has finished 254 m_data.m_view.Sync(); 255 return getImageData(rect, m_data, m_size, false); 61 256 } 62 257 63 258 PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const 64 259 { 65 notImplemented(); 66 return 0; 260 // Make sure all asynchronous drawing has finished 261 m_data.m_view.Sync(); 262 return getImageData(rect, m_data, m_size, true); 263 } 264 265 static void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size, bool premultiplied) 266 { 267 // If the source image is outside the destination image, we can return at 268 // this point. 269 // FIXME: Check if this isn't already done in WebCore. 270 if (destPoint.x() > size.width() || destPoint.y() > size.height() 271 || destPoint.x() + sourceRect.width() < 0 272 || destPoint.y() + sourceRect.height() < 0) { 273 return; 274 } 275 276 const unsigned char* sourceRows = source->data()->data()->data(); 277 unsigned sourceBytesPerRow = 4 * source->width(); 278 // Offset the source pointer to the first pixel of the source rect. 279 sourceRows += sourceRect.x() * 4 + sourceRect.y() * sourceBytesPerRow; 280 281 // We know there must be an intersection rect. 282 BRect destRect(destPoint.x(), destPoint.y(), sourceRect.width() - 1, sourceRect.height() - 1); 283 destRect = destRect & BRect(0, 0, size.width() - 1, size.height() - 1); 284 285 unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_bitmap.Bits()); 286 uint32 destBytesPerRow = imageData.m_bitmap.BytesPerRow(); 287 // Offset the source pointer to point at the first pixel of the 288 // intersection rect. 289 destRows += static_cast<int>(destRect.left) * 4 290 + static_cast<int>(destRect.top) * destBytesPerRow; 291 292 unsigned rows = sourceRect.height(); 293 unsigned columns = sourceRect.width(); 294 convertToInternalData(sourceRows, sourceBytesPerRow, destRows, destBytesPerRow, 295 rows, columns, premultiplied); 67 296 } 68 297 69 298 void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) 70 299 { 71 notImplemented(); 300 // Make sure all asynchronous drawing has finished 301 m_data.m_view.Sync(); 302 putImageData(source, sourceRect, destPoint, m_data, m_size, false); 72 303 } 73 304 74 305 void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) 75 306 { 76 notImplemented(); 77 } 78 79 String ImageBuffer::toDataURL(const String&) const 80 { 81 notImplemented(); 82 return String(); 83 } 84 85 Image* ImageBuffer::image() const 86 { 87 notImplemented(); 88 return 0; 89 } 90 91 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) 92 { 93 notImplemented(); 307 // Make sure all asynchronous drawing has finished 308 m_data.m_view.Sync(); 309 putImageData(source, sourceRect, destPoint, m_data, m_size, true); 310 } 311 312 String ImageBuffer::toDataURL(const String& mimeType) const 313 { 314 if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) 315 return "data:,"; 316 317 BString mimeTypeString(mimeType); 318 319 uint32 translatorType = 0; 320 321 BTranslatorRoster* roster = BTranslatorRoster::Default(); 322 translator_id* translators; 323 int32 translatorCount; 324 roster->GetAllTranslators(&translators, &translatorCount); 325 for (int32 i = 0; i < translatorCount; i++) { 326 // Skip translators that don't support archived BBitmaps as input data. 327 const translation_format* inputFormats; 328 int32 formatCount; 329 roster->GetInputFormats(translators[i], &inputFormats, &formatCount); 330 bool supportsBitmaps = false; 331 for (int32 j = 0; j < formatCount; j++) { 332 if (inputFormats[j].type == B_TRANSLATOR_BITMAP) { 333 supportsBitmaps = true; 334 break; 335 } 336 } 337 if (!supportsBitmaps) 338 continue; 339 340 const translation_format* outputFormats; 341 roster->GetOutputFormats(translators[i], &outputFormats, &formatCount); 342 for (int32 j = 0; j < formatCount; j++) { 343 if (outputFormats[j].group == B_TRANSLATOR_BITMAP 344 && mimeTypeString == outputFormats[j].MIME) { 345 translatorType = outputFormats[j].type; 346 } 347 } 348 if (translatorType) 349 break; 350 } 351 352 353 BMallocIO translatedStream; 354 BBitmap* bitmap = const_cast<BBitmap*>(&m_data.m_bitmap); 355 // BBitmapStream doesn't take "const Bitmap*"... 356 BBitmapStream bitmapStream(bitmap); 357 if (roster->Translate(&bitmapStream, 0, 0, &translatedStream, translatorType, 358 B_TRANSLATOR_BITMAP, mimeType.utf8().data()) != B_OK) { 359 bitmapStream.DetachBitmap(&bitmap); 360 return "data:,"; 361 } 362 363 bitmapStream.DetachBitmap(&bitmap); 364 365 Vector<char> encodedBuffer; 366 base64Encode(reinterpret_cast<const char*>(translatedStream.Buffer()), 367 translatedStream.BufferLength(), encodedBuffer); 368 369 return String::format("data:%s;base64,%s", mimeType.utf8().data(), 370 encodedBuffer.data()); 94 371 } 95 372
Note: See TracChangeset
for help on using the changeset viewer.