Chromium Code Reviews| Index: core/fxge/skia/fx_skia_device.cpp |
| diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp |
| index f0c7d4e442072fc44d083456651b09bc67846947..d465605e590b06a2f8f573638f09c04d188a205b 100644 |
| --- a/core/fxge/skia/fx_skia_device.cpp |
| +++ b/core/fxge/skia/fx_skia_device.cpp |
| @@ -7,6 +7,10 @@ |
| #if defined(_SKIA_SUPPORT_) |
| #include "core/include/fxcodec/fx_codec.h" |
| +#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h" |
| +#include "core/fpdfapi/fpdf_page/pageint.h" |
| +#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" |
| +#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" |
| #include "core/fxge/agg/fx_agg_driver.h" |
| #include "core/fxge/skia/fx_skia_device.h" |
| @@ -18,6 +22,8 @@ |
| #include "third_party/skia/include/core/SkStream.h" |
| #include "third_party/skia/include/core/SkTypeface.h" |
| #include "third_party/skia/include/effects/SkDashPathEffect.h" |
| +#include "third_party/skia/include/effects/SkGradientShader.h" |
| +#include "third_party/skia/include/pathops/SkPathOps.h" |
| namespace { |
| @@ -150,6 +156,49 @@ SkXfermode::Mode GetSkiaBlendMode(int blend_type) { |
| } |
| } |
| +bool AddColors(const CPDF_Function* pFunc, SkTDArray<SkColor>* skColors) { |
| + if (pFunc->CountInputs() != 1) |
| + return false; |
| + 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.
|
| + static_cast<const CPDF_ExpIntFunc*>(pFunc); |
| + if (expIntFunc->m_Exponent != 1) |
| + return false; |
| + if (expIntFunc->m_nOrigOutputs != 3) |
| + return false; |
| + skColors->push(SkColorSetARGB( |
| + 0xFF, SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[0]), |
| + SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[1]), |
| + SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[2]))); |
| + skColors->push( |
| + SkColorSetARGB(0xFF, SkUnitScalarClampToByte(expIntFunc->m_pEndValues[0]), |
| + SkUnitScalarClampToByte(expIntFunc->m_pEndValues[1]), |
| + SkUnitScalarClampToByte(expIntFunc->m_pEndValues[2]))); |
| + return true; |
| +} |
| + |
| +bool AddStitching(const CPDF_Function* pFunc, |
| + SkTDArray<SkColor>* skColors, |
| + SkTDArray<SkScalar>* skPos) { |
| + int inputs = pFunc->CountInputs(); |
| + const CPDF_StitchFunc* stitchFunc = |
|
Tom Sepez
2016/03/24 18:07:08
dittp
caryclark
2016/03/25 20:47:56
Done.
|
| + static_cast<const CPDF_StitchFunc*>(pFunc); |
| + FX_FLOAT boundsStart = stitchFunc->GetDomain(0); |
| + |
| + for (int i = 0; i < inputs; ++i) { |
| + const CPDF_Function* pSubFunc = stitchFunc->m_pSubFunctions[i]; |
| + if (pSubFunc->GetType() != 2) |
| + return false; |
| + if (!AddColors(pSubFunc, skColors)) |
| + return false; |
| + FX_FLOAT boundsEnd = |
| + i < inputs - 1 ? stitchFunc->m_pBounds[i] : stitchFunc->GetDomain(1); |
| + skPos->push(boundsStart); |
| + skPos->push(boundsEnd); |
| + boundsStart = boundsEnd; |
| + } |
| + return true; |
| +} |
| + |
| } // namespace |
| // convert a stroking path to scanlines |
| @@ -303,7 +352,8 @@ int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) { |
| return 0; |
| case FXDC_RENDER_CAPS: |
| return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | |
| - FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT; |
| + FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT | |
| + FXRC_FILLSTROKE_PATH | FXRC_SHADING; |
| case FXDC_DITHER_BITS: |
| return m_ditherBits; |
| } |
| @@ -385,32 +435,45 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawPath( |
| SkIRect rect; |
| rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), |
| GetDeviceCaps(FXDC_PIXEL_HEIGHT)); |
| + SkMatrix skMatrix = ToSkMatrix(*pObject2Device); |
| + SkPaint skPaint; |
| + skPaint.setAntiAlias(true); |
| + int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) |
| + ? FXGETFLAG_ALPHA_STROKE(alpha_flag) |
| + : FXARGB_A(stroke_color); |
| + if (pGraphState && stroke_alpha) { |
| + PaintStroke(&skPaint, pGraphState, skMatrix); |
| + } |
|
dsinclair
2016/03/24 17:43:38
nit: No {}s
caryclark
2016/03/25 20:47:56
Done.
|
| SkPath skPath = BuildPath(pPathData); |
| - SkPaint spaint; |
| - spaint.setAntiAlias(true); |
| - spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); |
| m_pCanvas->save(); |
| - SkMatrix skMatrix = ToSkMatrix(*pObject2Device); |
| m_pCanvas->concat(skMatrix); |
| if ((fill_mode & 3) && fill_color) { |
| skPath.setFillType((fill_mode & 3) == FXFILL_WINDING |
| ? SkPath::kWinding_FillType |
| : SkPath::kEvenOdd_FillType); |
| - |
| - spaint.setStyle(SkPaint::kFill_Style); |
| - spaint.setColor(fill_color); |
| - m_pCanvas->drawPath(skPath, spaint); |
| + SkPath strokePath; |
| + const SkPath* fillPath = &skPath; |
| + if (pGraphState && stroke_alpha) { |
| + SkAlpha fillA = SkColorGetA(fill_color); |
| + SkAlpha strokeA = SkColorGetA(stroke_color); |
| + if (fillA && fillA < 0xFF && strokeA && strokeA < 0xFF) { |
| + skPaint.getFillPath(skPath, &strokePath); |
| + if (Op(skPath, strokePath, SkPathOp::kDifference_SkPathOp, |
| + &strokePath)) { |
| + fillPath = &strokePath; |
| + } |
| + } |
| + } |
| + skPaint.setStyle(SkPaint::kFill_Style); |
| + skPaint.setColor(fill_color); |
| + m_pCanvas->drawPath(*fillPath, skPaint); |
| } |
| - int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) |
| - ? FXGETFLAG_ALPHA_STROKE(alpha_flag) |
| - : FXARGB_A(stroke_color); |
| - |
| if (pGraphState && stroke_alpha) { |
| - spaint.setColor(stroke_color); |
| - PaintStroke(&spaint, pGraphState, skMatrix); |
| DebugShowSkiaPath(skPath); |
| DebugShowCanvasMatrix(m_pCanvas); |
| - m_pCanvas->drawPath(skPath, spaint); |
| + skPaint.setStyle(SkPaint::kStroke_Style); |
| + skPaint.setColor(stroke_color); |
| + m_pCanvas->drawPath(skPath, skPaint); |
| } |
| m_pCanvas->restore(); |
| return TRUE; |
| @@ -432,6 +495,70 @@ FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect, |
| return TRUE; |
| } |
| +FX_BOOL CFX_SkiaDeviceDriver::DrawShading(CPDF_ShadingPattern* pPattern, |
| + CFX_Matrix* pMatrix, |
| + int alpha, |
| + FX_BOOL bAlphaMode) { |
| + CPDF_Function** pFuncs = pPattern->m_pFunctions; |
| + int nFuncs = pPattern->m_nFuncs; |
| + CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); |
| + CPDF_Array* pCoords = pDict->GetArrayBy("Coords"); |
| + if (!pCoords) |
| + return true; |
| + FX_FLOAT start_x = pCoords->GetNumberAt(0); |
| + FX_FLOAT start_y = pCoords->GetNumberAt(1); |
| + FX_FLOAT end_x = pCoords->GetNumberAt(2); |
| + FX_FLOAT end_y = pCoords->GetNumberAt(3); |
| + 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.
|
| + CPDF_Array* pArray = pDict->GetArrayBy("Domain"); |
| + if (pArray) { |
| + t_min = pArray->GetNumberAt(0); |
| + t_max = pArray->GetNumberAt(1); |
| + } |
| + FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; |
| + pArray = pDict->GetArrayBy("Extend"); |
| + if (pArray) { |
| + bStartExtend = pArray->GetIntegerAt(0); |
| + bEndExtend = pArray->GetIntegerAt(1); |
| + } |
| + SkTDArray<SkColor> skColors; |
| + SkTDArray<SkScalar> skPos; |
| + 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.
|
| + return false; |
| + for (int j = 0; j < nFuncs; j++) { |
| + const CPDF_Function* pFunc = pFuncs[j]; |
| + if (!pFunc) |
| + continue; |
| + switch (pFunc->GetType()) { |
| + 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.
|
| + if (!AddColors(pFunc, &skColors)) |
| + return false; |
| + skPos.push(0); |
| + skPos.push(1); |
| + break; |
| + case 3: // stitching functions |
| + if (!AddStitching(pFunc, &skColors, &skPos)) |
| + return false; |
| + break; |
| + default: |
| + return false; |
| + } |
| + } |
| + SkMatrix skMatrix = ToSkMatrix(*pMatrix); |
| + SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; |
| + SkPaint paint; |
| + paint.setAntiAlias(true); |
| + paint.setShader(SkGradientShader::MakeLinear(pts, skColors.begin(), |
| + skPos.begin(), skColors.count(), |
| + SkShader::kClamp_TileMode)); |
| + paint.setAlpha(alpha); |
| + m_pCanvas->save(); |
| + m_pCanvas->concat(skMatrix); |
| + m_pCanvas->drawRect(SkRect::MakeWH(1, 1), paint); |
| + m_pCanvas->restore(); |
| + return true; |
| +} |
| + |
| FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { |
| // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead |
| pRect->left = 0; |