| OLD | NEW | 
|---|
| 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/fxge/include/fx_ge.h" | 5 #include "core/fxge/include/fx_ge.h" | 
| 6 | 6 | 
| 7 #if defined(_SKIA_SUPPORT_) | 7 #if defined(_SKIA_SUPPORT_) | 
| 8 #include "core/fxcodec/include/fx_codec.h" | 8 #include "core/fxcodec/include/fx_codec.h" | 
| 9 | 9 | 
| 10 #include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h" | 10 #include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h" | 
| 11 #include "core/fpdfapi/fpdf_page/pageint.h" | 11 #include "core/fpdfapi/fpdf_page/pageint.h" | 
| 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | 
| 13 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" | 13 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" | 
|  | 14 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" | 
| 14 #include "core/fxge/skia/fx_skia_device.h" | 15 #include "core/fxge/skia/fx_skia_device.h" | 
| 15 | 16 | 
| 16 #include "third_party/skia/include/core/SkCanvas.h" | 17 #include "third_party/skia/include/core/SkCanvas.h" | 
| 17 #include "third_party/skia/include/core/SkColorPriv.h" | 18 #include "third_party/skia/include/core/SkColorPriv.h" | 
| 18 #include "third_party/skia/include/core/SkPaint.h" | 19 #include "third_party/skia/include/core/SkPaint.h" | 
| 19 #include "third_party/skia/include/core/SkPath.h" | 20 #include "third_party/skia/include/core/SkPath.h" | 
| 20 #include "third_party/skia/include/core/SkPictureRecorder.h" | 21 #include "third_party/skia/include/core/SkPictureRecorder.h" | 
| 21 #include "third_party/skia/include/core/SkStream.h" | 22 #include "third_party/skia/include/core/SkStream.h" | 
| 22 #include "third_party/skia/include/core/SkTypeface.h" | 23 #include "third_party/skia/include/core/SkTypeface.h" | 
| 23 #include "third_party/skia/include/effects/SkDashPathEffect.h" | 24 #include "third_party/skia/include/effects/SkDashPathEffect.h" | 
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 170       0xFF, SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[0]), | 171       0xFF, SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[0]), | 
| 171       SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[1]), | 172       SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[1]), | 
| 172       SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[2]))); | 173       SkUnitScalarClampToByte(expIntFunc->m_pBeginValues[2]))); | 
| 173   skColors->push( | 174   skColors->push( | 
| 174       SkColorSetARGB(0xFF, SkUnitScalarClampToByte(expIntFunc->m_pEndValues[0]), | 175       SkColorSetARGB(0xFF, SkUnitScalarClampToByte(expIntFunc->m_pEndValues[0]), | 
| 175                      SkUnitScalarClampToByte(expIntFunc->m_pEndValues[1]), | 176                      SkUnitScalarClampToByte(expIntFunc->m_pEndValues[1]), | 
| 176                      SkUnitScalarClampToByte(expIntFunc->m_pEndValues[2]))); | 177                      SkUnitScalarClampToByte(expIntFunc->m_pEndValues[2]))); | 
| 177   return true; | 178   return true; | 
| 178 } | 179 } | 
| 179 | 180 | 
|  | 181 uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits) { | 
|  | 182   ASSERT(0 < nbits && nbits <= 32); | 
|  | 183   const uint8_t* dataPtr = &pData[bitpos / 8]; | 
|  | 184   int bitShift; | 
|  | 185   int bitMask; | 
|  | 186   int dstShift; | 
|  | 187   int bitCount = bitpos & 0x07; | 
|  | 188   if (nbits < 8 && nbits + bitCount <= 8) { | 
|  | 189     bitShift = 8 - nbits - bitCount; | 
|  | 190     bitMask = (1 << nbits) - 1; | 
|  | 191     dstShift = 0; | 
|  | 192   } else { | 
|  | 193     bitShift = 0; | 
|  | 194     int bitOffset = 8 - bitCount; | 
|  | 195     bitMask = (1 << SkTMin(bitOffset, nbits)) - 1; | 
|  | 196     dstShift = nbits - bitOffset; | 
|  | 197   } | 
|  | 198   uint32_t result = (uint32_t)(*dataPtr++ >> bitShift & bitMask) << dstShift; | 
|  | 199   while (dstShift >= 8) { | 
|  | 200     dstShift -= 8; | 
|  | 201     result |= *dataPtr++ << dstShift; | 
|  | 202   } | 
|  | 203   if (dstShift > 0) { | 
|  | 204     bitShift = 8 - dstShift; | 
|  | 205     bitMask = (1 << dstShift) - 1; | 
|  | 206     result |= *dataPtr++ >> bitShift & bitMask; | 
|  | 207   } | 
|  | 208   return result; | 
|  | 209 } | 
|  | 210 | 
|  | 211 uint8_t FloatToByte(FX_FLOAT f) { | 
|  | 212   ASSERT(0 <= f && f <= 1); | 
|  | 213   return (uint8_t)(f * 255.99f); | 
|  | 214 } | 
|  | 215 | 
|  | 216 bool AddSamples(const CPDF_Function* pFunc, | 
|  | 217                 SkTDArray<SkColor>* skColors, | 
|  | 218                 SkTDArray<SkScalar>* skPos) { | 
|  | 219   if (pFunc->CountInputs() != 1) | 
|  | 220     return false; | 
|  | 221   if (pFunc->CountOutputs() != 3)  // expect rgb | 
|  | 222     return false; | 
|  | 223   ASSERT(CPDF_Function::Type::kType0Sampled == pFunc->GetType()); | 
|  | 224   const CPDF_SampledFunc* sampledFunc = | 
|  | 225       static_cast<const CPDF_SampledFunc*>(pFunc); | 
|  | 226   if (!sampledFunc->m_pEncodeInfo) | 
|  | 227     return false; | 
|  | 228   const CPDF_SampledFunc::SampleEncodeInfo& encodeInfo = | 
|  | 229       sampledFunc->m_pEncodeInfo[0]; | 
|  | 230   if (encodeInfo.encode_min != 0) | 
|  | 231     return false; | 
|  | 232   if (encodeInfo.encode_max != encodeInfo.sizes - 1) | 
|  | 233     return false; | 
|  | 234   uint32_t sampleSize = sampledFunc->m_nBitsPerSample; | 
|  | 235   uint32_t sampleCount = encodeInfo.sizes; | 
|  | 236   if (sampleCount != 1 << sampleSize) | 
|  | 237     return false; | 
|  | 238   if (sampledFunc->m_pSampleStream->GetSize() < | 
|  | 239       sampleCount * 3 * sampleSize / 8) { | 
|  | 240     return false; | 
|  | 241   } | 
|  | 242   FX_FLOAT colorsMin[3]; | 
|  | 243   FX_FLOAT colorsMax[3]; | 
|  | 244   for (int i = 0; i < 3; ++i) { | 
|  | 245     colorsMin[i] = sampledFunc->GetRange(i * 2); | 
|  | 246     colorsMax[i] = sampledFunc->GetRange(i * 2 + 1); | 
|  | 247   } | 
|  | 248   const uint8_t* pSampleData = sampledFunc->m_pSampleStream->GetData(); | 
|  | 249   for (uint32_t i = 0; i < sampleCount; ++i) { | 
|  | 250     FX_FLOAT floatColors[3]; | 
|  | 251     for (uint32_t j = 0; j < 3; ++j) { | 
|  | 252       int sample = GetBits32(pSampleData, (i * 3 + j) * sampleSize, sampleSize); | 
|  | 253       FX_FLOAT interp = (FX_FLOAT)sample / (sampleCount - 1); | 
|  | 254       floatColors[j] = colorsMin[j] + (colorsMax[j] - colorsMin[j]) * interp; | 
|  | 255     } | 
|  | 256     SkColor color = | 
|  | 257         SkPackARGB32(0xFF, FloatToByte(floatColors[0]), | 
|  | 258                      FloatToByte(floatColors[1]), FloatToByte(floatColors[2])); | 
|  | 259     skColors->push(color); | 
|  | 260     skPos->push((FX_FLOAT)i / (sampleCount - 1)); | 
|  | 261   } | 
|  | 262   return true; | 
|  | 263 } | 
|  | 264 | 
| 180 bool AddStitching(const CPDF_Function* pFunc, | 265 bool AddStitching(const CPDF_Function* pFunc, | 
| 181                   SkTDArray<SkColor>* skColors, | 266                   SkTDArray<SkColor>* skColors, | 
| 182                   SkTDArray<SkScalar>* skPos) { | 267                   SkTDArray<SkScalar>* skPos) { | 
| 183   int inputs = pFunc->CountInputs(); | 268   int inputs = pFunc->CountInputs(); | 
| 184   ASSERT(CPDF_Function::Type::kType3Stitching == pFunc->GetType()); | 269   ASSERT(CPDF_Function::Type::kType3Stitching == pFunc->GetType()); | 
| 185   const CPDF_StitchFunc* stitchFunc = | 270   const CPDF_StitchFunc* stitchFunc = | 
| 186       static_cast<const CPDF_StitchFunc*>(pFunc); | 271       static_cast<const CPDF_StitchFunc*>(pFunc); | 
| 187   FX_FLOAT boundsStart = stitchFunc->GetDomain(0); | 272   FX_FLOAT boundsStart = stitchFunc->GetDomain(0); | 
| 188 | 273 | 
| 189   for (int i = 0; i < inputs; ++i) { | 274   for (int i = 0; i < inputs; ++i) { | 
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 297           src_scan += 4; | 382           src_scan += 4; | 
| 298           dest_scan += 4; | 383           dest_scan += 4; | 
| 299         } | 384         } | 
| 300       } | 385       } | 
| 301     } | 386     } | 
| 302   } else { | 387   } else { | 
| 303     ASSERT(FALSE); | 388     ASSERT(FALSE); | 
| 304   } | 389   } | 
| 305 } | 390 } | 
| 306 | 391 | 
|  | 392 // see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line | 
|  | 393 SkScalar LineSide(const SkPoint line[2], const SkPoint& pt) { | 
|  | 394   return (line[1].fY - line[0].fY) * pt.fX - (line[1].fX - line[0].fX) * pt.fY + | 
|  | 395          line[1].fX * line[0].fY - line[1].fY * line[0].fX; | 
|  | 396 } | 
|  | 397 | 
|  | 398 SkPoint IntersectSides(const SkPoint& parallelPt, | 
|  | 399                        const SkVector& paraRay, | 
|  | 400                        const SkPoint& perpendicularPt) { | 
|  | 401   SkVector perpRay = {paraRay.fY, -paraRay.fX}; | 
|  | 402   SkScalar denom = perpRay.fY * paraRay.fX - paraRay.fY * perpRay.fX; | 
|  | 403   if (!denom) { | 
|  | 404     SkPoint zeroPt = {0, 0}; | 
|  | 405     return zeroPt; | 
|  | 406   } | 
|  | 407   SkVector ab0 = parallelPt - perpendicularPt; | 
|  | 408   SkScalar numerA = ab0.fY * perpRay.fX - perpRay.fY * ab0.fX; | 
|  | 409   numerA /= denom; | 
|  | 410   SkPoint result = {parallelPt.fX + paraRay.fX * numerA, | 
|  | 411                     parallelPt.fY + paraRay.fY * numerA}; | 
|  | 412   return result; | 
|  | 413 } | 
|  | 414 | 
|  | 415 void ClipAngledGradient(const SkPoint pts[2], | 
|  | 416                         SkPoint rectPts[4], | 
|  | 417                         bool clipStart, | 
|  | 418                         bool clipEnd, | 
|  | 419                         SkPath* clip) { | 
|  | 420   // find the corners furthest from the gradient perpendiculars | 
|  | 421   SkScalar minPerpDist = SK_ScalarMax; | 
|  | 422   SkScalar maxPerpDist = SK_ScalarMin; | 
|  | 423   int minPerpPtIndex = -1; | 
|  | 424   int maxPerpPtIndex = -1; | 
|  | 425   SkVector slope = pts[1] - pts[0]; | 
|  | 426   SkPoint startPerp[2] = {pts[0], {pts[0].fX + slope.fY, pts[0].fY - slope.fX}}; | 
|  | 427   SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}}; | 
|  | 428   for (int i = 0; i < 4; ++i) { | 
|  | 429     SkScalar sDist = LineSide(startPerp, rectPts[i]); | 
|  | 430     SkScalar eDist = LineSide(endPerp, rectPts[i]); | 
|  | 431     if (sDist * eDist <= 0)  // if the signs are different, | 
|  | 432       continue;              // the point is inside the gradient | 
|  | 433     if (sDist < 0) { | 
|  | 434       SkScalar smaller = SkTMin(sDist, eDist); | 
|  | 435       if (minPerpDist > smaller) { | 
|  | 436         minPerpDist = smaller; | 
|  | 437         minPerpPtIndex = i; | 
|  | 438       } | 
|  | 439     } else { | 
|  | 440       SkScalar larger = SkTMax(sDist, eDist); | 
|  | 441       if (maxPerpDist < larger) { | 
|  | 442         maxPerpDist = larger; | 
|  | 443         maxPerpPtIndex = i; | 
|  | 444       } | 
|  | 445     } | 
|  | 446   } | 
|  | 447   if (minPerpPtIndex < 0 && maxPerpPtIndex < 0)  // nothing's outside | 
|  | 448     return; | 
|  | 449   // determine if negative distances are before start or after end | 
|  | 450   SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX, pts[0].fY * 2 - pts[1].fY}; | 
|  | 451   bool beforeNeg = LineSide(startPerp, beforeStart) < 0; | 
|  | 452   const SkPoint& startEdgePt = | 
|  | 453       clipStart ? pts[0] : beforeNeg ? rectPts[minPerpPtIndex] | 
|  | 454                                      : rectPts[maxPerpPtIndex]; | 
|  | 455   const SkPoint& endEdgePt = clipEnd ? pts[1] : beforeNeg | 
|  | 456                                                     ? rectPts[maxPerpPtIndex] | 
|  | 457                                                     : rectPts[minPerpPtIndex]; | 
|  | 458   // find the corners that bound the gradient | 
|  | 459   SkScalar minDist = SK_ScalarMax; | 
|  | 460   SkScalar maxDist = SK_ScalarMin; | 
|  | 461   int minBounds = -1; | 
|  | 462   int maxBounds = -1; | 
|  | 463   for (int i = 0; i < 4; ++i) { | 
|  | 464     SkScalar dist = LineSide(pts, rectPts[i]); | 
|  | 465     if (minDist > dist) { | 
|  | 466       minDist = dist; | 
|  | 467       minBounds = i; | 
|  | 468     } | 
|  | 469     if (maxDist < dist) { | 
|  | 470       maxDist = dist; | 
|  | 471       maxBounds = i; | 
|  | 472     } | 
|  | 473   } | 
|  | 474   ASSERT(minBounds >= 0); | 
|  | 475   ASSERT(maxBounds != minBounds && maxBounds >= 0); | 
|  | 476   // construct a clip parallel to the gradient that goes through | 
|  | 477   // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the | 
|  | 478   // gradient that goes through startEdgePt, endEdgePt. | 
|  | 479   clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt)); | 
|  | 480   clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt)); | 
|  | 481   clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt)); | 
|  | 482   clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); | 
|  | 483 } | 
|  | 484 | 
| 307 }  // namespace | 485 }  // namespace | 
| 308 | 486 | 
| 309 // convert a stroking path to scanlines | 487 // convert a stroking path to scanlines | 
| 310 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, | 488 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, | 
| 311                                        const CFX_GraphStateData* pGraphState, | 489                                        const CFX_GraphStateData* pGraphState, | 
| 312                                        const SkMatrix& matrix) { | 490                                        const SkMatrix& matrix) { | 
| 313   SkPaint::Cap cap; | 491   SkPaint::Cap cap; | 
| 314   switch (pGraphState->m_LineCap) { | 492   switch (pGraphState->m_LineCap) { | 
| 315     case CFX_GraphStateData::LineCapRound: | 493     case CFX_GraphStateData::LineCapRound: | 
| 316       cap = SkPaint::kRound_Cap; | 494       cap = SkPaint::kRound_Cap; | 
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 597   spaint.setAntiAlias(true); | 775   spaint.setAntiAlias(true); | 
| 598   spaint.setColor(fill_color); | 776   spaint.setColor(fill_color); | 
| 599   spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); | 777   spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); | 
| 600 | 778 | 
| 601   m_pCanvas->drawRect( | 779   m_pCanvas->drawRect( | 
| 602       SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), | 780       SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), | 
| 603       spaint); | 781       spaint); | 
| 604   return TRUE; | 782   return TRUE; | 
| 605 } | 783 } | 
| 606 | 784 | 
| 607 FX_BOOL CFX_SkiaDeviceDriver::DrawShading(CPDF_ShadingPattern* pPattern, | 785 FX_BOOL CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, | 
| 608                                           CFX_Matrix* pMatrix, | 786                                           const CFX_Matrix* pMatrix, | 
|  | 787                                           const FX_RECT& clip_rect, | 
| 609                                           int alpha, | 788                                           int alpha, | 
| 610                                           FX_BOOL bAlphaMode) { | 789                                           FX_BOOL bAlphaMode) { | 
| 611   CPDF_Function** pFuncs = pPattern->m_pFunctions; | 790   if (kAxialShading != pPattern->m_ShadingType && | 
|  | 791       kRadialShading != pPattern->m_ShadingType) { | 
|  | 792     // TODO(caryclark) more types | 
|  | 793     return false; | 
|  | 794   } | 
|  | 795   CPDF_Function* const* pFuncs = pPattern->m_pFunctions; | 
| 612   int nFuncs = pPattern->m_nFuncs; | 796   int nFuncs = pPattern->m_nFuncs; | 
| 613   if (nFuncs != 1)  // TODO(caryclark) remove this restriction | 797   if (nFuncs != 1)  // TODO(caryclark) remove this restriction | 
| 614     return false; | 798     return false; | 
| 615   CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); | 799   CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); | 
| 616   CPDF_Array* pCoords = pDict->GetArrayBy("Coords"); | 800   CPDF_Array* pCoords = pDict->GetArrayBy("Coords"); | 
| 617   if (!pCoords) | 801   if (!pCoords) | 
| 618     return true; | 802     return true; | 
| 619   FX_FLOAT start_x = pCoords->GetNumberAt(0); | 803   // TODO(caryclark) Respect Domain[0], Domain[1]. (Don't know what they do | 
| 620   FX_FLOAT start_y = pCoords->GetNumberAt(1); | 804   // yet.) | 
| 621   FX_FLOAT end_x = pCoords->GetNumberAt(2); |  | 
| 622   FX_FLOAT end_y = pCoords->GetNumberAt(3); |  | 
| 623   FX_FLOAT t_min = 0; |  | 
| 624   FX_FLOAT t_max = 1; |  | 
| 625   CPDF_Array* pArray = pDict->GetArrayBy("Domain"); |  | 
| 626   if (pArray) { |  | 
| 627     t_min = pArray->GetNumberAt(0); |  | 
| 628     t_max = pArray->GetNumberAt(1); |  | 
| 629   } |  | 
| 630   FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; |  | 
| 631   pArray = pDict->GetArrayBy("Extend"); |  | 
| 632   if (pArray) { |  | 
| 633     bStartExtend = pArray->GetIntegerAt(0); |  | 
| 634     bEndExtend = pArray->GetIntegerAt(1); |  | 
| 635   } |  | 
| 636   SkTDArray<SkColor> skColors; | 805   SkTDArray<SkColor> skColors; | 
| 637   SkTDArray<SkScalar> skPos; | 806   SkTDArray<SkScalar> skPos; | 
| 638   for (int j = 0; j < nFuncs; j++) { | 807   for (int j = 0; j < nFuncs; j++) { | 
| 639     const CPDF_Function* pFunc = pFuncs[j]; | 808     const CPDF_Function* pFunc = pFuncs[j]; | 
| 640     if (!pFunc) | 809     if (!pFunc) | 
| 641       continue; | 810       continue; | 
| 642     switch (pFunc->GetType()) { | 811     switch (pFunc->GetType()) { | 
|  | 812       case CPDF_Function::Type::kType0Sampled: | 
|  | 813         /* TODO(caryclark) | 
|  | 814            Type 0 Sampled Functions in PostScript can also have an Order integer | 
|  | 815            in the dictionary. PDFium doesn't appear to check for this anywhere. | 
|  | 816          */ | 
|  | 817         if (!AddSamples(pFunc, &skColors, &skPos)) | 
|  | 818           return false; | 
|  | 819         break; | 
| 643       case CPDF_Function::Type::kType2ExpotentialInterpolation: | 820       case CPDF_Function::Type::kType2ExpotentialInterpolation: | 
| 644         if (!AddColors(pFunc, &skColors)) | 821         if (!AddColors(pFunc, &skColors)) | 
| 645           return false; | 822           return false; | 
| 646         skPos.push(0); | 823         skPos.push(0); | 
| 647         skPos.push(1); | 824         skPos.push(1); | 
| 648         break; | 825         break; | 
| 649       case CPDF_Function::Type::kType3Stitching: | 826       case CPDF_Function::Type::kType3Stitching: | 
| 650         if (!AddStitching(pFunc, &skColors, &skPos)) | 827         if (!AddStitching(pFunc, &skColors, &skPos)) | 
| 651           return false; | 828           return false; | 
| 652         break; | 829         break; | 
| 653       default: | 830       default: | 
| 654         return false; | 831         return false; | 
| 655     } | 832     } | 
| 656   } | 833   } | 
| 657   SkMatrix skMatrix = ToSkMatrix(*pMatrix); | 834   CPDF_Array* pArray = pDict->GetArrayBy("Extend"); | 
| 658   SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; | 835   bool clipStart = !pArray || !pArray->GetIntegerAt(0); | 
|  | 836   bool clipEnd = !pArray || !pArray->GetIntegerAt(1); | 
| 659   SkPaint paint; | 837   SkPaint paint; | 
| 660   paint.setAntiAlias(true); | 838   paint.setAntiAlias(true); | 
| 661   paint.setShader(SkGradientShader::MakeLinear(pts, skColors.begin(), |  | 
| 662                                                skPos.begin(), skColors.count(), |  | 
| 663                                                SkShader::kClamp_TileMode)); |  | 
| 664   paint.setAlpha(alpha); | 839   paint.setAlpha(alpha); | 
|  | 840   SkMatrix skMatrix = ToSkMatrix(*pMatrix); | 
|  | 841   SkRect skRect = SkRect::MakeLTRB(clip_rect.left, clip_rect.top, | 
|  | 842                                    clip_rect.right, clip_rect.bottom); | 
|  | 843   SkPath skClip; | 
|  | 844   SkPath skPath; | 
|  | 845   if (kAxialShading == pPattern->m_ShadingType) { | 
|  | 846     FX_FLOAT start_x = pCoords->GetNumberAt(0); | 
|  | 847     FX_FLOAT start_y = pCoords->GetNumberAt(1); | 
|  | 848     FX_FLOAT end_x = pCoords->GetNumberAt(2); | 
|  | 849     FX_FLOAT end_y = pCoords->GetNumberAt(3); | 
|  | 850     SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; | 
|  | 851     skMatrix.mapPoints(pts, SK_ARRAY_COUNT(pts)); | 
|  | 852     paint.setShader(SkGradientShader::MakeLinear( | 
|  | 853         pts, skColors.begin(), skPos.begin(), skColors.count(), | 
|  | 854         SkShader::kClamp_TileMode)); | 
|  | 855     if (clipStart || clipEnd) { | 
|  | 856       // if the gradient is horizontal or vertical, modify the draw rectangle | 
|  | 857       if (pts[0].fX == pts[1].fX) {  // vertical | 
|  | 858         if (pts[0].fY > pts[1].fY) { | 
|  | 859           SkTSwap(pts[0].fY, pts[1].fY); | 
|  | 860           SkTSwap(clipStart, clipEnd); | 
|  | 861         } | 
|  | 862         if (clipStart) | 
|  | 863           skRect.fTop = SkTMax(skRect.fTop, pts[0].fY); | 
|  | 864         if (clipEnd) | 
|  | 865           skRect.fBottom = SkTMin(skRect.fBottom, pts[1].fY); | 
|  | 866       } else if (pts[0].fY == pts[1].fY) {  // horizontal | 
|  | 867         if (pts[0].fX > pts[1].fX) { | 
|  | 868           SkTSwap(pts[0].fX, pts[1].fX); | 
|  | 869           SkTSwap(clipStart, clipEnd); | 
|  | 870         } | 
|  | 871         if (clipStart) | 
|  | 872           skRect.fLeft = SkTMax(skRect.fLeft, pts[0].fX); | 
|  | 873         if (clipEnd) | 
|  | 874           skRect.fRight = SkTMin(skRect.fRight, pts[1].fX); | 
|  | 875       } else {  // if the gradient is angled and contained by the rect, clip | 
|  | 876         SkPoint rectPts[4] = {{skRect.fLeft, skRect.fTop}, | 
|  | 877                               {skRect.fRight, skRect.fTop}, | 
|  | 878                               {skRect.fRight, skRect.fBottom}, | 
|  | 879                               {skRect.fLeft, skRect.fBottom}}; | 
|  | 880         ClipAngledGradient(pts, rectPts, clipStart, clipEnd, &skClip); | 
|  | 881       } | 
|  | 882     } | 
|  | 883     skPath.addRect(skRect); | 
|  | 884     skMatrix.setIdentity(); | 
|  | 885   } else { | 
|  | 886     ASSERT(kRadialShading == pPattern->m_ShadingType); | 
|  | 887     FX_FLOAT start_x = pCoords->GetNumberAt(0); | 
|  | 888     FX_FLOAT start_y = pCoords->GetNumberAt(1); | 
|  | 889     FX_FLOAT start_r = pCoords->GetNumberAt(2); | 
|  | 890     FX_FLOAT end_x = pCoords->GetNumberAt(3); | 
|  | 891     FX_FLOAT end_y = pCoords->GetNumberAt(4); | 
|  | 892     FX_FLOAT end_r = pCoords->GetNumberAt(5); | 
|  | 893     SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; | 
|  | 894 | 
|  | 895     paint.setShader(SkGradientShader::MakeTwoPointConical( | 
|  | 896         pts[0], start_r, pts[1], end_r, skColors.begin(), skPos.begin(), | 
|  | 897         skColors.count(), SkShader::kClamp_TileMode)); | 
|  | 898     if (clipStart || clipEnd) { | 
|  | 899       if (clipStart && start_r) | 
|  | 900         skClip.addCircle(pts[0].fX, pts[0].fY, start_r); | 
|  | 901       if (clipEnd) | 
|  | 902         skClip.addCircle(pts[1].fX, pts[1].fY, end_r, SkPath::kCCW_Direction); | 
|  | 903       else | 
|  | 904         skClip.setFillType(SkPath::kInverseWinding_FillType); | 
|  | 905       skClip.transform(skMatrix); | 
|  | 906     } | 
|  | 907     SkMatrix inverse; | 
|  | 908     skMatrix.invert(&inverse); | 
|  | 909     skPath.addRect(skRect); | 
|  | 910     skPath.transform(inverse); | 
|  | 911   } | 
| 665   m_pCanvas->save(); | 912   m_pCanvas->save(); | 
|  | 913   if (!skClip.isEmpty()) | 
|  | 914     m_pCanvas->clipPath(skClip); | 
| 666   m_pCanvas->concat(skMatrix); | 915   m_pCanvas->concat(skMatrix); | 
| 667   m_pCanvas->drawRect(SkRect::MakeWH(1, 1), paint); | 916   m_pCanvas->drawPath(skPath, paint); | 
| 668   m_pCanvas->restore(); | 917   m_pCanvas->restore(); | 
| 669   return true; | 918   return true; | 
| 670 } | 919 } | 
| 671 | 920 | 
| 672 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { | 921 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { | 
| 673   // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead | 922   // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead | 
| 674   pRect->left = 0; | 923   pRect->left = 0; | 
| 675   pRect->top = 0; | 924   pRect->top = 0; | 
| 676   const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); | 925   const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); | 
| 677   pRect->right = canvasSize.width(); | 926   pRect->right = canvasSize.width(); | 
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 928   SetDeviceDriver(pDriver); | 1177   SetDeviceDriver(pDriver); | 
| 929   return TRUE; | 1178   return TRUE; | 
| 930 } | 1179 } | 
| 931 | 1180 | 
| 932 CFX_SkiaDevice::~CFX_SkiaDevice() { | 1181 CFX_SkiaDevice::~CFX_SkiaDevice() { | 
| 933   if (m_bOwnedBitmap && GetBitmap()) | 1182   if (m_bOwnedBitmap && GetBitmap()) | 
| 934     delete GetBitmap(); | 1183     delete GetBitmap(); | 
| 935 } | 1184 } | 
| 936 | 1185 | 
| 937 #endif | 1186 #endif | 
| OLD | NEW | 
|---|