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 ASSERT(CPDF_Function::Type::kType2ExpotentialInterpolation == |
| 163 pFunc->GetType()); |
| 164 const CPDF_ExpIntFunc* expIntFunc = |
| 165 static_cast<const CPDF_ExpIntFunc*>(pFunc); |
| 166 if (expIntFunc->m_Exponent != 1) |
| 167 return false; |
| 168 if (expIntFunc->m_nOrigOutputs != 3) |
| 169 return false; |
| 170 skColors->push(SkColorSetARGB( |
| 171 0xFF, SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[0]), |
| 172 SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[1]), |
| 173 SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[2]))); |
| 174 skColors->push( |
| 175 SkColorSetARGB(0xFF, SkUnitScalarClampToByte(expIntFunc->m_pEndValues[0]), |
| 176 SkUnitScalarClampToByte(expIntFunc->m_pEndValues[1]), |
| 177 SkUnitScalarClampToByte(expIntFunc->m_pEndValues[2]))); |
| 178 return true; |
| 179 } |
| 180 |
| 181 bool AddStitching(const CPDF_Function* pFunc, |
| 182 SkTDArray<SkColor>* skColors, |
| 183 SkTDArray<SkScalar>* skPos) { |
| 184 int inputs = pFunc->CountInputs(); |
| 185 ASSERT(CPDF_Function::Type::kType3Stitching == pFunc->GetType()); |
| 186 const CPDF_StitchFunc* stitchFunc = |
| 187 static_cast<const CPDF_StitchFunc*>(pFunc); |
| 188 FX_FLOAT boundsStart = stitchFunc->GetDomain(0); |
| 189 |
| 190 for (int i = 0; i < inputs; ++i) { |
| 191 const CPDF_Function* pSubFunc = stitchFunc->m_pSubFunctions[i]; |
| 192 if (pSubFunc->GetType() != |
| 193 CPDF_Function::Type::kType2ExpotentialInterpolation) |
| 194 return false; |
| 195 if (!AddColors(pSubFunc, skColors)) |
| 196 return false; |
| 197 FX_FLOAT boundsEnd = |
| 198 i < inputs - 1 ? stitchFunc->m_pBounds[i] : stitchFunc->GetDomain(1); |
| 199 skPos->push(boundsStart); |
| 200 skPos->push(boundsEnd); |
| 201 boundsStart = boundsEnd; |
| 202 } |
| 203 return true; |
| 204 } |
| 205 |
153 } // namespace | 206 } // namespace |
154 | 207 |
155 // convert a stroking path to scanlines | 208 // convert a stroking path to scanlines |
156 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, | 209 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, |
157 const CFX_GraphStateData* pGraphState, | 210 const CFX_GraphStateData* pGraphState, |
158 const SkMatrix& matrix) { | 211 const SkMatrix& matrix) { |
159 SkPaint::Cap cap; | 212 SkPaint::Cap cap; |
160 switch (pGraphState->m_LineCap) { | 213 switch (pGraphState->m_LineCap) { |
161 case CFX_GraphStateData::LineCapRound: | 214 case CFX_GraphStateData::LineCapRound: |
162 cap = SkPaint::kRound_Cap; | 215 cap = SkPaint::kRound_Cap; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 return m_pCanvas->imageInfo().width(); | 349 return m_pCanvas->imageInfo().width(); |
297 case FXDC_PIXEL_HEIGHT: | 350 case FXDC_PIXEL_HEIGHT: |
298 return m_pCanvas->imageInfo().height(); | 351 return m_pCanvas->imageInfo().height(); |
299 case FXDC_BITS_PIXEL: | 352 case FXDC_BITS_PIXEL: |
300 return 32; | 353 return 32; |
301 case FXDC_HORZ_SIZE: | 354 case FXDC_HORZ_SIZE: |
302 case FXDC_VERT_SIZE: | 355 case FXDC_VERT_SIZE: |
303 return 0; | 356 return 0; |
304 case FXDC_RENDER_CAPS: | 357 case FXDC_RENDER_CAPS: |
305 return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | | 358 return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | |
306 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT; | 359 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT | |
| 360 FXRC_FILLSTROKE_PATH | FXRC_SHADING; |
307 case FXDC_DITHER_BITS: | 361 case FXDC_DITHER_BITS: |
308 return m_ditherBits; | 362 return m_ditherBits; |
309 } | 363 } |
310 return 0; | 364 return 0; |
311 } | 365 } |
312 | 366 |
313 void CFX_SkiaDeviceDriver::SaveState() { | 367 void CFX_SkiaDeviceDriver::SaveState() { |
314 m_pCanvas->save(); | 368 m_pCanvas->save(); |
315 } | 369 } |
316 | 370 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 const CFX_GraphStateData* pGraphState, // graphic state, for pen attributes | 432 const CFX_GraphStateData* pGraphState, // graphic state, for pen attributes |
379 FX_DWORD fill_color, // fill color | 433 FX_DWORD fill_color, // fill color |
380 FX_DWORD stroke_color, // stroke color | 434 FX_DWORD stroke_color, // stroke color |
381 int fill_mode, // fill mode, WINDING or ALTERNATE. 0 for not filled | 435 int fill_mode, // fill mode, WINDING or ALTERNATE. 0 for not filled |
382 int alpha_flag, | 436 int alpha_flag, |
383 void* pIccTransform, | 437 void* pIccTransform, |
384 int blend_type) { | 438 int blend_type) { |
385 SkIRect rect; | 439 SkIRect rect; |
386 rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), | 440 rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), |
387 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); | 441 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); |
| 442 SkMatrix skMatrix = ToSkMatrix(*pObject2Device); |
| 443 SkPaint skPaint; |
| 444 skPaint.setAntiAlias(true); |
| 445 int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) |
| 446 ? FXGETFLAG_ALPHA_STROKE(alpha_flag) |
| 447 : FXARGB_A(stroke_color); |
| 448 if (pGraphState && stroke_alpha) |
| 449 PaintStroke(&skPaint, pGraphState, skMatrix); |
388 SkPath skPath = BuildPath(pPathData); | 450 SkPath skPath = BuildPath(pPathData); |
389 SkPaint spaint; | |
390 spaint.setAntiAlias(true); | |
391 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); | |
392 m_pCanvas->save(); | 451 m_pCanvas->save(); |
393 SkMatrix skMatrix = ToSkMatrix(*pObject2Device); | |
394 m_pCanvas->concat(skMatrix); | 452 m_pCanvas->concat(skMatrix); |
395 if ((fill_mode & 3) && fill_color) { | 453 if ((fill_mode & 3) && fill_color) { |
396 skPath.setFillType((fill_mode & 3) == FXFILL_WINDING | 454 skPath.setFillType((fill_mode & 3) == FXFILL_WINDING |
397 ? SkPath::kWinding_FillType | 455 ? SkPath::kWinding_FillType |
398 : SkPath::kEvenOdd_FillType); | 456 : SkPath::kEvenOdd_FillType); |
399 | 457 SkPath strokePath; |
400 spaint.setStyle(SkPaint::kFill_Style); | 458 const SkPath* fillPath = &skPath; |
401 spaint.setColor(fill_color); | 459 if (pGraphState && stroke_alpha) { |
402 m_pCanvas->drawPath(skPath, spaint); | 460 SkAlpha fillA = SkColorGetA(fill_color); |
| 461 SkAlpha strokeA = SkColorGetA(stroke_color); |
| 462 if (fillA && fillA < 0xFF && strokeA && strokeA < 0xFF) { |
| 463 skPaint.getFillPath(skPath, &strokePath); |
| 464 if (Op(skPath, strokePath, SkPathOp::kDifference_SkPathOp, |
| 465 &strokePath)) { |
| 466 fillPath = &strokePath; |
| 467 } |
| 468 } |
| 469 } |
| 470 skPaint.setStyle(SkPaint::kFill_Style); |
| 471 skPaint.setColor(fill_color); |
| 472 m_pCanvas->drawPath(*fillPath, skPaint); |
403 } | 473 } |
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) { | 474 if (pGraphState && stroke_alpha) { |
409 spaint.setColor(stroke_color); | |
410 PaintStroke(&spaint, pGraphState, skMatrix); | |
411 DebugShowSkiaPath(skPath); | 475 DebugShowSkiaPath(skPath); |
412 DebugShowCanvasMatrix(m_pCanvas); | 476 DebugShowCanvasMatrix(m_pCanvas); |
413 m_pCanvas->drawPath(skPath, spaint); | 477 skPaint.setStyle(SkPaint::kStroke_Style); |
| 478 skPaint.setColor(stroke_color); |
| 479 m_pCanvas->drawPath(skPath, skPaint); |
414 } | 480 } |
415 m_pCanvas->restore(); | 481 m_pCanvas->restore(); |
416 return TRUE; | 482 return TRUE; |
417 } | 483 } |
418 | 484 |
419 FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect, | 485 FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect, |
420 FX_DWORD fill_color, | 486 FX_DWORD fill_color, |
421 int alpha_flag, | 487 int alpha_flag, |
422 void* pIccTransform, | 488 void* pIccTransform, |
423 int blend_type) { | 489 int blend_type) { |
424 SkPaint spaint; | 490 SkPaint spaint; |
425 spaint.setAntiAlias(true); | 491 spaint.setAntiAlias(true); |
426 spaint.setColor(fill_color); | 492 spaint.setColor(fill_color); |
427 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); | 493 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); |
428 | 494 |
429 m_pCanvas->drawRect( | 495 m_pCanvas->drawRect( |
430 SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), | 496 SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), |
431 spaint); | 497 spaint); |
432 return TRUE; | 498 return TRUE; |
433 } | 499 } |
434 | 500 |
| 501 FX_BOOL CFX_SkiaDeviceDriver::DrawShading(CPDF_ShadingPattern* pPattern, |
| 502 CFX_Matrix* pMatrix, |
| 503 int alpha, |
| 504 FX_BOOL bAlphaMode) { |
| 505 CPDF_Function** pFuncs = pPattern->m_pFunctions; |
| 506 int nFuncs = pPattern->m_nFuncs; |
| 507 if (nFuncs != 1) // TODO(caryclark) remove this restriction |
| 508 return false; |
| 509 CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); |
| 510 CPDF_Array* pCoords = pDict->GetArrayBy("Coords"); |
| 511 if (!pCoords) |
| 512 return true; |
| 513 FX_FLOAT start_x = pCoords->GetNumberAt(0); |
| 514 FX_FLOAT start_y = pCoords->GetNumberAt(1); |
| 515 FX_FLOAT end_x = pCoords->GetNumberAt(2); |
| 516 FX_FLOAT end_y = pCoords->GetNumberAt(3); |
| 517 FX_FLOAT t_min = 0; |
| 518 FX_FLOAT t_max = 1; |
| 519 CPDF_Array* pArray = pDict->GetArrayBy("Domain"); |
| 520 if (pArray) { |
| 521 t_min = pArray->GetNumberAt(0); |
| 522 t_max = pArray->GetNumberAt(1); |
| 523 } |
| 524 FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; |
| 525 pArray = pDict->GetArrayBy("Extend"); |
| 526 if (pArray) { |
| 527 bStartExtend = pArray->GetIntegerAt(0); |
| 528 bEndExtend = pArray->GetIntegerAt(1); |
| 529 } |
| 530 SkTDArray<SkColor> skColors; |
| 531 SkTDArray<SkScalar> skPos; |
| 532 for (int j = 0; j < nFuncs; j++) { |
| 533 const CPDF_Function* pFunc = pFuncs[j]; |
| 534 if (!pFunc) |
| 535 continue; |
| 536 switch (pFunc->GetType()) { |
| 537 case CPDF_Function::Type::kType2ExpotentialInterpolation: |
| 538 if (!AddColors(pFunc, &skColors)) |
| 539 return false; |
| 540 skPos.push(0); |
| 541 skPos.push(1); |
| 542 break; |
| 543 case CPDF_Function::Type::kType3Stitching: |
| 544 if (!AddStitching(pFunc, &skColors, &skPos)) |
| 545 return false; |
| 546 break; |
| 547 default: |
| 548 return false; |
| 549 } |
| 550 } |
| 551 SkMatrix skMatrix = ToSkMatrix(*pMatrix); |
| 552 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; |
| 553 SkPaint paint; |
| 554 paint.setAntiAlias(true); |
| 555 paint.setShader(SkGradientShader::MakeLinear(pts, skColors.begin(), |
| 556 skPos.begin(), skColors.count(), |
| 557 SkShader::kClamp_TileMode)); |
| 558 paint.setAlpha(alpha); |
| 559 m_pCanvas->save(); |
| 560 m_pCanvas->concat(skMatrix); |
| 561 m_pCanvas->drawRect(SkRect::MakeWH(1, 1), paint); |
| 562 m_pCanvas->restore(); |
| 563 return true; |
| 564 } |
| 565 |
435 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { | 566 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { |
436 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead | 567 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead |
437 pRect->left = 0; | 568 pRect->left = 0; |
438 pRect->top = 0; | 569 pRect->top = 0; |
439 const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); | 570 const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); |
440 pRect->right = canvasSize.width(); | 571 pRect->right = canvasSize.width(); |
441 pRect->bottom = canvasSize.height(); | 572 pRect->bottom = canvasSize.height(); |
442 return TRUE; | 573 return TRUE; |
443 } | 574 } |
444 | 575 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 SetDeviceDriver(pDriver); | 752 SetDeviceDriver(pDriver); |
622 return TRUE; | 753 return TRUE; |
623 } | 754 } |
624 | 755 |
625 CFX_SkiaDevice::~CFX_SkiaDevice() { | 756 CFX_SkiaDevice::~CFX_SkiaDevice() { |
626 if (m_bOwnedBitmap && GetBitmap()) | 757 if (m_bOwnedBitmap && GetBitmap()) |
627 delete GetBitmap(); | 758 delete GetBitmap(); |
628 } | 759 } |
629 | 760 |
630 #endif | 761 #endif |
OLD | NEW |