tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SkPixmapDraw.cpp (3311B)


      1 /*
      2 * Copyright 2023 Google LLC
      3 *
      4 * Use of this source code is governed by a BSD-style license that can be
      5 * found in the LICENSE file.
      6 *
      7 * This file contains implementations of SkPixmap methods which require the CPU backend.
      8 */
      9 
     10 #include "include/core/SkAlphaType.h"
     11 #include "include/core/SkBitmap.h"
     12 #include "include/core/SkBlendMode.h"
     13 #include "include/core/SkCanvas.h"
     14 #include "include/core/SkImageInfo.h"
     15 #include "include/core/SkMatrix.h"
     16 #include "include/core/SkPaint.h"
     17 #include "include/core/SkPixmap.h"
     18 #include "include/core/SkRect.h"
     19 #include "include/core/SkRefCnt.h"
     20 #include "include/core/SkShader.h"
     21 #include "include/core/SkSurface.h"
     22 #include "include/core/SkTileMode.h"
     23 #include "src/shaders/SkImageShader.h"
     24 
     25 #include <utility>
     26 
     27 struct SkSamplingOptions;
     28 
     29 bool SkPixmap::scalePixels(const SkPixmap& actualDst, const SkSamplingOptions& sampling) const {
     30    // We may need to tweak how we interpret these just a little below, so we make copies.
     31    SkPixmap src = *this,
     32             dst = actualDst;
     33 
     34    // Can't do anthing with empty src or dst
     35    if (src.width() <= 0 || src.height() <= 0 ||
     36        dst.width() <= 0 || dst.height() <= 0) {
     37        return false;
     38    }
     39 
     40    // no scaling involved?
     41    if (src.width() == dst.width() && src.height() == dst.height()) {
     42        return src.readPixels(dst);
     43    }
     44 
     45    // If src and dst are both unpremul, we'll fake the source out to appear as if premul,
     46    // and mark the destination as opaque.  This odd combination allows us to scale unpremul
     47    // pixels without ever premultiplying them (perhaps losing information in the color channels).
     48    // This is an idiosyncratic feature of scalePixels(), and is tested by scalepixels_unpremul GM.
     49    bool clampAsIfUnpremul = false;
     50    if (src.alphaType() == kUnpremul_SkAlphaType &&
     51        dst.alphaType() == kUnpremul_SkAlphaType) {
     52        src.reset(src.info().makeAlphaType(kPremul_SkAlphaType), src.addr(), src.rowBytes());
     53        dst.reset(dst.info().makeAlphaType(kOpaque_SkAlphaType), dst.addr(), dst.rowBytes());
     54 
     55        // We'll need to tell the image shader to clamp to [0,1] instead of the
     56        // usual [0,a] when using a bicubic scaling (kHigh_SkFilterQuality).
     57        clampAsIfUnpremul = true;
     58    }
     59 
     60    SkBitmap bitmap;
     61    if (!bitmap.installPixels(src)) {
     62        return false;
     63    }
     64    bitmap.setImmutable();        // Don't copy when we create an image.
     65 
     66    SkMatrix scale = SkMatrix::RectToRectOrIdentity(SkRect::Make(src.bounds()),
     67                                                    SkRect::Make(dst.bounds()));
     68 
     69    sk_sp<SkShader> shader = SkImageShader::Make(bitmap.asImage(),
     70                                                 SkTileMode::kClamp,
     71                                                 SkTileMode::kClamp,
     72                                                 sampling,
     73                                                 &scale,
     74                                                 clampAsIfUnpremul);
     75 
     76    sk_sp<SkSurface> surface =
     77            SkSurfaces::WrapPixels(dst.info(), dst.writable_addr(), dst.rowBytes());
     78    if (!shader || !surface) {
     79        return false;
     80    }
     81 
     82    SkPaint paint;
     83    paint.setBlendMode(SkBlendMode::kSrc);
     84    paint.setShader(std::move(shader));
     85    surface->getCanvas()->drawPaint(paint);
     86    return true;
     87 }