Chromium Code Reviews| 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" |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |