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" |
| 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 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 function.append("}"); | 469 function.append("}"); |
| 469 return function; | 470 return function; |
| 470 } | 471 } |
| 471 | 472 |
| 472 static void drawBitmapMatrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatri x& matrix) { | 473 static void drawBitmapMatrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatri x& matrix) { |
| 473 SkAutoCanvasRestore acr(canvas, true); | 474 SkAutoCanvasRestore acr(canvas, true); |
| 474 canvas->concat(matrix); | 475 canvas->concat(matrix); |
| 475 canvas->drawBitmap(bm, 0, 0); | 476 canvas->drawBitmap(bm, 0, 0); |
| 476 } | 477 } |
| 477 | 478 |
| 478 class SkPDFShader::State { | 479 class SkPDFShaderState { |
| 479 public: | 480 public: |
| 480 SkShader::GradientType fType; | 481 SkShader::GradientType fType; |
| 481 SkShader::GradientInfo fInfo; | 482 SkShader::GradientInfo fInfo; |
| 482 SkAutoFree fColorData; // This provides storage for arrays in fInfo. | 483 SkAutoFree fColorData; // This provides storage for arrays in fInfo. |
| 483 SkMatrix fCanvasTransform; | 484 SkMatrix fCanvasTransform; |
| 484 SkMatrix fShaderTransform; | 485 SkMatrix fShaderTransform; |
| 485 SkIRect fBBox; | 486 SkIRect fBBox; |
| 486 | 487 |
| 487 SkBitmap fImage; | 488 SkBitmap fImage; |
| 488 uint32_t fPixelGeneration; | 489 uint32_t fPixelGeneration; |
| 489 SkShader::TileMode fImageTileModes[2]; | 490 SkShader::TileMode fImageTileModes[2]; |
| 490 | 491 |
| 491 State(const SkShader& shader, const SkMatrix& canvasTransform, | 492 SkPDFShaderState(const SkShader& shader, |
| 492 const SkIRect& bbox); | 493 const SkMatrix& canvasTransform, |
| 494 const SkIRect& bbox); | |
| 493 | 495 |
| 494 bool operator==(const State& b) const; | 496 bool operator==(const SkPDFShaderState& b) const; |
| 495 | 497 |
| 496 SkPDFShader::State* CreateAlphaToLuminosityState() const; | 498 SkPDFShaderState* CreateAlphaToLuminosityState() const; |
| 497 SkPDFShader::State* CreateOpaqueState() const; | 499 SkPDFShaderState* CreateOpaqueState() const; |
| 498 | 500 |
| 499 bool GradientHasAlpha() const; | 501 bool GradientHasAlpha() const; |
| 500 | 502 |
| 501 private: | 503 private: |
| 502 State(const State& other); | 504 SkPDFShaderState(const SkPDFShaderState& other); |
| 503 State operator=(const State& rhs); | 505 SkPDFShaderState operator=(const SkPDFShaderState& rhs); |
| 504 void AllocateGradientInfoStorage(); | 506 void AllocateGradientInfoStorage(); |
| 505 }; | 507 }; |
| 506 | 508 |
| 507 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { | 509 class SkPDFFunctionShader : public SkPDFDict, public SkPDFShader { |
| 508 SK_DECLARE_INST_COUNT(SkPDFFunctionShader) | 510 SK_DECLARE_INST_COUNT(SkPDFFunctionShader) |
| 509 public: | 511 public: |
| 510 explicit SkPDFFunctionShader(SkPDFShader::State* state); | 512 explicit SkPDFFunctionShader(SkPDFShaderState* state); |
| 511 virtual ~SkPDFFunctionShader() { | 513 virtual ~SkPDFFunctionShader() { |
| 512 if (isValid()) { | 514 if (isValid()) { |
| 513 RemoveShader(this); | 515 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
| 516 SkPDFCanon::GetCanon().removeShader(this); | |
| 514 } | 517 } |
| 515 fResources.unrefAll(); | 518 fResources.unrefAll(); |
| 516 } | 519 } |
| 517 | 520 |
| 518 bool isValid() SK_OVERRIDE { return fResources.count() > 0; } | 521 bool isValid() SK_OVERRIDE { return fResources.count() > 0; } |
| 519 | 522 |
| 523 virtual SkPDFObject* toPDFObject() SK_OVERRIDE { | |
| 524 return this; | |
| 525 } | |
| 526 | |
| 520 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 527 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 521 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { | 528 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
| 522 GetResourcesHelper(&fResources, | 529 GetResourcesHelper(&fResources, |
| 523 knownResourceObjects, | 530 knownResourceObjects, |
| 524 newResourceObjects); | 531 newResourceObjects); |
| 525 } | 532 } |
| 526 | 533 |
| 527 private: | 534 private: |
| 528 static SkPDFObject* RangeObject(); | 535 static SkPDFObject* RangeObject(); |
| 529 | 536 |
| 530 SkTDArray<SkPDFObject*> fResources; | 537 SkTDArray<SkPDFObject*> fResources; |
| 531 SkAutoTDelete<const SkPDFShader::State> fState; | |
| 532 | 538 |
| 533 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); | 539 SkPDFStream* makePSFunction(const SkString& psCode, SkPDFArray* domain); |
| 534 typedef SkPDFDict INHERITED; | 540 typedef SkPDFDict INHERITED; |
| 535 }; | 541 }; |
| 536 | 542 |
| 537 /** | 543 /** |
| 538 * A shader for PDF gradients. This encapsulates the function shader | 544 * A shader for PDF gradients. This encapsulates the function shader |
| 539 * inside a tiling pattern while providing a common pattern interface. | 545 * inside a tiling pattern while providing a common pattern interface. |
| 540 * The encapsulation allows the use of a SMask for transparency gradients. | 546 * The encapsulation allows the use of a SMask for transparency gradients. |
| 541 */ | 547 */ |
| 542 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { | 548 class SkPDFAlphaFunctionShader : public SkPDFStream, public SkPDFShader { |
| 543 public: | 549 public: |
| 544 explicit SkPDFAlphaFunctionShader(SkPDFShader::State* state); | 550 explicit SkPDFAlphaFunctionShader(SkPDFShaderState* state); |
| 545 virtual ~SkPDFAlphaFunctionShader() { | 551 virtual ~SkPDFAlphaFunctionShader() { |
| 546 if (isValid()) { | 552 if (isValid()) { |
| 547 RemoveShader(this); | 553 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
| 554 SkPDFCanon::GetCanon().removeShader(this); | |
| 548 } | 555 } |
| 549 } | 556 } |
| 550 | 557 |
| 551 bool isValid() SK_OVERRIDE { | 558 bool isValid() SK_OVERRIDE { |
| 552 return fColorShader.get() != NULL; | 559 return fColorShader.get() != NULL; |
| 553 } | 560 } |
| 554 | 561 |
| 562 virtual SkPDFObject* toPDFObject() SK_OVERRIDE { | |
| 563 return this; | |
| 564 } | |
| 565 | |
| 555 private: | 566 private: |
| 556 SkAutoTDelete<const SkPDFShader::State> fState; | |
| 557 | |
| 558 SkPDFGraphicState* CreateSMaskGraphicState(); | 567 SkPDFGraphicState* CreateSMaskGraphicState(); |
| 559 | 568 |
| 560 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 569 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 561 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { | 570 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
| 562 fResourceDict->getReferencedResources(knownResourceObjects, | 571 fResourceDict->getReferencedResources(knownResourceObjects, |
| 563 newResourceObjects, | 572 newResourceObjects, |
| 564 true); | 573 true); |
| 565 } | 574 } |
| 566 | 575 |
| 567 SkAutoTUnref<SkPDFObject> fColorShader; | 576 SkAutoTUnref<SkPDFObject> fColorShader; |
| 568 SkAutoTUnref<SkPDFResourceDict> fResourceDict; | 577 SkAutoTUnref<SkPDFResourceDict> fResourceDict; |
| 569 }; | 578 }; |
| 570 | 579 |
| 571 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { | 580 class SkPDFImageShader : public SkPDFStream, public SkPDFShader { |
| 572 public: | 581 public: |
| 573 explicit SkPDFImageShader(SkPDFShader::State* state); | 582 explicit SkPDFImageShader(SkPDFShaderState* state); |
| 574 virtual ~SkPDFImageShader() { | 583 virtual ~SkPDFImageShader() { |
| 575 if (isValid()) { | 584 if (isValid()) { |
| 576 RemoveShader(this); | 585 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
| 586 SkPDFCanon::GetCanon().removeShader(this); | |
| 577 } | 587 } |
| 578 fResources.unrefAll(); | 588 fResources.unrefAll(); |
| 579 } | 589 } |
| 580 | 590 |
| 581 bool isValid() SK_OVERRIDE { return size() > 0; } | 591 bool isValid() SK_OVERRIDE { return size() > 0; } |
| 582 | 592 |
| 593 virtual SkPDFObject* toPDFObject() SK_OVERRIDE { | |
| 594 return this; | |
| 595 } | |
| 596 | |
| 583 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, | 597 void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, |
| 584 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { | 598 SkTSet<SkPDFObject*>* newResourceObjects) SK_OVERRIDE { |
| 585 GetResourcesHelper(&fResources.toArray(), | 599 GetResourcesHelper(&fResources.toArray(), |
| 586 knownResourceObjects, | 600 knownResourceObjects, |
| 587 newResourceObjects); | 601 newResourceObjects); |
| 588 } | 602 } |
| 589 | 603 |
| 590 private: | 604 private: |
| 591 SkTSet<SkPDFObject*> fResources; | 605 SkTSet<SkPDFObject*> fResources; |
| 592 SkAutoTDelete<const SkPDFShader::State> fState; | |
| 593 }; | 606 }; |
| 594 | 607 |
| 595 SkPDFShader::SkPDFShader() {} | 608 SkPDFShader::SkPDFShader(const SkPDFShaderState* state) |
| 609 : fPDFShaderState(state) { | |
| 610 } | |
| 611 | |
| 612 SkPDFShader::~SkPDFShader() { | |
| 613 } | |
| 614 | |
| 615 bool SkPDFShader::equals(const SkPDFShaderState& state) const { | |
| 616 return state == this->pdfShaderState(); | |
| 617 } | |
| 618 | |
| 619 const SkPDFShaderState& SkPDFShader::pdfShaderState() const { | |
| 620 return *fPDFShaderState; | |
| 621 } | |
| 596 | 622 |
| 597 // static | 623 // static |
| 598 SkPDFObject* SkPDFShader::GetPDFShaderByState(State* inState) { | 624 SkPDFObject* SkPDFShader::GetPDFShaderByState(SkPDFShaderState* inState) { |
| 599 SkPDFObject* result; | 625 SkAutoTDelete<SkPDFShaderState> shaderState(inState); |
| 600 | |
| 601 SkAutoTDelete<State> shaderState(inState); | |
| 602 if (shaderState.get()->fType == SkShader::kNone_GradientType && | 626 if (shaderState.get()->fType == SkShader::kNone_GradientType && |
| 603 shaderState.get()->fImage.isNull()) { | 627 shaderState.get()->fImage.isNull()) { |
| 604 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 628 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
| 605 // handle compose shader by pulling things up to a layer, drawing with | 629 // 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 | 630 // the first shader, applying the xfer mode and drawing again with the |
| 607 // second shader, then applying the layer to the original drawing. | 631 // second shader, then applying the layer to the original drawing. |
| 608 return NULL; | 632 return NULL; |
| 609 } | 633 } |
| 610 | 634 |
| 611 ShaderCanonicalEntry entry(NULL, shaderState.get()); | 635 SkPDFShader* pdfShader = SkPDFCanon::GetCanon().findShader(*shaderState); |
| 612 int index = CanonicalShaders().find(entry); | 636 if (pdfShader) { |
| 613 if (index >= 0) { | 637 return SkRef(pdfShader->toPDFObject()); |
| 614 result = CanonicalShaders()[index].fPDFShader; | |
| 615 result->ref(); | |
| 616 return result; | |
| 617 } | 638 } |
| 618 | 639 |
| 619 bool valid = false; | |
| 620 // The PDFShader takes ownership of the shaderSate. | 640 // The PDFShader takes ownership of the shaderSate. |
| 621 if (shaderState.get()->fType == SkShader::kNone_GradientType) { | 641 if (shaderState->fType == SkShader::kNone_GradientType) { |
| 622 SkPDFImageShader* imageShader = | 642 SkPDFImageShader* imageShader = |
| 623 new SkPDFImageShader(shaderState.detach()); | 643 new SkPDFImageShader(shaderState.detach()); |
| 624 valid = imageShader->isValid(); | 644 if (imageShader->isValid()) { |
|
mtklein
2015/01/20 21:59:52
Might want to extract this if-else block as add_to
hal.canary
2015/01/21 17:07:51
GREAT idea
| |
| 625 result = imageShader; | 645 SkPDFCanon::GetCanon().addShader(imageShader); |
| 646 return imageShader->toPDFObject(); | |
| 647 } else { | |
| 648 SkDELETE(imageShader); | |
| 649 return NULL; | |
| 650 } | |
| 651 } else if (shaderState->GradientHasAlpha()) { | |
| 652 SkPDFAlphaFunctionShader* gradientShader = | |
| 653 SkNEW_ARGS(SkPDFAlphaFunctionShader, (shaderState.detach())); | |
| 654 if (gradientShader->isValid()) { | |
| 655 SkPDFCanon::GetCanon().addShader(gradientShader); | |
| 656 return gradientShader->toPDFObject(); | |
| 657 } else { | |
| 658 SkDELETE(gradientShader); | |
| 659 return NULL; | |
| 660 } | |
| 626 } else { | 661 } else { |
| 627 if (shaderState.get()->GradientHasAlpha()) { | 662 SkPDFFunctionShader* functionShader = |
| 628 SkPDFAlphaFunctionShader* gradientShader = | 663 SkNEW_ARGS(SkPDFFunctionShader, (shaderState.detach())); |
| 629 SkNEW_ARGS(SkPDFAlphaFunctionShader, (shaderState.detach())); | 664 if (functionShader->isValid()) { |
| 630 valid = gradientShader->isValid(); | 665 SkPDFCanon::GetCanon().addShader(functionShader); |
| 631 result = gradientShader; | 666 return functionShader->toPDFObject(); |
| 632 } else { | 667 } else { |
| 633 SkPDFFunctionShader* functionShader = | 668 SkDELETE(functionShader); |
| 634 SkNEW_ARGS(SkPDFFunctionShader, (shaderState.detach())); | 669 return NULL; |
| 635 valid = functionShader->isValid(); | |
| 636 result = functionShader; | |
| 637 } | 670 } |
| 638 } | 671 } |
| 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 } | |
| 647 | |
| 648 // 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 } | 672 } |
| 656 | 673 |
| 657 // static | 674 // static |
| 658 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, | 675 SkPDFObject* SkPDFShader::GetPDFShader(const SkShader& shader, |
| 659 const SkMatrix& matrix, | 676 const SkMatrix& matrix, |
| 660 const SkIRect& surfaceBBox) { | 677 const SkIRect& surfaceBBox) { |
| 661 SkAutoMutexAcquire lock(CanonicalShadersMutex()); | 678 SkAutoMutexAcquire lock(SkPDFCanon::GetShaderMutex()); |
| 662 return GetPDFShaderByState( | 679 return GetPDFShaderByState( |
| 663 SkNEW_ARGS(State, (shader, matrix, surfaceBBox))); | 680 SkNEW_ARGS(SkPDFShaderState, (shader, matrix, surfaceBBox))); |
| 664 } | |
| 665 | |
| 666 // static | |
| 667 SkTDArray<SkPDFShader::ShaderCanonicalEntry>& SkPDFShader::CanonicalShaders() { | |
| 668 SkPDFShader::CanonicalShadersMutex().assertHeld(); | |
| 669 static SkTDArray<ShaderCanonicalEntry> gCanonicalShaders; | |
| 670 return gCanonicalShaders; | |
| 671 } | |
| 672 | |
| 673 SK_DECLARE_STATIC_MUTEX(gCanonicalShadersMutex); | |
| 674 // static | |
| 675 SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { | |
| 676 return gCanonicalShadersMutex; | |
| 677 } | 681 } |
| 678 | 682 |
| 679 // static | 683 // static |
| 680 SkPDFObject* SkPDFFunctionShader::RangeObject() { | 684 SkPDFObject* SkPDFFunctionShader::RangeObject() { |
| 681 SkPDFShader::CanonicalShadersMutex().assertHeld(); | 685 SkPDFCanon::GetShaderMutex().assertHeld(); |
| 682 static SkPDFArray* range = NULL; | 686 static SkPDFArray* range = NULL; |
| 683 // This method is only used with CanonicalShadersMutex, so it's safe to | 687 // This method is only used with CanonicalShadersMutex, so it's safe to |
| 684 // populate domain. | 688 // populate domain. |
| 685 if (range == NULL) { | 689 if (range == NULL) { |
| 686 range = new SkPDFArray; | 690 range = new SkPDFArray; |
| 687 range->reserve(6); | 691 range->reserve(6); |
| 688 range->appendInt(0); | 692 range->appendInt(0); |
| 689 range->appendInt(1); | 693 range->appendInt(1); |
| 690 range->appendInt(0); | 694 range->appendInt(0); |
| 691 range->appendInt(1); | 695 range->appendInt(1); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 | 753 |
| 750 return content.detachAsStream(); | 754 return content.detachAsStream(); |
| 751 } | 755 } |
| 752 | 756 |
| 753 /** | 757 /** |
| 754 * Creates a ExtGState with the SMask set to the luminosityShader in | 758 * Creates a ExtGState with the SMask set to the luminosityShader in |
| 755 * luminosity mode. The shader pattern extends to the bbox. | 759 * luminosity mode. The shader pattern extends to the bbox. |
| 756 */ | 760 */ |
| 757 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { | 761 SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { |
| 758 SkRect bbox; | 762 SkRect bbox; |
| 759 bbox.set(fState.get()->fBBox); | 763 bbox.set(this->pdfShaderState().fBBox); |
| 760 | 764 |
| 761 SkAutoTUnref<SkPDFObject> luminosityShader( | 765 SkAutoTUnref<SkPDFObject> luminosityShader(SkPDFShader::GetPDFShaderByState( |
| 762 SkPDFShader::GetPDFShaderByState( | 766 this->pdfShaderState().CreateAlphaToLuminosityState())); |
| 763 fState->CreateAlphaToLuminosityState())); | |
| 764 | 767 |
| 765 SkAutoTUnref<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); | 768 SkAutoTUnref<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); |
| 766 | 769 |
| 767 SkAutoTUnref<SkPDFResourceDict> | 770 SkAutoTUnref<SkPDFResourceDict> |
| 768 resources(get_gradient_resource_dict(luminosityShader, NULL)); | 771 resources(get_gradient_resource_dict(luminosityShader, NULL)); |
| 769 | 772 |
| 770 SkAutoTUnref<SkPDFFormXObject> alphaMask( | 773 SkAutoTUnref<SkPDFFormXObject> alphaMask( |
| 771 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); | 774 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); |
| 772 | 775 |
| 773 return SkPDFGraphicState::GetSMaskGraphicState( | 776 return SkPDFGraphicState::GetSMaskGraphicState( |
| 774 alphaMask.get(), false, | 777 alphaMask.get(), false, |
| 775 SkPDFGraphicState::kLuminosity_SMaskMode); | 778 SkPDFGraphicState::kLuminosity_SMaskMode); |
| 776 } | 779 } |
| 777 | 780 |
| 778 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) | 781 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShaderState* state) |
| 779 : fState(state) { | 782 : SkPDFShader(state) { |
| 780 SkRect bbox; | 783 SkRect bbox; |
| 781 bbox.set(fState.get()->fBBox); | 784 bbox.set(this->pdfShaderState().fBBox); |
| 782 | 785 |
| 783 fColorShader.reset( | 786 fColorShader.reset( |
| 784 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); | 787 SkPDFShader::GetPDFShaderByState(state->CreateOpaqueState())); |
| 785 | 788 |
| 786 // Create resource dict with alpha graphics state as G0 and | 789 // Create resource dict with alpha graphics state as G0 and |
| 787 // pattern shader as P0, then write content stream. | 790 // pattern shader as P0, then write content stream. |
| 788 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); | 791 SkAutoTUnref<SkPDFGraphicState> alphaGs(CreateSMaskGraphicState()); |
| 789 fResourceDict.reset( | 792 fResourceDict.reset( |
| 790 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); | 793 get_gradient_resource_dict(fColorShader.get(), alphaGs.get())); |
| 791 | 794 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 828 zero, one, zero, | 831 zero, one, zero, |
| 829 -p0/p2, -p1/p2, 1/p2); | 832 -p0/p2, -p1/p2, 1/p2); |
| 830 | 833 |
| 831 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2, | 834 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2, |
| 832 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2, | 835 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2, |
| 833 zero, zero, one); | 836 zero, zero, one); |
| 834 | 837 |
| 835 return true; | 838 return true; |
| 836 } | 839 } |
| 837 | 840 |
| 838 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) | 841 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShaderState* state) |
| 839 : SkPDFDict("Pattern"), | 842 : SkPDFDict("Pattern"), SkPDFShader(state) { |
| 840 fState(state) { | |
| 841 SkString (*codeFunction)(const SkShader::GradientInfo& info, | 843 SkString (*codeFunction)(const SkShader::GradientInfo& info, |
| 842 const SkMatrix& perspectiveRemover) = NULL; | 844 const SkMatrix& perspectiveRemover) = NULL; |
| 843 SkPoint transformPoints[2]; | 845 SkPoint transformPoints[2]; |
| 844 | 846 |
| 845 // Depending on the type of the gradient, we want to transform the | 847 // Depending on the type of the gradient, we want to transform the |
| 846 // coordinate space in different ways. | 848 // coordinate space in different ways. |
| 847 const SkShader::GradientInfo* info = &fState.get()->fInfo; | 849 const SkShader::GradientInfo* info = &this->pdfShaderState().fInfo; |
|
mtklein
2015/01/20 21:59:52
Why don't we just write "this->pdfShaderState()" a
hal.canary
2015/01/21 17:07:51
Done.
| |
| 848 transformPoints[0] = info->fPoint[0]; | 850 transformPoints[0] = info->fPoint[0]; |
| 849 transformPoints[1] = info->fPoint[1]; | 851 transformPoints[1] = info->fPoint[1]; |
| 850 switch (fState.get()->fType) { | 852 switch (this->pdfShaderState().fType) { |
| 851 case SkShader::kLinear_GradientType: | 853 case SkShader::kLinear_GradientType: |
| 852 codeFunction = &linearCode; | 854 codeFunction = &linearCode; |
| 853 break; | 855 break; |
| 854 case SkShader::kRadial_GradientType: | 856 case SkShader::kRadial_GradientType: |
| 855 transformPoints[1] = transformPoints[0]; | 857 transformPoints[1] = transformPoints[0]; |
| 856 transformPoints[1].fX += info->fRadius[0]; | 858 transformPoints[1].fX += info->fRadius[0]; |
| 857 codeFunction = &radialCode; | 859 codeFunction = &radialCode; |
| 858 break; | 860 break; |
| 859 case SkShader::kRadial2_GradientType: { | 861 case SkShader::kRadial2_GradientType: { |
| 860 // Bail out if the radii are the same. Empty fResources signals | 862 // Bail out if the radii are the same. Empty fResources signals |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 885 return; | 887 return; |
| 886 } | 888 } |
| 887 | 889 |
| 888 // Move any scaling (assuming a unit gradient) or translation | 890 // Move any scaling (assuming a unit gradient) or translation |
| 889 // (and rotation for linear gradient), of the final gradient from | 891 // (and rotation for linear gradient), of the final gradient from |
| 890 // info->fPoints to the matrix (updating bbox appropriately). Now | 892 // info->fPoints to the matrix (updating bbox appropriately). Now |
| 891 // the gradient can be drawn on on the unit segment. | 893 // the gradient can be drawn on on the unit segment. |
| 892 SkMatrix mapperMatrix; | 894 SkMatrix mapperMatrix; |
| 893 unitToPointsMatrix(transformPoints, &mapperMatrix); | 895 unitToPointsMatrix(transformPoints, &mapperMatrix); |
| 894 | 896 |
| 895 SkMatrix finalMatrix = fState.get()->fCanvasTransform; | 897 SkMatrix finalMatrix = this->pdfShaderState().fCanvasTransform; |
| 896 finalMatrix.preConcat(fState.get()->fShaderTransform); | 898 finalMatrix.preConcat(this->pdfShaderState().fShaderTransform); |
| 897 finalMatrix.preConcat(mapperMatrix); | 899 finalMatrix.preConcat(mapperMatrix); |
| 898 | 900 |
| 899 // Preserves as much as posible in the final matrix, and only removes | 901 // Preserves as much as posible in the final matrix, and only removes |
| 900 // the perspective. The inverse of the perspective is stored in | 902 // the perspective. The inverse of the perspective is stored in |
| 901 // perspectiveInverseOnly matrix and has 3 useful numbers | 903 // perspectiveInverseOnly matrix and has 3 useful numbers |
| 902 // (p0, p1, p2), while everything else is either 0 or 1. | 904 // (p0, p1, p2), while everything else is either 0 or 1. |
| 903 // In this way the shader will handle it eficiently, with minimal code. | 905 // In this way the shader will handle it eficiently, with minimal code. |
| 904 SkMatrix perspectiveInverseOnly = SkMatrix::I(); | 906 SkMatrix perspectiveInverseOnly = SkMatrix::I(); |
| 905 if (finalMatrix.hasPerspective()) { | 907 if (finalMatrix.hasPerspective()) { |
| 906 if (!split_perspective(finalMatrix, | 908 if (!split_perspective(finalMatrix, |
| 907 &finalMatrix, &perspectiveInverseOnly)) { | 909 &finalMatrix, &perspectiveInverseOnly)) { |
| 908 return; | 910 return; |
| 909 } | 911 } |
| 910 } | 912 } |
| 911 | 913 |
| 912 SkRect bbox; | 914 SkRect bbox; |
| 913 bbox.set(fState.get()->fBBox); | 915 bbox.set(this->pdfShaderState().fBBox); |
| 914 if (!inverseTransformBBox(finalMatrix, &bbox)) { | 916 if (!inverseTransformBBox(finalMatrix, &bbox)) { |
| 915 return; | 917 return; |
| 916 } | 918 } |
| 917 | 919 |
| 918 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); | 920 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); |
| 919 domain->reserve(4); | 921 domain->reserve(4); |
| 920 domain->appendScalar(bbox.fLeft); | 922 domain->appendScalar(bbox.fLeft); |
| 921 domain->appendScalar(bbox.fRight); | 923 domain->appendScalar(bbox.fRight); |
| 922 domain->appendScalar(bbox.fTop); | 924 domain->appendScalar(bbox.fTop); |
| 923 domain->appendScalar(bbox.fBottom); | 925 domain->appendScalar(bbox.fBottom); |
| 924 | 926 |
| 925 SkString functionCode; | 927 SkString functionCode; |
| 926 // The two point radial gradient further references fState.get()->fInfo | 928 // The two point radial gradient further references |
| 929 // this->pdfShaderState().fInfo | |
| 927 // in translating from x, y coordinates to the t parameter. So, we have | 930 // in translating from x, y coordinates to the t parameter. So, we have |
| 928 // to transform the points and radii according to the calculated matrix. | 931 // to transform the points and radii according to the calculated matrix. |
| 929 if (fState.get()->fType == SkShader::kRadial2_GradientType) { | 932 if (this->pdfShaderState().fType == SkShader::kRadial2_GradientType) { |
| 930 SkShader::GradientInfo twoPointRadialInfo = *info; | 933 SkShader::GradientInfo twoPointRadialInfo = *info; |
| 931 SkMatrix inverseMapperMatrix; | 934 SkMatrix inverseMapperMatrix; |
| 932 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | 935 if (!mapperMatrix.invert(&inverseMapperMatrix)) { |
| 933 return; | 936 return; |
| 934 } | 937 } |
| 935 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | 938 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); |
| 936 twoPointRadialInfo.fRadius[0] = | 939 twoPointRadialInfo.fRadius[0] = |
| 937 inverseMapperMatrix.mapRadius(info->fRadius[0]); | 940 inverseMapperMatrix.mapRadius(info->fRadius[0]); |
| 938 twoPointRadialInfo.fRadius[1] = | 941 twoPointRadialInfo.fRadius[1] = |
| 939 inverseMapperMatrix.mapRadius(info->fRadius[1]); | 942 inverseMapperMatrix.mapRadius(info->fRadius[1]); |
| 940 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); | 943 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); |
| 941 } else { | 944 } else { |
| 942 functionCode = codeFunction(*info, perspectiveInverseOnly); | 945 functionCode = codeFunction(*info, perspectiveInverseOnly); |
| 943 } | 946 } |
| 944 | 947 |
| 945 SkAutoTUnref<SkPDFDict> pdfShader(new SkPDFDict); | 948 SkAutoTUnref<SkPDFDict> pdfShader(new SkPDFDict); |
| 946 pdfShader->insertInt("ShadingType", 1); | 949 pdfShader->insertInt("ShadingType", 1); |
| 947 pdfShader->insertName("ColorSpace", "DeviceRGB"); | 950 pdfShader->insertName("ColorSpace", "DeviceRGB"); |
| 948 pdfShader->insert("Domain", domain.get()); | 951 pdfShader->insert("Domain", domain.get()); |
| 949 | 952 |
| 950 SkPDFStream* function = makePSFunction(functionCode, domain.get()); | 953 SkPDFStream* function = makePSFunction(functionCode, domain.get()); |
| 951 pdfShader->insert("Function", new SkPDFObjRef(function))->unref(); | 954 pdfShader->insert("Function", new SkPDFObjRef(function))->unref(); |
| 952 fResources.push(function); // Pass ownership to resource list. | 955 fResources.push(function); // Pass ownership to resource list. |
| 953 | 956 |
| 954 insertInt("PatternType", 2); | 957 insertInt("PatternType", 2); |
| 955 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); | 958 insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); |
| 956 insert("Shading", pdfShader.get()); | 959 insert("Shading", pdfShader.get()); |
| 957 } | 960 } |
| 958 | 961 |
| 959 SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { | 962 SkPDFImageShader::SkPDFImageShader(SkPDFShaderState* state) |
| 960 fState.get()->fImage.lockPixels(); | 963 : SkPDFShader(state) { |
| 964 this->pdfShaderState().fImage.lockPixels(); | |
| 961 | 965 |
| 962 // 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 |
| 963 // 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 |
| 964 // translations so that all content is in the device, coordinates > 0). | 968 // translations so that all content is in the device, coordinates > 0). |
| 965 | 969 |
| 966 // 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 |
| 967 // to handle fake clamping. | 971 // to handle fake clamping. |
| 968 SkMatrix finalMatrix = fState.get()->fCanvasTransform; | 972 SkMatrix finalMatrix = this->pdfShaderState().fCanvasTransform; |
| 969 finalMatrix.preConcat(fState.get()->fShaderTransform); | 973 finalMatrix.preConcat(this->pdfShaderState().fShaderTransform); |
| 970 SkRect deviceBounds; | 974 SkRect deviceBounds; |
| 971 deviceBounds.set(fState.get()->fBBox); | 975 deviceBounds.set(this->pdfShaderState().fBBox); |
| 972 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) { | 976 if (!inverseTransformBBox(finalMatrix, &deviceBounds)) { |
| 973 return; | 977 return; |
| 974 } | 978 } |
| 975 | 979 |
| 976 const SkBitmap* image = &fState.get()->fImage; | 980 const SkBitmap* image = &this->pdfShaderState().fImage; |
| 977 SkRect bitmapBounds; | 981 SkRect bitmapBounds; |
| 978 image->getBounds(&bitmapBounds); | 982 image->getBounds(&bitmapBounds); |
| 979 | 983 |
| 980 // 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, |
| 981 // 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. |
| 982 // 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 |
| 983 // or not the main bitmap is in it. | 987 // or not the main bitmap is in it. |
| 984 SkShader::TileMode tileModes[2]; | 988 SkShader::TileMode tileModes[2]; |
| 985 tileModes[0] = fState.get()->fImageTileModes[0]; | 989 tileModes[0] = this->pdfShaderState().fImageTileModes[0]; |
| 986 tileModes[1] = fState.get()->fImageTileModes[1]; | 990 tileModes[1] = this->pdfShaderState().fImageTileModes[1]; |
| 987 if (tileModes[0] != SkShader::kClamp_TileMode || | 991 if (tileModes[0] != SkShader::kClamp_TileMode || |
| 988 tileModes[1] != SkShader::kClamp_TileMode) { | 992 tileModes[1] != SkShader::kClamp_TileMode) { |
| 989 deviceBounds.join(bitmapBounds); | 993 deviceBounds.join(bitmapBounds); |
| 990 } | 994 } |
| 991 | 995 |
| 992 SkMatrix unflip; | 996 SkMatrix unflip; |
| 993 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height())); | 997 unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height())); |
| 994 unflip.preScale(SK_Scalar1, -SK_Scalar1); | 998 unflip.preScale(SK_Scalar1, -SK_Scalar1); |
| 995 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), | 999 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), |
| 996 SkScalarRoundToInt(deviceBounds.height())); | 1000 SkScalarRoundToInt(deviceBounds.height())); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 | 1160 |
| 1157 // Put the canvas into the pattern stream (fContent). | 1161 // Put the canvas into the pattern stream (fContent). |
| 1158 SkAutoTUnref<SkStream> content(pattern.content()); | 1162 SkAutoTUnref<SkStream> content(pattern.content()); |
| 1159 setData(content.get()); | 1163 setData(content.get()); |
| 1160 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); | 1164 SkPDFResourceDict* resourceDict = pattern.getResourceDict(); |
| 1161 resourceDict->getReferencedResources(fResources, &fResources, false); | 1165 resourceDict->getReferencedResources(fResources, &fResources, false); |
| 1162 | 1166 |
| 1163 populate_tiling_pattern_dict(this, patternBBox, | 1167 populate_tiling_pattern_dict(this, patternBBox, |
| 1164 pattern.getResourceDict(), finalMatrix); | 1168 pattern.getResourceDict(), finalMatrix); |
| 1165 | 1169 |
| 1166 fState.get()->fImage.unlockPixels(); | 1170 this->pdfShaderState().fImage.unlockPixels(); |
| 1167 } | 1171 } |
| 1168 | 1172 |
| 1169 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFAr ray* domain) { | 1173 SkPDFStream* SkPDFFunctionShader::makePSFunction(const SkString& psCode, SkPDFAr ray* domain) { |
| 1170 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), psCode.size())) ; | 1174 SkAutoDataUnref funcData(SkData::NewWithCopy(psCode.c_str(), psCode.size())) ; |
| 1171 SkPDFStream* result = new SkPDFStream(funcData.get()); | 1175 SkPDFStream* result = new SkPDFStream(funcData.get()); |
| 1172 result->insertInt("FunctionType", 4); | 1176 result->insertInt("FunctionType", 4); |
| 1173 result->insert("Domain", domain); | 1177 result->insert("Domain", domain); |
| 1174 result->insert("Range", RangeObject()); | 1178 result->insert("Range", RangeObject()); |
| 1175 return result; | 1179 return result; |
| 1176 } | 1180 } |
| 1177 | 1181 |
| 1178 SkPDFShader::ShaderCanonicalEntry::ShaderCanonicalEntry(SkPDFObject* pdfShader, const State* state) | 1182 bool SkPDFShaderState::operator==(const SkPDFShaderState& b) const { |
| 1179 : fPDFShader(pdfShader) | |
| 1180 , fState(state) | |
| 1181 {} | |
| 1182 | |
| 1183 bool SkPDFShader::ShaderCanonicalEntry::operator==(const ShaderCanonicalEntry& b ) const { | |
| 1184 return fPDFShader == b.fPDFShader || | |
| 1185 (fState != NULL && b.fState != NULL && *fState == *b.fState); | |
| 1186 } | |
| 1187 | |
| 1188 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { | |
| 1189 if (fType != b.fType || | 1183 if (fType != b.fType || |
| 1190 fCanvasTransform != b.fCanvasTransform || | 1184 fCanvasTransform != b.fCanvasTransform || |
| 1191 fShaderTransform != b.fShaderTransform || | 1185 fShaderTransform != b.fShaderTransform || |
| 1192 fBBox != b.fBBox) { | 1186 fBBox != b.fBBox) { |
| 1193 return false; | 1187 return false; |
| 1194 } | 1188 } |
| 1195 | 1189 |
| 1196 if (fType == SkShader::kNone_GradientType) { | 1190 if (fType == SkShader::kNone_GradientType) { |
| 1197 if (fPixelGeneration != b.fPixelGeneration || | 1191 if (fPixelGeneration != b.fPixelGeneration || |
| 1198 fPixelGeneration == 0 || | 1192 fPixelGeneration == 0 || |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1232 break; | 1226 break; |
| 1233 case SkShader::kSweep_GradientType: | 1227 case SkShader::kSweep_GradientType: |
| 1234 case SkShader::kNone_GradientType: | 1228 case SkShader::kNone_GradientType: |
| 1235 case SkShader::kColor_GradientType: | 1229 case SkShader::kColor_GradientType: |
| 1236 break; | 1230 break; |
| 1237 } | 1231 } |
| 1238 } | 1232 } |
| 1239 return true; | 1233 return true; |
| 1240 } | 1234 } |
| 1241 | 1235 |
| 1242 SkPDFShader::State::State(const SkShader& shader, | 1236 SkPDFShaderState::SkPDFShaderState(const SkShader& shader, |
| 1243 const SkMatrix& canvasTransform, const SkIRect& bbox) | 1237 const SkMatrix& canvasTransform, |
| 1244 : fCanvasTransform(canvasTransform), | 1238 const SkIRect& bbox) |
| 1245 fBBox(bbox), | 1239 : fCanvasTransform(canvasTransform), fBBox(bbox), fPixelGeneration(0) { |
| 1246 fPixelGeneration(0) { | |
| 1247 fInfo.fColorCount = 0; | 1240 fInfo.fColorCount = 0; |
| 1248 fInfo.fColors = NULL; | 1241 fInfo.fColors = NULL; |
| 1249 fInfo.fColorOffsets = NULL; | 1242 fInfo.fColorOffsets = NULL; |
| 1250 fShaderTransform = shader.getLocalMatrix(); | 1243 fShaderTransform = shader.getLocalMatrix(); |
| 1251 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; | 1244 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; |
| 1252 | 1245 |
| 1253 fType = shader.asAGradient(&fInfo); | 1246 fType = shader.asAGradient(&fInfo); |
| 1254 | 1247 |
| 1255 if (fType == SkShader::kNone_GradientType) { | 1248 if (fType == SkShader::kNone_GradientType) { |
| 1256 SkShader::BitmapType bitmapType; | 1249 SkShader::BitmapType bitmapType; |
| 1257 SkMatrix matrix; | 1250 SkMatrix matrix; |
| 1258 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); | 1251 bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); |
| 1259 if (bitmapType != SkShader::kDefault_BitmapType) { | 1252 if (bitmapType != SkShader::kDefault_BitmapType) { |
| 1260 fImage.reset(); | 1253 fImage.reset(); |
| 1261 return; | 1254 return; |
| 1262 } | 1255 } |
| 1263 SkASSERT(matrix.isIdentity()); | 1256 SkASSERT(matrix.isIdentity()); |
| 1264 fPixelGeneration = fImage.getGenerationID(); | 1257 fPixelGeneration = fImage.getGenerationID(); |
| 1265 } else { | 1258 } else { |
| 1266 AllocateGradientInfoStorage(); | 1259 AllocateGradientInfoStorage(); |
| 1267 shader.asAGradient(&fInfo); | 1260 shader.asAGradient(&fInfo); |
| 1268 } | 1261 } |
| 1269 } | 1262 } |
| 1270 | 1263 |
| 1271 SkPDFShader::State::State(const SkPDFShader::State& other) | 1264 SkPDFShaderState::SkPDFShaderState(const SkPDFShaderState& other) |
| 1272 : fType(other.fType), | 1265 : fType(other.fType) |
| 1273 fCanvasTransform(other.fCanvasTransform), | 1266 , fCanvasTransform(other.fCanvasTransform) |
| 1274 fShaderTransform(other.fShaderTransform), | 1267 , fShaderTransform(other.fShaderTransform) |
| 1275 fBBox(other.fBBox) | 1268 , fBBox(other.fBBox) { |
| 1276 { | |
| 1277 // Only gradients supported for now, since that is all that is used. | 1269 // Only gradients supported for now, since that is all that is used. |
| 1278 // If needed, image state copy constructor can be added here later. | 1270 // If needed, image state copy constructor can be added here later. |
| 1279 SkASSERT(fType != SkShader::kNone_GradientType); | 1271 SkASSERT(fType != SkShader::kNone_GradientType); |
| 1280 | 1272 |
| 1281 if (fType != SkShader::kNone_GradientType) { | 1273 if (fType != SkShader::kNone_GradientType) { |
| 1282 fInfo = other.fInfo; | 1274 fInfo = other.fInfo; |
| 1283 | 1275 |
| 1284 AllocateGradientInfoStorage(); | 1276 AllocateGradientInfoStorage(); |
| 1285 for (int i = 0; i < fInfo.fColorCount; i++) { | 1277 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1286 fInfo.fColors[i] = other.fInfo.fColors[i]; | 1278 fInfo.fColors[i] = other.fInfo.fColors[i]; |
| 1287 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; | 1279 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; |
| 1288 } | 1280 } |
| 1289 } | 1281 } |
| 1290 } | 1282 } |
| 1291 | 1283 |
| 1292 /** | 1284 /** |
| 1293 * Create a copy of this gradient state with alpha assigned to RGB luminousity. | 1285 * Create a copy of this gradient state with alpha assigned to RGB luminousity. |
| 1294 * Only valid for gradient states. | 1286 * Only valid for gradient states. |
| 1295 */ | 1287 */ |
| 1296 SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const { | 1288 SkPDFShaderState* SkPDFShaderState::CreateAlphaToLuminosityState() const { |
| 1297 SkASSERT(fType != SkShader::kNone_GradientType); | 1289 SkASSERT(fType != SkShader::kNone_GradientType); |
| 1298 | 1290 |
| 1299 SkPDFShader::State* newState = new SkPDFShader::State(*this); | 1291 SkPDFShaderState* newState = new SkPDFShaderState(*this); |
| 1300 | 1292 |
| 1301 for (int i = 0; i < fInfo.fColorCount; i++) { | 1293 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1302 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | 1294 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
| 1303 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); | 1295 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); |
| 1304 } | 1296 } |
| 1305 | 1297 |
| 1306 return newState; | 1298 return newState; |
| 1307 } | 1299 } |
| 1308 | 1300 |
| 1309 /** | 1301 /** |
| 1310 * Create a copy of this gradient state with alpha set to fully opaque | 1302 * Create a copy of this gradient state with alpha set to fully opaque |
| 1311 * Only valid for gradient states. | 1303 * Only valid for gradient states. |
| 1312 */ | 1304 */ |
| 1313 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const { | 1305 SkPDFShaderState* SkPDFShaderState::CreateOpaqueState() const { |
| 1314 SkASSERT(fType != SkShader::kNone_GradientType); | 1306 SkASSERT(fType != SkShader::kNone_GradientType); |
| 1315 | 1307 |
| 1316 SkPDFShader::State* newState = new SkPDFShader::State(*this); | 1308 SkPDFShaderState* newState = new SkPDFShaderState(*this); |
| 1317 for (int i = 0; i < fInfo.fColorCount; i++) { | 1309 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1318 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], | 1310 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], |
| 1319 SK_AlphaOPAQUE); | 1311 SK_AlphaOPAQUE); |
| 1320 } | 1312 } |
| 1321 | 1313 |
| 1322 return newState; | 1314 return newState; |
| 1323 } | 1315 } |
| 1324 | 1316 |
| 1325 /** | 1317 /** |
| 1326 * Returns true if state is a gradient and the gradient has alpha. | 1318 * Returns true if state is a gradient and the gradient has alpha. |
| 1327 */ | 1319 */ |
| 1328 bool SkPDFShader::State::GradientHasAlpha() const { | 1320 bool SkPDFShaderState::GradientHasAlpha() const { |
| 1329 if (fType == SkShader::kNone_GradientType) { | 1321 if (fType == SkShader::kNone_GradientType) { |
| 1330 return false; | 1322 return false; |
| 1331 } | 1323 } |
| 1332 | 1324 |
| 1333 for (int i = 0; i < fInfo.fColorCount; i++) { | 1325 for (int i = 0; i < fInfo.fColorCount; i++) { |
| 1334 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | 1326 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
| 1335 if (alpha != SK_AlphaOPAQUE) { | 1327 if (alpha != SK_AlphaOPAQUE) { |
| 1336 return true; | 1328 return true; |
| 1337 } | 1329 } |
| 1338 } | 1330 } |
| 1339 return false; | 1331 return false; |
| 1340 } | 1332 } |
| 1341 | 1333 |
| 1342 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1334 void SkPDFShaderState::AllocateGradientInfoStorage() { |
| 1343 fColorData.set(sk_malloc_throw( | 1335 fColorData.set(sk_malloc_throw( |
| 1344 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1336 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
| 1345 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1337 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
| 1346 fInfo.fColorOffsets = | 1338 fInfo.fColorOffsets = |
| 1347 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | 1339 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
| 1348 } | 1340 } |
| OLD | NEW |