| Index: core/fxge/skia/fx_skia_device.cpp
|
| diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
|
| index 49c463986681ab8333eb0c211b972c2c4dbc290a..3effa0a6a6fbe2f6ece9e25044ecb8f52954208e 100644
|
| --- a/core/fxge/skia/fx_skia_device.cpp
|
| +++ b/core/fxge/skia/fx_skia_device.cpp
|
| @@ -24,9 +24,11 @@
|
| #include "third_party/skia/include/core/SkCanvas.h"
|
| #include "third_party/skia/include/core/SkColorFilter.h"
|
| #include "third_party/skia/include/core/SkColorPriv.h"
|
| +#include "third_party/skia/include/core/SkMaskFilter.h"
|
| #include "third_party/skia/include/core/SkPaint.h"
|
| #include "third_party/skia/include/core/SkPath.h"
|
| #include "third_party/skia/include/core/SkPictureRecorder.h"
|
| +#include "third_party/skia/include/core/SkShader.h"
|
| #include "third_party/skia/include/core/SkStream.h"
|
| #include "third_party/skia/include/core/SkTypeface.h"
|
| #include "third_party/skia/include/effects/SkDashPathEffect.h"
|
| @@ -140,9 +142,10 @@ SkMatrix ToSkMatrix(const CFX_Matrix& m) {
|
| }
|
|
|
| // use when pdf's y-axis points up insead of down
|
| -SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m) {
|
| +SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m, SkScalar flip) {
|
| SkMatrix skMatrix;
|
| - skMatrix.setAll(m.a, -m.c, m.e, m.b, -m.d, m.f, 0, 0, 1);
|
| + skMatrix.setAll(m.a * flip, -m.c * flip, m.e, m.b * flip, -m.d * flip, m.f, 0,
|
| + 0, 1);
|
| return skMatrix;
|
| }
|
|
|
| @@ -367,6 +370,107 @@ void ClipAngledGradient(const SkPoint pts[2],
|
| clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt));
|
| }
|
|
|
| +void SetBitmapMatrix(const CFX_Matrix* pMatrix,
|
| + int width,
|
| + int height,
|
| + SkMatrix* skMatrix) {
|
| + const CFX_Matrix& m = *pMatrix;
|
| + skMatrix->setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width,
|
| + -m.d / height, m.d + m.f, 0, 0, 1);
|
| +}
|
| +
|
| +void SetBitmapPaint(bool isAlphaMask,
|
| + uint32_t argb,
|
| + int bitmap_alpha,
|
| + int blend_type,
|
| + SkPaint* paint) {
|
| + paint->setAntiAlias(true);
|
| + if (isAlphaMask) {
|
| + paint->setColorFilter(
|
| + SkColorFilter::MakeModeFilter(argb, SkXfermode::kSrc_Mode));
|
| + }
|
| + // paint->setFilterQuality(kHigh_SkFilterQuality);
|
| + paint->setXfermodeMode(GetSkiaBlendMode(blend_type));
|
| + paint->setAlpha(bitmap_alpha);
|
| +}
|
| +
|
| +bool Upsample(const CFX_DIBSource* pSource,
|
| + std::unique_ptr<uint8_t, FxFreeDeleter>& dst8Storage,
|
| + std::unique_ptr<uint32_t, FxFreeDeleter>& dst32Storage,
|
| + SkColorTable** ctPtr,
|
| + SkBitmap* skBitmap,
|
| + int* widthPtr,
|
| + int* heightPtr,
|
| + bool forceAlpha) {
|
| + void* buffer = pSource->GetBuffer();
|
| + if (!buffer)
|
| + return false;
|
| + SkColorType colorType = forceAlpha || pSource->IsAlphaMask()
|
| + ? SkColorType::kAlpha_8_SkColorType
|
| + : SkColorType::kGray_8_SkColorType;
|
| + SkAlphaType alphaType =
|
| + pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
|
| + int width = pSource->GetWidth();
|
| + int height = pSource->GetHeight();
|
| + int rowBytes = pSource->GetPitch();
|
| + switch (pSource->GetBPP()) {
|
| + case 1: {
|
| + dst8Storage.reset(FX_Alloc2D(uint8_t, width, height));
|
| + uint8_t* dst8Pixels = dst8Storage.get();
|
| + for (int y = 0; y < height; ++y) {
|
| + const uint8_t* srcRow =
|
| + static_cast<const uint8_t*>(buffer) + y * rowBytes;
|
| + uint8_t* dstRow = dst8Pixels + y * width;
|
| + for (int x = 0; x < width; ++x)
|
| + dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00;
|
| + }
|
| + buffer = dst8Storage.get();
|
| + rowBytes = width;
|
| + break;
|
| + }
|
| + case 8:
|
| + if (pSource->GetPalette()) {
|
| + *ctPtr =
|
| + new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize());
|
| + colorType = SkColorType::kIndex_8_SkColorType;
|
| + }
|
| + break;
|
| + case 24: {
|
| + dst32Storage.reset(FX_Alloc2D(uint32_t, width, height));
|
| + uint32_t* dst32Pixels = dst32Storage.get();
|
| + for (int y = 0; y < height; ++y) {
|
| + const uint8_t* srcRow =
|
| + static_cast<const uint8_t*>(buffer) + y * rowBytes;
|
| + uint32_t* dstRow = dst32Pixels + y * width;
|
| + for (int x = 0; x < width; ++x) {
|
| + dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1],
|
| + srcRow[x * 3 + 0]);
|
| + }
|
| + }
|
| + buffer = dst32Storage.get();
|
| + rowBytes = width * sizeof(uint32_t);
|
| + colorType = SkColorType::kN32_SkColorType;
|
| + alphaType = kOpaque_SkAlphaType;
|
| + break;
|
| + }
|
| + case 32:
|
| + colorType = SkColorType::kN32_SkColorType;
|
| + alphaType = kPremul_SkAlphaType;
|
| + pSource->DebugVerifyBitmapIsPreMultiplied(buffer);
|
| + break;
|
| + default:
|
| + SkASSERT(0); // TODO(caryclark) ensure that all cases are covered
|
| + colorType = SkColorType::kUnknown_SkColorType;
|
| + }
|
| + SkImageInfo imageInfo =
|
| + SkImageInfo::Make(width, height, colorType, alphaType);
|
| + skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr,
|
| + nullptr);
|
| + *widthPtr = width;
|
| + *heightPtr = height;
|
| + return true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| // Encapsulate the state used for successive text and path draws so that
|
| @@ -500,22 +604,24 @@ class SkiaState {
|
| int count = m_positions.count();
|
| m_positions.setCount(nChars + count);
|
| m_glyphs.setCount(nChars + count);
|
| + SkScalar flip = m_fontSize < 0 ? -1 : 1;
|
| for (int index = 0; index < nChars; ++index) {
|
| const FXTEXT_CHARPOS& cp = pCharPos[index];
|
| - m_positions[index + count] = {cp.m_OriginX, cp.m_OriginY};
|
| + m_positions[index + count] = {cp.m_OriginX * flip, cp.m_OriginY * flip};
|
| m_glyphs[index + count] = (uint16_t)cp.m_GlyphIndex;
|
| }
|
| SkPoint delta;
|
| if (MatrixOffset(pMatrix, &delta)) {
|
| for (int index = 0; index < nChars; ++index)
|
| - m_positions[index + count].offset(delta.fX, -delta.fY);
|
| + m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip);
|
| }
|
| m_drawText = true;
|
| return true;
|
| }
|
|
|
| void FlushText(CFX_SkiaDeviceDriver* pDriver) {
|
| - SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix);
|
| + SkScalar flip = m_fontSize < 0 ? -1 : 1;
|
| + SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip);
|
| SkPaint skPaint;
|
| skPaint.setAntiAlias(true);
|
| skPaint.setColor(m_fillColor);
|
| @@ -919,7 +1025,8 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
|
| paint.setTextSize(font_size);
|
| paint.setSubpixelText(true);
|
| m_pCanvas->save();
|
| - SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device);
|
| + SkScalar flip = font_size < 0 ? -1 : 1;
|
| + SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device, flip);
|
| m_pCanvas->concat(skMatrix);
|
| SkTDArray<SkPoint> positions;
|
| positions.setCount(nChars);
|
| @@ -927,7 +1034,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
|
| glyphs.setCount(nChars);
|
| for (int index = 0; index < nChars; ++index) {
|
| const FXTEXT_CHARPOS& cp = pCharPos[index];
|
| - positions[index] = {cp.m_OriginX, cp.m_OriginY};
|
| + positions[index] = {cp.m_OriginX * flip, cp.m_OriginY * flip};
|
| glyphs[index] = (uint16_t)cp.m_GlyphIndex;
|
| }
|
| m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint);
|
| @@ -1339,86 +1446,39 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
|
| void*& handle,
|
| int blend_type) {
|
| DebugValidate(m_pBitmap, m_pOriDevice);
|
| - SkColorType colorType = pSource->IsAlphaMask()
|
| - ? SkColorType::kAlpha_8_SkColorType
|
| - : SkColorType::kGray_8_SkColorType;
|
| - SkAlphaType alphaType =
|
| - pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
|
| SkColorTable* ct = nullptr;
|
| - void* buffer = pSource->GetBuffer();
|
| - if (!buffer)
|
| - return FALSE;
|
| std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage;
|
| std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage;
|
| - int width = pSource->GetWidth();
|
| - int height = pSource->GetHeight();
|
| - int rowBytes = pSource->GetPitch();
|
| - switch (pSource->GetBPP()) {
|
| - case 1: {
|
| - dst8Storage.reset(FX_Alloc2D(uint8_t, width, height));
|
| - uint8_t* dst8Pixels = dst8Storage.get();
|
| - for (int y = 0; y < height; ++y) {
|
| - const uint8_t* srcRow =
|
| - static_cast<const uint8_t*>(buffer) + y * rowBytes;
|
| - uint8_t* dstRow = dst8Pixels + y * width;
|
| - for (int x = 0; x < width; ++x)
|
| - dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00;
|
| - }
|
| - buffer = dst8Storage.get();
|
| - rowBytes = width;
|
| - } break;
|
| - case 8:
|
| - if (pSource->GetPalette()) {
|
| - ct = new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize());
|
| - colorType = SkColorType::kIndex_8_SkColorType;
|
| - }
|
| - break;
|
| - case 24: {
|
| - dst32Storage.reset(FX_Alloc2D(uint32_t, width, height));
|
| - uint32_t* dst32Pixels = dst32Storage.get();
|
| - for (int y = 0; y < height; ++y) {
|
| - const uint8_t* srcRow =
|
| - static_cast<const uint8_t*>(buffer) + y * rowBytes;
|
| - uint32_t* dstRow = dst32Pixels + y * width;
|
| - for (int x = 0; x < width; ++x) {
|
| - dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1],
|
| - srcRow[x * 3 + 0]);
|
| - }
|
| - }
|
| - buffer = dst32Storage.get();
|
| - rowBytes = width * sizeof(uint32_t);
|
| - colorType = SkColorType::kN32_SkColorType;
|
| - alphaType = kOpaque_SkAlphaType;
|
| - } break;
|
| - case 32:
|
| - colorType = SkColorType::kN32_SkColorType;
|
| - alphaType = kPremul_SkAlphaType;
|
| - pSource->DebugVerifyBitmapIsPreMultiplied(buffer);
|
| - break;
|
| - default:
|
| - SkASSERT(0); // TODO(caryclark) ensure that all cases are covered
|
| - colorType = SkColorType::kUnknown_SkColorType;
|
| - }
|
| - SkImageInfo imageInfo =
|
| - SkImageInfo::Make(width, height, colorType, alphaType);
|
| SkBitmap skBitmap;
|
| - skBitmap.installPixels(imageInfo, buffer, rowBytes, ct, nullptr, nullptr);
|
| + int width, height;
|
| + if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width,
|
| + &height, false)) {
|
| + return FALSE;
|
| + }
|
| m_pCanvas->save();
|
| SkMatrix skMatrix;
|
| - const CFX_Matrix& m = *pMatrix;
|
| - skMatrix.setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width,
|
| - -m.d / height, m.d + m.f, 0, 0, 1);
|
| + SetBitmapMatrix(pMatrix, width, height, &skMatrix);
|
| m_pCanvas->concat(skMatrix);
|
| SkPaint paint;
|
| - paint.setAntiAlias(true);
|
| - if (pSource->IsAlphaMask()) {
|
| - paint.setColorFilter(
|
| - SkColorFilter::MakeModeFilter(argb, SkXfermode::kSrc_Mode));
|
| + SetBitmapPaint(pSource->IsAlphaMask(), argb, bitmap_alpha, blend_type,
|
| + &paint);
|
| + // TODO(caryclark) Once Skia supports 8 bit src to 8 bit dst remove this
|
| + if (m_pBitmap->GetBPP() == 8 && pSource->GetBPP() == 8) {
|
| + SkMatrix inv;
|
| + SkAssertResult(skMatrix.invert(&inv));
|
| + for (int y = 0; y < m_pBitmap->GetHeight(); ++y) {
|
| + for (int x = 0; x < m_pBitmap->GetWidth(); ++x) {
|
| + SkPoint src = {x + 0.5f, y + 0.5f};
|
| + inv.mapPoints(&src, 1);
|
| + // TODO(caryclark) Why does the matrix map require clamping?
|
| + src.fX = SkTMax(0.5f, SkTMin(src.fX, width - 0.5f));
|
| + src.fY = SkTMax(0.5f, SkTMin(src.fY, height - 0.5f));
|
| + m_pBitmap->SetPixel(x, y, skBitmap.getColor(src.fX, src.fY));
|
| + }
|
| + }
|
| + } else {
|
| + m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint);
|
| }
|
| - // paint.setFilterQuality(kHigh_SkFilterQuality);
|
| - paint.setXfermodeMode(GetSkiaBlendMode(blend_type));
|
| - paint.setAlpha(bitmap_alpha);
|
| - m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint);
|
| m_pCanvas->restore();
|
| if (ct)
|
| ct->unref();
|
| @@ -1450,6 +1510,68 @@ void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) {
|
| pDIBitmap->DebugVerifyBitmapIsPreMultiplied();
|
| }
|
|
|
| +bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource,
|
| + const CFX_DIBSource* pMask,
|
| + int bitmap_alpha,
|
| + const CFX_Matrix* pMatrix,
|
| + int blend_type) {
|
| + DebugValidate(m_pBitmap, m_pOriDevice);
|
| + SkColorTable* srcCt = nullptr;
|
| + SkColorTable* maskCt = nullptr;
|
| + std::unique_ptr<uint8_t, FxFreeDeleter> src8Storage, mask8Storage;
|
| + std::unique_ptr<uint32_t, FxFreeDeleter> src32Storage, mask32Storage;
|
| + SkBitmap skBitmap, skMask;
|
| + int srcWidth, srcHeight, maskWidth, maskHeight;
|
| + if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap,
|
| + &srcWidth, &srcHeight, false)) {
|
| + return false;
|
| + }
|
| + if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask,
|
| + &maskWidth, &maskHeight, true)) {
|
| + return false;
|
| + }
|
| + m_pCanvas->save();
|
| + SkMatrix skMatrix;
|
| + SetBitmapMatrix(pMatrix, srcWidth, srcHeight, &skMatrix);
|
| + m_pCanvas->concat(skMatrix);
|
| + SkPaint paint;
|
| + SetBitmapPaint(pSource->IsAlphaMask(), 0xFFFFFFFF, bitmap_alpha, blend_type,
|
| + &paint);
|
| + sk_sp<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap);
|
| + sk_sp<SkShader> skSrcShader =
|
| + skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
|
| + sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask);
|
| + sk_sp<SkShader> skMaskShader = skMaskImage->makeShader(
|
| + SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
|
| + sk_sp<SkXfermode> dstInMode = SkXfermode::Make(SkXfermode::kSrcIn_Mode);
|
| + paint.setShader(
|
| + SkShader::MakeComposeShader(skMaskShader, skSrcShader, dstInMode));
|
| + SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)};
|
| + m_pCanvas->drawRect(r, paint);
|
| + m_pCanvas->restore();
|
| + if (srcCt)
|
| + srcCt->unref();
|
| + DebugValidate(m_pBitmap, m_pOriDevice);
|
| + return true;
|
| +}
|
| +
|
| +bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap,
|
| + const CFX_DIBSource* pMask,
|
| + int dest_left,
|
| + int dest_top,
|
| + int bitmap_alpha,
|
| + int blend_type) {
|
| + if (!m_pBitmap || !m_pBitmap->GetBuffer())
|
| + return true;
|
| + CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left,
|
| + dest_top + pBitmap->GetHeight());
|
| + return DrawBitsWithMask(pBitmap, pMask, bitmap_alpha, &m, blend_type);
|
| +}
|
| +
|
| +void CFX_SkiaDeviceDriver::Clear(uint32_t color) {
|
| + m_pCanvas->clear(color);
|
| +}
|
| +
|
| void CFX_SkiaDeviceDriver::Dump() const {
|
| #ifdef SK_DEBUG
|
| if (m_pCache)
|
| @@ -1466,6 +1588,12 @@ CFX_FxgeDevice::CFX_FxgeDevice() {
|
| m_bOwnedBitmap = FALSE;
|
| }
|
|
|
| +void CFX_FxgeDevice::Clear(uint32_t color) {
|
| + CFX_SkiaDeviceDriver* skDriver =
|
| + static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
|
| + skDriver->Clear(color);
|
| +}
|
| +
|
| SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) {
|
| CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y);
|
| SetDeviceDriver(WrapUnique(skDriver));
|
| @@ -1523,6 +1651,20 @@ void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const {
|
| #endif
|
| }
|
|
|
| +bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap,
|
| + const CFX_DIBSource* pMask,
|
| + int left,
|
| + int top,
|
| + int bitmap_alpha,
|
| + int blend_type) {
|
| + CFX_SkiaDeviceDriver* skDriver =
|
| + static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
|
| + if (skDriver)
|
| + return skDriver->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha,
|
| + blend_type);
|
| + return false;
|
| +}
|
| +
|
| void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const {
|
| #ifdef SK_DEBUG
|
| SkASSERT(32 == GetBPP());
|
|
|