1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "pdf/draw_utils.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <algorithm> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <math.h> 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector> 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/numerics/safe_math.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace chrome_pdf { 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetBlue(const uint32& pixel) { 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<uint8>(pixel & 0xFF); 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetGreen(const uint32& pixel) { 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<uint8>((pixel >> 8) & 0xFF); 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetRed(const uint32& pixel) { 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<uint8>((pixel >> 16) & 0xFF); 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetAlpha(const uint32& pixel) { 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<uint8>((pixel >> 24) & 0xFF); 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint32_t MakePixel(uint8 red, uint8 green, uint8 blue, uint8 alpha) { 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (static_cast<uint32_t>(alpha) << 24) | 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (static_cast<uint32_t>(red) << 16) | 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (static_cast<uint32_t>(green) << 8) | 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static_cast<uint32_t>(blue); 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GradientChannel(uint8 start, uint8 end, double ratio) { 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double new_channel = start - (static_cast<double>(start) - end) * ratio; 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_channel < 0) 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_channel > 255) 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 255; 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<uint8>(new_channel + 0.5); 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 ProcessColor(uint8 src_color, uint8 dest_color, uint8 alpha) { 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32 processed = static_cast<uint32>(src_color) * alpha + 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static_cast<uint32>(dest_color) * (0xFF - alpha); 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<uint8>((processed / 0xFF) & 0xFF); 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciinline bool ImageDataContainsRect(const pp::ImageData& image_data, 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const pp::Rect& rect) { 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return rect.width() >= 0 && rect.height() >= 0 && 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::Rect(image_data.size()).Contains(rect); 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AlphaBlend(const pp::ImageData& src, const pp::Rect& src_rc, 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::ImageData* dest, const pp::Point& dest_origin, 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 alpha_adjustment) { 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (src_rc.IsEmpty() || !ImageDataContainsRect(src, src_rc)) 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::Rect dest_rc(dest_origin, src_rc.size()); 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (dest_rc.IsEmpty() || !ImageDataContainsRect(*dest, dest_rc)) 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point()); 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* dest_origin_pixel = dest->GetAddr32(dest_origin); 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int height = src_rc.height(); 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int width = src_rc.width(); 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int y = 0; y < height; y++) { 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint32_t* src_pixel = src_origin_pixel; 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* dest_pixel = dest_origin_pixel; 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int x = 0; x < width; x++) { 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 alpha = static_cast<uint8>(static_cast<uint32_t>(alpha_adjustment) * 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetAlpha(*src_pixel) / 0xFF); 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 red = ProcessColor(GetRed(*src_pixel), GetRed(*dest_pixel), alpha); 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 green = ProcessColor(GetGreen(*src_pixel), 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetGreen(*dest_pixel), alpha); 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 blue = ProcessColor(GetBlue(*src_pixel), 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetBlue(*dest_pixel), alpha); 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *dest_pixel = MakePixel(red, green, blue, GetAlpha(*dest_pixel)); 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) src_pixel++; 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dest_pixel++; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) src_origin_pixel = reinterpret_cast<const uint32_t*>( 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<const char*>(src_origin_pixel) + src.stride()); 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dest_origin_pixel = reinterpret_cast<uint32_t*>( 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<char*>(dest_origin_pixel) + dest->stride()); 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GradientFill(pp::ImageData* image, const pp::Rect& rc, 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32 start_color, uint32 end_color, bool horizontal) { 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<uint32> colors; 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) colors.resize(horizontal ? rc.width() : rc.height()); 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < colors.size(); ++i) { 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double ratio = static_cast<double>(i) / colors.size(); 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) colors[i] = MakePixel( 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GradientChannel(GetRed(start_color), GetRed(end_color), ratio), 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GradientChannel(GetGreen(start_color), GetGreen(end_color), ratio), 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GradientChannel(GetBlue(start_color), GetBlue(end_color), ratio), 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GradientChannel(GetAlpha(start_color), GetAlpha(end_color), ratio)); 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (horizontal) { 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const void* data = &(colors[0]); 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t size = colors.size() * 4; 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* origin_pixel = image->GetAddr32(rc.point()); 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int y = 0; y < rc.height(); y++) { 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memcpy(origin_pixel, data, size); 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) origin_pixel = reinterpret_cast<uint32_t*>( 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<char*>(origin_pixel) + image->stride()); 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* origin_pixel = image->GetAddr32(rc.point()); 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int y = 0; y < rc.height(); y++) { 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* pixel = origin_pixel; 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int x = 0; x < rc.width(); x++) { 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *pixel = colors[y]; 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pixel++; 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) origin_pixel = reinterpret_cast<uint32_t*>( 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<char*>(origin_pixel) + image->stride()); 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GradientFill(pp::Instance* instance, 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::ImageData* image, 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const pp::Rect& dirty_rc, 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const pp::Rect& gradient_rc, 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32 start_color, 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32 end_color, 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool horizontal, 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 transparency) { 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Rect draw_rc = gradient_rc.Intersect(dirty_rc); 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (draw_rc.IsEmpty()) 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::ImageData gradient(instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL, 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) gradient_rc.size(), false); 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GradientFill(&gradient, pp::Rect(pp::Point(), gradient_rc.size()), 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) start_color, end_color, horizontal); 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Rect copy_rc(draw_rc); 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) copy_rc.Offset(-gradient_rc.x(), -gradient_rc.y()); 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AlphaBlend(gradient, copy_rc, image, draw_rc.point(), transparency); 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CopyImage(const pp::ImageData& src, const pp::Rect& src_rc, 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::ImageData* dest, const pp::Rect& dest_rc, 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool stretch) { 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (src_rc.IsEmpty() || !ImageDataContainsRect(src, src_rc)) 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pp::Rect stretched_rc(dest_rc.point(), 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci stretch ? dest_rc.size() : src_rc.size()); 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (stretched_rc.IsEmpty() || !ImageDataContainsRect(*dest, stretched_rc)) 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point()); 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* dest_origin_pixel = dest->GetAddr32(dest_rc.point()); 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stretch) { 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double x_ratio = static_cast<double>(src_rc.width()) / dest_rc.width(); 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double y_ratio = static_cast<double>(src_rc.height()) / dest_rc.height(); 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int32_t height = dest_rc.height(); 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int32_t width = dest_rc.width(); 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int32_t y = 0; y < height; ++y) { 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* dest_pixel = dest_origin_pixel; 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int32_t x = 0; x < width; ++x) { 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32 src_x = static_cast<uint32>(x * x_ratio); 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32 src_y = static_cast<uint32>(y * y_ratio); 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint32_t* src_pixel = src.GetAddr32( 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Point(src_rc.x() + src_x, src_rc.y() + src_y)); 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *dest_pixel = *src_pixel; 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dest_pixel++; 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dest_origin_pixel = reinterpret_cast<uint32_t*>( 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<char*>(dest_origin_pixel) + dest->stride()); 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int32_t height = src_rc.height(); 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::CheckedNumeric<int32_t> width_bytes = src_rc.width(); 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch width_bytes *= 4; 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int32_t y = 0; y < height; ++y) { 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch memcpy(dest_origin_pixel, src_origin_pixel, width_bytes.ValueOrDie()); 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) src_origin_pixel = reinterpret_cast<const uint32_t*>( 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<const char*>(src_origin_pixel) + src.stride()); 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dest_origin_pixel = reinterpret_cast<uint32_t*>( 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<char*>(dest_origin_pixel) + dest->stride()); 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FillRect(pp::ImageData* image, const pp::Rect& rc, uint32 color) { 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int height = rc.height(); 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (height == 0) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fill in first row. 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* top_line = image->GetAddr32(rc.point()); 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int width = rc.width(); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int x = 0; x < width; x++) 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) top_line[x] = color; 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fill in the rest of the rectangle. 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int byte_width = width * 4; 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* cur_line = reinterpret_cast<uint32_t*>( 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<char*>(top_line) + image->stride()); 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int y = 1; y < height; y++) { 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memcpy(cur_line, top_line, byte_width); 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cur_line = reinterpret_cast<uint32_t*>( 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reinterpret_cast<char*>(cur_line) + image->stride()); 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShadowMatrix::ShadowMatrix(uint32 depth, double factor, uint32 background) 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : depth_(depth), factor_(factor), background_(background) { 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(depth_ > 0); 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) matrix_.resize(depth_ * depth_); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // pv - is a rounding power factor for smoothing corners. 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // pv = 2.0 will make corners completely round. 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const double pv = 4.0; 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // pow_pv - cache to avoid recalculating pow(x, pv) every time. 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<double> pow_pv(depth_, 0.0); 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double r = static_cast<double>(depth_); 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double coef = 256.0 / pow(r, factor); 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (uint32 y = 0; y < depth_; y++) { 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Since matrix is symmetrical, we can reduce the number of calculations 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // by mirroring results. 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (uint32 x = 0; x <= y; x++) { 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fill cache if needed. 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (pow_pv[x] == 0.0) 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pow_pv[x] = pow(x, pv); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (pow_pv[y] == 0.0) 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pow_pv[y] = pow(y, pv); 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // v - is a value for the smoothing function. 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If x == 0 simplify calculations. 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double v = (x == 0) ? y : pow(pow_pv[x] + pow_pv[y], 1 / pv); 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Smoothing function. 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If factor == 1, smoothing will be linear from 0 to the end, 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // if 0 < factor < 1, smoothing will drop faster near 0. 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // if factor > 1, smoothing will drop faster near the end (depth). 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) double f = 256.0 - coef * pow(v, factor); 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 alpha = 0; 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (f > kOpaqueAlpha) 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) alpha = kOpaqueAlpha; 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (f < kTransparentAlpha) 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) alpha = kTransparentAlpha; 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) alpha = static_cast<uint8>(f); 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 red = ProcessColor(0, GetRed(background), alpha); 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 green = ProcessColor(0, GetGreen(background), alpha); 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 blue = ProcessColor(0, GetBlue(background), alpha); 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32 pixel = MakePixel(red, green, blue, GetAlpha(background)); 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Mirror matrix. 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) matrix_[y * depth_ + x] = pixel; 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) matrix_[x * depth_ + y] = pixel; 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShadowMatrix::~ShadowMatrix() { 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintShadow(pp::ImageData* image, 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const pp::Rect& clip_rc, 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const pp::Rect& shadow_rc, 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const ShadowMatrix& matrix) { 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Rect draw_rc = shadow_rc.Intersect(clip_rc); 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (draw_rc.IsEmpty()) 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int32 depth = static_cast<int32>(matrix.depth()); 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int32_t y = draw_rc.y(); y < draw_rc.bottom(); y++) { 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int32_t x = draw_rc.x(); x < draw_rc.right(); x++) { 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int32_t matrix_x = std::max(depth + shadow_rc.x() - x - 1, 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) depth - shadow_rc.right() + x); 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int32_t matrix_y = std::max(depth + shadow_rc.y() - y - 1, 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) depth - shadow_rc.bottom() + y); 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t* pixel = image->GetAddr32(pp::Point(x, y)); 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (matrix_x < 0) 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) matrix_x = 0; 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (matrix_x >= static_cast<int32>(depth)) 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) matrix_x = depth - 1; 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (matrix_y < 0) 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) matrix_y = 0; 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (matrix_y >= static_cast<int32>(depth)) 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) matrix_y = depth - 1; 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *pixel = matrix.GetValue(matrix_x, matrix_y); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DrawShadow(pp::ImageData* image, 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const pp::Rect& shadow_rc, 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const pp::Rect& object_rc, 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const pp::Rect& clip_rc, 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const ShadowMatrix& matrix) { 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (shadow_rc == object_rc) 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; // Nothing to paint. 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fill top part. 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Rect rc(shadow_rc.point(), 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pp::Size(shadow_rc.width(), object_rc.y() - shadow_rc.y())); 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fill bottom part. 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) rc = pp::Rect(shadow_rc.x(), object_rc.bottom(), 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shadow_rc.width(), shadow_rc.bottom() - object_rc.bottom()); 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fill left part. 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) rc = pp::Rect(shadow_rc.x(), object_rc.y(), 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) object_rc.x() - shadow_rc.x(), object_rc.height()); 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Fill right part. 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) rc = pp::Rect(object_rc.right(), object_rc.y(), 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shadow_rc.right() - object_rc.right(), object_rc.height()); 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace chrome_pdf 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 344