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

Side by Side Diff: core/fxge/skia/fx_skia_device.cpp

Issue 1870463002: flesh out gradient shaders (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: address comments Created 4 years, 8 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/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
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) {
Tom Sepez 2016/04/11 16:41:50 Presumably, this is copied from some other code th
caryclark 2016/04/11 20:41:51 Unit test added.
182 ASSERT(0 < nbits && nbits <= 32);
183 const uint8_t* dataPtr = &pData[bitpos / 8];
184 int bitShift;
185 int bitMask;
186 int dstShift;
187 if (nbits < 8) {
188 bitShift = 8 - nbits - (bitpos & 0x07);
189 bitMask = (1 << nbits) - 1;
190 dstShift = 0;
Tom Sepez 2016/04/11 16:41:50 what if say, bitpos == 7 and nbits == 7? then 1 <<
caryclark 2016/04/11 20:41:52 Fixed.
191 } else {
192 bitShift = 0;
193 bitMask = 0xFF;
194 dstShift = nbits - 8 + (bitpos & 0x07);
Tom Sepez 2016/04/11 16:41:50 what if, say, bitpos = 7 and nbits == 32, then we
caryclark 2016/04/11 20:41:52 Fixed.
195 }
196 uint32_t result = (*dataPtr++ >> bitShift & bitMask) << dstShift;
Tom Sepez 2016/04/11 16:41:50 Then we get dataptr's contents as a uint8_t, promo
caryclark 2016/04/11 20:41:52 Fixed.
197 while (dstShift >= 8) {
198 dstShift -= 8;
199 result |= *dataPtr++ << dstShift;
200 }
201 if (dstShift > 0) {
202 bitShift = 8 - dstShift;
203 bitMask = (1 << dstShift) - 1;
204 result |= *dataPtr++ >> bitShift & bitMask;
205 }
206 return result;
207 }
208
209 uint8_t FloatToByte(FX_FLOAT f) {
210 ASSERT(0 <= f && f <= 1);
211 return (uint8_t)(f * 255.99f);
212 }
213
214 bool AddSamples(const CPDF_Function* pFunc,
215 SkTDArray<SkColor>* skColors,
216 SkTDArray<SkScalar>* skPos) {
217 if (pFunc->CountInputs() != 1)
218 return false;
219 if (pFunc->CountOutputs() != 3) // expect rgb
220 return false;
221 ASSERT(CPDF_Function::Type::kType0Sampled == pFunc->GetType());
222 const CPDF_SampledFunc* sampledFunc =
223 static_cast<const CPDF_SampledFunc*>(pFunc);
224 if (!sampledFunc->m_pEncodeInfo)
225 return false;
226 const CPDF_SampledFunc::SampleEncodeInfo& encodeInfo =
227 sampledFunc->m_pEncodeInfo[0];
228 if (encodeInfo.encode_min != 0)
229 return false;
230 if (encodeInfo.encode_max != encodeInfo.sizes - 1)
231 return false;
232 int sampleSize = sampledFunc->m_nBitsPerSample;
Tom Sepez 2016/04/11 16:41:49 should be uint32_t to match m_nBitsPerSample?
caryclark 2016/04/11 20:41:51 Done.
233 int sampleCount = encodeInfo.sizes;
234 if (sampleCount != 1 << sampleSize)
235 return false;
236 FX_FLOAT colorsMin[3];
237 FX_FLOAT colorsMax[3];
238 for (int i = 0; i < 3; ++i) {
239 colorsMin[i] = sampledFunc->GetRange(i * 2);
240 colorsMax[i] = sampledFunc->GetRange(i * 2 + 1);
241 }
242 const uint8_t* pSampleData = sampledFunc->m_pSampleStream->GetData();
243 for (int i = 0; i < sampleCount; ++i) {
Tom Sepez 2016/04/11 16:41:50 how do we know that sampleCount is within the boun
caryclark 2016/04/11 20:41:51 Added check.
244 FX_FLOAT floatColors[3];
245 for (int j = 0; j < 3; ++j) {
246 int sample = GetBits32(pSampleData, (i * 3 + j) * sampleSize, sampleSize);
247 FX_FLOAT interp = (FX_FLOAT)sample / (sampleCount - 1);
248 floatColors[j] = colorsMin[j] + (colorsMax[j] - colorsMin[j]) * interp;
249 }
250 SkColor color =
251 SkPackARGB32(0xFF, FloatToByte(floatColors[0]),
252 FloatToByte(floatColors[1]), FloatToByte(floatColors[2]));
253 skColors->push(color);
254 skPos->push((FX_FLOAT)i / (sampleCount - 1));
255 }
256 return true;
257 }
258
180 bool AddStitching(const CPDF_Function* pFunc, 259 bool AddStitching(const CPDF_Function* pFunc,
181 SkTDArray<SkColor>* skColors, 260 SkTDArray<SkColor>* skColors,
182 SkTDArray<SkScalar>* skPos) { 261 SkTDArray<SkScalar>* skPos) {
183 int inputs = pFunc->CountInputs(); 262 int inputs = pFunc->CountInputs();
184 ASSERT(CPDF_Function::Type::kType3Stitching == pFunc->GetType()); 263 ASSERT(CPDF_Function::Type::kType3Stitching == pFunc->GetType());
185 const CPDF_StitchFunc* stitchFunc = 264 const CPDF_StitchFunc* stitchFunc =
186 static_cast<const CPDF_StitchFunc*>(pFunc); 265 static_cast<const CPDF_StitchFunc*>(pFunc);
187 FX_FLOAT boundsStart = stitchFunc->GetDomain(0); 266 FX_FLOAT boundsStart = stitchFunc->GetDomain(0);
188 267
189 for (int i = 0; i < inputs; ++i) { 268 for (int i = 0; i < inputs; ++i) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 src_scan += 4; 376 src_scan += 4;
298 dest_scan += 4; 377 dest_scan += 4;
299 } 378 }
300 } 379 }
301 } 380 }
302 } else { 381 } else {
303 ASSERT(FALSE); 382 ASSERT(FALSE);
304 } 383 }
305 } 384 }
306 385
386 // see en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
Tom Sepez 2016/04/11 16:41:50 nit: if you put https:// in front of this, the li
caryclark 2016/04/11 20:41:52 Done.
387 SkScalar LineSide(const SkPoint l[2], const SkPoint& pt) {
Tom Sepez 2016/04/11 16:41:50 nit: any chance we could call "l" something like "
caryclark 2016/04/11 20:41:52 Done.
388 return (l[1].fY - l[0].fY) * pt.fX - (l[1].fX - l[0].fX) * pt.fY +
389 l[1].fX * l[0].fY - l[1].fY * l[0].fX;
390 }
391
392 SkPoint IntersectSides(const SkPoint& parallelPt,
393 const SkVector& paraRay,
394 const SkPoint& perpendicularPt) {
395 SkVector perpRay = {paraRay.fY, -paraRay.fX};
396 double denom = perpRay.fY * paraRay.fX - paraRay.fY * perpRay.fX;
397 SkVector ab0 = parallelPt - perpendicularPt;
398 double numerA = ab0.fY * perpRay.fX - perpRay.fY * ab0.fX;
399 numerA /= denom;
Tom Sepez 2016/04/11 16:41:49 do we need to check for div by 0?
caryclark 2016/04/11 20:41:51 Done.
400 SkPoint result = {parallelPt.fX + paraRay.fX * numerA,
401 parallelPt.fY + paraRay.fY * numerA};
402 return result;
403 }
404
405 void ClipAngledGradient(const SkPoint pts[2],
406 SkPoint rectPts[4],
407 bool clipStart,
408 bool clipEnd,
409 SkPath* clip) {
410 // find the corners furthest from the gradient perpendiculars
411 SkScalar minPerpDist = SK_ScalarMax;
412 SkScalar maxPerpDist = SK_ScalarMin;
413 int minPerpPtIndex = -1;
414 int maxPerpPtIndex = -1;
415 SkVector slope = pts[1] - pts[0];
416 SkPoint startPerp[2] = {pts[0], {pts[0].fX + slope.fY, pts[0].fY - slope.fX}};
417 SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}};
418 for (int i = 0; i < 4; ++i) {
419 SkScalar sDist = LineSide(startPerp, rectPts[i]);
420 SkScalar eDist = LineSide(endPerp, rectPts[i]);
421 if (sDist * eDist <= 0) // if the signs are different,
422 continue; // the point is inside the gradient
423 if (sDist < 0) {
424 SkScalar smaller = SkTMin(sDist, eDist);
425 if (minPerpDist > smaller) {
426 minPerpDist = smaller;
427 minPerpPtIndex = i;
428 }
429 } else {
430 SkScalar larger = SkTMax(sDist, eDist);
431 if (maxPerpDist < larger) {
432 maxPerpDist = larger;
433 maxPerpPtIndex = i;
434 }
435 }
436 }
437 if (minPerpPtIndex < 0 && maxPerpPtIndex < 0) // nothing's outside
438 return;
439 // determine if negative distances are before start or after end
440 SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX, pts[0].fY * 2 - pts[1].fY};
441 bool beforeNeg = LineSide(startPerp, beforeStart) < 0;
442 const SkPoint& startEdgePt =
443 clipStart ? pts[0] : beforeNeg ? rectPts[minPerpPtIndex]
444 : rectPts[maxPerpPtIndex];
445 const SkPoint& endEdgePt = clipEnd ? pts[1] : beforeNeg
446 ? rectPts[maxPerpPtIndex]
447 : rectPts[minPerpPtIndex];
448 // find the corners that bound the gradient
449 SkScalar minDist = SK_ScalarMax;
450 SkScalar maxDist = SK_ScalarMin;
451 int minBounds = -1;
452 int maxBounds = -1;
453 for (int i = 0; i < 4; ++i) {
454 SkScalar dist = LineSide(pts, rectPts[i]);
455 if (minDist > dist) {
456 minDist = dist;
457 minBounds = i;
458 }
459 if (maxDist < dist) {
460 maxDist = dist;
461 maxBounds = i;
462 }
463 }
464 ASSERT(minBounds >= 0);
465 ASSERT(maxBounds != minBounds && maxBounds >= 0);
466 // construct a clip parallel to the gradient that goes through
467 // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the
468 // gradient that goes through startEdgePt, endEdgePt.
469 clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt));
470 clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt));
471 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt));
472 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt));
473 }
474
307 } // namespace 475 } // namespace
308 476
309 // convert a stroking path to scanlines 477 // convert a stroking path to scanlines
310 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, 478 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint,
311 const CFX_GraphStateData* pGraphState, 479 const CFX_GraphStateData* pGraphState,
312 const SkMatrix& matrix) { 480 const SkMatrix& matrix) {
313 SkPaint::Cap cap; 481 SkPaint::Cap cap;
314 switch (pGraphState->m_LineCap) { 482 switch (pGraphState->m_LineCap) {
315 case CFX_GraphStateData::LineCapRound: 483 case CFX_GraphStateData::LineCapRound:
316 cap = SkPaint::kRound_Cap; 484 cap = SkPaint::kRound_Cap;
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 spaint.setAntiAlias(true); 765 spaint.setAntiAlias(true);
598 spaint.setColor(fill_color); 766 spaint.setColor(fill_color);
599 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); 767 spaint.setXfermodeMode(GetSkiaBlendMode(blend_type));
600 768
601 m_pCanvas->drawRect( 769 m_pCanvas->drawRect(
602 SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), 770 SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom),
603 spaint); 771 spaint);
604 return TRUE; 772 return TRUE;
605 } 773 }
606 774
607 FX_BOOL CFX_SkiaDeviceDriver::DrawShading(CPDF_ShadingPattern* pPattern, 775 FX_BOOL CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern,
608 CFX_Matrix* pMatrix, 776 const CFX_Matrix* pMatrix,
777 const FX_RECT& clip_rect,
609 int alpha, 778 int alpha,
610 FX_BOOL bAlphaMode) { 779 FX_BOOL bAlphaMode) {
611 CPDF_Function** pFuncs = pPattern->m_pFunctions; 780 if (kAxialShading != pPattern->m_ShadingType &&
781 kRadialShading !=
782 pPattern->m_ShadingType) { // TODO(caryclark) more types
Tom Sepez 2016/04/11 16:41:50 nit: this might look better if there's a newline b
caryclark 2016/04/11 20:41:52 Done.
783 return false;
784 }
785 CPDF_Function* const* pFuncs = pPattern->m_pFunctions;
612 int nFuncs = pPattern->m_nFuncs; 786 int nFuncs = pPattern->m_nFuncs;
613 if (nFuncs != 1) // TODO(caryclark) remove this restriction 787 if (nFuncs != 1) // TODO(caryclark) remove this restriction
614 return false; 788 return false;
615 CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); 789 CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict();
616 CPDF_Array* pCoords = pDict->GetArrayBy("Coords"); 790 CPDF_Array* pCoords = pDict->GetArrayBy("Coords");
617 if (!pCoords) 791 if (!pCoords)
618 return true; 792 return true;
619 FX_FLOAT start_x = pCoords->GetNumberAt(0); 793 // TODO(caryclark) Respect Domain[0], Domain[1]. (Don't know what they do
620 FX_FLOAT start_y = pCoords->GetNumberAt(1); 794 // 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; 795 SkTDArray<SkColor> skColors;
637 SkTDArray<SkScalar> skPos; 796 SkTDArray<SkScalar> skPos;
638 for (int j = 0; j < nFuncs; j++) { 797 for (int j = 0; j < nFuncs; j++) {
639 const CPDF_Function* pFunc = pFuncs[j]; 798 const CPDF_Function* pFunc = pFuncs[j];
640 if (!pFunc) 799 if (!pFunc)
641 continue; 800 continue;
642 switch (pFunc->GetType()) { 801 switch (pFunc->GetType()) {
802 case CPDF_Function::Type::kType0Sampled:
803 /* TODO(caryclark)
804 Type 0 Sampled Functions in PostScript can also have an Order integer
805 in the dictionary. PDFium doesn't appear to check for this anywhere.
806 */
807 if (!AddSamples(pFunc, &skColors, &skPos))
808 return false;
809 break;
643 case CPDF_Function::Type::kType2ExpotentialInterpolation: 810 case CPDF_Function::Type::kType2ExpotentialInterpolation:
644 if (!AddColors(pFunc, &skColors)) 811 if (!AddColors(pFunc, &skColors))
645 return false; 812 return false;
646 skPos.push(0); 813 skPos.push(0);
647 skPos.push(1); 814 skPos.push(1);
648 break; 815 break;
649 case CPDF_Function::Type::kType3Stitching: 816 case CPDF_Function::Type::kType3Stitching:
650 if (!AddStitching(pFunc, &skColors, &skPos)) 817 if (!AddStitching(pFunc, &skColors, &skPos))
651 return false; 818 return false;
652 break; 819 break;
653 default: 820 default:
654 return false; 821 return false;
655 } 822 }
656 } 823 }
657 SkMatrix skMatrix = ToSkMatrix(*pMatrix); 824 CPDF_Array* pArray = pDict->GetArrayBy("Extend");
658 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; 825 bool clipStart = !pArray || !pArray->GetIntegerAt(0);
826 bool clipEnd = !pArray || !pArray->GetIntegerAt(1);
659 SkPaint paint; 827 SkPaint paint;
660 paint.setAntiAlias(true); 828 paint.setAntiAlias(true);
661 paint.setShader(SkGradientShader::MakeLinear(pts, skColors.begin(),
662 skPos.begin(), skColors.count(),
663 SkShader::kClamp_TileMode));
664 paint.setAlpha(alpha); 829 paint.setAlpha(alpha);
830 SkMatrix skMatrix = ToSkMatrix(*pMatrix);
831 SkRect skRect = SkRect::MakeLTRB(clip_rect.left, clip_rect.top,
832 clip_rect.right, clip_rect.bottom);
833 SkPath skClip;
834 SkPath skPath;
835 if (kAxialShading == pPattern->m_ShadingType) {
836 FX_FLOAT start_x = pCoords->GetNumberAt(0);
837 FX_FLOAT start_y = pCoords->GetNumberAt(1);
838 FX_FLOAT end_x = pCoords->GetNumberAt(2);
839 FX_FLOAT end_y = pCoords->GetNumberAt(3);
840 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
841 skMatrix.mapPoints(pts, SK_ARRAY_COUNT(pts));
842 paint.setShader(SkGradientShader::MakeLinear(
843 pts, skColors.begin(), skPos.begin(), skColors.count(),
844 SkShader::kClamp_TileMode));
845 if (clipStart || clipEnd) {
846 // if the gradient is horizontal or vertical, modify the draw rectangle
847 if (pts[0].fX == pts[1].fX) { // vertical
848 if (pts[0].fY > pts[1].fY) {
849 SkTSwap(pts[0].fY, pts[1].fY);
850 SkTSwap(clipStart, clipEnd);
851 }
852 if (clipStart)
853 skRect.fTop = SkTMax(skRect.fTop, pts[0].fY);
854 if (clipEnd)
855 skRect.fBottom = SkTMin(skRect.fBottom, pts[1].fY);
856 } else if (pts[0].fY == pts[1].fY) { // horizontal
857 if (pts[0].fX > pts[1].fX) {
858 SkTSwap(pts[0].fX, pts[1].fX);
859 SkTSwap(clipStart, clipEnd);
860 }
861 if (clipStart)
862 skRect.fLeft = SkTMax(skRect.fLeft, pts[0].fX);
863 if (clipEnd)
864 skRect.fRight = SkTMin(skRect.fRight, pts[1].fX);
865 } else { // if the gradient is angled and contained by the rect, clip
866 SkPoint rectPts[4] = {{skRect.fLeft, skRect.fTop},
867 {skRect.fRight, skRect.fTop},
868 {skRect.fRight, skRect.fBottom},
869 {skRect.fLeft, skRect.fBottom}};
870 ClipAngledGradient(pts, rectPts, clipStart, clipEnd, &skClip);
871 }
872 }
873 skPath.addRect(skRect);
874 skMatrix.setIdentity();
875 } else {
876 ASSERT(kRadialShading == pPattern->m_ShadingType);
877 FX_FLOAT start_x = pCoords->GetNumberAt(0);
878 FX_FLOAT start_y = pCoords->GetNumberAt(1);
879 FX_FLOAT start_r = pCoords->GetNumberAt(2);
880 FX_FLOAT end_x = pCoords->GetNumberAt(3);
881 FX_FLOAT end_y = pCoords->GetNumberAt(4);
882 FX_FLOAT end_r = pCoords->GetNumberAt(5);
883 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
884
885 paint.setShader(SkGradientShader::MakeTwoPointConical(
886 pts[0], start_r, pts[1], end_r, skColors.begin(), skPos.begin(),
887 skColors.count(), SkShader::kClamp_TileMode));
888 if (clipStart || clipEnd) {
889 if (clipStart && start_r)
890 skClip.addCircle(pts[0].fX, pts[0].fY, start_r);
891 if (clipEnd)
892 skClip.addCircle(pts[1].fX, pts[1].fY, end_r, SkPath::kCCW_Direction);
893 else
894 skClip.setFillType(SkPath::kInverseWinding_FillType);
895 skClip.transform(skMatrix);
896 }
897 SkMatrix inverse;
898 skMatrix.invert(&inverse);
899 skPath.addRect(skRect);
900 skPath.transform(inverse);
901 }
665 m_pCanvas->save(); 902 m_pCanvas->save();
903 if (!skClip.isEmpty())
904 m_pCanvas->clipPath(skClip);
666 m_pCanvas->concat(skMatrix); 905 m_pCanvas->concat(skMatrix);
667 m_pCanvas->drawRect(SkRect::MakeWH(1, 1), paint); 906 m_pCanvas->drawPath(skPath, paint);
668 m_pCanvas->restore(); 907 m_pCanvas->restore();
669 return true; 908 return true;
670 } 909 }
671 910
672 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { 911 FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) {
673 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead 912 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead
674 pRect->left = 0; 913 pRect->left = 0;
675 pRect->top = 0; 914 pRect->top = 0;
676 const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); 915 const SkImageInfo& canvasSize = m_pCanvas->imageInfo();
677 pRect->right = canvasSize.width(); 916 pRect->right = canvasSize.width();
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 SetDeviceDriver(pDriver); 1167 SetDeviceDriver(pDriver);
929 return TRUE; 1168 return TRUE;
930 } 1169 }
931 1170
932 CFX_SkiaDevice::~CFX_SkiaDevice() { 1171 CFX_SkiaDevice::~CFX_SkiaDevice() {
933 if (m_bOwnedBitmap && GetBitmap()) 1172 if (m_bOwnedBitmap && GetBitmap())
934 delete GetBitmap(); 1173 delete GetBitmap();
935 } 1174 }
936 1175
937 #endif 1176 #endif
OLDNEW
« core/fpdfapi/fpdf_page/pageint.h ('K') | « core/fxge/skia/fx_skia_device.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698