本文整理汇总了C++中NativeImageSkia类的典型用法代码示例。如果您正苦于以下问题:C++ NativeImageSkia类的具体用法?C++ NativeImageSkia怎么用?C++ NativeImageSkia使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了NativeImageSkia类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: paintSkBitmap
static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp)
{
#if PLATFORM(CHROMIUM)
TRACE_EVENT("paintSkBitmap", platformContext, 0);
#endif
SkPaint paint;
paint.setXfermodeMode(compOp);
paint.setFilterBitmap(true);
paint.setAlpha(platformContext->getNormalizedAlpha());
paint.setLooper(platformContext->getDrawLooper());
// only antialias if we're rotated or skewed
paint.setAntiAlias(hasNon90rotation(platformContext));
SkCanvas* canvas = platformContext->canvas();
ResamplingMode resampling;
if (platformContext->isAccelerated())
resampling = RESAMPLE_LINEAR;
else
resampling = platformContext->printing() ? RESAMPLE_NONE :
computeResamplingMode(platformContext, bitmap, srcRect.width(), srcRect.height(), SkScalarToFloat(destRect.width()), SkScalarToFloat(destRect.height()));
if (resampling == RESAMPLE_AWESOME) {
drawResampledBitmap(*canvas, paint, bitmap, srcRect, destRect);
} else {
// No resampling necessary, we can just draw the bitmap. We want to
// filter it if we decided to do linear interpolation above, or if there
// is something interesting going on with the matrix (like a rotation).
// Note: for serialization, we will want to subset the bitmap first so
// we don't send extra pixels.
canvas->drawBitmapRect(bitmap.bitmap(), &srcRect, destRect, &paint);
}
platformContext->didDrawRect(destRect, paint, &bitmap.bitmap());
}
示例2: loadBufferingImageData
static void loadBufferingImageData()
{
static bool loaded = false;
if (!loaded) {
static Image* bufferingIcon = Image::loadPlatformResource("vidbuffer").leakRef();
NativeImageSkia* nativeImage = bufferingIcon->nativeImageForCurrentFrame();
if (!nativeImage)
return;
if (!nativeImage->isDataComplete())
return;
loaded = true;
nativeImage->bitmap().lockPixels();
int bufSize = nativeImage->bitmap().width() * nativeImage->bitmap().height() * 4;
s_bufferingImageWidth = nativeImage->bitmap().width();
s_bufferingImageHeight = nativeImage->bitmap().height();
s_bufferingImageData = static_cast<char*>(malloc(bufSize));
memcpy(s_bufferingImageData, nativeImage->bitmap().getPixels(), bufSize);
nativeImage->bitmap().unlockPixels();
bufferingIcon->deref();
}
}
示例3: createDragImageFromImage
DragImageRef createDragImageFromImage(Image* image)
{
if (!image)
return 0;
NativeImageSkia* bitmap = image->nativeImageForCurrentFrame();
if (!bitmap)
return 0;
SkBitmap* dragImage = new SkBitmap();
bitmap->bitmap().copyTo(dragImage, SkBitmap::kARGB_8888_Config);
return dragImage;
}
示例4: startAnimation
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, RespectImageOrientationEnum shouldRespectImageOrientation)
{
if (!m_source.initialized())
return;
// Spin the animation to the correct frame before we try to draw it, so we
// don't draw an old frame and then immediately need to draw a newer one,
// causing flicker and wasting CPU.
startAnimation();
NativeImageSkia* bm = nativeImageForCurrentFrame();
if (!bm)
return; // It's too early and we don't have an image yet.
FloatRect normDstRect = normalizeRect(dstRect);
FloatRect normSrcRect = normalizeRect(srcRect);
normSrcRect.intersect(FloatRect(0, 0, bm->bitmap().width(), bm->bitmap().height()));
if (normSrcRect.isEmpty() || normDstRect.isEmpty())
return; // Nothing to draw.
ImageOrientation orientation = DefaultImageOrientation;
if (shouldRespectImageOrientation == RespectImageOrientation)
orientation = frameOrientationAtIndex(m_currentFrame);
GraphicsContextStateSaver saveContext(*ctxt, false);
if (orientation != DefaultImageOrientation) {
saveContext.save();
// ImageOrientation expects the origin to be at (0, 0)
ctxt->translate(normDstRect.x(), normDstRect.y());
normDstRect.setLocation(FloatPoint());
ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size()));
if (orientation.usesWidthAsHeight()) {
// The destination rect will have it's width and height already reversed for the orientation of
// the image, as it was needed for page layout, so we need to reverse it back here.
normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRect.height(), normDstRect.width());
}
}
paintSkBitmap(ctxt->platformContext(),
*bm,
normSrcRect,
normDstRect,
WebCoreCompositeToSkiaComposite(compositeOp));
if (ImageObserver* observer = imageObserver())
observer->didDraw(this);
}
示例5: iconDatabase
void FrameLoaderClientBlackBerry::dispatchDidReceiveIcon()
{
String url = m_frame->document()->url().string();
Image* img = iconDatabase().synchronousIconForPageURL(url, IntSize(10, 10));
if (!img || !img->data())
return;
NativeImageSkia* bitmap = img->nativeImageForCurrentFrame();
if (!bitmap)
return;
bitmap->lockPixels();
String iconUrl = iconDatabase().synchronousIconURLForPageURL(url);
m_webPagePrivate->m_client->setFavicon(img->width(), img->height(), (unsigned char*)bitmap->getPixels(), iconUrl.utf8().data());
bitmap->unlockPixels();
}
示例6: createDragImageFromImage
DragImageRef createDragImageFromImage(Image* image, RespectImageOrientationEnum shouldRespectImageOrientation)
{
if (!image)
return 0;
NativeImageSkia* bitmap = image->nativeImageForCurrentFrame();
if (!bitmap)
return 0;
DragImageChromium* dragImageChromium = new DragImageChromium;
dragImageChromium->bitmap = new SkBitmap();
dragImageChromium->resolutionScale = bitmap->resolutionScale();
if (image->isBitmapImage()) {
ImageOrientation orientation = DefaultImageOrientation;
BitmapImage* bitmapImage = static_cast<BitmapImage*>(image);
IntSize sizeRespectingOrientation = bitmapImage->sizeRespectingOrientation();
if (shouldRespectImageOrientation == RespectImageOrientation)
orientation = bitmapImage->currentFrameOrientation();
if (orientation != DefaultImageOrientation) {
// Construct a correctly-rotated copy of the image to use as the drag image.
dragImageChromium->bitmap->setConfig(
SkBitmap::kARGB_8888_Config, sizeRespectingOrientation.width(), sizeRespectingOrientation.height());
dragImageChromium->bitmap->allocPixels();
FloatRect destRect(FloatPoint(), sizeRespectingOrientation);
SkCanvas canvas(*dragImageChromium->bitmap);
canvas.concat(orientation.transformFromDefault(sizeRespectingOrientation));
if (orientation.usesWidthAsHeight())
destRect = FloatRect(destRect.x(), destRect.y(), destRect.height(), destRect.width());
canvas.drawBitmapRect(bitmap->bitmap(), 0, destRect);
return dragImageChromium;
}
}
bitmap->bitmap().copyTo(dragImageChromium->bitmap, SkBitmap::kARGB_8888_Config);
return dragImageChromium;
}
示例7: extractScaledImageFragment
// This function is used to scale an image and extract a scaled fragment.
//
// ALGORITHM
//
// Because the scaled image size has to be integers, we approximate the real
// scale with the following formula (only X direction is shown):
//
// scaledImageWidth = round(scaleX * imageRect.width())
// approximateScaleX = scaledImageWidth / imageRect.width()
//
// With this method we maintain a constant scale factor among fragments in
// the scaled image. This allows fragments to stitch together to form the
// full scaled image. The downside is there will be a small difference
// between |scaleX| and |approximateScaleX|.
//
// A scaled image fragment is identified by:
//
// - Scaled image size
// - Scaled image fragment rectangle (IntRect)
//
// Scaled image size has been determined and the next step is to compute the
// rectangle for the scaled image fragment which needs to be an IntRect.
//
// scaledSrcRect = srcRect * (approximateScaleX, approximateScaleY)
// enclosingScaledSrcRect = enclosingIntRect(scaledSrcRect)
//
// Finally we extract the scaled image fragment using
// (scaledImageSize, enclosingScaledSrcRect).
//
static SkBitmap extractScaledImageFragment(const NativeImageSkia& bitmap, const SkRect& srcRect, float scaleX, float scaleY, SkRect* scaledSrcRect, SkIRect* enclosingScaledSrcRect)
{
SkISize imageSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height());
SkISize scaledImageSize = SkISize::Make(clampToInteger(roundf(imageSize.width() * scaleX)),
clampToInteger(roundf(imageSize.height() * scaleY)));
SkRect imageRect = SkRect::MakeWH(imageSize.width(), imageSize.height());
SkRect scaledImageRect = SkRect::MakeWH(scaledImageSize.width(), scaledImageSize.height());
SkMatrix scaleTransform;
scaleTransform.setRectToRect(imageRect, scaledImageRect, SkMatrix::kFill_ScaleToFit);
scaleTransform.mapRect(scaledSrcRect, srcRect);
scaledSrcRect->intersect(scaledImageRect);
*enclosingScaledSrcRect = enclosingIntRect(*scaledSrcRect);
// |enclosingScaledSrcRect| can be larger than |scaledImageSize| because
// of float inaccuracy so clip to get inside.
enclosingScaledSrcRect->intersect(SkIRect::MakeSize(scaledImageSize));
return bitmap.resizedBitmap(scaledImageSize, *enclosingScaledSrcRect);
}
示例8: inputEffect
bool FEComponentTransfer::platformApplySkia()
{
FilterEffect* in = inputEffect(0);
ImageBuffer* resultImage = createImageBufferResult();
if (!resultImage)
return false;
RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame();
if (!nativeImage)
return false;
unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
getValues(rValues, gValues, bValues, aValues);
SkPaint paint;
paint.setColorFilter(SkTableColorFilter::CreateARGB(aValues, rValues, gValues, bValues))->unref();
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
resultImage->context()->platformContext()->drawBitmap(nativeImage->bitmap(), 0, 0, &paint);
return true;
}
示例9: decoder
bool GraphicsContext3D::getImageData(Image* image,
GC3Denum format,
GC3Denum type,
bool premultiplyAlpha,
bool ignoreGammaAndColorProfile,
Vector<uint8_t>& outputVector)
{
if (!image)
return false;
OwnPtr<NativeImageSkia> pixels;
NativeImageSkia* skiaImage = 0;
AlphaOp neededAlphaOp = AlphaDoNothing;
bool hasAlpha = image->isBitmapImage() ? static_cast<BitmapImage*>(image)->frameHasAlphaAtIndex(0) : true;
if ((ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && image->data()) {
ImageSource decoder(ImageSource::AlphaNotPremultiplied,
ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
// Attempt to get raw unpremultiplied image data
decoder.setData(image->data(), true);
if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
return false;
hasAlpha = decoder.frameHasAlphaAtIndex(0);
pixels = adoptPtr(decoder.createFrameAtIndex(0));
if (!pixels.get() || !pixels->isDataComplete() || !pixels->width() || !pixels->height())
return false;
SkBitmap::Config skiaConfig = pixels->config();
if (skiaConfig != SkBitmap::kARGB_8888_Config)
return false;
skiaImage = pixels.get();
if (hasAlpha && premultiplyAlpha)
neededAlphaOp = AlphaDoPremultiply;
} else {
skiaImage = image->nativeImageForCurrentFrame();
if (!premultiplyAlpha && hasAlpha)
neededAlphaOp = AlphaDoUnmultiply;
}
if (!skiaImage)
return false;
SkBitmap& skiaImageRef = *skiaImage;
SkAutoLockPixels lock(skiaImageRef);
ASSERT(skiaImage->rowBytes() == skiaImage->width() * 4);
outputVector.resize(skiaImage->rowBytes() * skiaImage->height());
return packPixels(reinterpret_cast<const uint8_t*>(skiaImage->getPixels()),
SourceFormatBGRA8, skiaImage->width(), skiaImage->height(), 0,
format, type, neededAlphaOp, outputVector.data());
}
示例10: drawResampledBitmap
// 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.
//
// Note: this code is only used when the canvas transformation is limited to
// scaling or translation.
static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkIRect& srcIRect, const SkRect& destRect)
{
#if PLATFORM(CHROMIUM)
TRACE_EVENT("drawResampledBitmap", &canvas, 0);
#endif
// Apply forward transform to destRect to estimate required size of
// re-sampled bitmap, and use only in calls required to resize, or that
// check for the required size.
SkRect destRectTransformed;
canvas.getTotalMatrix().mapRect(&destRectTransformed, destRect);
SkIRect destRectTransformedRounded;
destRectTransformed.round(&destRectTransformedRounded);
// Compute the visible portion of our rect.
SkRect destRectVisibleSubset;
ClipRectToCanvas(canvas, destRect, &destRectVisibleSubset);
// ClipRectToCanvas often overshoots, resulting in a larger region than our
// original destRect. Intersecting gets us back inside.
if (!destRectVisibleSubset.intersect(destRect))
return; // Nothing visible in destRect.
// Compute the transformed (screen space) portion of the visible portion for
// use below.
SkRect destRectVisibleSubsetTransformed;
canvas.getTotalMatrix().mapRect(&destRectVisibleSubsetTransformed, destRectVisibleSubset);
SkRect destBitmapSubsetTransformed = destRectVisibleSubsetTransformed;
destBitmapSubsetTransformed.offset(-destRectTransformed.fLeft,
-destRectTransformed.fTop);
SkIRect destBitmapSubsetTransformedRounded;
destBitmapSubsetTransformed.round(&destBitmapSubsetTransformedRounded);
// Transforms above plus rounding may cause destBitmapSubsetTransformedRounded
// to go outside the image, so need to clip to avoid problems.
if (!destBitmapSubsetTransformedRounded.intersect(
0, 0, destRectTransformedRounded.width(), destRectTransformedRounded.height()))
return; // Image is not visible.
SkBitmap resampled = bitmap.resizedBitmap(srcIRect,
destRectTransformedRounded.width(),
destRectTransformedRounded.height(),
destBitmapSubsetTransformedRounded);
canvas.drawBitmapRect(resampled, 0, destRectVisibleSubset, &paint);
}
示例11: lock
bool GraphicsContext3D::getImageData(Image* image,
Vector<uint8_t>& outputVector,
bool premultiplyAlpha,
bool* hasAlphaChannel,
AlphaOp* neededAlphaOp,
unsigned int* format)
{
if (!image)
return false;
NativeImageSkia* skiaImage = image->nativeImageForCurrentFrame();
if (!skiaImage)
return false;
SkBitmap::Config skiaConfig = skiaImage->config();
// FIXME: must support more image configurations.
if (skiaConfig != SkBitmap::kARGB_8888_Config)
return false;
SkBitmap& skiaImageRef = *skiaImage;
SkAutoLockPixels lock(skiaImageRef);
int height = skiaImage->height();
int rowBytes = skiaImage->rowBytes();
ASSERT(rowBytes == skiaImage->width() * 4);
uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels());
outputVector.resize(rowBytes * height);
int size = rowBytes * height;
memcpy(outputVector.data(), pixels, size);
*hasAlphaChannel = true;
if (!premultiplyAlpha)
// FIXME: must fetch the image data before the premultiplication step
*neededAlphaOp = kAlphaDoUnmultiply;
// Convert from BGRA to RGBA. FIXME: add GL_BGRA extension support
// to all underlying OpenGL implementations.
for (int i = 0; i < size; i += 4)
std::swap(outputVector[i], outputVector[i + 2]);
*format = RGBA;
return true;
}
示例12: computeResamplingMode
static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const NativeImageSkia& bitmap, float srcWidth, float srcHeight, float destWidth, float 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.
float diffWidth = fabs(destWidth - srcWidth);
float diffHeight = fabs(destHeight - srcHeight);
bool widthNearlyEqual = diffWidth < std::numeric_limits<float>::epsilon();
bool heightNearlyEqual = diffHeight < std::numeric_limits<float>::epsilon();
// We don't need to resample if the source and destination are the same.
if (widthNearlyEqual && heightNearlyEqual)
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 (widthNearlyEqual || heightNearlyEqual)
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 ((diffWidth / srcWidth < kFractionalChangeThreshold)
&& (diffHeight / 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.
// High quality interpolation only enabled for scaling and translation.
if (!(matrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
return RESAMPLE_AWESOME;
return RESAMPLE_LINEAR;
}
示例13: PLATFORM
void Image::drawPattern(GraphicsContext* context,
const FloatRect& floatSrcRect,
const AffineTransform& patternTransform,
const FloatPoint& phase,
ColorSpace styleColorSpace,
CompositeOperator compositeOp,
const FloatRect& destRect)
{
#if PLATFORM(CHROMIUM)
TRACE_EVENT0("skia", "Image::drawPattern");
#endif
FloatRect normSrcRect = normalizeRect(floatSrcRect);
if (destRect.isEmpty() || normSrcRect.isEmpty())
return; // nothing to draw
NativeImageSkia* bitmap = nativeImageForCurrentFrame();
if (!bitmap)
return;
SkMatrix ctm = context->platformContext()->canvas()->getTotalMatrix();
SkMatrix totalMatrix;
totalMatrix.setConcat(ctm, patternTransform);
// Figure out what size the bitmap will be in the destination. The
// destination rect is the bounds of the pattern, we need to use the
// matrix to see how big it will be.
SkRect destRectTarget;
totalMatrix.mapRect(&destRectTarget, normSrcRect);
float destBitmapWidth = SkScalarToFloat(destRectTarget.width());
float destBitmapHeight = SkScalarToFloat(destRectTarget.height());
// Compute the resampling mode.
ResamplingMode resampling;
if (context->platformContext()->isAccelerated() || context->platformContext()->printing())
resampling = RESAMPLE_LINEAR;
else
resampling = computeResamplingMode(totalMatrix, *bitmap, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight);
resampling = limitResamplingMode(context->platformContext(), resampling);
// Load the transform WebKit requested.
SkMatrix matrix(patternTransform);
SkShader* shader;
if (resampling == RESAMPLE_AWESOME) {
// Do nice resampling.
float scaleX = destBitmapWidth / normSrcRect.width();
float scaleY = destBitmapHeight / normSrcRect.height();
SkRect scaledSrcRect;
SkIRect enclosingScaledSrcRect;
// The image fragment generated here is not exactly what is
// requested. The scale factor used is approximated and image
// fragment is slightly larger to align to integer
// boundaries.
SkBitmap resampled = extractScaledImageFragment(*bitmap, normSrcRect, scaleX, scaleY, &scaledSrcRect, &enclosingScaledSrcRect);
shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
// Since we just resized the bitmap, we need to remove the scale
// applied to the pixels in the bitmap shader. This means we need
// CTM * patternTransform to have identity scale. Since we
// can't modify CTM (or the rectangle will be drawn in the wrong
// place), we must set patternTransform's scale to the inverse of
// CTM scale.
matrix.setScaleX(ctm.getScaleX() ? 1 / ctm.getScaleX() : 1);
matrix.setScaleY(ctm.getScaleY() ? 1 / ctm.getScaleY() : 1);
} else {
// No need to do nice resampling.
SkBitmap srcSubset;
bitmap->bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect));
shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
}
// We also need to translate it such that the origin of the pattern is the
// origin of the destination rect, which is what WebKit expects. Skia uses
// the coordinate system origin as the base for the patter. If WebKit wants
// a shifted image, it will shift it from there using the patternTransform.
float adjustedX = phase.x() + normSrcRect.x() *
narrowPrecisionToFloat(patternTransform.a());
float adjustedY = phase.y() + normSrcRect.y() *
narrowPrecisionToFloat(patternTransform.d());
matrix.postTranslate(SkFloatToScalar(adjustedX),
SkFloatToScalar(adjustedY));
shader->setLocalMatrix(matrix);
SkPaint paint;
paint.setShader(shader)->unref();
paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
context->platformContext()->paintSkPaint(destRect, paint);
}
示例14: paintSkBitmap
static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp)
{
#if PLATFORM(CHROMIUM)
TRACE_EVENT0("skia", "paintSkBitmap");
#endif
SkPaint paint;
paint.setXfermodeMode(compOp);
paint.setAlpha(platformContext->getNormalizedAlpha());
paint.setLooper(platformContext->getDrawLooper());
// only antialias if we're rotated or skewed
paint.setAntiAlias(hasNon90rotation(platformContext));
ResamplingMode resampling;
if (platformContext->isAccelerated())
resampling = RESAMPLE_LINEAR;
else if (platformContext->printing())
resampling = RESAMPLE_NONE;
else {
// Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale).
SkRect destRectTarget = destRect;
if (!(platformContext->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
platformContext->getTotalMatrix().mapRect(&destRectTarget, destRect);
resampling = computeResamplingMode(platformContext->getTotalMatrix(), bitmap,
SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()),
SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height()));
}
if (resampling == RESAMPLE_NONE) {
// FIXME: This is to not break tests (it results in the filter bitmap flag
// being set to true). We need to decide if we respect RESAMPLE_NONE
// being returned from computeResamplingMode.
resampling = RESAMPLE_LINEAR;
}
resampling = limitResamplingMode(platformContext, resampling);
paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
if (resampling == RESAMPLE_AWESOME)
drawResampledBitmap(platformContext, paint, bitmap, srcRect, destRect);
else {
// No resampling necessary, we can just draw the bitmap. We want to
// filter it if we decided to do linear interpolation above, or if there
// is something interesting going on with the matrix (like a rotation).
// Note: for serialization, we will want to subset the bitmap first so
// we don't send extra pixels.
SkIRect enclosingSrcRect;
SkRect enclosingDestRect;
SkISize bitmapSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height());
bool needsClipping = computeBitmapDrawRects(bitmapSize, srcRect, destRect, &enclosingSrcRect, &enclosingDestRect);
if (enclosingSrcRect.isEmpty() || enclosingDestRect.isEmpty())
return;
// If destination is enlarged because source rectangle didn't align to
// integer boundaries then we draw a slightly larger rectangle and clip
// to the original destination rectangle.
// See http://crbug.com/145540.
if (needsClipping) {
platformContext->save();
platformContext->clipRect(destRect);
}
platformContext->drawBitmapRect(bitmap.bitmap(), &enclosingSrcRect, enclosingDestRect, &paint);
if (needsClipping)
platformContext->restore();
}
platformContext->didDrawRect(destRect, paint, &bitmap.bitmap());
}
示例15: computeResamplingMode
static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight)
{
if (platformContext->hasImageResamplingHint()) {
IntSize srcSize;
FloatSize dstSize;
platformContext->getImageResamplingHint(&srcSize, &dstSize);
srcWidth = srcSize.width();
srcHeight = srcSize.height();
destWidth = dstSize.width();
destHeight = dstSize.height();
}
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.
// If the platform context permits high quality interpolation, use it.
// High quality interpolation only enabled for scaling and translation.
if (platformContext->interpolationQuality() == InterpolationHigh
&& !(platformContext->canvas()->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
return RESAMPLE_AWESOME;
return RESAMPLE_LINEAR;
}