| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkPDFShader.h" | 10 #include "SkPDFShader.h" |
| 11 | 11 |
| 12 #include "SkData.h" | 12 #include "SkData.h" |
| 13 #include "SkPDFCanon.h" |
| 13 #include "SkPDFCatalog.h" | 14 #include "SkPDFCatalog.h" |
| 14 #include "SkPDFDevice.h" | 15 #include "SkPDFDevice.h" |
| 15 #include "SkPDFFormXObject.h" | 16 #include "SkPDFFormXObject.h" |
| 16 #include "SkPDFGraphicState.h" | 17 #include "SkPDFGraphicState.h" |
| 17 #include "SkPDFResourceDict.h" | 18 #include "SkPDFResourceDict.h" |
| 18 #include "SkPDFUtils.h" | 19 #include "SkPDFUtils.h" |
| 19 #include "SkScalar.h" | 20 #include "SkScalar.h" |
| 20 #include "SkStream.h" | 21 #include "SkStream.h" |
| 21 #include "SkTemplates.h" | 22 #include "SkTemplates.h" |
| 22 #include "SkThread.h" | 23 #include "SkThread.h" |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 State(const State& other); | 503 State(const State& other); |
| 503 State operator=(const State& rhs); | 504 State operator=(const State& rhs); |
| 504 void AllocateGradientInfoStorage(); | 505 void AllocateGradientInfoStorage(); |
| 505 }; | 506 }; |
| 506 | 507 |
| 507 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { | 508 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { |
| 508 SK_DECLARE_INST_COUNT(SkPDFFunctionShader) | 509 SK_DECLARE_INST_COUNT(SkPDFFunctionShader) |
| 509 public: | 510 public: |
| 510 explicit SkPDFFunctionShader(SkPDFShader::State* state); | 511 explicit SkPDFFunctionShader(SkPDFShader::State* state); |
| 511 virtual ~SkPDFFunctionShader() { | 512 virtual ~SkPDFFunctionShader() { |
| 512 if (isValid()) { | 513 SkPDFShader::RemoveFromCanonIfValid(this); |
| 513 RemoveShader(this); | |
| 514 } | |
| 515 fResources.unrefAll(); | 514 fResources.unrefAll(); |
| 516 } | 515 } |
| 517 | 516 |
| 518 bool isValid() SK_OVERRIDE { return fResources.count() > 0; } | 517 bool isValid() SK_OVERRIDE { return fResources.count() > 0; } |
| 518 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; } |
| 519 | 519 |
| 520 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 520 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 521 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { | 521 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
| 522 GetResourcesHelper(&fResources, | 522 GetResourcesHelper(&fResources, |
| 523 knownResourceObjects, | 523 knownResourceObjects, |
| 524 newResourceObjects); | 524 newResourceObjects); |
| 525 } | 525 } |
| 526 | 526 |
| 527 private: | 527 private: |
| 528 static SkPDFObject* RangeObject(); | 528 static SkPDFObject* RangeObject(); |
| 529 | 529 |
| 530 SkTDArray<SkPDFObject*> fResources; | 530 SkTDArray<SkPDFObject*> fResources; |
| 531 SkAutoTDelete<const SkPDFShader::State> fState; | |
| 532 | 531 |
| 533 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); | 532 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); |
| 534 typedef SkPDFDict INHERITED; | 533 typedef SkPDFDict INHERITED; |
| 535 }; | 534 }; |
| 536 | 535 |
| 537 /** | 536 /** |
| 538 * A shader for PDF gradients. This encapsulates the function shader | 537 * A shader for PDF gradients. This encapsulates the function shader |
| 539 * inside a tiling pattern while providing a common pattern interface. | 538 * inside a tiling pattern while providing a common pattern interface. |
| 540 * The encapsulation allows the use of a SMask for transparency gradients. | 539 * The encapsulation allows the use of a SMask for transparency gradients. |
| 541 */ | 540 */ |
| 542 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { | 541 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { |
| 543 public: | 542 public: |
| 544 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state); | 543 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state); |
| 545 virtual ~SkPDFAlphaFunctionShader() { | 544 virtual ~SkPDFAlphaFunctionShader() { |
| 546 if (isValid()) { | 545 SkPDFShader::RemoveFromCanonIfValid(this); |
| 547 RemoveShader(this); | |
| 548 } | |
| 549 } | 546 } |
| 550 | 547 |
| 551 bool isValid() SK_OVERRIDE { | 548 bool isValid() SK_OVERRIDE { |
| 552 return fColorShader.get() != NULL; | 549 return fColorShader.get() != NULL; |
| 553 } | 550 } |
| 551 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; } |
| 554 | 552 |
| 555 private: | 553 private: |
| 556 SkAutoTDelete<const SkPDFShader::State> fState; | |
| 557 | |
| 558 SkPDFGraphicState* CreateSMaskGraphicState(); | 554 SkPDFGraphicState* CreateSMaskGraphicState(); |
| 559 | 555 |
| 560 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 556 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 561 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { | 557 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
| 562 fResourceDict->getReferencedResources(knownResourceObjects, | 558 fResourceDict->getReferencedResources(knownResourceObjects, |
| 563 newResourceObjects, | 559 newResourceObjects, |
| 564 true); | 560 true); |
| 565 } | 561 } |
| 566 | 562 |
| 567 SkAutoTUnref<SkPDFObject> fColorShader; | 563 SkAutoTUnref<SkPDFObject> fColorShader; |
| 568 SkAutoTUnref<SkPDFResourceDict> fResourceDict; | 564 SkAutoTUnref<SkPDFResourceDict> fResourceDict; |
| 569 }; | 565 }; |
| 570 | 566 |
| 571 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { | 567 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { |
| 572 public: | 568 public: |
| 573 explicit SkPDFImageShader(SkPDFShader::State* state); | 569 explicit SkPDFImageShader(SkPDFShader::State* state); |
| 574 virtual ~SkPDFImageShader() { | 570 virtual ~SkPDFImageShader() { |
| 575 if (isValid()) { | 571 SkPDFShader::RemoveFromCanonIfValid(this); |
| 576 RemoveShader(this); | |
| 577 } | |
| 578 fResources.unrefAll(); | 572 fResources.unrefAll(); |
| 579 } | 573 } |
| 580 | 574 |
| 581 bool isValid() SK_OVERRIDE { return size() > 0; } | 575 bool isValid() SK_OVERRIDE { return size() > 0; } |
| 576 SkPDFObject* toPDFObject() SK_OVERRIDE { return this; } |
| 582 | 577 |
| 583 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 578 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 584 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { | 579 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
| 585 GetResourcesHelper(&fResources.toArray(), | 580 GetResourcesHelper(&fResources.toArray(), |
| 586 knownResourceObjects, | 581 knownResourceObjects, |
| 587 newResourceObjects); | 582 newResourceObjects); |
| 588 } | 583 } |
| 589 | 584 |
| 590 private: | 585 private: |
| 591 SkTSet<SkPDFObject*> fResources; | 586 SkTSet<SkPDFObject*> fResources; |
| 592 SkAutoTDelete<const SkPDFShader::State> fState; | |
| 593 }; | 587 }; |
| 594 | 588 |
| 595 SkPDFShader::SkPDFShader() {} | 589 SkPDFShader::SkPDFShader(SkPDFShader::State* s) : fShaderState(s) {} |
| 590 |
| 591 SkPDFShader::~SkPDFShader() {} |
| 592 |
| 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 { |
| 601 return state == *fShaderState.get(); |
| 602 } |
| 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 } |
| 596 | 612 |
| 597 // static | 613 // static |
| 598 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { | 614 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { |
| 599 SkPDFObject* result; | 615 SkAutoTDelete<State> state(inState); |
| 600 | 616 if (state->fType == SkShader::kNone_GradientType && |
| 601 SkAutoTDelete<State> shaderState(inState); | 617 state->fImage.isNull()) { |
| 602 if (shaderState.get()->fType == SkShader::kNone_GradientType && | |
| 603 shaderState.get()->fImage.isNull()) { | |
| 604 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 618 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
| 605 // handle compose shader by pulling things up to a layer, drawing with | 619 // handle compose shader by pulling things up to a layer, drawing with |
| 606 // the first shader, applying the xfer mode and drawing again with the | 620 // the first shader, applying the xfer mode and drawing again with the |
| 607 // second shader, then applying the layer to the original drawing. | 621 // second shader, then applying the layer to the original drawing. |
| 608 return NULL; | 622 return NULL; |
| 609 } | 623 } |
| 610 | 624 |
| 611 ShaderCanonicalEntry entry(NULL, shaderState.get()); | 625 SkPDFShader* pdfShader = SkPDFCanon::GetCanon().findShader(*state); |
| 612 int index = CanonicalShaders().find(entry); | 626 if (pdfShader) { |
| 613 if (index >= 0) { | 627 SkASSERT(pdfShader->isValid()); |
| 614 result = CanonicalShaders()[index].fPDFShader; | 628 return SkRef(pdfShader->toPDFObject()); |
| 615 result->ref(); | |
| 616 return result; | |
| 617 } | 629 } |
| 618 | 630 |
| 619 bool valid = false; | |
| 620 // The PDFShader takes ownership of the shaderSate. | 631 // The PDFShader takes ownership of the shaderSate. |
| 621 if (shaderState.get()->fType == SkShader::kNone_GradientType) { | 632 if (state->fType == SkShader::kNone_GradientType) { |
| 622 SkPDFImageShader* imageShader = | 633 return SkPDFShader::AddToCanonIfValid( |
| 623 new SkPDFImageShader(shaderState.detach()); | 634 SkNEW_ARGS(SkPDFImageShader, (state.detach()))); |
| 624 valid = imageShader->isValid(); | 635 } else if (state->GradientHasAlpha()) { |
| 625 result = imageShader; | 636 return SkPDFShader::AddToCanonIfValid( |
| 637 SkNEW_ARGS(SkPDFAlphaFunctionShader, (state.detach()))); |
| 626 } else { | 638 } else { |
| 627 if (shaderState.get()->GradientHasAlpha()) { | 639 return SkPDFShader::AddToCanonIfValid( |
| 628 SkPDFAlphaFunctionShader* gradientShader = | 640 SkNEW_ARGS(SkPDFFunctionShader, (state.detach()))); |
| 629 SkNEW_ARGS(SkPDFAlphaFunctionShader, (shaderState.detach())); | |
| 630 valid = gradientShader->isValid(); | |
| 631 result = gradientShader; | |
| 632 } else { | |
| 633 SkPDFFunctionShader* functionShader = | |
| 634 SkNEW_ARGS(SkPDFFunctionShader, (shaderState.detach())); | |
| 635 valid = functionShader->isValid(); | |
| 636 result = functionShader; | |
| 637 } | |
| 638 } | 641 } |
| 639 if (!valid) { | |
| 640 delete result; | |
| 641 return NULL; | |
| 642 } | |
| 643 entry.fPDFShader = result; | |
| 644 CanonicalShaders().push(entry); | |
| 645 return result; // return the reference that came from new. | |
| 646 } | 642 } |
| 647 | 643 |
| 648 // static | 644 // static |
| 649 void SkPDFShader::RemoveShader(SkPDFObject* shader) { | |
| 650 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | |
| 651 ShaderCanonicalEntry entry(shader, NULL); | |
| 652 int index = CanonicalShaders().find(entry); | |
| 653 SkASSERT(index >= 0); | |
| 654 CanonicalShaders().removeShuffle(index); | |
| 655 } | |
| 656 | |
| 657 // static | |
| 658 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, | 645 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, |
| 659 const SkMatrix& matrix, | 646 const SkMatrix& matrix, |
| 660 const SkIRect& surfaceBBox, | 647 const SkIRect& surfaceBBox, |
| 661 SkScalar rasterScale) { | 648 SkScalar rasterScale) { |
| 662 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | 649 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
| 663 return GetPDFShaderByState( | 650 return GetPDFShaderByState( |
| 664 SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale))); | 651 SkNEW_ARGS(State, (shader, matrix, surfaceBBox, rasterScale))); |
| 665 } | 652 } |
| 666 | 653 |
| 667 // static | |
| 668 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { | |
| 669 SkPDFShader::CanonicalShadersMutex().assertHeld(); | |
| 670 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; | |
| 671 return gCanonicalShaders; | |
| 672 } | |
| 673 | |
| 674 SK_DECLARE_STATIC_MUTEX(gCanonicalShadersMutex); | |
| 675 // static | |
| 676 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { | |
| 677 return gCanonicalShadersMutex; | |
| 678 } | |
| 679 | 654 |
| 680 // static | 655 // static |
| 681 SkPDFObject* SkPDFFunctionShader::RangeObject() { | 656 SkPDFObject* SkPDFFunctionShader::RangeObject() { |
| 682 SkPDFShader::CanonicalShadersMutex().assertHeld(); | 657 SkPDFCanon::GetShaderMutex().assertHeld(); |
| 683 static SkPDFArray* range = NULL; | 658 static SkPDFArray* range = NULL; |
| 684 // This method is only used with CanonicalShadersMutex, so it's safe to | 659 // This method is only used with CanonicalShadersMutex, so it's safe to |
| 685 // populate domain. | 660 // populate domain. |
| 686 if (range == NULL) { | 661 if (range == NULL) { |
| 687 range = new SkPDFArray; | 662 range = new SkPDFArray; |
| 688 range->reserve(6); | 663 range->reserve(6); |
| 689 range->appendInt(0); | 664 range->appendInt(0); |
| 690 range->appendInt(1); | 665 range->appendInt(1); |
| 691 range->appendInt(0); | 666 range->appendInt(0); |
| 692 range->appendInt(1); | 667 range->appendInt(1); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 | 725 |
| 751 return content.detachAsStream(); | 726 return content.detachAsStream(); |
| 752 } | 727 } |
| 753 | 728 |
| 754 /** | 729 /** |
| 755 * Creates a ExtGState with the SMask set to the luminosityShader in | 730 * Creates a ExtGState with the SMask set to the luminosityShader in |
| 756 * luminosity mode. The shader pattern extends to the bbox. | 731 * luminosity mode. The shader pattern extends to the bbox. |
| 757 */ | 732 */ |
| 758 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { | 733 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { |
| 759 SkRect bbox; | 734 SkRect bbox; |
| 760 bbox.set(fState.get()->fBBox); | 735 bbox.set(fShaderState->fBBox); |
| 761 | 736 |
| 762 SkAutoTUnref<SkPDFObject> luminosityShader( | 737 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState( |
| 763 SkPDFShader::GetPDFShaderByState( | 738 fShaderState->CreateAlphaToLuminosityState())); |
| 764 fState->CreateAlphaToLuminosityState())); | |
| 765 | 739 |
| 766 SkAutoTUnref<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); | 740 SkAutoTUnref<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); |
| 767 | 741 |
| 768 SkAutoTUnref<SkPDFResourceDict> | 742 SkAutoTUnref<SkPDFResourceDict> |
| 769 resources(get_gradient_resource_dict(luminosityShader, NULL)); | 743 resources(get_gradient_resource_dict(luminosityShader, NULL)); |
| 770 | 744 |
| 771 SkAutoTUnref<SkPDFFormXObject> alphaMask( | 745 SkAutoTUnref<SkPDFFormXObject> alphaMask( |
| 772 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); | 746 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); |
| 773 | 747 |
| 774 return SkPDFGraphicState::GetSMaskGraphicState( | 748 return SkPDFGraphicState::GetSMaskGraphicState( |
| 775 alphaMask.get(), false, | 749 alphaMask.get(), false, |
| 776 SkPDFGraphicState::kLuminosity_SMaskMode); | 750 SkPDFGraphicState::kLuminosity_SMaskMode); |
| 777 } | 751 } |
| 778 | 752 |
| 779 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) | 753 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) |
| 780 : fState(state) { | 754 : SkPDFShader(state) { |
| 781 SkRect bbox; | 755 SkRect bbox; |
| 782 bbox.set(fState.get()->fBBox); | 756 bbox.set(fShaderState->fBBox); |
| 783 | 757 |
| 784 fColorShader.reset( | 758 fColorShader.reset( |
| 785 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); | 759 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); |
| 786 | 760 |
| 787 // Create resource dict with alpha graphics state as G0 and | 761 // Create resource dict with alpha graphics state as G0 and |
| 788 // pattern shader as P0, then write content stream. | 762 // pattern shader as P0, then write content stream. |
| 789 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); | 763 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); |
| 790 fResourceDict.reset( | 764 fResourceDict.reset( |
| 791 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); | 765 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); |
| 792 | 766 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 -p0/p2, -p1/p2, 1/p2); | 804 -p0/p2, -p1/p2, 1/p2); |
| 831 | 805 |
| 832 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2, | 806 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2, |
| 833 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2, | 807 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2, |
| 834 zero, zero, one); | 808 zero, zero, one); |
| 835 | 809 |
| 836 return true; | 810 return true; |
| 837 } | 811 } |
| 838 | 812 |
| 839 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) | 813 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) |
| 840 : SkPDFDict("Pattern"), | 814 : SkPDFDict("Pattern"), SkPDFShader(state) { |
| 841 fState(state) { | |
| 842 SkString (*codeFunction)(const SkShader::GradientInfo& info, | 815 SkString (*codeFunction)(const SkShader::GradientInfo& info, |
| 843 const SkMatrix& perspectiveRemover) = NULL; | 816 const SkMatrix& perspectiveRemover) = NULL; |
| 844 SkPoint transformPoints[2]; | 817 SkPoint transformPoints[2]; |
| 845 | 818 |
| 846 // Depending on the type of the gradient, we want to transform the | 819 // Depending on the type of the gradient, we want to transform the |
| 847 // coordinate space in different ways. | 820 // coordinate space in different ways. |
| 848 const SkShader::GradientInfo* info = &fState.get()->fInfo; | 821 const SkShader::GradientInfo* info = &fShaderState->fInfo; |
| 849 transformPoints[0] = info->fPoint[0]; | 822 transformPoints[0] = info->fPoint[0]; |
| 850 transformPoints[1] = info->fPoint[1]; | 823 transformPoints[1] = info->fPoint[1]; |
| 851 switch (fState.get()->fType) { | 824 switch (fShaderState->fType) { |
| 852 case SkShader::kLinear_GradientType: | 825 case SkShader::kLinear_GradientType: |
| 853 codeFunction = &linearCode; | 826 codeFunction = &linearCode; |
| 854 break; | 827 break; |
| 855 case SkShader::kRadial_GradientType: | 828 case SkShader::kRadial_GradientType: |
| 856 transformPoints[1] = transformPoints[0]; | 829 transformPoints[1] = transformPoints[0]; |
| 857 transformPoints[1].fX += info->fRadius[0]; | 830 transformPoints[1].fX += info->fRadius[0]; |
| 858 codeFunction = &radialCode; | 831 codeFunction = &radialCode; |
| 859 break; | 832 break; |
| 860 case SkShader::kRadial2_GradientType: { | 833 case SkShader::kRadial2_GradientType: { |
| 861 // Bail out if the radii are the same. Empty fResources signals | 834 // Bail out if the radii are the same. Empty fResources signals |
| (...skipping 24 matching lines...) Expand all Loading... |
| 886 return; | 859 return; |
| 887 } | 860 } |
| 888 | 861 |
| 889 // Move any scaling (assuming a unit gradient) or translation | 862 // Move any scaling (assuming a unit gradient) or translation |
| 890 // (and rotation for linear gradient), of the final gradient from | 863 // (and rotation for linear gradient), of the final gradient from |
| 891 // info->fPoints to the matrix (updating bbox appropriately). Now | 864 // info->fPoints to the matrix (updating bbox appropriately). Now |
| 892 // the gradient can be drawn on on the unit segment. | 865 // the gradient can be drawn on on the unit segment. |
| 893 SkMatrix mapperMatrix; | 866 SkMatrix mapperMatrix; |
| 894 unitToPointsMatrix(transformPoints, &mapperMatrix); | 867 unitToPointsMatrix(transformPoints, &mapperMatrix); |
| 895 | 868 |
| 896 SkMatrix finalMatrix = fState.get()->fCanvasTransform; | 869 SkMatrix finalMatrix = fShaderState->fCanvasTransform; |
| 897 finalMatrix.preConcat(fState.get()->fShaderTransform); | 870 finalMatrix.preConcat(fShaderState->fShaderTransform); |
| 898 finalMatrix.preConcat(mapperMatrix); | 871 finalMatrix.preConcat(mapperMatrix); |
| 899 | 872 |
| 900 // Preserves as much as posible in the final matrix, and only removes | 873 // Preserves as much as posible in the final matrix, and only removes |
| 901 // the perspective. The inverse of the perspective is stored in | 874 // the perspective. The inverse of the perspective is stored in |
| 902 // perspectiveInverseOnly matrix and has 3 useful numbers | 875 // perspectiveInverseOnly matrix and has 3 useful numbers |
| 903 // (p0, p1, p2), while everything else is either 0 or 1. | 876 // (p0, p1, p2), while everything else is either 0 or 1. |
| 904 // In this way the shader will handle it eficiently, with minimal code. | 877 // In this way the shader will handle it eficiently, with minimal code. |
| 905 SkMatrix perspectiveInverseOnly = SkMatrix::I(); | 878 SkMatrix perspectiveInverseOnly = SkMatrix::I(); |
| 906 if (finalMatrix.hasPerspective()) { | 879 if (finalMatrix.hasPerspective()) { |
| 907 if (!split_perspective(finalMatrix, | 880 if (!split_perspective(finalMatrix, |
| 908 &finalMatrix, &perspectiveInverseOnly)) { | 881 &finalMatrix, &perspectiveInverseOnly)) { |
| 909 return; | 882 return; |
| 910 } | 883 } |
| 911 } | 884 } |
| 912 | 885 |
| 913 SkRect bbox; | 886 SkRect bbox; |
| 914 bbox.set(fState.get()->fBBox); | 887 bbox.set(fShaderState->fBBox); |
| 915 if (!inverseTransformBBox(finalMatrix, &bbox)) { | 888 if (!inverseTransformBBox(finalMatrix, &bbox)) { |
| 916 return; | 889 return; |
| 917 } | 890 } |
| 918 | 891 |
| 919 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); | 892 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); |
| 920 domain->reserve(4); | 893 domain->reserve(4); |
| 921 domain->appendScalar(bbox.fLeft); | 894 domain->appendScalar(bbox.fLeft); |
| 922 domain->appendScalar(bbox.fRight); | 895 domain->appendScalar(bbox.fRight); |
| 923 domain->appendScalar(bbox.fTop); | 896 domain->appendScalar(bbox.fTop); |
| 924 domain->appendScalar(bbox.fBottom); | 897 domain->appendScalar(bbox.fBottom); |
| 925 | 898 |
| 926 SkString functionCode; | 899 SkString functionCode; |
| 927 // The two point radial gradient further references fState.get()->fInfo | 900 // The two point radial gradient further references |
| 901 // fShaderState->fInfo |
| 928 // in translating from x, y coordinates to the t parameter. So, we have | 902 // in translating from x, y coordinates to the t parameter. So, we have |
| 929 // to transform the points and radii according to the calculated matrix. | 903 // to transform the points and radii according to the calculated matrix. |
| 930 if (fState.get()->fType == SkShader::kRadial2_GradientType) { | 904 if (fShaderState->fType == SkShader::kRadial2_GradientType) { |
| 931 SkShader::GradientInfo twoPointRadialInfo = *info; | 905 SkShader::GradientInfo twoPointRadialInfo = *info; |
| 932 SkMatrix inverseMapperMatrix; | 906 SkMatrix inverseMapperMatrix; |
| 933 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | 907 if (!mapperMatrix.invert(&inverseMapperMatrix)) { |
| 934 return; | 908 return; |
| 935 } | 909 } |
| 936 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | 910 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); |
| 937 twoPointRadialInfo.fRadius[0] = | 911 twoPointRadialInfo.fRadius[0] = |
| 938 inverseMapperMatrix.mapRadius(info->fRadius[0]); | 912 inverseMapperMatrix.mapRadius(info->fRadius[0]); |
| 939 twoPointRadialInfo.fRadius[1] = | 913 twoPointRadialInfo.fRadius[1] = |
| 940 inverseMapperMatrix.mapRadius(info->fRadius[1]); | 914 inverseMapperMatrix.mapRadius(info->fRadius[1]); |
| 941 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); | 915 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); |
| 942 } else { | 916 } else { |
| 943 functionCode = codeFunction(*info, perspectiveInverseOnly); | 917 functionCode = codeFunction(*info, perspectiveInverseOnly); |
| 944 } | 918 } |
| 945 | 919 |
| 946 SkAutoTUnref<SkPDFDict> pdfShader(new SkPDFDict); | 920 SkAutoTUnref<SkPDFDict> pdfShader(new SkPDFDict); |
| 947 pdfShader->insertInt("ShadingType", 1); | 921 pdfShader->insertInt("ShadingType", 1); |
| 948 pdfShader->insertName("ColorSpace", "DeviceRGB"); | 922 pdfShader->insertName("ColorSpace", "DeviceRGB"); |
| 949 pdfShader->insert("Domain", domain.get()); | 923 pdfShader->insert("Domain", domain.get()); |
| 950 | 924 |
| 951 SkPDFStream* function = makePSFunction(functionCode, domain.get()); | 925 SkPDFStream* function = makePSFunction(functionCode, domain.get()); |
| 952 pdfShader->insert("Function", new SkPDFObjRef(function))->unref(); | 926 pdfShader->insert("Function", new SkPDFObjRef(function))->unref(); |
| 953 fResources.push(function); // Pass ownership to resource list. | 927 fResources.push(function); // Pass ownership to resource list. |
| 954 | 928 |
| 955 insertInt("PatternType", 2); | 929 insertInt("PatternType", 2); |
| 956 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); | 930 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); |
| 957 insert("Shading", pdfShader.get()); | 931 insert("Shading", pdfShader.get()); |
| 958 } | 932 } |
| 959 | 933 |
| 960 SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { | 934 SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) |
| 961 fState.get()->fImage.lockPixels(); | 935 : SkPDFShader(state) { |
| 936 fShaderState->fImage.lockPixels(); |
| 962 | 937 |
| 963 // The image shader pattern cell will be drawn into a separate device | 938 // The image shader pattern cell will be drawn into a separate device |
| 964 // in pattern cell space (no scaling on the bitmap, though there may be | 939 // in pattern cell space (no scaling on the bitmap, though there may be |
| 965 // translations so that all content is in the device, coordinates > 0). | 940 // translations so that all content is in the device, coordinates > 0). |
| 966 | 941 |
| 967 // Map clip bounds to shader space to ensure the device is large enough | 942 // Map clip bounds to shader space to ensure the device is large enough |
| 968 // to handle fake clamping. | 943 // to handle fake clamping. |
| 969 SkMatrix finalMatrix = fState.get()->fCanvasTransform; | 944 SkMatrix finalMatrix = fShaderState->fCanvasTransform; |
| 970 finalMatrix.preConcat(fState.get()->fShaderTransform); | 945 finalMatrix.preConcat(fShaderState->fShaderTransform); |
| 971 SkRect deviceBounds; | 946 SkRect deviceBounds; |
| 972 deviceBounds.set(fState.get()->fBBox); | 947 deviceBounds.set(fShaderState->fBBox); |
| 973 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) { | 948 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) { |
| 974 return; | 949 return; |
| 975 } | 950 } |
| 976 | 951 |
| 977 const SkBitmap* image = &fState.get()->fImage; | 952 const SkBitmap* image = &fShaderState->fImage; |
| 978 SkRect bitmapBounds; | 953 SkRect bitmapBounds; |
| 979 image->getBounds(&bitmapBounds); | 954 image->getBounds(&bitmapBounds); |
| 980 | 955 |
| 981 // For tiling modes, the bounds should be extended to include the bitmap, | 956 // For tiling modes, the bounds should be extended to include the bitmap, |
| 982 // otherwise the bitmap gets clipped out and the shader is empty and awful. | 957 // otherwise the bitmap gets clipped out and the shader is empty and awful. |
| 983 // For clamp modes, we're only interested in the clip region, whether | 958 // For clamp modes, we're only interested in the clip region, whether |
| 984 // or not the main bitmap is in it. | 959 // or not the main bitmap is in it. |
| 985 SkShader::TileMode tileModes[2]; | 960 SkShader::TileMode tileModes[2]; |
| 986 tileModes[0] = fState.get()->fImageTileModes[0]; | 961 tileModes[0] = fShaderState->fImageTileModes[0]; |
| 987 tileModes[1] = fState.get()->fImageTileModes[1]; | 962 tileModes[1] = fShaderState->fImageTileModes[1]; |
| 988 if (tileModes[0] != SkShader::kClamp_TileMode || | 963 if (tileModes[0] != SkShader::kClamp_TileMode || |
| 989 tileModes[1] != SkShader::kClamp_TileMode) { | 964 tileModes[1] != SkShader::kClamp_TileMode) { |
| 990 deviceBounds.join(bitmapBounds); | 965 deviceBounds.join(bitmapBounds); |
| 991 } | 966 } |
| 992 | 967 |
| 993 SkMatrix unflip; | 968 SkMatrix unflip; |
| 994 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height())); | 969 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height())); |
| 995 unflip.preScale(SK_Scalar1, -SK_Scalar1); | 970 unflip.preScale(SK_Scalar1, -SK_Scalar1); |
| 996 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), | 971 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), |
| 997 SkScalarRoundToInt(deviceBounds.height())); | 972 SkScalarRoundToInt(deviceBounds.height())); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 | 1132 |
| 1158 // Put the canvas into the pattern stream (fContent). | 1133 // Put the canvas into the pattern stream (fContent). |
| 1159 SkAutoTUnref<SkStream> content(pattern.content()); | 1134 SkAutoTUnref<SkStream> content(pattern.content()); |
| 1160 setData(content.get()); | 1135 setData(content.get()); |
| 1161 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); | 1136 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); |
| 1162 resourceDict->getReferencedResources(fResources, &fResources, false); | 1137 resourceDict->getReferencedResources(fResources, &fResources, false); |
| 1163 | 1138 |
| 1164 populate_tiling_pattern_dict(this, patternBBox, | 1139 populate_tiling_pattern_dict(this, patternBBox, |
| 1165 pattern.getResourceDict(), finalMatrix); | 1140 pattern.getResourceDict(), finalMatrix); |
| 1166 | 1141 |
| 1167 fState.get()->fImage.unlockPixels(); | 1142 fShaderState->fImage.unlockPixels(); |
| 1168 } | 1143 } |
| 1169 | 1144 |
| 1170 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFAr
ray* domain) { | 1145 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFAr
ray* domain) { |
| 1171 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), psCode.size()))
; | 1146 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), psCode.size()))
; |
| 1172 SkPDFStream* result = new SkPDFStream(funcData.get()); | 1147 SkPDFStream* result = new SkPDFStream(funcData.get()); |
| 1173 result->insertInt("FunctionType", 4); | 1148 result->insertInt("FunctionType", 4); |
| 1174 result->insert("Domain", domain); | 1149 result->insert("Domain", domain); |
| 1175 result->insert("Range", RangeObject()); | 1150 result->insert("Range", RangeObject()); |
| 1176 return result; | 1151 return result; |
| 1177 } | 1152 } |
| 1178 | 1153 |
| 1179 SkPDFShader::ShaderCanonicalEntry::ShaderCanonicalEntry(SkPDFObject* pdfShader,
const State* state) | |
| 1180 : fPDFShader(pdfShader) | |
| 1181 , fState(state) | |
| 1182 {} | |
| 1183 | |
| 1184 bool SkPDFShader::ShaderCanonicalEntry::operator==(const ShaderCanonicalEntry& b
) const { | |
| 1185 return fPDFShader == b.fPDFShader || | |
| 1186 (fState != NULL && b.fState != NULL && *fState == *b.fState); | |
| 1187 } | |
| 1188 | |
| 1189 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { | 1154 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { |
| 1190 if (fType != b.fType || | 1155 if (fType != b.fType || |
| 1191 fCanvasTransform != b.fCanvasTransform || | 1156 fCanvasTransform != b.fCanvasTransform || |
| 1192 fShaderTransform != b.fShaderTransform || | 1157 fShaderTransform != b.fShaderTransform || |
| 1193 fBBox != b.fBBox) { | 1158 fBBox != b.fBBox) { |
| 1194 return false; | 1159 return false; |
| 1195 } | 1160 } |
| 1196 | 1161 |
| 1197 if (fType == SkShader::kNone_GradientType) { | 1162 if (fType == SkShader::kNone_GradientType) { |
| 1198 if (fPixelGeneration != b.fPixelGeneration || | 1163 if (fPixelGeneration != b.fPixelGeneration || |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 return false; | 1334 return false; |
| 1370 } | 1335 } |
| 1371 | 1336 |
| 1372 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1337 void SkPDFShader::State::AllocateGradientInfoStorage() { |
| 1373 fColorData.set(sk_malloc_throw( | 1338 fColorData.set(sk_malloc_throw( |
| 1374 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1339 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
| 1375 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1340 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
| 1376 fInfo.fColorOffsets = | 1341 fInfo.fColorOffsets = |
| 1377 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | 1342 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
| 1378 } | 1343 } |
| OLD | NEW |