⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imageskia.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2008, Google Inc. All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: *  *     * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. *     * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. *     * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "BitmapImage.h"#include "BitmapImageSingleFrameSkia.h"#include "ChromiumBridge.h"#include "FloatConversion.h"#include "FloatRect.h"#include "GraphicsContext.h"#include "Logging.h"#include "NativeImageSkia.h"#include "NotImplemented.h"#include "PlatformContextSkia.h"#include "PlatformString.h"#include "SkiaUtils.h"#include "SkShader.h"#include "TransformationMatrix.h"#include "skia/ext/image_operations.h"#include "skia/ext/platform_canvas.h"namespace WebCore {// Used by computeResamplingMode to tell how bitmaps should be resampled.enum ResamplingMode {    // Nearest neighbor resampling. Used when we detect that the page is    // trying to make a pattern by stretching a small bitmap very large.    RESAMPLE_NONE,    // Default skia resampling. Used for large growing of images where high    // quality resampling doesn't get us very much except a slowdown.    RESAMPLE_LINEAR,    // High quality resampling.    RESAMPLE_AWESOME,};static ResamplingMode computeResamplingMode(const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight){    int destIWidth = static_cast<int>(destWidth);    int destIHeight = static_cast<int>(destHeight);    // The percent change below which we will not resample. This usually means    // an off-by-one error on the web page, and just doing nearest neighbor    // sampling is usually good enough.    const float kFractionalChangeThreshold = 0.025f;    // Images smaller than this in either direction are considered "small" and    // are not resampled ever (see below).    const int kSmallImageSizeThreshold = 8;    // The amount an image can be stretched in a single direction before we    // say that it is being stretched so much that it must be a line or    // background that doesn't need resampling.    const float kLargeStretch = 3.0f;    // Figure out if we should resample this image. We try to prune out some    // common cases where resampling won't give us anything, since it is much    // slower than drawing stretched.    if (srcWidth == destIWidth && srcHeight == destIHeight) {        // We don't need to resample if the source and destination are the same.        return RESAMPLE_NONE;    }    if (srcWidth <= kSmallImageSizeThreshold        || srcHeight <= kSmallImageSizeThreshold        || destWidth <= kSmallImageSizeThreshold        || destHeight <= kSmallImageSizeThreshold) {        // Never resample small images. These are often used for borders and        // rules (think 1x1 images used to make lines).        return RESAMPLE_NONE;    }    if (srcHeight * kLargeStretch <= destHeight || srcWidth * kLargeStretch <= destWidth) {        // Large image detected.        // Don't resample if it is being stretched a lot in only one direction.        // This is trying to catch cases where somebody has created a border        // (which might be large) and then is stretching it to fill some part        // of the page.        if (srcWidth == destWidth || srcHeight == destHeight)            return RESAMPLE_NONE;        // The image is growing a lot and in more than one direction. Resampling        // is slow and doesn't give us very much when growing a lot.        return RESAMPLE_LINEAR;    }    if ((fabs(destWidth - srcWidth) / srcWidth < kFractionalChangeThreshold)        && (fabs(destHeight - srcHeight) / srcHeight < kFractionalChangeThreshold)) {        // It is disappointingly common on the web for image sizes to be off by        // one or two pixels. We don't bother resampling if the size difference        // is a small fraction of the original size.        return RESAMPLE_NONE;    }    // When the image is not yet done loading, use linear. We don't cache the    // partially resampled images, and as they come in incrementally, it causes    // us to have to resample the whole thing every time.    if (!bitmap.isDataComplete())        return RESAMPLE_LINEAR;    // Everything else gets resampled.    return RESAMPLE_AWESOME;}// Draws the given bitmap to the given canvas. The subset of the source bitmap// identified by src_rect is drawn to the given destination rect. The bitmap// will be resampled to resample_width * resample_height (this is the size of// the whole image, not the subset). See shouldResampleBitmap for more.//// This does a lot of computation to resample only the portion of the bitmap// that will only be drawn. This is critical for performance since when we are// scrolling, for example, we are only drawing a small strip of the image.// Resampling the whole image every time is very slow, so this speeds up things// dramatically.static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkIRect& srcIRect, const SkRect& destRect){    // First get the subset we need. This is efficient and does not copy pixels.    SkBitmap subset;    bitmap.extractSubset(&subset, srcIRect);    SkRect srcRect;    srcRect.set(srcIRect);    // Whether we're doing a subset or using the full source image.    bool srcIsFull = srcIRect.fLeft == 0 && srcIRect.fTop == 0        && srcIRect.width() == bitmap.width()        && srcIRect.height() == bitmap.height();    // We will always draw in integer sizes, so round the destination rect.    SkIRect destRectRounded;    destRect.round(&destRectRounded);    SkIRect resizedImageRect;  // Represents the size of the resized image.    resizedImageRect.set(0, 0, destRectRounded.width(), destRectRounded.height());    if (srcIsFull && bitmap.hasResizedBitmap(destRectRounded.width(), destRectRounded.height())) {        // Yay, this bitmap frame already has a resized version.        SkBitmap resampled = bitmap.resizedBitmap(destRectRounded.width(), destRectRounded.height());        canvas.drawBitmapRect(resampled, 0, destRect, &paint);        return;    }    // Compute the visible portion of our rect.    SkRect destBitmapSubsetSk;    ClipRectToCanvas(canvas, destRect, &destBitmapSubsetSk);    destBitmapSubsetSk.offset(-destRect.fLeft, -destRect.fTop);    // The matrix inverting, etc. could have introduced rounding error which    // causes the bounds to be outside of the resized bitmap. We round outward    // so we always lean toward it being larger rather than smaller than we    // need, and then clamp to the bitmap bounds so we don't get any invalid    // data.    SkIRect destBitmapSubsetSkI;    destBitmapSubsetSk.roundOut(&destBitmapSubsetSkI);    if (!destBitmapSubsetSkI.intersect(resizedImageRect))        return;  // Resized image does not intersect.    if (srcIsFull && bitmap.shouldCacheResampling(            resizedImageRect.width(),            resizedImageRect.height(),            destBitmapSubsetSkI.width(),            destBitmapSubsetSkI.height())) {        // We're supposed to resize the entire image and cache it, even though        // we don't need all of it.        SkBitmap resampled = bitmap.resizedBitmap(destRectRounded.width(),                                                  destRectRounded.height());        canvas.drawBitmapRect(resampled, 0, destRect, &paint);    } else {        // We should only resize the exposed part of the bitmap to do the        // minimal possible work.        gfx::Rect destBitmapSubset(destBitmapSubsetSkI.fLeft,                                   destBitmapSubsetSkI.fTop,                                   destBitmapSubsetSkI.width(),                                   destBitmapSubsetSkI.height());        // Resample the needed part of the image.        SkBitmap resampled = skia::ImageOperations::Resize(subset,            skia::ImageOperations::RESIZE_LANCZOS3,            destRectRounded.width(), destRectRounded.height(),            destBitmapSubset);        // Compute where the new bitmap should be drawn. Since our new bitmap        // may be smaller than the original, we have to shift it over by the        // same amount that we cut off the top and left.        SkRect offsetDestRect = {            destBitmapSubset.x() + destRect.fLeft,            destBitmapSubset.y() + destRect.fTop,            destBitmapSubset.right() + destRect.fLeft,            destBitmapSubset.bottom() + destRect.fTop };        canvas.drawBitmapRect(resampled, 0, offsetDestRect, &paint);    }}static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkPorterDuff::Mode& compOp){    SkPaint paint;    paint.setPorterDuffXfermode(compOp);    paint.setFilterBitmap(true);    skia::PlatformCanvas* canvas = platformContext->canvas();    ResamplingMode resampling = platformContext->isPrinting() ? RESAMPLE_NONE :

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -