diff options
Diffstat (limited to 'core/fxge/skia')
-rw-r--r-- | core/fxge/skia/fx_skia_device.cpp | 163 | ||||
-rw-r--r-- | core/fxge/skia/fx_skia_device.h | 5 |
2 files changed, 152 insertions, 16 deletions
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index f0c7d4e442..ed6ff82fd0 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; diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h index 012e370717..8ce7c6c61f 100644 --- a/core/fxge/skia/fx_skia_device.h +++ b/core/fxge/skia/fx_skia_device.h @@ -128,6 +128,11 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { int alpha_flag = 0, void* pIccTransform = NULL) override; + FX_BOOL DrawShading(CPDF_ShadingPattern* pPattern, + CFX_Matrix* pMatrix, + int alpha, + FX_BOOL bAlphaMode) override; + virtual uint8_t* GetBuffer() const { return m_pAggDriver->GetBuffer(); } void PaintStroke(SkPaint* spaint, const CFX_GraphStateData* pGraphState, |