Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: core/fxge/skia/fx_skia_device.cpp

Issue 1828283002: support gradients and stroke+fill (Closed) Base URL: https://pdfium.googlesource.com/pdfium@master
Patch Set: address comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fxge/skia/fx_skia_device.h ('k') | core/fxge/win32/win32_int.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « core/fxge/skia/fx_skia_device.h ('k') | core/fxge/win32/win32_int.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698