Chromium Code Reviews| 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 #include "core/include/fxge/fx_ge.h" | 5 #include "core/include/fxge/fx_ge.h" |
| 6 | 6 |
| 7 #if defined(_SKIA_SUPPORT_) | 7 #if defined(_SKIA_SUPPORT_) |
| 8 #include "core/include/fxcodec/fx_codec.h" | 8 #include "core/include/fxcodec/fx_codec.h" |
| 9 | 9 |
| 10 #include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h" | |
| 11 #include "core/fpdfapi/fpdf_page/pageint.h" | |
| 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | |
| 13 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" | |
| 10 #include "core/fxge/agg/fx_agg_driver.h" | 14 #include "core/fxge/agg/fx_agg_driver.h" |
| 11 #include "core/fxge/skia/fx_skia_device.h" | 15 #include "core/fxge/skia/fx_skia_device.h" |
| 12 | 16 |
| 13 #include "third_party/skia/include/core/SkCanvas.h" | 17 #include "third_party/skia/include/core/SkCanvas.h" |
| 14 #include "third_party/skia/include/core/SkColorPriv.h" | 18 #include "third_party/skia/include/core/SkColorPriv.h" |
| 15 #include "third_party/skia/include/core/SkPaint.h" | 19 #include "third_party/skia/include/core/SkPaint.h" |
| 16 #include "third_party/skia/include/core/SkPath.h" | 20 #include "third_party/skia/include/core/SkPath.h" |
| 17 #include "third_party/skia/include/core/SkPictureRecorder.h" | 21 #include "third_party/skia/include/core/SkPictureRecorder.h" |
| 18 #include "third_party/skia/include/core/SkStream.h" | 22 #include "third_party/skia/include/core/SkStream.h" |
| 19 #include "third_party/skia/include/core/SkTypeface.h" | 23 #include "third_party/skia/include/core/SkTypeface.h" |
| 20 #include "third_party/skia/include/effects/SkDashPathEffect.h" | 24 #include "third_party/skia/include/effects/SkDashPathEffect.h" |
| 25 #include "third_party/skia/include/effects/SkGradientShader.h" | |
| 26 #include "third_party/skia/include/pathops/SkPathOps.h" | |
| 21 | 27 |
| 22 namespace { | 28 namespace { |
| 23 | 29 |
| 24 #define SHOW_SKIA_PATH 0 // set to 1 to print the path contents | 30 #define SHOW_SKIA_PATH 0 // set to 1 to print the path contents |
| 25 #define DRAW_SKIA_CLIP 0 // set to 1 to draw a green rectangle around the clip | 31 #define DRAW_SKIA_CLIP 0 // set to 1 to draw a green rectangle around the clip |
| 26 | 32 |
| 27 void DebugShowSkiaPath(const SkPath& path) { | 33 void DebugShowSkiaPath(const SkPath& path) { |
| 28 #if SHOW_SKIA_PATH | 34 #if SHOW_SKIA_PATH |
| 29 char buffer[4096]; | 35 char buffer[4096]; |
| 30 sk_bzero(buffer, sizeof(buffer)); | 36 sk_bzero(buffer, sizeof(buffer)); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 case FXDIB_BLEND_COLOR: | 149 case FXDIB_BLEND_COLOR: |
| 144 return SkXfermode::kColor_Mode; | 150 return SkXfermode::kColor_Mode; |
| 145 case FXDIB_BLEND_LUMINOSITY: | 151 case FXDIB_BLEND_LUMINOSITY: |
| 146 return SkXfermode::kLuminosity_Mode; | 152 return SkXfermode::kLuminosity_Mode; |
| 147 case FXDIB_BLEND_NORMAL: | 153 case FXDIB_BLEND_NORMAL: |
| 148 default: | 154 default: |
| 149 return SkXfermode::kSrcOver_Mode; | 155 return SkXfermode::kSrcOver_Mode; |
| 150 } | 156 } |
| 151 } | 157 } |
| 152 | 158 |
| 159 bool AddColors(const CPDF_Function* pFunc, SkTDArray<SkColor>* skColors) { | |
| 160 if (pFunc->CountInputs() != 1) | |
| 161 return false; | |
| 162 const CPDF_ExpIntFunc* expIntFunc = | |
|
Tom Sepez
2016/03/24 18:07:08
nit: want to assert on type before the cast?
caryclark
2016/03/25 20:47:56
Done.
| |
| 163 static_cast<const CPDF_ExpIntFunc*>(pFunc); | |
| 164 if (expIntFunc->m_Exponent != 1) | |
| 165 return false; | |
| 166 if (expIntFunc->m_nOrigOutputs != 3) | |
| 167 return false; | |
| 168 skColors->push(SkColorSetARGB( | |
| 169 0xFF, SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[0]), | |
| 170 SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[1]), | |
| 171 SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[2]))); | |
| 172 skColors->push( | |
| 173 SkColorSetARGB(0xFF, SkUnitScalarClampToByte(expIntFunc->m_pEndValues[0]), | |
| 174 SkUnitScalarClampToByte(expIntFunc->m_pEndValues[1]), | |
| 175 SkUnitScalarClampToByte(expIntFunc->m_pEndValues[2]))); | |
| 176 return true; | |
| 177 } | |
| 178 | |
| 179 bool AddStitching(const CPDF_Function* pFunc, | |
| 180 SkTDArray<SkColor>* skColors, | |
| 181 SkTDArray<SkScalar>* skPos) { | |
| 182 int inputs = pFunc->CountInputs(); | |
| 183 const CPDF_StitchFunc* stitchFunc = | |
|
Tom Sepez
2016/03/24 18:07:08
dittp
caryclark
2016/03/25 20:47:56
Done.
| |
| 184 static_cast<const CPDF_StitchFunc*>(pFunc); | |
| 185 FX_FLOAT boundsStart = stitchFunc->GetDomain(0); | |
| 186 | |
| 187 for (int i = 0; i < inputs; ++i) { | |
| 188 const CPDF_Function* pSubFunc = stitchFunc->m_pSubFunctions[i]; | |
| 189 if (pSubFunc->GetType() != 2) | |
| 190 return false; | |
| 191 if (!AddColors(pSubFunc, skColors)) | |
| 192 return false; | |
| 193 FX_FLOAT boundsEnd = | |
| 194 i < inputs - 1 ? stitchFunc->m_pBounds[i] : stitchFunc->GetDomain(1); | |
| 195 skPos->push(boundsStart); | |
| 196 skPos->push(boundsEnd); | |
| 197 boundsStart = boundsEnd; | |
| 198 } | |
| 199 return true; | |
| 200 } | |
| 201 | |
| 153 } // namespace | 202 } // namespace |
| 154 | 203 |
| 155 // convert a stroking path to scanlines | 204 // convert a stroking path to scanlines |
| 156 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, | 205 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, |
| 157 const CFX_GraphStateData* pGraphState, | 206 const CFX_GraphStateData* pGraphState, |
| 158 const SkMatrix& matrix) { | 207 const SkMatrix& matrix) { |
| 159 SkPaint::Cap cap; | 208 SkPaint::Cap cap; |
| 160 switch (pGraphState->m_LineCap) { | 209 switch (pGraphState->m_LineCap) { |
| 161 case CFX_GraphStateData::LineCapRound: | 210 case CFX_GraphStateData::LineCapRound: |
| 162 cap = SkPaint::kRound_Cap; | 211 cap = SkPaint::kRound_Cap; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 return m_pCanvas->imageInfo().width(); | 345 return m_pCanvas->imageInfo().width(); |
| 297 case FXDC_PIXEL_HEIGHT: | 346 case FXDC_PIXEL_HEIGHT: |
| 298 return m_pCanvas->imageInfo().height(); | 347 return m_pCanvas->imageInfo().height(); |
| 299 case FXDC_BITS_PIXEL: | 348 case FXDC_BITS_PIXEL: |
| 300 return 32; | 349 return 32; |
| 301 case FXDC_HORZ_SIZE: | 350 case FXDC_HORZ_SIZE: |
| 302 case FXDC_VERT_SIZE: | 351 case FXDC_VERT_SIZE: |
| 303 return 0; | 352 return 0; |
| 304 case FXDC_RENDER_CAPS: | 353 case FXDC_RENDER_CAPS: |
| 305 return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | | 354 return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | |
| 306 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT; | 355 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT | |
| 356 FXRC_FILLSTROKE_PATH | FXRC_SHADING; | |
| 307 case FXDC_DITHER_BITS: | 357 case FXDC_DITHER_BITS: |
| 308 return m_ditherBits; | 358 return m_ditherBits; |
| 309 } | 359 } |
| 310 return 0; | 360 return 0; |
| 311 } | 361 } |
| 312 | 362 |
| 313 void CFX_SkiaDeviceDriver::SaveState() { | 363 void CFX_SkiaDeviceDriver::SaveState() { |
| 314 m_pCanvas->save(); | 364 m_pCanvas->save(); |
| 315 } | 365 } |
| 316 | 366 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 const CFX_GraphStateData* pGraphState, // graphic state, for pen attributes | 428 const CFX_GraphStateData* pGraphState, // graphic state, for pen attributes |
| 379 FX_DWORD fill_color, // fill color | 429 FX_DWORD fill_color, // fill color |
| 380 FX_DWORD stroke_color, // stroke color | 430 FX_DWORD stroke_color, // stroke color |
| 381 int fill_mode, // fill mode, WINDING or ALTERNATE. 0 for not filled | 431 int fill_mode, // fill mode, WINDING or ALTERNATE. 0 for not filled |
| 382 int alpha_flag, | 432 int alpha_flag, |
| 383 void* pIccTransform, | 433 void* pIccTransform, |
| 384 int blend_type) { | 434 int blend_type) { |
| 385 SkIRect rect; | 435 SkIRect rect; |
| 386 rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), | 436 rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), |
| 387 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); | 437 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); |
| 438 SkMatrix skMatrix = ToSkMatrix(*pObject2Device); | |
| 439 SkPaint skPaint; | |
| 440 skPaint.setAntiAlias(true); | |
| 441 int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) | |
| 442 ? FXGETFLAG_ALPHA_STROKE(alpha_flag) | |
| 443 : FXARGB_A(stroke_color); | |
| 444 if (pGraphState && stroke_alpha) { | |
| 445 PaintStroke(&skPaint, pGraphState, skMatrix); | |
| 446 } | |
|
dsinclair
2016/03/24 17:43:38
nit: No {}s
caryclark
2016/03/25 20:47:56
Done.
| |
| 388 SkPath skPath = BuildPath(pPathData); | 447 SkPath skPath = BuildPath(pPathData); |
| 389 SkPaint spaint; | |
| 390 spaint.setAntiAlias(true); | |
| 391 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); | |
| 392 m_pCanvas->save(); | 448 m_pCanvas->save(); |
| 393 SkMatrix skMatrix = ToSkMatrix(*pObject2Device); | |
| 394 m_pCanvas->concat(skMatrix); | 449 m_pCanvas->concat(skMatrix); |
| 395 if ((fill_mode & 3) && fill_color) { | 450 if ((fill_mode & 3) && fill_color) { |
| 396 skPath.setFillType((fill_mode & 3) == FXFILL_WINDING | 451 skPath.setFillType((fill_mode & 3) == FXFILL_WINDING |
| 397 ? SkPath::kWinding_FillType | 452 ? SkPath::kWinding_FillType |
| 398 : SkPath::kEvenOdd_FillType); | 453 : SkPath::kEvenOdd_FillType); |
| 399 | 454 SkPath strokePath; |
| 400 spaint.setStyle(SkPaint::kFill_Style); | 455 const SkPath* fillPath = &skPath; |
| 401 spaint.setColor(fill_color); | 456 if (pGraphState && stroke_alpha) { |
| 402 m_pCanvas->drawPath(skPath, spaint); | 457 SkAlpha fillA = SkColorGetA(fill_color); |
| 458 SkAlpha strokeA = SkColorGetA(stroke_color); | |
| 459 if (fillA && fillA < 0xFF && strokeA && strokeA < 0xFF) { | |
| 460 skPaint.getFillPath(skPath, &strokePath); | |
| 461 if (Op(skPath, strokePath, SkPathOp::kDifference_SkPathOp, | |
| 462 &strokePath)) { | |
| 463 fillPath = &strokePath; | |
| 464 } | |
| 465 } | |
| 466 } | |
| 467 skPaint.setStyle(SkPaint::kFill_Style); | |
| 468 skPaint.setColor(fill_color); | |
| 469 m_pCanvas->drawPath(*fillPath, skPaint); | |
| 403 } | 470 } |
| 404 int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) | |
| 405 ? FXGETFLAG_ALPHA_STROKE(alpha_flag) | |
| 406 : FXARGB_A(stroke_color); | |
| 407 | |
| 408 if (pGraphState && stroke_alpha) { | 471 if (pGraphState && stroke_alpha) { |
| 409 spaint.setColor(stroke_color); | |
| 410 PaintStroke(&spaint, pGraphState, skMatrix); | |
| 411 DebugShowSkiaPath(skPath); | 472 DebugShowSkiaPath(skPath); |
| 412 DebugShowCanvasMatrix(m_pCanvas); | 473 DebugShowCanvasMatrix(m_pCanvas); |
| 413 m_pCanvas->drawPath(skPath, spaint); | 474 skPaint.setStyle(SkPaint::kStroke_Style); |
| 475 skPaint.setColor(stroke_color); | |
| 476 m_pCanvas->drawPath(skPath, skPaint); | |
| 414 } | 477 } |
| 415 m_pCanvas->restore(); | 478 m_pCanvas->restore(); |
| 416 return TRUE; | 479 return TRUE; |
| 417 } | 480 } |
| 418 | 481 |
| 419 FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect, | 482 FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect, |
| 420 FX_DWORD fill_color, | 483 FX_DWORD fill_color, |
| 421 int alpha_flag, | 484 int alpha_flag, |
| 422 void* pIccTransform, | 485 void* pIccTransform, |
| 423 int blend_type) { | 486 int blend_type) { |
| 424 SkPaint spaint; | 487 SkPaint spaint; |
| 425 spaint.setAntiAlias(true); | 488 spaint.setAntiAlias(true); |
| 426 spaint.setColor(fill_color); | 489 spaint.setColor(fill_color); |
| 427 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); | 490 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); |
| 428 | 491 |
| 429 m_pCanvas->drawRect( | 492 m_pCanvas->drawRect( |
| 430 SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), | 493 SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), |
| 431 spaint); | 494 spaint); |
| 432 return TRUE; | 495 return TRUE; |
| 433 } | 496 } |
| 434 | 497 |
| 498 FX_BOOL CFX_SkiaDeviceDriver::DrawShading(CPDF_ShadingPattern* pPattern, | |
| 499 CFX_Matrix* pMatrix, | |
| 500 int alpha, | |
| 501 FX_BOOL bAlphaMode) { | |
| 502 CPDF_Function** pFuncs = pPattern->m_pFunctions; | |
| 503 int nFuncs = pPattern->m_nFuncs; | |
| 504 CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); | |
| 505 CPDF_Array* pCoords = pDict->GetArrayBy("Coords"); | |
| 506 if (!pCoords) | |
| 507 return true; | |
| 508 FX_FLOAT start_x = pCoords->GetNumberAt(0); | |
| 509 FX_FLOAT start_y = pCoords->GetNumberAt(1); | |
| 510 FX_FLOAT end_x = pCoords->GetNumberAt(2); | |
| 511 FX_FLOAT end_y = pCoords->GetNumberAt(3); | |
| 512 FX_FLOAT t_min = 0, t_max = 1.0f; | |
|
dsinclair
2016/03/24 17:43:38
nit: one per line.
caryclark
2016/03/25 20:47:56
Done.
| |
| 513 CPDF_Array* pArray = pDict->GetArrayBy("Domain"); | |
| 514 if (pArray) { | |
| 515 t_min = pArray->GetNumberAt(0); | |
| 516 t_max = pArray->GetNumberAt(1); | |
| 517 } | |
| 518 FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; | |
| 519 pArray = pDict->GetArrayBy("Extend"); | |
| 520 if (pArray) { | |
| 521 bStartExtend = pArray->GetIntegerAt(0); | |
| 522 bEndExtend = pArray->GetIntegerAt(1); | |
| 523 } | |
| 524 SkTDArray<SkColor> skColors; | |
| 525 SkTDArray<SkScalar> skPos; | |
| 526 if (nFuncs != 1) | |
|
dsinclair
2016/03/24 17:43:38
Can we do this earlier before all the other work?
caryclark
2016/03/25 20:47:56
Done.
| |
| 527 return false; | |
| 528 for (int j = 0; j < nFuncs; j++) { | |
| 529 const CPDF_Function* pFunc = pFuncs[j]; | |
| 530 if (!pFunc) | |
| 531 continue; | |
| 532 switch (pFunc->GetType()) { | |
| 533 case 2: // exp interp function | |
|
dsinclair
2016/03/24 17:43:38
Can you expand 'exp interp' as I don't know what t
caryclark
2016/03/25 20:47:56
Done.
| |
| 534 if (!AddColors(pFunc, &skColors)) | |
| 535 return false; | |
| 536 skPos.push(0); | |
| 537 skPos.push(1); | |
| 538 break; | |
| 539 case 3: // stitching functions | |
| 540 if (!AddStitching(pFunc, &skColors, &skPos)) | |
| 541 return false; | |
| 542 break; | |
| 543 default: | |
| 544 return false; | |
| 545 } | |
| 546 } | |
| 547 SkMatrix skMatrix = ToSkMatrix(*pMatrix); | |
| 548 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; | |
| 549 SkPaint paint; | |
| 550 paint.setAntiAlias(true); | |
| 551 paint.setShader(SkGradientShader::MakeLinear(pts, skColors.begin(), | |
| 552 skPos.begin(), skColors.count(), | |
| 553 SkShader::kClamp_TileMode)); | |
| 554 paint.setAlpha(alpha); | |
| 555 m_pCanvas->save(); | |
| 556 m_pCanvas->concat(skMatrix); | |
| 557 m_pCanvas->drawRect(SkRect::MakeWH(1, 1), paint); | |
| 558 m_pCanvas->restore(); | |
| 559 return true; | |
| 560 } | |
| 561 | |
| 435 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { | 562 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { |
| 436 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead | 563 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead |
| 437 pRect->left = 0; | 564 pRect->left = 0; |
| 438 pRect->top = 0; | 565 pRect->top = 0; |
| 439 const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); | 566 const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); |
| 440 pRect->right = canvasSize.width(); | 567 pRect->right = canvasSize.width(); |
| 441 pRect->bottom = canvasSize.height(); | 568 pRect->bottom = canvasSize.height(); |
| 442 return TRUE; | 569 return TRUE; |
| 443 } | 570 } |
| 444 | 571 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 SetDeviceDriver(pDriver); | 748 SetDeviceDriver(pDriver); |
| 622 return TRUE; | 749 return TRUE; |
| 623 } | 750 } |
| 624 | 751 |
| 625 CFX_SkiaDevice::~CFX_SkiaDevice() { | 752 CFX_SkiaDevice::~CFX_SkiaDevice() { |
| 626 if (m_bOwnedBitmap && GetBitmap()) | 753 if (m_bOwnedBitmap && GetBitmap()) |
| 627 delete GetBitmap(); | 754 delete GetBitmap(); |
| 628 } | 755 } |
| 629 | 756 |
| 630 #endif | 757 #endif |
| OLD | NEW |