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

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: get rid of fSelf crazyness 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; } 524 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; }
519 525
520 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 526 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
521 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { 527 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE {
522 GetResourcesHelper(&fResources, 528 GetResourcesHelper(&fResources,
523 knownResourceObjects, 529 knownResourceObjects,
524 newResourceObjects); 530 newResourceObjects);
525 } 531 }
526 532
527 private: 533 private:
528 static SkPDFObject* RangeObject();
529
530 SkTDArray<SkPDFObject*> fResources; 534 SkTDArray<SkPDFObject*> fResources;
531 535 explicit SkPDFFunctionShader(SkPDFShader::State* state)
532 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); 536 : SkPDFDict("Pattern"), SkPDFShader(state) {
537 }
533 typedef SkPDFDict INHERITED; 538 typedef SkPDFDict INHERITED;
534 }; 539 };
535 540
536 /** 541 /**
537 * A shader for PDF gradients. This encapsulates the function shader 542 * A shader for PDF gradients. This encapsulates the function shader
538 * inside a tiling pattern while providing a common pattern interface. 543 * inside a tiling pattern while providing a common pattern interface.
539 * The encapsulation allows the use of a SMask for transparency gradients. 544 * The encapsulation allows the use of a SMask for transparency gradients.
540 */ 545 */
541 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { 546 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader {
542 public: 547 public:
543 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state); 548 static SkPDFObject* Create(SkPDFShader::State*);
549
544 virtual ~SkPDFAlphaFunctionShader() { 550 virtual ~SkPDFAlphaFunctionShader() {
545 SkPDFShader::RemoveFromCanonIfValid(this); 551 remove_from_canon(this);
546 } 552 }
547 553
548 bool isValid() SK_OVERRIDE {
549 return fColorShader.get() != NULL;
550 }
551 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; } 554 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; }
552 555
553 private: 556 private:
554 SkPDFGraphicState* CreateSMaskGraphicState(); 557 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state);
558
559 static SkPDFGraphicState* CreateSMaskGraphicState(SkPDFShader::State*);
555 560
556 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 561 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
557 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { 562 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE {
558 fResourceDict->getReferencedResources(knownResourceObjects, 563 fResourceDict->getReferencedResources(knownResourceObjects,
559 newResourceObjects, 564 newResourceObjects,
560 true); 565 true);
561 } 566 }
562 567
563 SkAutoTUnref<SkPDFObject> fColorShader; 568 SkAutoTUnref<SkPDFObject> fColorShader;
564 SkAutoTUnref<SkPDFResourceDict> fResourceDict; 569 SkAutoTUnref<SkPDFResourceDict> fResourceDict;
565 }; 570 };
566 571
567 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { 572 class SkPDFImageShader : public SkPDFStream, public SkPDFShader {
568 public: 573 public:
569 explicit SkPDFImageShader(SkPDFShader::State* state); 574 static SkPDFObject* Create(SkPDFShader::State* state);
575
570 virtual ~SkPDFImageShader() { 576 virtual ~SkPDFImageShader() {
571 SkPDFShader::RemoveFromCanonIfValid(this); 577 remove_from_canon(this);
572 fResources.unrefAll(); 578 fResources.unrefAll();
573 } 579 }
574 580
575 bool isValid() SK_OVERRIDE { return size() > 0; }
576 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; } 581 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; }
577 582
578 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 583 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
579 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { 584 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE {
580 GetResourcesHelper(&fResources.toArray(), 585 GetResourcesHelper(&fResources.toArray(),
581 knownResourceObjects, 586 knownResourceObjects,
582 newResourceObjects); 587 newResourceObjects);
583 } 588 }
584 589
585 private: 590 private:
586 SkTSet<SkPDFObject*> fResources; 591 SkTSet<SkPDFObject*> fResources;
592 explicit SkPDFImageShader(SkPDFShader::State* state)
593 : SkPDFShader(state) {}
587 }; 594 };
588 595
589 SkPDFShader::SkPDFShader(SkPDFShader::State* s) : fShaderState(s) {} 596 SkPDFShader::SkPDFShader(SkPDFShader::State* s) : fShaderState(s) {}
590 597
591 SkPDFShader::~SkPDFShader() {} 598 SkPDFShader::~SkPDFShader() {}
592 599
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 { 600 bool SkPDFShader::equals(const SkPDFShader::State& state) const {
601 return state == *fShaderState.get(); 601 return state == *fShaderState.get();
602 } 602 }
603 603
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 604 // static
614 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { 605 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) {
615 SkAutoTDelete<State> state(inState); 606 SkAutoTDelete<State> state(inState);
616 if (state->fType == SkShader::kNone_GradientType && 607 if (state->fType == SkShader::kNone_GradientType &&
617 state->fImage.isNull()) { 608 state->fImage.isNull()) {
618 // TODO(vandebo) This drops SKComposeShader on the floor. We could 609 // TODO(vandebo) This drops SKComposeShader on the floor. We could
619 // handle compose shader by pulling things up to a layer, drawing with 610 // 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 611 // the first shader, applying the xfer mode and drawing again with the
621 // second shader, then applying the layer to the original drawing. 612 // second shader, then applying the layer to the original drawing.
622 return NULL; 613 return NULL;
623 } 614 }
624 615
625 SkPDFShader* pdfShader = SkPDFCanon::GetCanon().findShader(*state); 616 SkPDFShader* pdfShader = SkPDFCanon::GetCanon().findShader(*state);
626 if (pdfShader) { 617 if (pdfShader) {
627 SkASSERT(pdfShader->isValid());
628 return SkRef(pdfShader->toPDFObject()); 618 return SkRef(pdfShader->toPDFObject());
629 } 619 }
630 620
631 // The PDFShader takes ownership of the shaderSate. 621 // The PDFShader takes ownership of the shaderSate.
632 if (state->fType == SkShader::kNone_GradientType) { 622 if (state->fType == SkShader::kNone_GradientType) {
633 return SkPDFShader::AddToCanonIfValid( 623 return SkPDFImageShader::Create(state.detach());
634 SkNEW_ARGS(SkPDFImageShader, (state.detach())));
635 } else if (state->GradientHasAlpha()) { 624 } else if (state->GradientHasAlpha()) {
636 return SkPDFShader::AddToCanonIfValid( 625 return SkPDFAlphaFunctionShader::Create(state.detach());
637 SkNEW_ARGS(SkPDFAlphaFunctionShader, (state.detach())));
638 } else { 626 } else {
639 return SkPDFShader::AddToCanonIfValid( 627 return SkPDFFunctionShader::Create(state.detach());
640 SkNEW_ARGS(SkPDFFunctionShader, (state.detach())));
641 } 628 }
642 } 629 }
643 630
644 // static 631 // static
645 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, 632 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader,
646 const SkMatrix& matrix, 633 const SkMatrix& matrix,
647 const SkIRect& surfaceBBox, 634 const SkIRect& surfaceBBox,
648 SkScalar rasterScale) { 635 SkScalar rasterScale) {
649 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); 636 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex());
650 return GetPDFShaderByState( 637 return GetPDFShaderByState(
651 SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale))); 638 SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale)));
652 } 639 }
653 640
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( 641 static SkPDFResourceDict* get_gradient_resource_dict(
675 SkPDFObject* functionShader, 642 SkPDFObject* functionShader,
676 SkPDFObject* gState) { 643 SkPDFObject* gState) {
677 SkPDFResourceDict* dict = new SkPDFResourceDict(); 644 SkPDFResourceDict* dict = new SkPDFResourceDict();
678 645
679 if (functionShader != NULL) { 646 if (functionShader != NULL) {
680 dict->insertResourceAsReference( 647 dict->insertResourceAsReference(
681 SkPDFResourceDict::kPattern_ResourceType, 0, functionShader); 648 SkPDFResourceDict::kPattern_ResourceType, 0, functionShader);
682 } 649 }
683 if (gState != NULL) { 650 if (gState != NULL) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, 690 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType,
724 &content); 691 &content);
725 692
726 return content.detachAsStream(); 693 return content.detachAsStream();
727 } 694 }
728 695
729 /** 696 /**
730 * Creates a ExtGState with the SMask set to the luminosityShader in 697 * Creates a ExtGState with the SMask set to the luminosityShader in
731 * luminosity mode. The shader pattern extends to the bbox. 698 * luminosity mode. The shader pattern extends to the bbox.
732 */ 699 */
733 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { 700 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState(
701 SkPDFShader::State* state) {
734 SkRect bbox; 702 SkRect bbox;
735 bbox.set(fShaderState->fBBox); 703 bbox.set(state->fBBox);
736 704
737 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState( 705 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState(
738 fShaderState->CreateAlphaToLuminosityState())); 706 state->CreateAlphaToLuminosityState()));
739 707
740 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); 708 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox));
741 709
742 SkAutoTUnref<SkPDFResourceDict> 710 SkAutoTUnref<SkPDFResourceDict>
743 resources(get_gradient_resource_dict(luminosityShader, NULL)); 711 resources(get_gradient_resource_dict(luminosityShader, NULL));
744 712
745 SkAutoTUnref<SkPDFFormXObject> alphaMask( 713 SkAutoTUnref<SkPDFFormXObject> alphaMask(
746 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); 714 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get()));
747 715
748 return SkPDFGraphicState::GetSMaskGraphicState( 716 return SkPDFGraphicState::GetSMaskGraphicState(
749 alphaMask.get(), false, 717 alphaMask.get(), false,
750 SkPDFGraphicState::kLuminosity_SMaskMode); 718 SkPDFGraphicState::kLuminosity_SMaskMode);
751 } 719 }
752 720
753 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) 721 SkPDFObject* SkPDFAlphaFunctionShader::Create(
754 : SkPDFShader(state) { 722 SkPDFShader::State* state) {
755 SkRect bbox; 723 SkRect bbox;
756 bbox.set(fShaderState->fBBox); 724 bbox.set(state->fBBox);
757 725
758 fColorShader.reset( 726 SkPDFObject* colorShader =
759 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); 727 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState());
728 if (!colorShader) {
729 return NULL;
mtklein 2015/01/22 18:51:36 This leaks state. You might want to pass SkAutoTD
730 }
731
732 SkPDFAlphaFunctionShader* alphaFunctionShader =
733 SkNEW_ARGS(SkPDFAlphaFunctionShader, (state));
734
735 alphaFunctionShader->fColorShader.reset(colorShader);
760 736
761 // Create resource dict with alpha graphics state as G0 and 737 // Create resource dict with alpha graphics state as G0 and
762 // pattern shader as P0, then write content stream. 738 // pattern shader as P0, then write content stream.
763 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); 739 SkAutoTUnref<SkPDFGraphicState> alphaGs(
764 fResourceDict.reset( 740 SkPDFAlphaFunctionShader::CreateSMaskGraphicState(state));
765 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); 741 alphaFunctionShader->fResourceDict.reset(
742 get_gradient_resource_dict(alphaFunctionShader->fColorShader.get(),
743 alphaGs.get()));
766 744
767 SkAutoTDelete<SkStream> colorStream( 745 SkAutoTDelete<SkStream> colorStream(
768 create_pattern_fill_content(0, bbox)); 746 create_pattern_fill_content(0, bbox));
769 setData(colorStream.get()); 747 alphaFunctionShader->setData(colorStream.get());
770 748
771 populate_tiling_pattern_dict(this, bbox, fResourceDict.get(), 749 populate_tiling_pattern_dict(alphaFunctionShader, bbox,
750 alphaFunctionShader->fResourceDict.get(),
772 SkMatrix::I()); 751 SkMatrix::I());
752 SkPDFCanon::GetCanon().addShader(alphaFunctionShader);
753 return alphaFunctionShader;
754 }
755
756
757 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state)
758 : SkPDFShader(state) {
773 } 759 }
774 760
775 // Finds affine and persp such that in = affine * persp. 761 // Finds affine and persp such that in = affine * persp.
776 // but it returns the inverse of perspective matrix. 762 // but it returns the inverse of perspective matrix.
777 static bool split_perspective(const SkMatrix in, SkMatrix* affine, 763 static bool split_perspective(const SkMatrix in, SkMatrix* affine,
778 SkMatrix* perspectiveInverse) { 764 SkMatrix* perspectiveInverse) {
779 const SkScalar p2 = in[SkMatrix::kMPersp2]; 765 const SkScalar p2 = in[SkMatrix::kMPersp2];
780 766
781 if (SkScalarNearlyZero(p2)) { 767 if (SkScalarNearlyZero(p2)) {
782 return false; 768 return false;
(...skipping 20 matching lines...) Expand all
803 zero, one, zero, 789 zero, one, zero,
804 -p0/p2, -p1/p2, 1/p2); 790 -p0/p2, -p1/p2, 1/p2);
805 791
806 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2, 792 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2,
807 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2, 793 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2,
808 zero, zero, one); 794 zero, zero, one);
809 795
810 return true; 796 return true;
811 } 797 }
812 798
813 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) 799 namespace {
814 : SkPDFDict("Pattern"), SkPDFShader(state) { 800 SkPDFObject* create_range_object() {
801 SkPDFArray* range = SkNEW(SkPDFArray);
802 range->reserve(6);
803 range->appendInt(0);
804 range->appendInt(1);
805 range->appendInt(0);
806 range->appendInt(1);
807 range->appendInt(0);
808 range->appendInt(1);
809 return range;
810 }
811
812 template <typename T> void unref(T* ptr) { ptr->unref(); }
813 } // namespace
814
815 SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject, rangeObject,
816 create_range_object, unref<SkPDFObject>);
817
818 static SkPDFStream* make_ps_function(const SkString& psCode,
819 SkPDFArray* domain) {
820 SkAutoDataUnref funcData(
821 SkData::NewWithCopy(psCode.c_str(), psCode.size()));
822 SkPDFStream* result = SkNEW_ARGS(SkPDFStream, (funcData.get()));
823 result->insertInt("FunctionType", 4);
824 result->insert("Domain", domain);
825 result->insert("Range", rangeObject.get());
826 return result;
827 }
828
829 SkPDFObject* SkPDFFunctionShader::Create(SkPDFShader::State* inState) {
830 SkAutoTDelete<SkPDFShader::State> state(inState);
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, (state.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(SkPDFShader::State* inState) {
935 : SkPDFShader(state) { 962 SkAutoTDelete<SkPDFShader::State> state(inState);
936 fShaderState->fImage.lockPixels(); 963
964 state->fImage.lockPixels();
937 965
938 // The image shader pattern cell will be drawn into a separate device 966 // 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 967 // 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). 968 // translations so that all content is in the device, coordinates > 0).
941 969
942 // Map clip bounds to shader space to ensure the device is large enough 970 // Map clip bounds to shader space to ensure the device is large enough
943 // to handle fake clamping. 971 // to handle fake clamping.
944 SkMatrix finalMatrix = fShaderState->fCanvasTransform; 972 SkMatrix finalMatrix = state->fCanvasTransform;
945 finalMatrix.preConcat(fShaderState->fShaderTransform); 973 finalMatrix.preConcat(state->fShaderTransform);
946 SkRect deviceBounds; 974 SkRect deviceBounds;
947 deviceBounds.set(fShaderState->fBBox); 975 deviceBounds.set(state->fBBox);
948 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) { 976 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) {
949 return; 977 return NULL;
950 } 978 }
951 979
952 const SkBitmap* image = &fShaderState->fImage; 980 const SkBitmap* image = &state->fImage;
953 SkRect bitmapBounds; 981 SkRect bitmapBounds;
954 image->getBounds(&bitmapBounds); 982 image->getBounds(&bitmapBounds);
955 983
956 // For tiling modes, the bounds should be extended to include the bitmap, 984 // 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. 985 // 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 986 // For clamp modes, we're only interested in the clip region, whether
959 // or not the main bitmap is in it. 987 // or not the main bitmap is in it.
960 SkShader::TileMode tileModes[2]; 988 SkShader::TileMode tileModes[2];
961 tileModes[0] = fShaderState->fImageTileModes[0]; 989 tileModes[0] = state->fImageTileModes[0];
962 tileModes[1] = fShaderState->fImageTileModes[1]; 990 tileModes[1] = state->fImageTileModes[1];
963 if (tileModes[0] != SkShader::kClamp_TileMode || 991 if (tileModes[0] != SkShader::kClamp_TileMode ||
964 tileModes[1] != SkShader::kClamp_TileMode) { 992 tileModes[1] != SkShader::kClamp_TileMode) {
965 deviceBounds.join(bitmapBounds); 993 deviceBounds.join(bitmapBounds);
966 } 994 }
967 995
968 SkMatrix unflip; 996 SkMatrix unflip;
969 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height())); 997 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height()));
970 unflip.preScale(SK_Scalar1, -SK_Scalar1); 998 unflip.preScale(SK_Scalar1, -SK_Scalar1);
971 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), 999 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()),
972 SkScalarRoundToInt(deviceBounds.height())); 1000 SkScalarRoundToInt(deviceBounds.height()));
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 bottomMatrix.postScale(-1, 1); 1153 bottomMatrix.postScale(-1, 1);
1126 bottomMatrix.postTranslate(2 * width, 0); 1154 bottomMatrix.postTranslate(2 * width, 0);
1127 drawBitmapMatrix(&canvas, bottom, bottomMatrix); 1155 drawBitmapMatrix(&canvas, bottom, bottomMatrix);
1128 } 1156 }
1129 patternBBox.fBottom = deviceBounds.height(); 1157 patternBBox.fBottom = deviceBounds.height();
1130 } 1158 }
1131 } 1159 }
1132 1160
1133 // Put the canvas into the pattern stream (fContent). 1161 // Put the canvas into the pattern stream (fContent).
1134 SkAutoTDelete<SkStream> content(pattern.content()); 1162 SkAutoTDelete<SkStream> content(pattern.content());
1135 setData(content.get()); 1163
1164 SkPDFImageShader* imageShader =
1165 SkNEW_ARGS(SkPDFImageShader, (state.detach()));
1166 imageShader->setData(content.get());
1167
1136 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); 1168 SkPDFResourceDict* resourceDict = pattern.getResourceDict();
1137 resourceDict->getReferencedResources(fResources, &fResources, false); 1169 resourceDict->getReferencedResources(imageShader->fResources,
1170 &imageShader->fResources, false);
1138 1171
1139 populate_tiling_pattern_dict(this, patternBBox, 1172 populate_tiling_pattern_dict(imageShader, patternBBox,
1140 pattern.getResourceDict(), finalMatrix); 1173 pattern.getResourceDict(), finalMatrix);
1141 1174
1142 fShaderState->fImage.unlockPixels(); 1175 imageShader->fShaderState->fImage.unlockPixels();
1143 }
1144 1176
1145 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFAr ray* domain) { 1177 SkPDFCanon::GetCanon().addShader(imageShader);
1146 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), psCode.size())) ; 1178 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 } 1179 }
1153 1180
1154 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { 1181 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const {
1155 if (fType != b.fType || 1182 if (fType != b.fType ||
1156 fCanvasTransform != b.fCanvasTransform || 1183 fCanvasTransform != b.fCanvasTransform ||
1157 fShaderTransform != b.fShaderTransform || 1184 fShaderTransform != b.fShaderTransform ||
1158 fBBox != b.fBBox) { 1185 fBBox != b.fBBox) {
1159 return false; 1186 return false;
1160 } 1187 }
1161 1188
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1334 return false; 1361 return false;
1335 } 1362 }
1336 1363
1337 void SkPDFShader::State::AllocateGradientInfoStorage() { 1364 void SkPDFShader::State::AllocateGradientInfoStorage() {
1338 fColorData.set(sk_malloc_throw( 1365 fColorData.set(sk_malloc_throw(
1339 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); 1366 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar))));
1340 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); 1367 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get());
1341 fInfo.fColorOffsets = 1368 fInfo.fColorOffsets =
1342 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); 1369 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount);
1343 } 1370 }
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