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

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

Powered by Google App Engine
This is Rietveld 408576698