// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include #include "sprite.h" namespace { inline uint32_t Blend(uint32_t src1, uint32_t src2) { // Divide both sources by 2, then add them together using a mask // to avoid overflow. src1 = (src1 >> 1) & 0x7F7F7F7F; src2 = (src2 >> 1) & 0x7F7F7F7F; return src1 + src2; } } // namespace Sprite::Sprite(uint32_t* pixel_buffer, const pp::Size& size, int32_t row_bytes) { SetPixelBuffer(pixel_buffer, size, row_bytes); } Sprite::~Sprite() { delete[] pixel_buffer_; } void Sprite::SetPixelBuffer(uint32_t* pixel_buffer, const pp::Size& size, int32_t row_bytes) { pixel_buffer_ = pixel_buffer; pixel_buffer_size_ = size; row_bytes_ = row_bytes ? row_bytes : size.width() * sizeof(uint32_t); } void Sprite::CompositeFromRectToPoint(const pp::Rect& src_rect, uint32_t* dest_pixel_buffer, const pp::Rect& dest_bounds, int32_t dest_row_bytes, const pp::Point& dest_point) const { // Clip the source rect to the source image bounds. pp::Rect src_bounds(pp::Point(), size()); pp::Rect src_rect_clipped(src_rect.Intersect(src_bounds)); if (src_rect_clipped.IsEmpty()) return; // Create a clipped rect in the destination coordinate space that contains the // final image. pp::Rect draw_rect(dest_point, src_rect_clipped.size()); pp::Rect draw_rect_clipped(dest_bounds.Intersect(draw_rect)); if (draw_rect_clipped.IsEmpty()) return; // Transform the dest rect to the source image coordinate system. pp::Point src_offset(draw_rect_clipped.point()); src_offset -= dest_point; src_rect_clipped.Offset(src_offset); src_rect_clipped.set_size(draw_rect_clipped.size()); size_t src_byte_offset = src_rect_clipped.x() * sizeof(uint32_t) + src_rect_clipped.y() * row_bytes_; const uint8_t* src_pixels = reinterpret_cast(pixel_buffer_) + src_byte_offset; if (dest_row_bytes == 0) dest_row_bytes = dest_bounds.width() * sizeof(uint32_t); size_t dest_byte_offset = draw_rect_clipped.point().x() * sizeof(uint32_t) + draw_rect_clipped.point().y() * dest_row_bytes; uint8_t* dest_pixels = reinterpret_cast(dest_pixel_buffer) + dest_byte_offset; for (int32_t y = 0; y < src_rect_clipped.height(); ++y) { const uint32_t* src_scanline = reinterpret_cast(src_pixels); uint32_t* dest_scanline = reinterpret_cast(dest_pixels); for (int32_t x = 0; x < src_rect_clipped.width(); ++x) { uint32_t src = *src_scanline++; uint32_t dst = *dest_scanline; *dest_scanline++ = Blend(dst, src); } src_pixels += row_bytes_; dest_pixels += dest_row_bytes; } }