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

Side by Side Diff: src/pdf/SkPDFShader.cpp

Issue 18585002: Implemented transparent gradients (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Minor clean-up of previous patch set Created 7 years, 5 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 | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkPDFShader.h" 10 #include "SkPDFShader.h"
11 11
12 #include "SkCanvas.h" 12 #include "SkCanvas.h"
13 #include "SkData.h" 13 #include "SkData.h"
14 #include "SkPDFCatalog.h" 14 #include "SkPDFCatalog.h"
15 #include "SkPDFDevice.h" 15 #include "SkPDFDevice.h"
16 #include "SkPDFFormXObject.h"
17 #include "SkPDFGraphicState.h"
18 #include "SkPDFResourceDict.h"
16 #include "SkPDFTypes.h" 19 #include "SkPDFTypes.h"
17 #include "SkPDFResourceDict.h"
18 #include "SkPDFUtils.h" 20 #include "SkPDFUtils.h"
19 #include "SkScalar.h" 21 #include "SkScalar.h"
20 #include "SkStream.h" 22 #include "SkStream.h"
21 #include "SkTemplates.h" 23 #include "SkTemplates.h"
22 #include "SkThread.h" 24 #include "SkThread.h"
25 #include "SkTSet.h"
23 #include "SkTypes.h" 26 #include "SkTypes.h"
24 27
25 static bool transformBBox(const SkMatrix& matrix, SkRect* bbox) { 28 static bool transformBBox(const SkMatrix& matrix, SkRect* bbox) {
26 SkMatrix inverse; 29 SkMatrix inverse;
27 if (!matrix.invert(&inverse)) { 30 if (!matrix.invert(&inverse)) {
28 return false; 31 return false;
29 } 32 }
30 inverse.mapRect(bbox); 33 inverse.mapRect(bbox);
31 return true; 34 return true;
32 } 35 }
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 tileModeCode(info.fTileMode, &function); 395 tileModeCode(info.fTileMode, &function);
393 gradientFunctionCode(info, &function); 396 gradientFunctionCode(info, &function);
394 function.append("}"); 397 function.append("}");
395 return function; 398 return function;
396 } 399 }
397 400
398 class SkPDFShader::State { 401 class SkPDFShader::State {
399 public: 402 public:
400 SkShader::GradientType fType; 403 SkShader::GradientType fType;
401 SkShader::GradientInfo fInfo; 404 SkShader::GradientInfo fInfo;
402 SkAutoFree fColorData; 405 SkAutoFree fColorData; // This provides storage for arrays in fInfo.
403 SkMatrix fCanvasTransform; 406 SkMatrix fCanvasTransform;
404 SkMatrix fShaderTransform; 407 SkMatrix fShaderTransform;
405 SkIRect fBBox; 408 SkIRect fBBox;
406 409
407 SkBitmap fImage; 410 SkBitmap fImage;
408 uint32_t fPixelGeneration; 411 uint32_t fPixelGeneration;
409 SkShader::TileMode fImageTileModes[2]; 412 SkShader::TileMode fImageTileModes[2];
410 413
411 explicit State(const SkShader& shader, const SkMatrix& canvasTransform, 414 State(const SkShader& shader, const SkMatrix& canvasTransform,
412 const SkIRect& bbox); 415 const SkIRect& bbox);
416
413 bool operator==(const State& b) const; 417 bool operator==(const State& b) const;
418
419 SkPDFShader::State* CreateAlphaToLuminosityState() const;
420 SkPDFShader::State* CreateOpaqueState() const;
421
422 bool GradientHasAlpha() const;
423
424 private:
425 State(const State& other);
426 State operator=(const State& rhs) { return State(rhs); }
427 void AllocateGradientInfoStorage();
414 }; 428 };
415 429
416 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { 430 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader {
417 public: 431 public:
418 explicit SkPDFFunctionShader(SkPDFShader::State* state); 432 explicit SkPDFFunctionShader(SkPDFShader::State* state);
419 virtual ~SkPDFFunctionShader() { 433 virtual ~SkPDFFunctionShader() {
420 if (isValid()) { 434 if (isValid()) {
421 RemoveShader(this); 435 RemoveShader(this);
422 } 436 }
423 fResources.unrefAll(); 437 fResources.unrefAll();
(...skipping 10 matching lines...) Expand all
434 448
435 private: 449 private:
436 static SkPDFObject* RangeObject(); 450 static SkPDFObject* RangeObject();
437 451
438 SkTDArray<SkPDFObject*> fResources; 452 SkTDArray<SkPDFObject*> fResources;
439 SkAutoTDelete<const SkPDFShader::State> fState; 453 SkAutoTDelete<const SkPDFShader::State> fState;
440 454
441 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); 455 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain);
442 }; 456 };
443 457
458 /**
459 * A shader for PDF gradients. This encapsulates the function shader
460 * inside a tiling pattern while providing a common pattern interface.
461 * The encapsulation allows the use of a SMask for transparency gradients.
462 */
463 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader {
464 public:
465 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state);
466 virtual ~SkPDFAlphaFunctionShader() {
467 if (isValid()) {
468 RemoveShader(this);
469 }
470 }
471
472 virtual bool isValid() {
473 return fColorPattern.get() != NULL;
474 }
475
476 private:
477 SkAutoTDelete<const SkPDFShader::State> fState;
478
479 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
480 SkTSet<SkPDFObject*>* newResourceObjects) {
481 fResourceDict->getResources(knownResourceObjects,
482 newResourceObjects,
483 true);
484 }
485
486 SkAutoTUnref<SkPDFObject> fColorPattern;
487 SkAutoTUnref<SkPDFGraphicState> fAlphaGs;
488
489 SkAutoTUnref<SkPDFResourceDict> fResourceDict;
490 };
491
444 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { 492 class SkPDFImageShader : public SkPDFStream, public SkPDFShader {
445 public: 493 public:
446 explicit SkPDFImageShader(SkPDFShader::State* state); 494 explicit SkPDFImageShader(SkPDFShader::State* state);
447 virtual ~SkPDFImageShader() { 495 virtual ~SkPDFImageShader() {
448 RemoveShader(this); 496 RemoveShader(this);
449 fResources.unrefAll(); 497 fResources.unrefAll();
450 } 498 }
451 499
452 virtual bool isValid() { return size() > 0; } 500 virtual bool isValid() { return size() > 0; }
453 501
454 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 502 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
455 SkTSet<SkPDFObject*>* newResourceObjects) { 503 SkTSet<SkPDFObject*>* newResourceObjects) {
456 GetResourcesHelper(&fResources.toArray(), 504 GetResourcesHelper(&fResources.toArray(),
457 knownResourceObjects, 505 knownResourceObjects,
458 newResourceObjects); 506 newResourceObjects);
459 } 507 }
460 508
461 private: 509 private:
462 SkTSet<SkPDFObject*> fResources; 510 SkTSet<SkPDFObject*> fResources;
463 SkAutoTDelete<const SkPDFShader::State> fState; 511 SkAutoTDelete<const SkPDFShader::State> fState;
464 }; 512 };
465 513
466 SkPDFShader::SkPDFShader() {} 514 SkPDFShader::SkPDFShader() {}
467 515
468 // static 516 // static
469 void SkPDFShader::RemoveShader(SkPDFObject* shader) { 517 // This is an internal method. CanonicalShadersMutex() should already be acquire d.
470 SkAutoMutexAcquire lock(CanonicalShadersMutex()); 518 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) {
471 ShaderCanonicalEntry entry(shader, NULL); 519 SkPDFObject* result;
472 int index = CanonicalShaders().find(entry);
473 SkASSERT(index >= 0);
474 CanonicalShaders().removeShuffle(index);
475 }
476 520
477 // static 521 SkAutoTDelete<State> shaderState(inState);
478 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
479 const SkMatrix& matrix,
480 const SkIRect& surfaceBBox) {
481 SkPDFObject* result;
482 SkAutoMutexAcquire lock(CanonicalShadersMutex());
483 SkAutoTDelete<State> shaderState(new State(shader, matrix, surfaceBBox));
484 if (shaderState.get()->fType == SkShader::kNone_GradientType && 522 if (shaderState.get()->fType == SkShader::kNone_GradientType &&
485 shaderState.get()->fImage.isNull()) { 523 shaderState.get()->fImage.isNull()) {
486 // TODO(vandebo) This drops SKComposeShader on the floor. We could 524 // TODO(vandebo) This drops SKComposeShader on the floor. We could
487 // handle compose shader by pulling things up to a layer, drawing with 525 // handle compose shader by pulling things up to a layer, drawing with
488 // the first shader, applying the xfer mode and drawing again with the 526 // the first shader, applying the xfer mode and drawing again with the
489 // second shader, then applying the layer to the original drawing. 527 // second shader, then applying the layer to the original drawing.
490 return NULL; 528 return NULL;
491 } 529 }
492 530
493 ShaderCanonicalEntry entry(NULL, shaderState.get()); 531 ShaderCanonicalEntry entry(NULL, shaderState.get());
494 int index = CanonicalShaders().find(entry); 532 int index = CanonicalShaders().find(entry);
495 if (index >= 0) { 533 if (index >= 0) {
496 result = CanonicalShaders()[index].fPDFShader; 534 result = CanonicalShaders()[index].fPDFShader;
497 result->ref(); 535 result->ref();
498 return result; 536 return result;
499 } 537 }
500 538
501 bool valid = false; 539 bool valid = false;
502 // The PDFShader takes ownership of the shaderSate. 540 // The PDFShader takes ownership of the shaderSate.
503 if (shaderState.get()->fType == SkShader::kNone_GradientType) { 541 if (shaderState.get()->fType == SkShader::kNone_GradientType) {
504 SkPDFImageShader* imageShader = 542 SkPDFImageShader* imageShader =
505 new SkPDFImageShader(shaderState.detach()); 543 new SkPDFImageShader(shaderState.detach());
506 valid = imageShader->isValid(); 544 valid = imageShader->isValid();
507 result = imageShader; 545 result = imageShader;
508 } else { 546 } else {
509 SkPDFFunctionShader* functionShader = 547 if (shaderState.get()->GradientHasAlpha()) {
510 new SkPDFFunctionShader(shaderState.detach()); 548 SkPDFAlphaFunctionShader* gradientShader =
511 valid = functionShader->isValid(); 549 new SkPDFAlphaFunctionShader(shaderState.detach());
512 result = functionShader; 550 valid = gradientShader->isValid();
551 result = gradientShader;
552 } else {
553 SkPDFFunctionShader* functionShader =
554 new SkPDFFunctionShader(shaderState.detach());
555 valid = functionShader->isValid();
556 result = functionShader;
557 }
513 } 558 }
514 if (!valid) { 559 if (!valid) {
515 delete result; 560 delete result;
516 return NULL; 561 return NULL;
517 } 562 }
518 entry.fPDFShader = result; 563 entry.fPDFShader = result;
519 CanonicalShaders().push(entry); 564 CanonicalShaders().push(entry);
520 return result; // return the reference that came from new. 565 return result; // return the reference that came from new.
521 } 566 }
522 567
523 // static 568 // static
569 void SkPDFShader::RemoveShader(SkPDFObject* shader) {
570 SkAutoMutexAcquire lock(CanonicalShadersMutex());
571 ShaderCanonicalEntry entry(shader, NULL);
572 int index = CanonicalShaders().find(entry);
573 SkASSERT(index >= 0);
574 CanonicalShaders().removeShuffle(index);
575 }
576
577 // static
578 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
579 const SkMatrix& matrix,
580 const SkIRect& surfaceBBox) {
581 SkAutoMutexAcquire lock(CanonicalShadersMutex());
582 return GetPDFShaderByState(new State(shader, matrix, surfaceBBox));
583 }
584
585 // static
524 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { 586 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() {
525 // This initialization is only thread safe with gcc. 587 // This initialization is only thread safe with gcc.
526 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; 588 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders;
527 return gCanonicalShaders; 589 return gCanonicalShaders;
528 } 590 }
529 591
530 // static 592 // static
531 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { 593 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() {
532 // This initialization is only thread safe with gcc or when 594 // This initialization is only thread safe with gcc or when
533 // POD-style mutex initialization is used. 595 // POD-style mutex initialization is used.
(...skipping 13 matching lines...) Expand all
547 range->appendInt(0); 609 range->appendInt(0);
548 range->appendInt(1); 610 range->appendInt(1);
549 range->appendInt(0); 611 range->appendInt(0);
550 range->appendInt(1); 612 range->appendInt(1);
551 range->appendInt(0); 613 range->appendInt(0);
552 range->appendInt(1); 614 range->appendInt(1);
553 } 615 }
554 return range; 616 return range;
555 } 617 }
556 618
619 static SkPDFResourceDict* get_gradient_resource_dict(
620 SkPDFObject* functionShader,
621 SkPDFObject* gState) {
622 SkPDFResourceDict* dict = new SkPDFResourceDict(true);
623
624 if (functionShader != NULL) {
625 dict->insertResourceAsRef(SkPDFResourceDict::kPattern_ResourceType, 0,
626 functionShader);
627 }
628 if (gState != NULL) {
629 dict->insertResourceAsRef(SkPDFResourceDict::kExtGState_ResourceType, 0,
630 gState);
631 }
632
633 return dict;
634 }
635
636 static void populate_tiling_pattern_dict(SkPDFDict* pattern,
637 SkRect& bbox, SkPDFDict* resources,
638 const SkMatrix& matrix) {
639 pattern->insertName("Type", "Pattern");
640 pattern->insertInt("PatternType", 1);
641 pattern->insertInt("PaintType", 1);
642 pattern->insertInt("TilingType", 1);
643 pattern->insert("BBox", SkPDFUtils::RectToArray(bbox))->unref();
644 pattern->insertScalar("XStep", bbox.width());
645 pattern->insertScalar("YStep", bbox.height());
646 pattern->insert("Resources", resources);
647 if (!matrix.isIdentity()) {
648 pattern->insert("Matrix", SkPDFUtils::MatrixToArray(matrix))->unref();
649 }
650 }
651
652 /**
653 * Creates a content stream which fills the pattern P0 across bounds.
654 * The argument setup may contain any relevant PDF content stream operators
655 * and will be prepended to the output content stream.
656 */
657 static SkData* create_pattern_fill_content(const char setup[], SkRect& bounds) {
658 SkDynamicMemoryWStream content;
659 if (NULL != setup) {
660 content.writeText(setup);
661 }
662 content.writeText("/Pattern CS/Pattern cs/P0 SCN/P0 scn\n");
663
664 SkPDFUtils::AppendRectangle(bounds, &content);
665 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, &cont ent);
666
667 return content.copyToData();
668 }
669
670 /**
671 * Creates a ExtGState with the SMask set to the luminosityShader in
672 * luminosity mode. The shader pattern extends to the bbox.
673 */
674 static SkPDFGraphicState* create_smask_graphic_state(SkPDFObject* luminosityShad er, SkRect& bbox) {
675 SkAutoTUnref<SkData> alphaStream(create_pattern_fill_content(NULL, bbox));
676
677 SkAutoTUnref<SkPDFResourceDict>
678 resources(get_gradient_resource_dict(luminosityShader, NULL));
679
680 SkAutoTUnref<SkPDFFormXObject> alphaMask(
681 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get()));
682
683 return SkPDFGraphicState::GetSMaskGraphicState(
684 alphaMask.get(), false,
685 SkPDFGraphicState::kLuminosity_SMaskMode);
686 }
687
688 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) :
689 fState(state) {
690 SkRect bbox;
691 bbox.set(fState.get()->fBBox);
692
693 fColorPattern.reset(SkPDFShader::GetPDFShaderByState(state->CreateOpaqueStat e()));
694
695 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState(
696 state->CreateAlphaToLuminosityState()));
697 fAlphaGs.reset(create_smask_graphic_state(luminosityShader.get(), bbox));
698
699 fResourceDict.reset(get_gradient_resource_dict(fColorPattern.get(), fAlphaGs .get()));
700
701 SkAutoTUnref<SkData> colorStream(create_pattern_fill_content("/G0 gs", bbox) );
702 setData(colorStream.get());
703
704 populate_tiling_pattern_dict(this, bbox, fResourceDict.get(), SkMatrix::I()) ;
705 }
706
557 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) 707 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state)
558 : SkPDFDict("Pattern"), 708 : SkPDFDict("Pattern"),
559 fState(state) { 709 fState(state) {
560 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL; 710 SkString (*codeFunction)(const SkShader::GradientInfo& info) = NULL;
561 SkPoint transformPoints[2]; 711 SkPoint transformPoints[2];
562 712
563 // Depending on the type of the gradient, we want to transform the 713 // Depending on the type of the gradient, we want to transform the
564 // coordinate space in different ways. 714 // coordinate space in different ways.
565 const SkShader::GradientInfo* info = &fState.get()->fInfo; 715 const SkShader::GradientInfo* info = &fState.get()->fInfo;
566 transformPoints[0] = info->fPoint[0]; 716 transformPoints[0] = info->fPoint[0];
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 972
823 if (tileModes[0] == SkShader::kMirror_TileMode) { 973 if (tileModes[0] == SkShader::kMirror_TileMode) {
824 bottomMatrix.postScale(-1, 1); 974 bottomMatrix.postScale(-1, 1);
825 bottomMatrix.postTranslate(2 * width, 0); 975 bottomMatrix.postTranslate(2 * width, 0);
826 canvas.drawBitmapMatrix(bottom, bottomMatrix); 976 canvas.drawBitmapMatrix(bottom, bottomMatrix);
827 } 977 }
828 patternBBox.fBottom = surfaceBBox.height(); 978 patternBBox.fBottom = surfaceBBox.height();
829 } 979 }
830 } 980 }
831 981
832 SkAutoTUnref<SkPDFArray> patternBBoxArray(new SkPDFArray);
833 patternBBoxArray->reserve(4);
834 patternBBoxArray->appendScalar(patternBBox.fLeft);
835 patternBBoxArray->appendScalar(patternBBox.fTop);
836 patternBBoxArray->appendScalar(patternBBox.fRight);
837 patternBBoxArray->appendScalar(patternBBox.fBottom);
838
839 // Put the canvas into the pattern stream (fContent). 982 // Put the canvas into the pattern stream (fContent).
840 SkAutoTUnref<SkData> content(pattern.copyContentToData()); 983 SkAutoTUnref<SkData> content(pattern.copyContentToData());
841 setData(content.get()); 984 setData(content.get());
842 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); 985 SkPDFResourceDict* resourceDict = pattern.getResourceDict();
843 resourceDict->getResources(fResources, &fResources, false); 986 resourceDict->getResources(fResources, &fResources, false);
844 987
845 insertName("Type", "Pattern"); 988 populate_tiling_pattern_dict(this, patternBBox,
846 insertInt("PatternType", 1); 989 pattern.getResourceDict(), finalMatrix);
847 insertInt("PaintType", 1);
848 insertInt("TilingType", 1);
849 insert("BBox", patternBBoxArray.get());
850 insertScalar("XStep", patternBBox.width());
851 insertScalar("YStep", patternBBox.height());
852 insert("Resources", resourceDict);
853 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref();
854 990
855 fState.get()->fImage.unlockPixels(); 991 fState.get()->fImage.unlockPixels();
856 } 992 }
857 993
858 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, 994 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode,
859 SkPDFArray* domain) { 995 SkPDFArray* domain) {
860 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), 996 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(),
861 psCode.size())); 997 psCode.size()));
862 SkPDFStream* result = new SkPDFStream(funcData.get()); 998 SkPDFStream* result = new SkPDFStream(funcData.get());
863 result->insertInt("FunctionType", 4); 999 result->insertInt("FunctionType", 4);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 SkShader::BitmapType bitmapType; 1085 SkShader::BitmapType bitmapType;
950 SkMatrix matrix; 1086 SkMatrix matrix;
951 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); 1087 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes);
952 if (bitmapType != SkShader::kDefault_BitmapType) { 1088 if (bitmapType != SkShader::kDefault_BitmapType) {
953 fImage.reset(); 1089 fImage.reset();
954 return; 1090 return;
955 } 1091 }
956 SkASSERT(matrix.isIdentity()); 1092 SkASSERT(matrix.isIdentity());
957 fPixelGeneration = fImage.getGenerationID(); 1093 fPixelGeneration = fImage.getGenerationID();
958 } else { 1094 } else {
959 fColorData.set(sk_malloc_throw( 1095 AllocateGradientInfoStorage();
960 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
961 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
962 fInfo.fColorOffsets =
963 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount);
964 shader.asAGradient(&fInfo); 1096 shader.asAGradient(&fInfo);
965 } 1097 }
966 } 1098 }
1099
1100 SkPDFShader::State::State(const SkPDFShader::State& other)
1101 : fType(other.fType),
1102 fCanvasTransform(other.fCanvasTransform),
1103 fShaderTransform(other.fShaderTransform),
1104 fBBox(other.fBBox)
1105 {
1106 // Only gradients supported for now, since that is all that is used.
1107 // If needed, image state copy constructor can be added here later.
1108 SkASSERT(fType != SkShader::kNone_GradientType);
1109
1110 if (fType != SkShader::kNone_GradientType) {
1111 fInfo = other.fInfo;
1112
1113 AllocateGradientInfoStorage();
1114 for (int i = 0; i < fInfo.fColorCount; i++) {
1115 fInfo.fColors[i] = other.fInfo.fColors[i];
1116 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i];
1117 }
1118 }
1119 }
1120
1121 /**
1122 * Create a copy of this gradient state with alpha assigned to RGB luminousity.
1123 * Only valid for gradient states!
1124 */
1125 SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const {
1126 SkASSERT(fType != SkShader::kNone_GradientType);
1127
1128 SkPDFShader::State* newState = new SkPDFShader::State(*this);
1129
1130 for (int i = 0; i < fInfo.fColorCount; i++) {
1131 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]);
1132 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha);
1133 }
1134
1135 return newState;
1136 }
1137
1138 /**
1139 * Create a copy of this gradient state with alpha set to fully opaque
1140 * Only valid for gradient states.
1141 */
1142 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const {
1143 SkASSERT(fType != SkShader::kNone_GradientType);
1144
1145 SkPDFShader::State* newState = new SkPDFShader::State(*this);
1146 SkAlpha opaque = SkColorGetA(SK_ColorBLACK);
1147 for (int i = 0; i < fInfo.fColorCount; i++) {
1148 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], opaque);
1149 }
1150
1151 return newState;
1152 }
1153
1154 /**
1155 * Returns true if state is a gradient and the gradient has alpha.
1156 */
1157 bool SkPDFShader::State::GradientHasAlpha() const {
1158 if (fType == SkShader::kNone_GradientType) {
1159 return false;
1160 }
1161
1162 SkAlpha opaque = SkColorGetA(SK_ColorBLACK);
1163 for (int i = 0; i < fInfo.fColorCount; i++) {
1164 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]);
1165 if (alpha != opaque) {
1166 return true;
1167 }
1168 }
1169 return false;
1170 }
1171
1172 void SkPDFShader::State::AllocateGradientInfoStorage() {
1173 fColorData.set(sk_malloc_throw(
1174 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
1175 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
1176 fInfo.fColorOffsets =
1177 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCoun t);
1178 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698