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

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: Created 4 years, 9 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
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 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698