| 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..ed6ff82fd051df299a40fbf808c21045d7487835 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,53 @@ SkXfermode::Mode GetSkiaBlendMode(int blend_type) {
|
| }
|
| }
|
|
|
| +bool AddColors(const CPDF_Function* pFunc, SkTDArray<SkColor>* skColors) {
|
| + if (pFunc->CountInputs() != 1)
|
| + return false;
|
| + ASSERT(CPDF_Function::Type::kType2ExpotentialInterpolation ==
|
| + pFunc->GetType());
|
| + const CPDF_ExpIntFunc* expIntFunc =
|
| + 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();
|
| + ASSERT(CPDF_Function::Type::kType3Stitching == pFunc->GetType());
|
| + const CPDF_StitchFunc* stitchFunc =
|
| + 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() !=
|
| + CPDF_Function::Type::kType2ExpotentialInterpolation)
|
| + 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 +356,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 +439,44 @@ 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);
|
| 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 +498,71 @@ 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;
|
| + if (nFuncs != 1) // TODO(caryclark) remove this restriction
|
| + return false;
|
| + 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;
|
| + FX_FLOAT t_max = 1;
|
| + 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;
|
| + for (int j = 0; j < nFuncs; j++) {
|
| + const CPDF_Function* pFunc = pFuncs[j];
|
| + if (!pFunc)
|
| + continue;
|
| + switch (pFunc->GetType()) {
|
| + case CPDF_Function::Type::kType2ExpotentialInterpolation:
|
| + if (!AddColors(pFunc, &skColors))
|
| + return false;
|
| + skPos.push(0);
|
| + skPos.push(1);
|
| + break;
|
| + case CPDF_Function::Type::kType3Stitching:
|
| + 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;
|
|
|