1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #include <algorithm> 10 11 #include "sprite.h" 12 13 namespace { 14 15 inline uint32_t Blend(uint32_t src1, uint32_t src2) { 16 // Divide both sources by 2, then add them together using a mask 17 // to avoid overflow. 18 src1 = (src1 >> 1) & 0x7F7F7F7F; 19 src2 = (src2 >> 1) & 0x7F7F7F7F; 20 return src1 + src2; 21 } 22 23 } // namespace 24 25 26 Sprite::Sprite(uint32_t* pixel_buffer, 27 const pp::Size& size, 28 int32_t row_bytes) { 29 SetPixelBuffer(pixel_buffer, size, row_bytes); 30 } 31 32 Sprite::~Sprite() { 33 delete[] pixel_buffer_; 34 } 35 36 void Sprite::SetPixelBuffer(uint32_t* pixel_buffer, 37 const pp::Size& size, 38 int32_t row_bytes) { 39 pixel_buffer_ = pixel_buffer; 40 pixel_buffer_size_ = size; 41 row_bytes_ = row_bytes ? row_bytes : size.width() * sizeof(uint32_t); 42 } 43 44 void Sprite::CompositeFromRectToPoint(const pp::Rect& src_rect, 45 uint32_t* dest_pixel_buffer, 46 const pp::Rect& dest_bounds, 47 int32_t dest_row_bytes, 48 const pp::Point& dest_point) const { 49 // Clip the source rect to the source image bounds. 50 pp::Rect src_bounds(pp::Point(), size()); 51 pp::Rect src_rect_clipped(src_rect.Intersect(src_bounds)); 52 if (src_rect_clipped.IsEmpty()) 53 return; 54 55 // Create a clipped rect in the destination coordinate space that contains the 56 // final image. 57 pp::Rect draw_rect(dest_point, src_rect_clipped.size()); 58 pp::Rect draw_rect_clipped(dest_bounds.Intersect(draw_rect)); 59 if (draw_rect_clipped.IsEmpty()) 60 return; 61 // Transform the dest rect to the source image coordinate system. 62 pp::Point src_offset(draw_rect_clipped.point()); 63 src_offset -= dest_point; 64 src_rect_clipped.Offset(src_offset); 65 src_rect_clipped.set_size(draw_rect_clipped.size()); 66 size_t src_byte_offset = src_rect_clipped.x() * sizeof(uint32_t) + 67 src_rect_clipped.y() * row_bytes_; 68 const uint8_t* src_pixels = 69 reinterpret_cast<const uint8_t*>(pixel_buffer_) + src_byte_offset; 70 71 if (dest_row_bytes == 0) 72 dest_row_bytes = dest_bounds.width() * sizeof(uint32_t); 73 size_t dest_byte_offset = draw_rect_clipped.point().x() * sizeof(uint32_t) + 74 draw_rect_clipped.point().y() * dest_row_bytes; 75 uint8_t* dest_pixels = reinterpret_cast<uint8_t*>(dest_pixel_buffer) + 76 dest_byte_offset; 77 78 for (int32_t y = 0; y < src_rect_clipped.height(); ++y) { 79 const uint32_t* src_scanline = 80 reinterpret_cast<const uint32_t*>(src_pixels); 81 uint32_t* dest_scanline = reinterpret_cast<uint32_t*>(dest_pixels); 82 for (int32_t x = 0; x < src_rect_clipped.width(); ++x) { 83 uint32_t src = *src_scanline++; 84 uint32_t dst = *dest_scanline; 85 *dest_scanline++ = Blend(dst, src); 86 } 87 src_pixels += row_bytes_; 88 dest_pixels += dest_row_bytes; 89 } 90 } 91 92