OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if defined(_SKIA_SUPPORT_) | 5 #if defined(_SKIA_SUPPORT_) |
6 #include <algorithm> | 6 #include <algorithm> |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "core/fxcodec/include/fx_codec.h" | 9 #include "core/fxcodec/include/fx_codec.h" |
10 #include "core/fxcrt/include/fx_memory.h" | 10 #include "core/fxcrt/include/fx_memory.h" |
11 | 11 |
12 #include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h" | 12 #include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h" |
13 #include "core/fpdfapi/fpdf_page/pageint.h" | 13 #include "core/fpdfapi/fpdf_page/pageint.h" |
14 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | 14 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" |
15 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" | 15 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" |
16 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" | 16 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" |
17 #include "core/fxge/include/cfx_fxgedevice.h" | 17 #include "core/fxge/include/cfx_fxgedevice.h" |
18 #include "core/fxge/include/cfx_gemodule.h" | 18 #include "core/fxge/include/cfx_gemodule.h" |
19 #include "core/fxge/include/cfx_graphstatedata.h" | 19 #include "core/fxge/include/cfx_graphstatedata.h" |
20 #include "core/fxge/include/cfx_pathdata.h" | 20 #include "core/fxge/include/cfx_pathdata.h" |
21 #include "core/fxge/include/cfx_renderdevice.h" | 21 #include "core/fxge/include/cfx_renderdevice.h" |
22 #include "core/fxge/skia/fx_skia_device.h" | 22 #include "core/fxge/skia/fx_skia_device.h" |
23 | 23 |
24 #include "third_party/skia/include/core/SkCanvas.h" | 24 #include "third_party/skia/include/core/SkCanvas.h" |
25 #include "third_party/skia/include/core/SkColorFilter.h" | 25 #include "third_party/skia/include/core/SkColorFilter.h" |
26 #include "third_party/skia/include/core/SkColorPriv.h" | 26 #include "third_party/skia/include/core/SkColorPriv.h" |
| 27 #include "third_party/skia/include/core/SkMaskFilter.h" |
27 #include "third_party/skia/include/core/SkPaint.h" | 28 #include "third_party/skia/include/core/SkPaint.h" |
28 #include "third_party/skia/include/core/SkPath.h" | 29 #include "third_party/skia/include/core/SkPath.h" |
29 #include "third_party/skia/include/core/SkPictureRecorder.h" | 30 #include "third_party/skia/include/core/SkPictureRecorder.h" |
| 31 #include "third_party/skia/include/core/SkShader.h" |
30 #include "third_party/skia/include/core/SkStream.h" | 32 #include "third_party/skia/include/core/SkStream.h" |
31 #include "third_party/skia/include/core/SkTypeface.h" | 33 #include "third_party/skia/include/core/SkTypeface.h" |
32 #include "third_party/skia/include/effects/SkDashPathEffect.h" | 34 #include "third_party/skia/include/effects/SkDashPathEffect.h" |
33 #include "third_party/skia/include/effects/SkGradientShader.h" | 35 #include "third_party/skia/include/effects/SkGradientShader.h" |
34 #include "third_party/skia/include/pathops/SkPathOps.h" | 36 #include "third_party/skia/include/pathops/SkPathOps.h" |
35 | 37 |
36 #ifdef SK_DEBUG | 38 #ifdef SK_DEBUG |
37 #include "third_party/skia/include/core/SkClipStack.h" | 39 #include "third_party/skia/include/core/SkClipStack.h" |
38 #endif | 40 #endif |
39 | 41 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 return skPath; | 135 return skPath; |
134 } | 136 } |
135 | 137 |
136 SkMatrix ToSkMatrix(const CFX_Matrix& m) { | 138 SkMatrix ToSkMatrix(const CFX_Matrix& m) { |
137 SkMatrix skMatrix; | 139 SkMatrix skMatrix; |
138 skMatrix.setAll(m.a, m.b, m.e, m.c, m.d, m.f, 0, 0, 1); | 140 skMatrix.setAll(m.a, m.b, m.e, m.c, m.d, m.f, 0, 0, 1); |
139 return skMatrix; | 141 return skMatrix; |
140 } | 142 } |
141 | 143 |
142 // use when pdf's y-axis points up insead of down | 144 // use when pdf's y-axis points up insead of down |
143 SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m) { | 145 SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m, SkScalar flip) { |
144 SkMatrix skMatrix; | 146 SkMatrix skMatrix; |
145 skMatrix.setAll(m.a, -m.c, m.e, m.b, -m.d, m.f, 0, 0, 1); | 147 skMatrix.setAll(m.a * flip, -m.c * flip, m.e, m.b * flip, -m.d * flip, m.f, 0, |
| 148 0, 1); |
146 return skMatrix; | 149 return skMatrix; |
147 } | 150 } |
148 | 151 |
149 SkXfermode::Mode GetSkiaBlendMode(int blend_type) { | 152 SkXfermode::Mode GetSkiaBlendMode(int blend_type) { |
150 switch (blend_type) { | 153 switch (blend_type) { |
151 case FXDIB_BLEND_MULTIPLY: | 154 case FXDIB_BLEND_MULTIPLY: |
152 return SkXfermode::kMultiply_Mode; | 155 return SkXfermode::kMultiply_Mode; |
153 case FXDIB_BLEND_SCREEN: | 156 case FXDIB_BLEND_SCREEN: |
154 return SkXfermode::kScreen_Mode; | 157 return SkXfermode::kScreen_Mode; |
155 case FXDIB_BLEND_OVERLAY: | 158 case FXDIB_BLEND_OVERLAY: |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 ASSERT(maxBounds != minBounds && maxBounds >= 0); | 363 ASSERT(maxBounds != minBounds && maxBounds >= 0); |
361 // construct a clip parallel to the gradient that goes through | 364 // construct a clip parallel to the gradient that goes through |
362 // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the | 365 // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the |
363 // gradient that goes through startEdgePt, endEdgePt. | 366 // gradient that goes through startEdgePt, endEdgePt. |
364 clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt)); | 367 clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt)); |
365 clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt)); | 368 clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt)); |
366 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt)); | 369 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt)); |
367 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); | 370 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); |
368 } | 371 } |
369 | 372 |
| 373 void SetBitmapMatrix(const CFX_Matrix* pMatrix, |
| 374 int width, |
| 375 int height, |
| 376 SkMatrix* skMatrix) { |
| 377 const CFX_Matrix& m = *pMatrix; |
| 378 skMatrix->setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width, |
| 379 -m.d / height, m.d + m.f, 0, 0, 1); |
| 380 } |
| 381 |
| 382 void SetBitmapPaint(bool isAlphaMask, |
| 383 uint32_t argb, |
| 384 int bitmap_alpha, |
| 385 int blend_type, |
| 386 SkPaint* paint) { |
| 387 paint->setAntiAlias(true); |
| 388 if (isAlphaMask) { |
| 389 paint->setColorFilter( |
| 390 SkColorFilter::MakeModeFilter(argb, SkXfermode::kSrc_Mode)); |
| 391 } |
| 392 // paint->setFilterQuality(kHigh_SkFilterQuality); |
| 393 paint->setXfermodeMode(GetSkiaBlendMode(blend_type)); |
| 394 paint->setAlpha(bitmap_alpha); |
| 395 } |
| 396 |
| 397 bool Upsample(const CFX_DIBSource* pSource, |
| 398 std::unique_ptr<uint8_t, FxFreeDeleter>& dst8Storage, |
| 399 std::unique_ptr<uint32_t, FxFreeDeleter>& dst32Storage, |
| 400 SkColorTable** ctPtr, |
| 401 SkBitmap* skBitmap, |
| 402 int* widthPtr, |
| 403 int* heightPtr, |
| 404 bool forceAlpha) { |
| 405 void* buffer = pSource->GetBuffer(); |
| 406 if (!buffer) |
| 407 return false; |
| 408 SkColorType colorType = forceAlpha || pSource->IsAlphaMask() |
| 409 ? SkColorType::kAlpha_8_SkColorType |
| 410 : SkColorType::kGray_8_SkColorType; |
| 411 SkAlphaType alphaType = |
| 412 pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType; |
| 413 int width = pSource->GetWidth(); |
| 414 int height = pSource->GetHeight(); |
| 415 int rowBytes = pSource->GetPitch(); |
| 416 switch (pSource->GetBPP()) { |
| 417 case 1: { |
| 418 dst8Storage.reset(FX_Alloc2D(uint8_t, width, height)); |
| 419 uint8_t* dst8Pixels = dst8Storage.get(); |
| 420 for (int y = 0; y < height; ++y) { |
| 421 const uint8_t* srcRow = |
| 422 static_cast<const uint8_t*>(buffer) + y * rowBytes; |
| 423 uint8_t* dstRow = dst8Pixels + y * width; |
| 424 for (int x = 0; x < width; ++x) |
| 425 dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00; |
| 426 } |
| 427 buffer = dst8Storage.get(); |
| 428 rowBytes = width; |
| 429 break; |
| 430 } |
| 431 case 8: |
| 432 if (pSource->GetPalette()) { |
| 433 *ctPtr = |
| 434 new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize()); |
| 435 colorType = SkColorType::kIndex_8_SkColorType; |
| 436 } |
| 437 break; |
| 438 case 24: { |
| 439 dst32Storage.reset(FX_Alloc2D(uint32_t, width, height)); |
| 440 uint32_t* dst32Pixels = dst32Storage.get(); |
| 441 for (int y = 0; y < height; ++y) { |
| 442 const uint8_t* srcRow = |
| 443 static_cast<const uint8_t*>(buffer) + y * rowBytes; |
| 444 uint32_t* dstRow = dst32Pixels + y * width; |
| 445 for (int x = 0; x < width; ++x) { |
| 446 dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1], |
| 447 srcRow[x * 3 + 0]); |
| 448 } |
| 449 } |
| 450 buffer = dst32Storage.get(); |
| 451 rowBytes = width * sizeof(uint32_t); |
| 452 colorType = SkColorType::kN32_SkColorType; |
| 453 alphaType = kOpaque_SkAlphaType; |
| 454 break; |
| 455 } |
| 456 case 32: |
| 457 colorType = SkColorType::kN32_SkColorType; |
| 458 alphaType = kPremul_SkAlphaType; |
| 459 pSource->DebugVerifyBitmapIsPreMultiplied(buffer); |
| 460 break; |
| 461 default: |
| 462 SkASSERT(0); // TODO(caryclark) ensure that all cases are covered |
| 463 colorType = SkColorType::kUnknown_SkColorType; |
| 464 } |
| 465 SkImageInfo imageInfo = |
| 466 SkImageInfo::Make(width, height, colorType, alphaType); |
| 467 skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr, |
| 468 nullptr); |
| 469 *widthPtr = width; |
| 470 *heightPtr = height; |
| 471 return true; |
| 472 } |
| 473 |
370 } // namespace | 474 } // namespace |
371 | 475 |
372 // Encapsulate the state used for successive text and path draws so that | 476 // Encapsulate the state used for successive text and path draws so that |
373 // they can be combined. | 477 // they can be combined. |
374 class SkiaState { | 478 class SkiaState { |
375 public: | 479 public: |
376 enum class Clip { | 480 enum class Clip { |
377 kSave, | 481 kSave, |
378 kPath, | 482 kPath, |
379 }; | 483 }; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 m_glyphs.setCount(0); | 597 m_glyphs.setCount(0); |
494 m_pFont = pFont; | 598 m_pFont = pFont; |
495 m_pCache = pCache; | 599 m_pCache = pCache; |
496 m_fontSize = font_size; | 600 m_fontSize = font_size; |
497 m_fillColor = color; | 601 m_fillColor = color; |
498 m_drawMatrix = *pMatrix; | 602 m_drawMatrix = *pMatrix; |
499 } | 603 } |
500 int count = m_positions.count(); | 604 int count = m_positions.count(); |
501 m_positions.setCount(nChars + count); | 605 m_positions.setCount(nChars + count); |
502 m_glyphs.setCount(nChars + count); | 606 m_glyphs.setCount(nChars + count); |
| 607 SkScalar flip = m_fontSize < 0 ? -1 : 1; |
503 for (int index = 0; index < nChars; ++index) { | 608 for (int index = 0; index < nChars; ++index) { |
504 const FXTEXT_CHARPOS& cp = pCharPos[index]; | 609 const FXTEXT_CHARPOS& cp = pCharPos[index]; |
505 m_positions[index + count] = {cp.m_OriginX, cp.m_OriginY}; | 610 m_positions[index + count] = {cp.m_OriginX * flip, cp.m_OriginY * flip}; |
506 m_glyphs[index + count] = (uint16_t)cp.m_GlyphIndex; | 611 m_glyphs[index + count] = (uint16_t)cp.m_GlyphIndex; |
507 } | 612 } |
508 SkPoint delta; | 613 SkPoint delta; |
509 if (MatrixOffset(pMatrix, &delta)) { | 614 if (MatrixOffset(pMatrix, &delta)) { |
510 for (int index = 0; index < nChars; ++index) | 615 for (int index = 0; index < nChars; ++index) |
511 m_positions[index + count].offset(delta.fX, -delta.fY); | 616 m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip); |
512 } | 617 } |
513 m_drawText = true; | 618 m_drawText = true; |
514 return true; | 619 return true; |
515 } | 620 } |
516 | 621 |
517 void FlushText(CFX_SkiaDeviceDriver* pDriver) { | 622 void FlushText(CFX_SkiaDeviceDriver* pDriver) { |
518 SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix); | 623 SkScalar flip = m_fontSize < 0 ? -1 : 1; |
| 624 SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip); |
519 SkPaint skPaint; | 625 SkPaint skPaint; |
520 skPaint.setAntiAlias(true); | 626 skPaint.setAntiAlias(true); |
521 skPaint.setColor(m_fillColor); | 627 skPaint.setColor(m_fillColor); |
522 if (m_pFont->GetFace() && m_pCache) { // exclude placeholder test fonts | 628 if (m_pFont->GetFace() && m_pCache) { // exclude placeholder test fonts |
523 sk_sp<SkTypeface> typeface(SkSafeRef(m_pCache->GetDeviceCache(m_pFont))); | 629 sk_sp<SkTypeface> typeface(SkSafeRef(m_pCache->GetDeviceCache(m_pFont))); |
524 skPaint.setTypeface(typeface); | 630 skPaint.setTypeface(typeface); |
525 } | 631 } |
526 skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 632 skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
527 skPaint.setTextSize(m_fontSize); | 633 skPaint.setTextSize(m_fontSize); |
528 skPaint.setSubpixelText(true); | 634 skPaint.setSubpixelText(true); |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 SkSafeRef(pCache ? pCache->GetDeviceCache(pFont) : nullptr)); | 1018 SkSafeRef(pCache ? pCache->GetDeviceCache(pFont) : nullptr)); |
913 SkPaint paint; | 1019 SkPaint paint; |
914 paint.setAntiAlias(true); | 1020 paint.setAntiAlias(true); |
915 paint.setColor(color); | 1021 paint.setColor(color); |
916 paint.setTypeface(typeface); | 1022 paint.setTypeface(typeface); |
917 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 1023 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
918 paint.setHinting(SkPaint::kNo_Hinting); | 1024 paint.setHinting(SkPaint::kNo_Hinting); |
919 paint.setTextSize(font_size); | 1025 paint.setTextSize(font_size); |
920 paint.setSubpixelText(true); | 1026 paint.setSubpixelText(true); |
921 m_pCanvas->save(); | 1027 m_pCanvas->save(); |
922 SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device); | 1028 SkScalar flip = font_size < 0 ? -1 : 1; |
| 1029 SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device, flip); |
923 m_pCanvas->concat(skMatrix); | 1030 m_pCanvas->concat(skMatrix); |
924 SkTDArray<SkPoint> positions; | 1031 SkTDArray<SkPoint> positions; |
925 positions.setCount(nChars); | 1032 positions.setCount(nChars); |
926 SkTDArray<uint16_t> glyphs; | 1033 SkTDArray<uint16_t> glyphs; |
927 glyphs.setCount(nChars); | 1034 glyphs.setCount(nChars); |
928 for (int index = 0; index < nChars; ++index) { | 1035 for (int index = 0; index < nChars; ++index) { |
929 const FXTEXT_CHARPOS& cp = pCharPos[index]; | 1036 const FXTEXT_CHARPOS& cp = pCharPos[index]; |
930 positions[index] = {cp.m_OriginX, cp.m_OriginY}; | 1037 positions[index] = {cp.m_OriginX * flip, cp.m_OriginY * flip}; |
931 glyphs[index] = (uint16_t)cp.m_GlyphIndex; | 1038 glyphs[index] = (uint16_t)cp.m_GlyphIndex; |
932 } | 1039 } |
933 m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint); | 1040 m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint); |
934 m_pCanvas->restore(); | 1041 m_pCanvas->restore(); |
935 return TRUE; | 1042 return TRUE; |
936 } | 1043 } |
937 | 1044 |
938 int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const { | 1045 int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const { |
939 switch (caps_id) { | 1046 switch (caps_id) { |
940 case FXDC_DEVICE_CLASS: | 1047 case FXDC_DEVICE_CLASS: |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1332 } | 1439 } |
1333 | 1440 |
1334 FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, | 1441 FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, |
1335 int bitmap_alpha, | 1442 int bitmap_alpha, |
1336 uint32_t argb, | 1443 uint32_t argb, |
1337 const CFX_Matrix* pMatrix, | 1444 const CFX_Matrix* pMatrix, |
1338 uint32_t render_flags, | 1445 uint32_t render_flags, |
1339 void*& handle, | 1446 void*& handle, |
1340 int blend_type) { | 1447 int blend_type) { |
1341 DebugValidate(m_pBitmap, m_pOriDevice); | 1448 DebugValidate(m_pBitmap, m_pOriDevice); |
1342 SkColorType colorType = pSource->IsAlphaMask() | |
1343 ? SkColorType::kAlpha_8_SkColorType | |
1344 : SkColorType::kGray_8_SkColorType; | |
1345 SkAlphaType alphaType = | |
1346 pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType; | |
1347 SkColorTable* ct = nullptr; | 1449 SkColorTable* ct = nullptr; |
1348 void* buffer = pSource->GetBuffer(); | |
1349 if (!buffer) | |
1350 return FALSE; | |
1351 std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage; | 1450 std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage; |
1352 std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage; | 1451 std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage; |
1353 int width = pSource->GetWidth(); | 1452 SkBitmap skBitmap; |
1354 int height = pSource->GetHeight(); | 1453 int width, height; |
1355 int rowBytes = pSource->GetPitch(); | 1454 if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width, |
1356 switch (pSource->GetBPP()) { | 1455 &height, false)) { |
1357 case 1: { | 1456 return FALSE; |
1358 dst8Storage.reset(FX_Alloc2D(uint8_t, width, height)); | |
1359 uint8_t* dst8Pixels = dst8Storage.get(); | |
1360 for (int y = 0; y < height; ++y) { | |
1361 const uint8_t* srcRow = | |
1362 static_cast<const uint8_t*>(buffer) + y * rowBytes; | |
1363 uint8_t* dstRow = dst8Pixels + y * width; | |
1364 for (int x = 0; x < width; ++x) | |
1365 dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00; | |
1366 } | |
1367 buffer = dst8Storage.get(); | |
1368 rowBytes = width; | |
1369 } break; | |
1370 case 8: | |
1371 if (pSource->GetPalette()) { | |
1372 ct = new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize()); | |
1373 colorType = SkColorType::kIndex_8_SkColorType; | |
1374 } | |
1375 break; | |
1376 case 24: { | |
1377 dst32Storage.reset(FX_Alloc2D(uint32_t, width, height)); | |
1378 uint32_t* dst32Pixels = dst32Storage.get(); | |
1379 for (int y = 0; y < height; ++y) { | |
1380 const uint8_t* srcRow = | |
1381 static_cast<const uint8_t*>(buffer) + y * rowBytes; | |
1382 uint32_t* dstRow = dst32Pixels + y * width; | |
1383 for (int x = 0; x < width; ++x) { | |
1384 dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1], | |
1385 srcRow[x * 3 + 0]); | |
1386 } | |
1387 } | |
1388 buffer = dst32Storage.get(); | |
1389 rowBytes = width * sizeof(uint32_t); | |
1390 colorType = SkColorType::kN32_SkColorType; | |
1391 alphaType = kOpaque_SkAlphaType; | |
1392 } break; | |
1393 case 32: | |
1394 colorType = SkColorType::kN32_SkColorType; | |
1395 alphaType = kPremul_SkAlphaType; | |
1396 pSource->DebugVerifyBitmapIsPreMultiplied(buffer); | |
1397 break; | |
1398 default: | |
1399 SkASSERT(0); // TODO(caryclark) ensure that all cases are covered | |
1400 colorType = SkColorType::kUnknown_SkColorType; | |
1401 } | 1457 } |
1402 SkImageInfo imageInfo = | |
1403 SkImageInfo::Make(width, height, colorType, alphaType); | |
1404 SkBitmap skBitmap; | |
1405 skBitmap.installPixels(imageInfo, buffer, rowBytes, ct, nullptr, nullptr); | |
1406 m_pCanvas->save(); | 1458 m_pCanvas->save(); |
1407 SkMatrix skMatrix; | 1459 SkMatrix skMatrix; |
1408 const CFX_Matrix& m = *pMatrix; | 1460 SetBitmapMatrix(pMatrix, width, height, &skMatrix); |
1409 skMatrix.setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width, | |
1410 -m.d / height, m.d + m.f, 0, 0, 1); | |
1411 m_pCanvas->concat(skMatrix); | 1461 m_pCanvas->concat(skMatrix); |
1412 SkPaint paint; | 1462 SkPaint paint; |
1413 paint.setAntiAlias(true); | 1463 SetBitmapPaint(pSource->IsAlphaMask(), argb, bitmap_alpha, blend_type, |
1414 if (pSource->IsAlphaMask()) { | 1464 &paint); |
1415 paint.setColorFilter( | 1465 // TODO(caryclark) Once Skia supports 8 bit src to 8 bit dst remove this |
1416 SkColorFilter::MakeModeFilter(argb, SkXfermode::kSrc_Mode)); | 1466 if (m_pBitmap->GetBPP() == 8 && pSource->GetBPP() == 8) { |
| 1467 SkMatrix inv; |
| 1468 SkAssertResult(skMatrix.invert(&inv)); |
| 1469 for (int y = 0; y < m_pBitmap->GetHeight(); ++y) { |
| 1470 for (int x = 0; x < m_pBitmap->GetWidth(); ++x) { |
| 1471 SkPoint src = {x + 0.5f, y + 0.5f}; |
| 1472 inv.mapPoints(&src, 1); |
| 1473 // TODO(caryclark) Why does the matrix map require clamping? |
| 1474 src.fX = SkTMax(0.5f, SkTMin(src.fX, width - 0.5f)); |
| 1475 src.fY = SkTMax(0.5f, SkTMin(src.fY, height - 0.5f)); |
| 1476 m_pBitmap->SetPixel(x, y, skBitmap.getColor(src.fX, src.fY)); |
| 1477 } |
| 1478 } |
| 1479 } else { |
| 1480 m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); |
1417 } | 1481 } |
1418 // paint.setFilterQuality(kHigh_SkFilterQuality); | |
1419 paint.setXfermodeMode(GetSkiaBlendMode(blend_type)); | |
1420 paint.setAlpha(bitmap_alpha); | |
1421 m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); | |
1422 m_pCanvas->restore(); | 1482 m_pCanvas->restore(); |
1423 if (ct) | 1483 if (ct) |
1424 ct->unref(); | 1484 ct->unref(); |
1425 DebugValidate(m_pBitmap, m_pOriDevice); | 1485 DebugValidate(m_pBitmap, m_pOriDevice); |
1426 return TRUE; | 1486 return TRUE; |
1427 } | 1487 } |
1428 | 1488 |
1429 FX_BOOL CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { | 1489 FX_BOOL CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { |
1430 return FALSE; | 1490 return FALSE; |
1431 } | 1491 } |
(...skipping 11 matching lines...) Expand all Loading... |
1443 SkImageInfo unpremultipliedInfo = | 1503 SkImageInfo unpremultipliedInfo = |
1444 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); | 1504 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); |
1445 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); | 1505 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); |
1446 SkImageInfo premultipliedInfo = | 1506 SkImageInfo premultipliedInfo = |
1447 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); | 1507 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); |
1448 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); | 1508 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); |
1449 unpremultiplied.readPixels(premultiplied); | 1509 unpremultiplied.readPixels(premultiplied); |
1450 pDIBitmap->DebugVerifyBitmapIsPreMultiplied(); | 1510 pDIBitmap->DebugVerifyBitmapIsPreMultiplied(); |
1451 } | 1511 } |
1452 | 1512 |
| 1513 bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource, |
| 1514 const CFX_DIBSource* pMask, |
| 1515 int bitmap_alpha, |
| 1516 const CFX_Matrix* pMatrix, |
| 1517 int blend_type) { |
| 1518 DebugValidate(m_pBitmap, m_pOriDevice); |
| 1519 SkColorTable* srcCt = nullptr; |
| 1520 SkColorTable* maskCt = nullptr; |
| 1521 std::unique_ptr<uint8_t, FxFreeDeleter> src8Storage, mask8Storage; |
| 1522 std::unique_ptr<uint32_t, FxFreeDeleter> src32Storage, mask32Storage; |
| 1523 SkBitmap skBitmap, skMask; |
| 1524 int srcWidth, srcHeight, maskWidth, maskHeight; |
| 1525 if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap, |
| 1526 &srcWidth, &srcHeight, false)) { |
| 1527 return false; |
| 1528 } |
| 1529 if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask, |
| 1530 &maskWidth, &maskHeight, true)) { |
| 1531 return false; |
| 1532 } |
| 1533 m_pCanvas->save(); |
| 1534 SkMatrix skMatrix; |
| 1535 SetBitmapMatrix(pMatrix, srcWidth, srcHeight, &skMatrix); |
| 1536 m_pCanvas->concat(skMatrix); |
| 1537 SkPaint paint; |
| 1538 SetBitmapPaint(pSource->IsAlphaMask(), 0xFFFFFFFF, bitmap_alpha, blend_type, |
| 1539 &paint); |
| 1540 sk_sp<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap); |
| 1541 sk_sp<SkShader> skSrcShader = |
| 1542 skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); |
| 1543 sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask); |
| 1544 sk_sp<SkShader> skMaskShader = skMaskImage->makeShader( |
| 1545 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); |
| 1546 sk_sp<SkXfermode> dstInMode = SkXfermode::Make(SkXfermode::kSrcIn_Mode); |
| 1547 paint.setShader( |
| 1548 SkShader::MakeComposeShader(skMaskShader, skSrcShader, dstInMode)); |
| 1549 SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)}; |
| 1550 m_pCanvas->drawRect(r, paint); |
| 1551 m_pCanvas->restore(); |
| 1552 if (srcCt) |
| 1553 srcCt->unref(); |
| 1554 DebugValidate(m_pBitmap, m_pOriDevice); |
| 1555 return true; |
| 1556 } |
| 1557 |
| 1558 bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap, |
| 1559 const CFX_DIBSource* pMask, |
| 1560 int dest_left, |
| 1561 int dest_top, |
| 1562 int bitmap_alpha, |
| 1563 int blend_type) { |
| 1564 if (!m_pBitmap || !m_pBitmap->GetBuffer()) |
| 1565 return true; |
| 1566 CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left, |
| 1567 dest_top + pBitmap->GetHeight()); |
| 1568 return DrawBitsWithMask(pBitmap, pMask, bitmap_alpha, &m, blend_type); |
| 1569 } |
| 1570 |
| 1571 void CFX_SkiaDeviceDriver::Clear(uint32_t color) { |
| 1572 m_pCanvas->clear(color); |
| 1573 } |
| 1574 |
1453 void CFX_SkiaDeviceDriver::Dump() const { | 1575 void CFX_SkiaDeviceDriver::Dump() const { |
1454 #ifdef SK_DEBUG | 1576 #ifdef SK_DEBUG |
1455 if (m_pCache) | 1577 if (m_pCache) |
1456 m_pCache->Dump(this); | 1578 m_pCache->Dump(this); |
1457 #endif | 1579 #endif |
1458 } | 1580 } |
1459 | 1581 |
1460 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const { | 1582 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const { |
1461 if (m_pOriDevice) | 1583 if (m_pOriDevice) |
1462 m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(); | 1584 m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(); |
1463 } | 1585 } |
1464 | 1586 |
1465 CFX_FxgeDevice::CFX_FxgeDevice() { | 1587 CFX_FxgeDevice::CFX_FxgeDevice() { |
1466 m_bOwnedBitmap = FALSE; | 1588 m_bOwnedBitmap = FALSE; |
1467 } | 1589 } |
1468 | 1590 |
| 1591 void CFX_FxgeDevice::Clear(uint32_t color) { |
| 1592 CFX_SkiaDeviceDriver* skDriver = |
| 1593 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); |
| 1594 skDriver->Clear(color); |
| 1595 } |
| 1596 |
1469 SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) { | 1597 SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) { |
1470 CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y); | 1598 CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y); |
1471 SetDeviceDriver(WrapUnique(skDriver)); | 1599 SetDeviceDriver(WrapUnique(skDriver)); |
1472 return skDriver->GetRecorder(); | 1600 return skDriver->GetRecorder(); |
1473 } | 1601 } |
1474 | 1602 |
1475 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, | 1603 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, |
1476 bool bRgbByteOrder, | 1604 bool bRgbByteOrder, |
1477 CFX_DIBitmap* pOriDevice, | 1605 CFX_DIBitmap* pOriDevice, |
1478 bool bGroupKnockout) { | 1606 bool bGroupKnockout) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 | 1644 |
1517 void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { | 1645 void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { |
1518 #ifdef SK_DEBUG | 1646 #ifdef SK_DEBUG |
1519 CFX_SkiaDeviceDriver* skDriver = | 1647 CFX_SkiaDeviceDriver* skDriver = |
1520 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); | 1648 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); |
1521 if (skDriver) | 1649 if (skDriver) |
1522 skDriver->DebugVerifyBitmapIsPreMultiplied(); | 1650 skDriver->DebugVerifyBitmapIsPreMultiplied(); |
1523 #endif | 1651 #endif |
1524 } | 1652 } |
1525 | 1653 |
| 1654 bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, |
| 1655 const CFX_DIBSource* pMask, |
| 1656 int left, |
| 1657 int top, |
| 1658 int bitmap_alpha, |
| 1659 int blend_type) { |
| 1660 CFX_SkiaDeviceDriver* skDriver = |
| 1661 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); |
| 1662 if (skDriver) |
| 1663 return skDriver->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha, |
| 1664 blend_type); |
| 1665 return false; |
| 1666 } |
| 1667 |
1526 void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const { | 1668 void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const { |
1527 #ifdef SK_DEBUG | 1669 #ifdef SK_DEBUG |
1528 SkASSERT(32 == GetBPP()); | 1670 SkASSERT(32 == GetBPP()); |
1529 const uint32_t* buffer = (const uint32_t*)(opt ? opt : GetBuffer()); | 1671 const uint32_t* buffer = (const uint32_t*)(opt ? opt : GetBuffer()); |
1530 int width = GetWidth(); | 1672 int width = GetWidth(); |
1531 int height = GetHeight(); | 1673 int height = GetHeight(); |
1532 // verify that input is really premultiplied | 1674 // verify that input is really premultiplied |
1533 for (int y = 0; y < height; ++y) { | 1675 for (int y = 0; y < height; ++y) { |
1534 const uint32_t* srcRow = buffer + y * width; | 1676 const uint32_t* srcRow = buffer + y * width; |
1535 for (int x = 0; x < width; ++x) { | 1677 for (int x = 0; x < width; ++x) { |
1536 uint8_t a = SkGetPackedA32(srcRow[x]); | 1678 uint8_t a = SkGetPackedA32(srcRow[x]); |
1537 uint8_t r = SkGetPackedR32(srcRow[x]); | 1679 uint8_t r = SkGetPackedR32(srcRow[x]); |
1538 uint8_t g = SkGetPackedG32(srcRow[x]); | 1680 uint8_t g = SkGetPackedG32(srcRow[x]); |
1539 uint8_t b = SkGetPackedB32(srcRow[x]); | 1681 uint8_t b = SkGetPackedB32(srcRow[x]); |
1540 SkA32Assert(a); | 1682 SkA32Assert(a); |
1541 SkASSERT(r <= a); | 1683 SkASSERT(r <= a); |
1542 SkASSERT(g <= a); | 1684 SkASSERT(g <= a); |
1543 SkASSERT(b <= a); | 1685 SkASSERT(b <= a); |
1544 } | 1686 } |
1545 } | 1687 } |
1546 #endif | 1688 #endif |
1547 } | 1689 } |
1548 | 1690 |
1549 #endif | 1691 #endif |
OLD | NEW |