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 |