Home | History | Annotate | Download | only in flock
      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