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

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

Issue 862113004: Simplify SkPDFShader class. Now invalid objects are never created. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 11 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
« src/pdf/SkPDFShader.h ('K') | « src/pdf/SkPDFShader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 SkPDFShader::State* CreateOpaqueState() const; 498 SkPDFShader::State* CreateOpaqueState() const;
499 499
500 bool GradientHasAlpha() const; 500 bool GradientHasAlpha() const;
501 501
502 private: 502 private:
503 State(const State& other); 503 State(const State& other);
504 State operator=(const State& rhs); 504 State operator=(const State& rhs);
505 void AllocateGradientInfoStorage(); 505 void AllocateGradientInfoStorage();
506 }; 506 };
507 507
508 static void remove_from_canon(SkPDFShader* shader) {
509 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
510 SkPDFCanon::GetCanon().removeShader(shader);
511 }
512
508 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { 513 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader {
509 SK_DECLARE_INST_COUNT(SkPDFFunctionShader) 514 SK_DECLARE_INST_COUNT(SkPDFFunctionShader)
510 public: 515 public:
511 explicit SkPDFFunctionShader(SkPDFShader::State* state); 516 // takes ownership of state
517 static SkPDFObject* Create(SkPDFShader::State* state);
518
512 virtual ~SkPDFFunctionShader() { 519 virtual ~SkPDFFunctionShader() {
513 SkPDFShader::RemoveFromCanonIfValid(this); 520 remove_from_canon(this);
514 fResources.unrefAll(); 521 fResources.unrefAll();
515 } 522 }
516 523
517 bool isValid() SK_OVERRIDE { return fResources.count() > 0; }
518 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; }
519
520 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 524 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
521 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { 525 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE {
522 GetResourcesHelper(&fResources, 526 GetResourcesHelper(&fResources,
523 knownResourceObjects, 527 knownResourceObjects,
524 newResourceObjects); 528 newResourceObjects);
525 } 529 }
526 530
527 private: 531 private:
528 static SkPDFObject* RangeObject();
529
530 SkTDArray<SkPDFObject*> fResources; 532 SkTDArray<SkPDFObject*> fResources;
531 533 explicit SkPDFFunctionShader(SkPDFShader::State* state)
532 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); 534 : SkPDFDict("Pattern"), SkPDFShader(state) {
535 }
533 typedef SkPDFDict INHERITED; 536 typedef SkPDFDict INHERITED;
534 }; 537 };
535 538
536 /** 539 /**
537 * A shader for PDF gradients. This encapsulates the function shader 540 * A shader for PDF gradients. This encapsulates the function shader
538 * inside a tiling pattern while providing a common pattern interface. 541 * inside a tiling pattern while providing a common pattern interface.
539 * The encapsulation allows the use of a SMask for transparency gradients. 542 * The encapsulation allows the use of a SMask for transparency gradients.
540 */ 543 */
541 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { 544 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader {
542 public: 545 public:
543 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state); 546 static SkPDFObject* Create(SkPDFShader::State*);
547
544 virtual ~SkPDFAlphaFunctionShader() { 548 virtual ~SkPDFAlphaFunctionShader() {
545 SkPDFShader::RemoveFromCanonIfValid(this); 549 remove_from_canon(this);
546 } 550 }
547 551
548 bool isValid() SK_OVERRIDE { 552 private:
549 return fColorShader.get() != NULL; 553 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state);
550 }
551 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; }
552 554
553 private: 555 static SkPDFGraphicState* CreateSMaskGraphicState(SkPDFShader::State*);
554 SkPDFGraphicState* CreateSMaskGraphicState();
555 556
556 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 557 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
557 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { 558 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE {
558 fResourceDict->getReferencedResources(knownResourceObjects, 559 fResourceDict->getReferencedResources(knownResourceObjects,
559 newResourceObjects, 560 newResourceObjects,
560 true); 561 true);
561 } 562 }
562 563
563 SkAutoTUnref<SkPDFObject> fColorShader; 564 SkAutoTUnref<SkPDFObject> fColorShader;
564 SkAutoTUnref<SkPDFResourceDict> fResourceDict; 565 SkAutoTUnref<SkPDFResourceDict> fResourceDict;
565 }; 566 };
566 567
567 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { 568 class SkPDFImageShader : public SkPDFStream, public SkPDFShader {
568 public: 569 public:
569 explicit SkPDFImageShader(SkPDFShader::State* state); 570 static SkPDFObject* Create(SkPDFShader::State* state);
571
570 virtual ~SkPDFImageShader() { 572 virtual ~SkPDFImageShader() {
571 SkPDFShader::RemoveFromCanonIfValid(this); 573 remove_from_canon(this);
572 fResources.unrefAll(); 574 fResources.unrefAll();
573 } 575 }
574 576
575 bool isValid() SK_OVERRIDE { return size() > 0; }
576 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; }
577
578 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 577 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
579 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { 578 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE {
580 GetResourcesHelper(&fResources.toArray(), 579 GetResourcesHelper(&fResources.toArray(),
581 knownResourceObjects, 580 knownResourceObjects,
582 newResourceObjects); 581 newResourceObjects);
583 } 582 }
584 583
585 private: 584 private:
586 SkTSet<SkPDFObject*> fResources; 585 SkTSet<SkPDFObject*> fResources;
586 explicit SkPDFImageShader(SkPDFShader::State* state)
587 : SkPDFShader(state) {}
587 }; 588 };
588 589
589 SkPDFShader::SkPDFShader(SkPDFShader::State* s) : fShaderState(s) {} 590 SkPDFShader::SkPDFShader(SkPDFShader::State* s) : fShaderState(s) {}
590 591
591 SkPDFShader::~SkPDFShader() {} 592 SkPDFShader::~SkPDFShader() {}
592 593
593 void SkPDFShader::RemoveFromCanonIfValid(SkPDFShader* shader) {
594 if (shader->isValid()) {
595 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
596 SkPDFCanon::GetCanon().removeShader(shader);
597 }
598 }
599
600 bool SkPDFShader::equals(const SkPDFShader::State& state) const { 594 bool SkPDFShader::equals(const SkPDFShader::State& state) const {
601 return state == *fShaderState.get(); 595 return state == *fShaderState.get();
602 } 596 }
603 597
604 SkPDFObject* SkPDFShader::AddToCanonIfValid(SkPDFShader* shader) {
605 if (!shader->isValid()) {
606 SkDELETE(shader);
607 return NULL;
608 }
609 SkPDFCanon::GetCanon().addShader(shader);
610 return shader->toPDFObject();
611 }
612
613 // static 598 // static
614 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { 599 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) {
615 SkAutoTDelete<State> state(inState); 600 SkAutoTDelete<State> state(inState);
616 if (state->fType == SkShader::kNone_GradientType && 601 if (state->fType == SkShader::kNone_GradientType &&
617 state->fImage.isNull()) { 602 state->fImage.isNull()) {
618 // TODO(vandebo) This drops SKComposeShader on the floor. We could 603 // TODO(vandebo) This drops SKComposeShader on the floor. We could
619 // handle compose shader by pulling things up to a layer, drawing with 604 // handle compose shader by pulling things up to a layer, drawing with
620 // the first shader, applying the xfer mode and drawing again with the 605 // the first shader, applying the xfer mode and drawing again with the
621 // second shader, then applying the layer to the original drawing. 606 // second shader, then applying the layer to the original drawing.
622 return NULL; 607 return NULL;
623 } 608 }
624 609
625 SkPDFShader* pdfShader = SkPDFCanon::GetCanon().findShader(*state); 610 SkPDFShader* pdfShader = SkPDFCanon::GetCanon().findShader(*state);
626 if (pdfShader) { 611 if (pdfShader) {
627 SkASSERT(pdfShader->isValid()); 612 return SkRef(pdfShader->fSelf);
628 return SkRef(pdfShader->toPDFObject());
629 } 613 }
630 614
631 // The PDFShader takes ownership of the shaderSate. 615 // The PDFShader takes ownership of the shaderSate.
632 if (state->fType == SkShader::kNone_GradientType) { 616 if (state->fType == SkShader::kNone_GradientType) {
633 return SkPDFShader::AddToCanonIfValid( 617 return SkPDFImageShader::Create(state.detach());
634 SkNEW_ARGS(SkPDFImageShader, (state.detach())));
635 } else if (state->GradientHasAlpha()) { 618 } else if (state->GradientHasAlpha()) {
636 return SkPDFShader::AddToCanonIfValid( 619 return SkPDFAlphaFunctionShader::Create(state.detach());
637 SkNEW_ARGS(SkPDFAlphaFunctionShader, (state.detach())));
638 } else { 620 } else {
639 return SkPDFShader::AddToCanonIfValid( 621 return SkPDFFunctionShader::Create(state.detach());
640 SkNEW_ARGS(SkPDFFunctionShader, (state.detach())));
641 } 622 }
642 } 623 }
643 624
644 // static 625 // static
645 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, 626 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
646 const SkMatrix& matrix, 627 const SkMatrix& matrix,
647 const SkIRect& surfaceBBox, 628 const SkIRect& surfaceBBox,
648 SkScalar rasterScale) { 629 SkScalar rasterScale) {
649 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); 630 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
650 return GetPDFShaderByState( 631 return GetPDFShaderByState(
651 SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale))); 632 SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale)));
652 } 633 }
653 634
654
655 // static
656 SkPDFObject* SkPDFFunctionShader::RangeObject() {
657 SkPDFCanon::GetShaderMutex().assertHeld();
658 static SkPDFArray* range = NULL;
659 // This method is only used with CanonicalShadersMutex, so it's safe to
660 // populate domain.
661 if (range == NULL) {
662 range = new SkPDFArray;
663 range->reserve(6);
664 range->appendInt(0);
665 range->appendInt(1);
666 range->appendInt(0);
667 range->appendInt(1);
668 range->appendInt(0);
669 range->appendInt(1);
670 }
671 return range;
672 }
673
674 static SkPDFResourceDict* get_gradient_resource_dict( 635 static SkPDFResourceDict* get_gradient_resource_dict(
675 SkPDFObject* functionShader, 636 SkPDFObject* functionShader,
676 SkPDFObject* gState) { 637 SkPDFObject* gState) {
677 SkPDFResourceDict* dict = new SkPDFResourceDict(); 638 SkPDFResourceDict* dict = new SkPDFResourceDict();
678 639
679 if (functionShader != NULL) { 640 if (functionShader != NULL) {
680 dict->insertResourceAsReference( 641 dict->insertResourceAsReference(
681 SkPDFResourceDict::kPattern_ResourceType, 0, functionShader); 642 SkPDFResourceDict::kPattern_ResourceType, 0, functionShader);
682 } 643 }
683 if (gState != NULL) { 644 if (gState != NULL) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, 684 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType,
724 &content); 685 &content);
725 686
726 return content.detachAsStream(); 687 return content.detachAsStream();
727 } 688 }
728 689
729 /** 690 /**
730 * Creates a ExtGState with the SMask set to the luminosityShader in 691 * Creates a ExtGState with the SMask set to the luminosityShader in
731 * luminosity mode. The shader pattern extends to the bbox. 692 * luminosity mode. The shader pattern extends to the bbox.
732 */ 693 */
733 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { 694 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState(
695 SkPDFShader::State* state) {
734 SkRect bbox; 696 SkRect bbox;
735 bbox.set(fShaderState->fBBox); 697 bbox.set(state->fBBox);
736 698
737 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState( 699 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState(
738 fShaderState->CreateAlphaToLuminosityState())); 700 state->CreateAlphaToLuminosityState()));
739 701
740 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); 702 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox));
741 703
742 SkAutoTUnref<SkPDFResourceDict> 704 SkAutoTUnref<SkPDFResourceDict>
743 resources(get_gradient_resource_dict(luminosityShader, NULL)); 705 resources(get_gradient_resource_dict(luminosityShader, NULL));
744 706
745 SkAutoTUnref<SkPDFFormXObject> alphaMask( 707 SkAutoTUnref<SkPDFFormXObject> alphaMask(
746 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); 708 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get()));
747 709
748 return SkPDFGraphicState::GetSMaskGraphicState( 710 return SkPDFGraphicState::GetSMaskGraphicState(
749 alphaMask.get(), false, 711 alphaMask.get(), false,
750 SkPDFGraphicState::kLuminosity_SMaskMode); 712 SkPDFGraphicState::kLuminosity_SMaskMode);
751 } 713 }
752 714
753 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) 715 SkPDFObject* SkPDFAlphaFunctionShader::Create(
754 : SkPDFShader(state) { 716 SkPDFShader::State* state) {
755 SkRect bbox; 717 SkRect bbox;
756 bbox.set(fShaderState->fBBox); 718 bbox.set(state->fBBox);
757 719
758 fColorShader.reset( 720 SkPDFObject* colorShader =
759 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); 721 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState());
722 if (!colorShader) {
723 return NULL;
724 }
725
726 SkPDFAlphaFunctionShader* alphaFunctionShader =
727 SkNEW_ARGS(SkPDFAlphaFunctionShader, (state));
728
729 alphaFunctionShader->fColorShader.reset(colorShader);
760 730
761 // Create resource dict with alpha graphics state as G0 and 731 // Create resource dict with alpha graphics state as G0 and
762 // pattern shader as P0, then write content stream. 732 // pattern shader as P0, then write content stream.
763 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); 733 SkAutoTUnref<SkPDFGraphicState> alphaGs(
764 fResourceDict.reset( 734 SkPDFAlphaFunctionShader::CreateSMaskGraphicState(state));
765 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); 735 alphaFunctionShader->fResourceDict.reset(
736 get_gradient_resource_dict(alphaFunctionShader->fColorShader.get(),
737 alphaGs.get()));
766 738
767 SkAutoTDelete<SkStream> colorStream( 739 SkAutoTDelete<SkStream> colorStream(
768 create_pattern_fill_content(0, bbox)); 740 create_pattern_fill_content(0, bbox));
769 setData(colorStream.get()); 741 alphaFunctionShader->setData(colorStream.get());
770 742
771 populate_tiling_pattern_dict(this, bbox, fResourceDict.get(), 743 populate_tiling_pattern_dict(alphaFunctionShader, bbox,
744 alphaFunctionShader->fResourceDict.get(),
772 SkMatrix::I()); 745 SkMatrix::I());
746 alphaFunctionShader->fSelf = alphaFunctionShader;
mtklein 2015/01/22 15:54:30 What is the possible value in assigning x->fSelf =
747 SkPDFCanon::GetCanon().addShader(alphaFunctionShader);
748 return alphaFunctionShader;
749 }
750
751
752 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state)
753 : SkPDFShader(state) {
773 } 754 }
774 755
775 // Finds affine and persp such that in = affine * persp. 756 // Finds affine and persp such that in = affine * persp.
776 // but it returns the inverse of perspective matrix. 757 // but it returns the inverse of perspective matrix.
777 static bool split_perspective(const SkMatrix in, SkMatrix* affine, 758 static bool split_perspective(const SkMatrix in, SkMatrix* affine,
778 SkMatrix* perspectiveInverse) { 759 SkMatrix* perspectiveInverse) {
779 const SkScalar p2 = in[SkMatrix::kMPersp2]; 760 const SkScalar p2 = in[SkMatrix::kMPersp2];
780 761
781 if (SkScalarNearlyZero(p2)) { 762 if (SkScalarNearlyZero(p2)) {
782 return false; 763 return false;
(...skipping 20 matching lines...) Expand all
803 zero, one, zero, 784 zero, one, zero,
804 -p0/p2, -p1/p2, 1/p2); 785 -p0/p2, -p1/p2, 1/p2);
805 786
806 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2, 787 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2,
807 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2, 788 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2,
808 zero, zero, one); 789 zero, zero, one);
809 790
810 return true; 791 return true;
811 } 792 }
812 793
813 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) 794 namespace {
814 : SkPDFDict("Pattern"), SkPDFShader(state) { 795 SkPDFObject* create_range_object() {
796 SkPDFArray* range = SkNEW(SkPDFArray);
797 range->reserve(6);
798 range->appendInt(0);
799 range->appendInt(1);
800 range->appendInt(0);
801 range->appendInt(1);
802 range->appendInt(0);
803 range->appendInt(1);
804 return range;
805 }
806
807 template <typename T> void unref(T* ptr) { ptr->unref(); }
808 } // namespace
809
810 SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject, rangeObject,
811 create_range_object, unref<SkPDFObject>);
812
813 static SkPDFStream* make_ps_function(const SkString& psCode,
814 SkPDFArray* domain) {
815 SkAutoDataUnref funcData(
816 SkData::NewWithCopy(psCode.c_str(), psCode.size()));
817 SkPDFStream* result = SkNEW_ARGS(SkPDFStream, (funcData.get()));
818 result->insertInt("FunctionType", 4);
819 result->insert("Domain", domain);
820 result->insert("Range", rangeObject.get());
821 return result;
822 }
823
824 SkPDFObject* SkPDFFunctionShader::Create(SkPDFShader::State* inState) {
825 SkAutoTDelete<SkPDFShader::State> state(inState);
826
815 SkString (*codeFunction)(const SkShader::GradientInfo& info, 827 SkString (*codeFunction)(const SkShader::GradientInfo& info,
816 const SkMatrix& perspectiveRemover) = NULL; 828 const SkMatrix& perspectiveRemover) = NULL;
817 SkPoint transformPoints[2]; 829 SkPoint transformPoints[2];
818 830
819 // Depending on the type of the gradient, we want to transform the 831 // Depending on the type of the gradient, we want to transform the
820 // coordinate space in different ways. 832 // coordinate space in different ways.
821 const SkShader::GradientInfo* info = &fShaderState->fInfo; 833 const SkShader::GradientInfo* info = &state->fInfo;
822 transformPoints[0] = info->fPoint[0]; 834 transformPoints[0] = info->fPoint[0];
823 transformPoints[1] = info->fPoint[1]; 835 transformPoints[1] = info->fPoint[1];
824 switch (fShaderState->fType) { 836 switch (state->fType) {
825 case SkShader::kLinear_GradientType: 837 case SkShader::kLinear_GradientType:
826 codeFunction = &linearCode; 838 codeFunction = &linearCode;
827 break; 839 break;
828 case SkShader::kRadial_GradientType: 840 case SkShader::kRadial_GradientType:
829 transformPoints[1] = transformPoints[0]; 841 transformPoints[1] = transformPoints[0];
830 transformPoints[1].fX += info->fRadius[0]; 842 transformPoints[1].fX += info->fRadius[0];
831 codeFunction = &radialCode; 843 codeFunction = &radialCode;
832 break; 844 break;
833 case SkShader::kRadial2_GradientType: { 845 case SkShader::kRadial2_GradientType: {
834 // Bail out if the radii are the same. Empty fResources signals 846 // Bail out if the radii are the same.
835 // an error and isValid will return false.
836 if (info->fRadius[0] == info->fRadius[1]) { 847 if (info->fRadius[0] == info->fRadius[1]) {
837 return; 848 return NULL;
838 } 849 }
839 transformPoints[1] = transformPoints[0]; 850 transformPoints[1] = transformPoints[0];
840 SkScalar dr = info->fRadius[1] - info->fRadius[0]; 851 SkScalar dr = info->fRadius[1] - info->fRadius[0];
841 transformPoints[1].fX += dr; 852 transformPoints[1].fX += dr;
842 codeFunction = &twoPointRadialCode; 853 codeFunction = &twoPointRadialCode;
843 break; 854 break;
844 } 855 }
845 case SkShader::kConical_GradientType: { 856 case SkShader::kConical_GradientType: {
846 transformPoints[1] = transformPoints[0]; 857 transformPoints[1] = transformPoints[0];
847 transformPoints[1].fX += SK_Scalar1; 858 transformPoints[1].fX += SK_Scalar1;
848 codeFunction = &twoPointConicalCode; 859 codeFunction = &twoPointConicalCode;
849 break; 860 break;
850 } 861 }
851 case SkShader::kSweep_GradientType: 862 case SkShader::kSweep_GradientType:
852 transformPoints[1] = transformPoints[0]; 863 transformPoints[1] = transformPoints[0];
853 transformPoints[1].fX += SK_Scalar1; 864 transformPoints[1].fX += SK_Scalar1;
854 codeFunction = &sweepCode; 865 codeFunction = &sweepCode;
855 break; 866 break;
856 case SkShader::kColor_GradientType: 867 case SkShader::kColor_GradientType:
857 case SkShader::kNone_GradientType: 868 case SkShader::kNone_GradientType:
858 default: 869 default:
859 return; 870 return NULL;
860 } 871 }
861 872
862 // Move any scaling (assuming a unit gradient) or translation 873 // Move any scaling (assuming a unit gradient) or translation
863 // (and rotation for linear gradient), of the final gradient from 874 // (and rotation for linear gradient), of the final gradient from
864 // info->fPoints to the matrix (updating bbox appropriately). Now 875 // info->fPoints to the matrix (updating bbox appropriately). Now
865 // the gradient can be drawn on on the unit segment. 876 // the gradient can be drawn on on the unit segment.
866 SkMatrix mapperMatrix; 877 SkMatrix mapperMatrix;
867 unitToPointsMatrix(transformPoints, &mapperMatrix); 878 unitToPointsMatrix(transformPoints, &mapperMatrix);
868 879
869 SkMatrix finalMatrix = fShaderState->fCanvasTransform; 880 SkMatrix finalMatrix = state->fCanvasTransform;
870 finalMatrix.preConcat(fShaderState->fShaderTransform); 881 finalMatrix.preConcat(state->fShaderTransform);
871 finalMatrix.preConcat(mapperMatrix); 882 finalMatrix.preConcat(mapperMatrix);
872 883
873 // Preserves as much as posible in the final matrix, and only removes 884 // Preserves as much as posible in the final matrix, and only removes
874 // the perspective. The inverse of the perspective is stored in 885 // the perspective. The inverse of the perspective is stored in
875 // perspectiveInverseOnly matrix and has 3 useful numbers 886 // perspectiveInverseOnly matrix and has 3 useful numbers
876 // (p0, p1, p2), while everything else is either 0 or 1. 887 // (p0, p1, p2), while everything else is either 0 or 1.
877 // In this way the shader will handle it eficiently, with minimal code. 888 // In this way the shader will handle it eficiently, with minimal code.
878 SkMatrix perspectiveInverseOnly = SkMatrix::I(); 889 SkMatrix perspectiveInverseOnly = SkMatrix::I();
879 if (finalMatrix.hasPerspective()) { 890 if (finalMatrix.hasPerspective()) {
880 if (!split_perspective(finalMatrix, 891 if (!split_perspective(finalMatrix,
881 &finalMatrix, &perspectiveInverseOnly)) { 892 &finalMatrix, &perspectiveInverseOnly)) {
882 return; 893 return NULL;
883 } 894 }
884 } 895 }
885 896
886 SkRect bbox; 897 SkRect bbox;
887 bbox.set(fShaderState->fBBox); 898 bbox.set(state->fBBox);
888 if (!inverseTransformBBox(finalMatrix, &bbox)) { 899 if (!inverseTransformBBox(finalMatrix, &bbox)) {
889 return; 900 return NULL;
890 } 901 }
891 902
892 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); 903 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray);
893 domain->reserve(4); 904 domain->reserve(4);
894 domain->appendScalar(bbox.fLeft); 905 domain->appendScalar(bbox.fLeft);
895 domain->appendScalar(bbox.fRight); 906 domain->appendScalar(bbox.fRight);
896 domain->appendScalar(bbox.fTop); 907 domain->appendScalar(bbox.fTop);
897 domain->appendScalar(bbox.fBottom); 908 domain->appendScalar(bbox.fBottom);
898 909
899 SkString functionCode; 910 SkString functionCode;
900 // The two point radial gradient further references 911 // The two point radial gradient further references
901 // fShaderState->fInfo 912 // state->fInfo
902 // in translating from x, y coordinates to the t parameter. So, we have 913 // in translating from x, y coordinates to the t parameter. So, we have
903 // to transform the points and radii according to the calculated matrix. 914 // to transform the points and radii according to the calculated matrix.
904 if (fShaderState->fType == SkShader::kRadial2_GradientType) { 915 if (state->fType == SkShader::kRadial2_GradientType) {
905 SkShader::GradientInfo twoPointRadialInfo = *info; 916 SkShader::GradientInfo twoPointRadialInfo = *info;
906 SkMatrix inverseMapperMatrix; 917 SkMatrix inverseMapperMatrix;
907 if (!mapperMatrix.invert(&inverseMapperMatrix)) { 918 if (!mapperMatrix.invert(&inverseMapperMatrix)) {
908 return; 919 return NULL;
909 } 920 }
910 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); 921 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2);
911 twoPointRadialInfo.fRadius[0] = 922 twoPointRadialInfo.fRadius[0] =
912 inverseMapperMatrix.mapRadius(info->fRadius[0]); 923 inverseMapperMatrix.mapRadius(info->fRadius[0]);
913 twoPointRadialInfo.fRadius[1] = 924 twoPointRadialInfo.fRadius[1] =
914 inverseMapperMatrix.mapRadius(info->fRadius[1]); 925 inverseMapperMatrix.mapRadius(info->fRadius[1]);
915 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); 926 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly);
916 } else { 927 } else {
917 functionCode = codeFunction(*info, perspectiveInverseOnly); 928 functionCode = codeFunction(*info, perspectiveInverseOnly);
918 } 929 }
919 930
920 SkAutoTUnref<SkPDFDict> pdfShader(new SkPDFDict); 931 SkAutoTUnref<SkPDFDict> pdfShader(new SkPDFDict);
921 pdfShader->insertInt("ShadingType", 1); 932 pdfShader->insertInt("ShadingType", 1);
922 pdfShader->insertName("ColorSpace", "DeviceRGB"); 933 pdfShader->insertName("ColorSpace", "DeviceRGB");
923 pdfShader->insert("Domain", domain.get()); 934 pdfShader->insert("Domain", domain.get());
924 935
925 SkPDFStream* function = makePSFunction(functionCode, domain.get()); 936 SkPDFStream* function = make_ps_function(functionCode, domain.get());
926 pdfShader->insert("Function", new SkPDFObjRef(function))->unref(); 937 pdfShader->insert("Function", new SkPDFObjRef(function))->unref();
927 fResources.push(function); // Pass ownership to resource list.
928 938
929 insertInt("PatternType", 2); 939 SkAutoTUnref<SkPDFArray> matrixArray(
930 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); 940 SkPDFUtils::MatrixToArray(finalMatrix));
931 insert("Shading", pdfShader.get()); 941
942 SkPDFFunctionShader* pdfFunctionShader =
943 SkNEW_ARGS(SkPDFFunctionShader, (state.detach()));
944
945 pdfFunctionShader->fResources.push(function);
946 // Pass ownership to resource list.
947
948 pdfFunctionShader->insertInt("PatternType", 2);
949 pdfFunctionShader->insert("Matrix", matrixArray.get());
950 pdfFunctionShader->insert("Shading", pdfShader.get());
951
952 pdfFunctionShader->fSelf = pdfFunctionShader;
953 SkPDFCanon::GetCanon().addShader(pdfFunctionShader);
954 return pdfFunctionShader;
932 } 955 }
933 956
934 SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) 957 SkPDFObject* SkPDFImageShader::Create(SkPDFShader::State* inState) {
935 : SkPDFShader(state) { 958 SkAutoTDelete<SkPDFShader::State> state(inState);
936 fShaderState->fImage.lockPixels(); 959
960 state->fImage.lockPixels();
937 961
938 // The image shader pattern cell will be drawn into a separate device 962 // The image shader pattern cell will be drawn into a separate device
939 // in pattern cell space (no scaling on the bitmap, though there may be 963 // in pattern cell space (no scaling on the bitmap, though there may be
940 // translations so that all content is in the device, coordinates > 0). 964 // translations so that all content is in the device, coordinates > 0).
941 965
942 // Map clip bounds to shader space to ensure the device is large enough 966 // Map clip bounds to shader space to ensure the device is large enough
943 // to handle fake clamping. 967 // to handle fake clamping.
944 SkMatrix finalMatrix = fShaderState->fCanvasTransform; 968 SkMatrix finalMatrix = state->fCanvasTransform;
945 finalMatrix.preConcat(fShaderState->fShaderTransform); 969 finalMatrix.preConcat(state->fShaderTransform);
946 SkRect deviceBounds; 970 SkRect deviceBounds;
947 deviceBounds.set(fShaderState->fBBox); 971 deviceBounds.set(state->fBBox);
948 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) { 972 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) {
949 return; 973 return NULL;
950 } 974 }
951 975
952 const SkBitmap* image = &fShaderState->fImage; 976 const SkBitmap* image = &state->fImage;
953 SkRect bitmapBounds; 977 SkRect bitmapBounds;
954 image->getBounds(&bitmapBounds); 978 image->getBounds(&bitmapBounds);
955 979
956 // For tiling modes, the bounds should be extended to include the bitmap, 980 // For tiling modes, the bounds should be extended to include the bitmap,
957 // otherwise the bitmap gets clipped out and the shader is empty and awful. 981 // otherwise the bitmap gets clipped out and the shader is empty and awful.
958 // For clamp modes, we're only interested in the clip region, whether 982 // For clamp modes, we're only interested in the clip region, whether
959 // or not the main bitmap is in it. 983 // or not the main bitmap is in it.
960 SkShader::TileMode tileModes[2]; 984 SkShader::TileMode tileModes[2];
961 tileModes[0] = fShaderState->fImageTileModes[0]; 985 tileModes[0] = state->fImageTileModes[0];
962 tileModes[1] = fShaderState->fImageTileModes[1]; 986 tileModes[1] = state->fImageTileModes[1];
963 if (tileModes[0] != SkShader::kClamp_TileMode || 987 if (tileModes[0] != SkShader::kClamp_TileMode ||
964 tileModes[1] != SkShader::kClamp_TileMode) { 988 tileModes[1] != SkShader::kClamp_TileMode) {
965 deviceBounds.join(bitmapBounds); 989 deviceBounds.join(bitmapBounds);
966 } 990 }
967 991
968 SkMatrix unflip; 992 SkMatrix unflip;
969 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height())); 993 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height()));
970 unflip.preScale(SK_Scalar1, -SK_Scalar1); 994 unflip.preScale(SK_Scalar1, -SK_Scalar1);
971 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), 995 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()),
972 SkScalarRoundToInt(deviceBounds.height())); 996 SkScalarRoundToInt(deviceBounds.height()));
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 bottomMatrix.postScale(-1, 1); 1149 bottomMatrix.postScale(-1, 1);
1126 bottomMatrix.postTranslate(2 * width, 0); 1150 bottomMatrix.postTranslate(2 * width, 0);
1127 drawBitmapMatrix(&canvas, bottom, bottomMatrix); 1151 drawBitmapMatrix(&canvas, bottom, bottomMatrix);
1128 } 1152 }
1129 patternBBox.fBottom = deviceBounds.height(); 1153 patternBBox.fBottom = deviceBounds.height();
1130 } 1154 }
1131 } 1155 }
1132 1156
1133 // Put the canvas into the pattern stream (fContent). 1157 // Put the canvas into the pattern stream (fContent).
1134 SkAutoTDelete<SkStream> content(pattern.content()); 1158 SkAutoTDelete<SkStream> content(pattern.content());
1135 setData(content.get()); 1159
1160 SkPDFImageShader* imageShader =
1161 SkNEW_ARGS(SkPDFImageShader, (state.detach()));
1162 imageShader->setData(content.get());
1163
1136 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); 1164 SkPDFResourceDict* resourceDict = pattern.getResourceDict();
1137 resourceDict->getReferencedResources(fResources, &fResources, false); 1165 resourceDict->getReferencedResources(imageShader->fResources,
1166 &imageShader->fResources, false);
1138 1167
1139 populate_tiling_pattern_dict(this, patternBBox, 1168 populate_tiling_pattern_dict(imageShader, patternBBox,
1140 pattern.getResourceDict(), finalMatrix); 1169 pattern.getResourceDict(), finalMatrix);
1141 1170
1142 fShaderState->fImage.unlockPixels(); 1171 imageShader->fShaderState->fImage.unlockPixels();
1143 }
1144 1172
1145 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFAr ray* domain) { 1173 imageShader->fSelf = imageShader;
1146 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), psCode.size())) ; 1174 SkPDFCanon::GetCanon().addShader(imageShader);
1147 SkPDFStream* result = new SkPDFStream(funcData.get()); 1175 return imageShader;
1148 result->insertInt("FunctionType", 4);
1149 result->insert("Domain", domain);
1150 result->insert("Range", RangeObject());
1151 return result;
1152 } 1176 }
1153 1177
1154 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { 1178 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const {
1155 if (fType != b.fType || 1179 if (fType != b.fType ||
1156 fCanvasTransform != b.fCanvasTransform || 1180 fCanvasTransform != b.fCanvasTransform ||
1157 fShaderTransform != b.fShaderTransform || 1181 fShaderTransform != b.fShaderTransform ||
1158 fBBox != b.fBBox) { 1182 fBBox != b.fBBox) {
1159 return false; 1183 return false;
1160 } 1184 }
1161 1185
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1334 return false; 1358 return false;
1335 } 1359 }
1336 1360
1337 void SkPDFShader::State::AllocateGradientInfoStorage() { 1361 void SkPDFShader::State::AllocateGradientInfoStorage() {
1338 fColorData.set(sk_malloc_throw( 1362 fColorData.set(sk_malloc_throw(
1339 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); 1363 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
1340 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); 1364 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
1341 fInfo.fColorOffsets = 1365 fInfo.fColorOffsets =
1342 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); 1366 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount);
1343 } 1367 }
OLDNEW
« src/pdf/SkPDFShader.h ('K') | « src/pdf/SkPDFShader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698