OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 | 8 |
9 #include "SkPDFShader.h" | 9 #include "SkPDFShader.h" |
10 | 10 |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 gradientFunctionCode(info, function); | 516 gradientFunctionCode(info, function); |
517 function->writeText("}"); | 517 function->writeText("}"); |
518 } | 518 } |
519 | 519 |
520 static void drawBitmapMatrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatri
x& matrix) { | 520 static void drawBitmapMatrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatri
x& matrix) { |
521 SkAutoCanvasRestore acr(canvas, true); | 521 SkAutoCanvasRestore acr(canvas, true); |
522 canvas->concat(matrix); | 522 canvas->concat(matrix); |
523 canvas->drawBitmap(bm, 0, 0); | 523 canvas->drawBitmap(bm, 0, 0); |
524 } | 524 } |
525 | 525 |
526 class SkPDFShader::State { | |
527 public: | |
528 SkShader::GradientType fType; | |
529 SkShader::GradientInfo fInfo; | |
530 SkAutoFree fColorData; // This provides storage for arrays in fInfo. | |
531 SkMatrix fCanvasTransform; | |
532 SkMatrix fShaderTransform; | |
533 SkIRect fBBox; | |
534 | |
535 SkBitmap fImage; | |
536 SkBitmapKey fBitmapKey; | |
537 SkShader::TileMode fImageTileModes[2]; | |
538 | |
539 State(SkShader* shader, const SkMatrix& canvasTransform, | |
540 const SkIRect& bbox, SkScalar rasterScale); | |
541 | |
542 bool operator==(const State& b) const; | |
543 | |
544 SkPDFShader::State* CreateAlphaToLuminosityState() const; | |
545 SkPDFShader::State* CreateOpaqueState() const; | |
546 | |
547 bool GradientHasAlpha() const; | |
548 | |
549 private: | |
550 State(const State& other); | |
551 State operator=(const State& rhs); | |
552 void AllocateGradientInfoStorage(); | |
553 }; | |
554 | |
555 //////////////////////////////////////////////////////////////////////////////// | |
556 | |
557 SkPDFFunctionShader::SkPDFFunctionShader(SkPDFShader::State* state) | |
558 : SkPDFDict("Pattern"), fShaderState(state) { | |
559 state->fImage.reset(); | |
560 } | |
561 | |
562 SkPDFFunctionShader::~SkPDFFunctionShader() {} | |
563 | |
564 bool SkPDFFunctionShader::equals(const SkPDFShader::State& state) const { | |
565 return state == *fShaderState; | |
566 } | |
567 | |
568 //////////////////////////////////////////////////////////////////////////////// | 526 //////////////////////////////////////////////////////////////////////////////// |
569 | 527 |
570 SkPDFAlphaFunctionShader::SkPDFAlphaFunctionShader(SkPDFShader::State* state) | 528 static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, |
571 : fShaderState(state) { | 529 SkScalar dpi, |
572 state->fImage.reset(); | 530 const SkPDFShader::State& s
tate); |
573 } | 531 static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, |
| 532 const SkPDFShader::State& state); |
574 | 533 |
575 bool SkPDFAlphaFunctionShader::equals(const SkPDFShader::State& state) const { | 534 static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc, |
576 return state == *fShaderState; | 535 SkScalar dpi, |
577 } | 536 const SkPDFShader::State& state, |
| 537 SkBitmap image); |
578 | 538 |
579 SkPDFAlphaFunctionShader::~SkPDFAlphaFunctionShader() {} | 539 static sk_sp<SkPDFObject> get_pdf_shader_by_state( |
580 | |
581 //////////////////////////////////////////////////////////////////////////////// | |
582 | |
583 SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) | |
584 : fShaderState(state) { | |
585 state->fImage.reset(); | |
586 } | |
587 | |
588 bool SkPDFImageShader::equals(const SkPDFShader::State& state) const { | |
589 return state == *fShaderState; | |
590 } | |
591 | |
592 SkPDFImageShader::~SkPDFImageShader() {} | |
593 | |
594 //////////////////////////////////////////////////////////////////////////////// | |
595 | |
596 static SkPDFObject* get_pdf_shader_by_state( | |
597 SkPDFDocument* doc, | 540 SkPDFDocument* doc, |
598 SkScalar dpi, | 541 SkScalar dpi, |
599 std::unique_ptr<SkPDFShader::State>* autoState) { | 542 SkPDFShader::State state, |
600 const SkPDFShader::State& state = **autoState; | 543 SkBitmap image) { |
601 SkPDFCanon* canon = doc->canon(); | 544 SkPDFCanon* canon = doc->canon(); |
602 if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) { | 545 if (state.fType == SkShader::kNone_GradientType && image.isNull()) { |
603 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 546 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
604 // handle compose shader by pulling things up to a layer, drawing with | 547 // handle compose shader by pulling things up to a layer, drawing with |
605 // the first shader, applying the xfer mode and drawing again with the | 548 // the first shader, applying the xfer mode and drawing again with the |
606 // second shader, then applying the layer to the original drawing. | 549 // second shader, then applying the layer to the original drawing. |
607 return nullptr; | 550 return nullptr; |
608 } else if (state.fType == SkShader::kNone_GradientType) { | 551 } else if (state.fType == SkShader::kNone_GradientType) { |
609 SkPDFObject* shader = canon->findImageShader(state); | 552 sk_sp<SkPDFObject> shader = canon->findImageShader(state); |
610 return shader ? SkRef(shader) | 553 if (!shader) { |
611 : SkPDFImageShader::Create(doc, dpi, autoState); | 554 shader = make_image_shader(doc, dpi, state, std::move(image)); |
| 555 canon->addImageShader(shader, std::move(state)); |
| 556 } |
| 557 return shader; |
612 } else if (state.GradientHasAlpha()) { | 558 } else if (state.GradientHasAlpha()) { |
613 SkPDFObject* shader = canon->findAlphaShader(state); | 559 sk_sp<SkPDFObject> shader = canon->findAlphaShader(state); |
614 return shader ? SkRef(shader) | 560 if (!shader) { |
615 : SkPDFAlphaFunctionShader::Create(doc, dpi, autoState); | 561 shader = make_alpha_function_shader(doc, dpi, state); |
| 562 canon->addAlphaShader(shader, std::move(state)); |
| 563 } |
| 564 return shader; |
616 } else { | 565 } else { |
617 SkPDFObject* shader = canon->findFunctionShader(state); | 566 sk_sp<SkPDFObject> shader = canon->findFunctionShader(state); |
618 return shader ? SkRef(shader) | 567 if (!shader) { |
619 : SkPDFFunctionShader::Create(canon, autoState); | 568 shader = make_function_shader(canon, state); |
| 569 canon->addFunctionShader(shader, std::move(state)); |
| 570 } |
| 571 return shader; |
620 } | 572 } |
621 } | 573 } |
622 | 574 |
623 // static | 575 sk_sp<SkPDFObject> SkPDFShader::GetPDFShader(SkPDFDocument* doc, |
624 SkPDFObject* SkPDFShader::GetPDFShader(SkPDFDocument* doc, | 576 SkScalar dpi, |
625 SkScalar dpi, | 577 SkShader* shader, |
626 SkShader* shader, | 578 const SkMatrix& matrix, |
627 const SkMatrix& matrix, | 579 const SkIRect& surfaceBBox, |
628 const SkIRect& surfaceBBox, | 580 SkScalar rasterScale) { |
629 SkScalar rasterScale) { | 581 SkBitmap image; |
630 std::unique_ptr<SkPDFShader::State> state(new State(shader, matrix, surfaceB
Box, rasterScale)); | 582 State state(shader, matrix, surfaceBBox, rasterScale, &image); |
631 return get_pdf_shader_by_state(doc, dpi, &state); | 583 return get_pdf_shader_by_state( |
| 584 doc, dpi, std::move(state), std::move(image)); |
632 } | 585 } |
633 | 586 |
634 static sk_sp<SkPDFDict> get_gradient_resource_dict( | 587 static sk_sp<SkPDFDict> get_gradient_resource_dict( |
635 SkPDFObject* functionShader, | 588 SkPDFObject* functionShader, |
636 SkPDFObject* gState) { | 589 SkPDFObject* gState) { |
637 SkTDArray<SkPDFObject*> patterns; | 590 SkTDArray<SkPDFObject*> patterns; |
638 if (functionShader) { | 591 if (functionShader) { |
639 patterns.push(functionShader); | 592 patterns.push(functionShader); |
640 } | 593 } |
641 SkTDArray<SkPDFObject*> graphicStates; | 594 SkTDArray<SkPDFObject*> graphicStates; |
642 if (gState) { | 595 if (gState) { |
643 graphicStates.push(gState); | 596 graphicStates.push(gState); |
644 } | 597 } |
645 return SkPDFResourceDict::Make(&graphicStates, &patterns, nullptr, nullptr); | 598 return SkPDFResourceDict::Make(&graphicStates, &patterns, nullptr, nullptr); |
646 } | 599 } |
647 | 600 |
648 static void populate_tiling_pattern_dict(SkPDFDict* pattern, | 601 static void populate_tiling_pattern_dict(SkPDFDict* pattern, |
649 SkRect& bbox, | 602 SkRect& bbox, |
650 SkPDFDict* resources, | 603 sk_sp<SkPDFDict> resources, |
651 const SkMatrix& matrix) { | 604 const SkMatrix& matrix) { |
652 const int kTiling_PatternType = 1; | 605 const int kTiling_PatternType = 1; |
653 const int kColoredTilingPattern_PaintType = 1; | 606 const int kColoredTilingPattern_PaintType = 1; |
654 const int kConstantSpacing_TilingType = 1; | 607 const int kConstantSpacing_TilingType = 1; |
655 | 608 |
656 pattern->insertName("Type", "Pattern"); | 609 pattern->insertName("Type", "Pattern"); |
657 pattern->insertInt("PatternType", kTiling_PatternType); | 610 pattern->insertInt("PatternType", kTiling_PatternType); |
658 pattern->insertInt("PaintType", kColoredTilingPattern_PaintType); | 611 pattern->insertInt("PaintType", kColoredTilingPattern_PaintType); |
659 pattern->insertInt("TilingType", kConstantSpacing_TilingType); | 612 pattern->insertInt("TilingType", kConstantSpacing_TilingType); |
660 pattern->insertObject("BBox", SkPDFUtils::RectToArray(bbox)); | 613 pattern->insertObject("BBox", SkPDFUtils::RectToArray(bbox)); |
661 pattern->insertScalar("XStep", bbox.width()); | 614 pattern->insertScalar("XStep", bbox.width()); |
662 pattern->insertScalar("YStep", bbox.height()); | 615 pattern->insertScalar("YStep", bbox.height()); |
663 pattern->insertObject("Resources", sk_ref_sp(resources)); | 616 pattern->insertObject("Resources", std::move(resources)); |
664 if (!matrix.isIdentity()) { | 617 if (!matrix.isIdentity()) { |
665 pattern->insertObject("Matrix", SkPDFUtils::MatrixToArray(matrix)); | 618 pattern->insertObject("Matrix", SkPDFUtils::MatrixToArray(matrix)); |
666 } | 619 } |
667 } | 620 } |
668 | 621 |
669 /** | 622 /** |
670 * Creates a content stream which fills the pattern P0 across bounds. | 623 * Creates a content stream which fills the pattern P0 across bounds. |
671 * @param gsIndex A graphics state resource index to apply, or <0 if no | 624 * @param gsIndex A graphics state resource index to apply, or <0 if no |
672 * graphics state to apply. | 625 * graphics state to apply. |
673 */ | 626 */ |
674 static SkStreamAsset* create_pattern_fill_content(int gsIndex, SkRect& bounds) { | 627 static std::unique_ptr<SkStreamAsset> create_pattern_fill_content( |
| 628 int gsIndex, SkRect& bounds) { |
675 SkDynamicMemoryWStream content; | 629 SkDynamicMemoryWStream content; |
676 if (gsIndex >= 0) { | 630 if (gsIndex >= 0) { |
677 SkPDFUtils::ApplyGraphicState(gsIndex, &content); | 631 SkPDFUtils::ApplyGraphicState(gsIndex, &content); |
678 } | 632 } |
679 SkPDFUtils::ApplyPattern(0, &content); | 633 SkPDFUtils::ApplyPattern(0, &content); |
680 SkPDFUtils::AppendRectangle(bounds, &content); | 634 SkPDFUtils::AppendRectangle(bounds, &content); |
681 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, | 635 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kEvenOdd_FillType, |
682 &content); | 636 &content); |
683 | 637 |
684 return content.detachAsStream(); | 638 return std::unique_ptr<SkStreamAsset>(content.detachAsStream()); |
685 } | 639 } |
686 | 640 |
687 /** | 641 /** |
688 * Creates a ExtGState with the SMask set to the luminosityShader in | 642 * Creates a ExtGState with the SMask set to the luminosityShader in |
689 * luminosity mode. The shader pattern extends to the bbox. | 643 * luminosity mode. The shader pattern extends to the bbox. |
690 */ | 644 */ |
691 static sk_sp<SkPDFObject> create_smask_graphic_state( | 645 static sk_sp<SkPDFObject> create_smask_graphic_state( |
692 SkPDFDocument* doc, SkScalar dpi, const SkPDFShader::State& state) { | 646 SkPDFDocument* doc, SkScalar dpi, const SkPDFShader::State& state) { |
693 SkRect bbox; | 647 SkRect bbox; |
694 bbox.set(state.fBBox); | 648 bbox.set(state.fBBox); |
695 | 649 |
696 std::unique_ptr<SkPDFShader::State> alphaToLuminosityState( | |
697 state.CreateAlphaToLuminosityState()); | |
698 sk_sp<SkPDFObject> luminosityShader( | 650 sk_sp<SkPDFObject> luminosityShader( |
699 get_pdf_shader_by_state(doc, dpi, &alphaToLuminosityState)); | 651 get_pdf_shader_by_state(doc, dpi, state.MakeAlphaToLuminosityState()
, |
| 652 SkBitmap())); |
700 | 653 |
701 std::unique_ptr<SkStreamAsset> alphaStream(create_pattern_fill_content(-1, b
box)); | 654 std::unique_ptr<SkStreamAsset> alphaStream(create_pattern_fill_content(-1, b
box)); |
702 | 655 |
703 auto resources = | 656 auto resources = |
704 get_gradient_resource_dict(luminosityShader.get(), nullptr); | 657 get_gradient_resource_dict(luminosityShader.get(), nullptr); |
705 | 658 |
706 auto alphaMask = SkPDFMakeFormXObject(std::move(alphaStream), | 659 auto alphaMask = SkPDFMakeFormXObject(std::move(alphaStream), |
707 SkPDFUtils::RectToArray(bbox), | 660 SkPDFUtils::RectToArray(bbox), |
708 std::move(resources), | 661 std::move(resources), |
709 SkMatrix::I(), | 662 SkMatrix::I(), |
710 "DeviceRGB"); | 663 "DeviceRGB"); |
711 return SkPDFGraphicState::GetSMaskGraphicState( | 664 return SkPDFGraphicState::GetSMaskGraphicState( |
712 alphaMask.get(), false, | 665 std::move(alphaMask), false, |
713 SkPDFGraphicState::kLuminosity_SMaskMode, doc->canon()); | 666 SkPDFGraphicState::kLuminosity_SMaskMode, doc->canon()); |
714 } | 667 } |
715 | 668 |
716 SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( | 669 static sk_sp<SkPDFStream> make_alpha_function_shader(SkPDFDocument* doc, |
717 SkPDFDocument* doc, | 670 SkScalar dpi, |
718 SkScalar dpi, | 671 const SkPDFShader::State& s
tate) { |
719 std::unique_ptr<SkPDFShader::State>* autoState) { | |
720 const SkPDFShader::State& state = **autoState; | |
721 SkRect bbox; | 672 SkRect bbox; |
722 bbox.set(state.fBBox); | 673 bbox.set(state.fBBox); |
723 | 674 |
724 std::unique_ptr<SkPDFShader::State> opaqueState(state.CreateOpaqueState()); | 675 SkPDFShader::State opaqueState(state.MakeOpaqueState()); |
725 | 676 |
726 sk_sp<SkPDFObject> colorShader( | 677 sk_sp<SkPDFObject> colorShader( |
727 get_pdf_shader_by_state(doc, dpi, &opaqueState)); | 678 get_pdf_shader_by_state(doc, dpi, std::move(opaqueState), SkBitmap()
)); |
728 if (!colorShader) { | 679 if (!colorShader) { |
729 return nullptr; | 680 return nullptr; |
730 } | 681 } |
731 | 682 |
732 // Create resource dict with alpha graphics state as G0 and | 683 // Create resource dict with alpha graphics state as G0 and |
733 // pattern shader as P0, then write content stream. | 684 // pattern shader as P0, then write content stream. |
734 auto alphaGs = create_smask_graphic_state(doc, dpi, state); | 685 auto alphaGs = create_smask_graphic_state(doc, dpi, state); |
735 | 686 |
736 SkPDFAlphaFunctionShader* alphaFunctionShader = | |
737 new SkPDFAlphaFunctionShader(autoState->release()); | |
738 | |
739 auto resourceDict = | 687 auto resourceDict = |
740 get_gradient_resource_dict(colorShader.get(), alphaGs.get()); | 688 get_gradient_resource_dict(colorShader.get(), alphaGs.get()); |
741 | 689 |
742 std::unique_ptr<SkStreamAsset> colorStream( | 690 std::unique_ptr<SkStreamAsset> colorStream( |
743 create_pattern_fill_content(0, bbox)); | 691 create_pattern_fill_content(0, bbox)); |
744 alphaFunctionShader->setData(std::move(colorStream)); | 692 auto alphaFunctionShader = sk_make_sp<SkPDFStream>(std::move(colorStream)); |
745 | 693 |
746 populate_tiling_pattern_dict( | 694 populate_tiling_pattern_dict(alphaFunctionShader->dict(), bbox, |
747 alphaFunctionShader->dict(), bbox, resourceDict.get(), | 695 std::move(resourceDict), SkMatrix::I()); |
748 SkMatrix::I()); | |
749 doc->canon()->addAlphaShader(alphaFunctionShader); | |
750 return alphaFunctionShader; | 696 return alphaFunctionShader; |
751 } | 697 } |
752 | 698 |
753 // Finds affine and persp such that in = affine * persp. | 699 // Finds affine and persp such that in = affine * persp. |
754 // but it returns the inverse of perspective matrix. | 700 // but it returns the inverse of perspective matrix. |
755 static bool split_perspective(const SkMatrix in, SkMatrix* affine, | 701 static bool split_perspective(const SkMatrix in, SkMatrix* affine, |
756 SkMatrix* perspectiveInverse) { | 702 SkMatrix* perspectiveInverse) { |
757 const SkScalar p2 = in[SkMatrix::kMPersp2]; | 703 const SkScalar p2 = in[SkMatrix::kMPersp2]; |
758 | 704 |
759 if (SkScalarNearlyZero(p2)) { | 705 if (SkScalarNearlyZero(p2)) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 range->appendInt(1); | 741 range->appendInt(1); |
796 range->appendInt(0); | 742 range->appendInt(0); |
797 range->appendInt(1); | 743 range->appendInt(1); |
798 range->appendInt(0); | 744 range->appendInt(0); |
799 range->appendInt(1); | 745 range->appendInt(1); |
800 return range; | 746 return range; |
801 } | 747 } |
802 | 748 |
803 static sk_sp<SkPDFStream> make_ps_function( | 749 static sk_sp<SkPDFStream> make_ps_function( |
804 std::unique_ptr<SkStreamAsset> psCode, | 750 std::unique_ptr<SkStreamAsset> psCode, |
805 SkPDFArray* domain, | 751 sk_sp<SkPDFArray> domain, |
806 sk_sp<SkPDFObject> range) { | 752 sk_sp<SkPDFObject> range) { |
807 auto result = sk_make_sp<SkPDFStream>(std::move(psCode)); | 753 auto result = sk_make_sp<SkPDFStream>(std::move(psCode)); |
808 result->dict()->insertInt("FunctionType", 4); | 754 result->dict()->insertInt("FunctionType", 4); |
809 result->dict()->insertObject("Domain", sk_ref_sp(domain)); | 755 result->dict()->insertObject("Domain", std::move(domain)); |
810 result->dict()->insertObject("Range", std::move(range)); | 756 result->dict()->insertObject("Range", std::move(range)); |
811 return result; | 757 return result; |
812 } | 758 } |
813 | 759 |
814 // catch cases where the inner just touches the outer circle | 760 // catch cases where the inner just touches the outer circle |
815 // and make the inner circle just inside the outer one to match raster | 761 // and make the inner circle just inside the outer one to match raster |
816 static void FixUpRadius(const SkPoint& p1, SkScalar& r1, const SkPoint& p2, SkSc
alar& r2) { | 762 static void FixUpRadius(const SkPoint& p1, SkScalar& r1, const SkPoint& p2, SkSc
alar& r2) { |
817 // detect touching circles | 763 // detect touching circles |
818 SkScalar distance = SkPoint::Distance(p1, p2); | 764 SkScalar distance = SkPoint::Distance(p1, p2); |
819 SkScalar subtractRadii = fabs(r1 - r2); | 765 SkScalar subtractRadii = fabs(r1 - r2); |
820 if (fabs(distance - subtractRadii) < 0.002f) { | 766 if (fabs(distance - subtractRadii) < 0.002f) { |
821 if (r1 > r2) { | 767 if (r1 > r2) { |
822 r1 += 0.002f; | 768 r1 += 0.002f; |
823 } else { | 769 } else { |
824 r2 += 0.002f; | 770 r2 += 0.002f; |
825 } | 771 } |
826 } | 772 } |
827 } | 773 } |
828 | 774 |
829 SkPDFFunctionShader* SkPDFFunctionShader::Create( | 775 static sk_sp<SkPDFDict> make_function_shader(SkPDFCanon* canon, |
830 SkPDFCanon* canon, std::unique_ptr<SkPDFShader::State>* autoState) { | 776 const SkPDFShader::State& state) { |
831 const SkPDFShader::State& state = **autoState; | |
832 | |
833 void (*codeFunction)(const SkShader::GradientInfo& info, | 777 void (*codeFunction)(const SkShader::GradientInfo& info, |
834 const SkMatrix& perspectiveRemover, | 778 const SkMatrix& perspectiveRemover, |
835 SkDynamicMemoryWStream* function) = nullptr; | 779 SkDynamicMemoryWStream* function) = nullptr; |
836 SkPoint transformPoints[2]; | 780 SkPoint transformPoints[2]; |
837 const SkShader::GradientInfo* info = &state.fInfo; | 781 const SkShader::GradientInfo* info = &state.fInfo; |
838 SkMatrix finalMatrix = state.fCanvasTransform; | 782 SkMatrix finalMatrix = state.fCanvasTransform; |
839 finalMatrix.preConcat(state.fShaderTransform); | 783 finalMatrix.preConcat(state.fShaderTransform); |
840 | 784 |
841 bool doStitchFunctions = (state.fType == SkShader::kLinear_GradientType || | 785 bool doStitchFunctions = (state.fType == SkShader::kLinear_GradientType || |
842 state.fType == SkShader::kRadial_GradientType || | 786 state.fType == SkShader::kRadial_GradientType || |
843 state.fType == SkShader::kConical_GradientType)
&& | 787 state.fType == SkShader::kConical_GradientType) && |
844 info->fTileMode == SkShader::kClamp_TileMode && | 788 info->fTileMode == SkShader::kClamp_TileMode && |
845 !finalMatrix.hasPerspective(); | 789 !finalMatrix.hasPerspective(); |
846 | 790 |
847 auto domain = sk_make_sp<SkPDFArray>(); | 791 auto domain = sk_make_sp<SkPDFArray>(); |
848 | 792 |
849 int32_t shadingType = 1; | 793 int32_t shadingType = 1; |
850 auto pdfShader = sk_make_sp<SkPDFDict>(); | 794 auto pdfShader = sk_make_sp<SkPDFDict>(); |
851 // The two point radial gradient further references | 795 // The two point radial gradient further references |
852 // state.fInfo | 796 // state.fInfo |
853 // in translating from x, y coordinates to the t parameter. So, we have | 797 // in translating from x, y coordinates to the t parameter. So, we have |
854 // to transform the points and radii according to the calculated matrix. | 798 // to transform the points and radii according to the calculated matrix. |
855 if (doStitchFunctions) { | 799 if (doStitchFunctions) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | 921 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); |
978 twoPointRadialInfo.fRadius[0] = | 922 twoPointRadialInfo.fRadius[0] = |
979 inverseMapperMatrix.mapRadius(info->fRadius[0]); | 923 inverseMapperMatrix.mapRadius(info->fRadius[0]); |
980 twoPointRadialInfo.fRadius[1] = | 924 twoPointRadialInfo.fRadius[1] = |
981 inverseMapperMatrix.mapRadius(info->fRadius[1]); | 925 inverseMapperMatrix.mapRadius(info->fRadius[1]); |
982 codeFunction(twoPointRadialInfo, perspectiveInverseOnly, &functionCo
de); | 926 codeFunction(twoPointRadialInfo, perspectiveInverseOnly, &functionCo
de); |
983 } else { | 927 } else { |
984 codeFunction(*info, perspectiveInverseOnly, &functionCode); | 928 codeFunction(*info, perspectiveInverseOnly, &functionCode); |
985 } | 929 } |
986 | 930 |
987 pdfShader->insertObject("Domain", sk_ref_sp(domain.get())); | 931 pdfShader->insertObject("Domain", domain); |
988 | 932 |
989 // Call canon->makeRangeObject() instead of | 933 // Call canon->makeRangeObject() instead of |
990 // SkPDFShader::MakeRangeObject() so that the canon can | 934 // SkPDFShader::MakeRangeObject() so that the canon can |
991 // deduplicate. | 935 // deduplicate. |
992 std::unique_ptr<SkStreamAsset> functionStream( | 936 std::unique_ptr<SkStreamAsset> functionStream( |
993 functionCode.detachAsStream()); | 937 functionCode.detachAsStream()); |
994 auto function = make_ps_function(std::move(functionStream), domain.get()
, | 938 sk_sp<SkPDFStream> function = make_ps_function(std::move(functionStream)
, |
995 canon->makeRangeObject()); | 939 std::move(domain), |
| 940 canon->makeRangeObject())
; |
996 pdfShader->insertObjRef("Function", std::move(function)); | 941 pdfShader->insertObjRef("Function", std::move(function)); |
997 } | 942 } |
998 | 943 |
999 pdfShader->insertInt("ShadingType", shadingType); | 944 pdfShader->insertInt("ShadingType", shadingType); |
1000 pdfShader->insertName("ColorSpace", "DeviceRGB"); | 945 pdfShader->insertName("ColorSpace", "DeviceRGB"); |
1001 | 946 |
1002 sk_sp<SkPDFFunctionShader> pdfFunctionShader( | 947 auto pdfFunctionShader = sk_make_sp<SkPDFDict>("Pattern"); |
1003 new SkPDFFunctionShader(autoState->release())); | |
1004 pdfFunctionShader->insertInt("PatternType", 2); | 948 pdfFunctionShader->insertInt("PatternType", 2); |
1005 pdfFunctionShader->insertObject("Matrix", | 949 pdfFunctionShader->insertObject("Matrix", |
1006 SkPDFUtils::MatrixToArray(finalMatrix)); | 950 SkPDFUtils::MatrixToArray(finalMatrix)); |
1007 pdfFunctionShader->insertObject("Shading", std::move(pdfShader)); | 951 pdfFunctionShader->insertObject("Shading", std::move(pdfShader)); |
1008 | 952 |
1009 canon->addFunctionShader(pdfFunctionShader.get()); | 953 return pdfFunctionShader; |
1010 return pdfFunctionShader.release(); | |
1011 } | 954 } |
1012 | 955 |
1013 SkPDFImageShader* SkPDFImageShader::Create( | 956 static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc, |
1014 SkPDFDocument* doc, | 957 SkScalar dpi, |
1015 SkScalar dpi, | 958 const SkPDFShader::State& state, |
1016 std::unique_ptr<SkPDFShader::State>* autoState) { | 959 SkBitmap image) { |
1017 const SkPDFShader::State& state = **autoState; | 960 SkASSERT(state.fBitmapKey == SkBitmapKey(image)); |
1018 | 961 SkAutoLockPixels SkAutoLockPixels(image); |
1019 state.fImage.lockPixels(); | |
1020 | 962 |
1021 // The image shader pattern cell will be drawn into a separate device | 963 // The image shader pattern cell will be drawn into a separate device |
1022 // in pattern cell space (no scaling on the bitmap, though there may be | 964 // in pattern cell space (no scaling on the bitmap, though there may be |
1023 // translations so that all content is in the device, coordinates > 0). | 965 // translations so that all content is in the device, coordinates > 0). |
1024 | 966 |
1025 // Map clip bounds to shader space to ensure the device is large enough | 967 // Map clip bounds to shader space to ensure the device is large enough |
1026 // to handle fake clamping. | 968 // to handle fake clamping. |
1027 SkMatrix finalMatrix = state.fCanvasTransform; | 969 SkMatrix finalMatrix = state.fCanvasTransform; |
1028 finalMatrix.preConcat(state.fShaderTransform); | 970 finalMatrix.preConcat(state.fShaderTransform); |
1029 SkRect deviceBounds; | 971 SkRect deviceBounds; |
1030 deviceBounds.set(state.fBBox); | 972 deviceBounds.set(state.fBBox); |
1031 if (!inverse_transform_bbox(finalMatrix, &deviceBounds)) { | 973 if (!inverse_transform_bbox(finalMatrix, &deviceBounds)) { |
1032 return nullptr; | 974 return nullptr; |
1033 } | 975 } |
1034 | 976 |
1035 const SkBitmap* image = &state.fImage; | |
1036 SkRect bitmapBounds; | 977 SkRect bitmapBounds; |
1037 image->getBounds(&bitmapBounds); | 978 image.getBounds(&bitmapBounds); |
1038 | 979 |
1039 // For tiling modes, the bounds should be extended to include the bitmap, | 980 // For tiling modes, the bounds should be extended to include the bitmap, |
1040 // otherwise the bitmap gets clipped out and the shader is empty and awful. | 981 // otherwise the bitmap gets clipped out and the shader is empty and awful. |
1041 // For clamp modes, we're only interested in the clip region, whether | 982 // For clamp modes, we're only interested in the clip region, whether |
1042 // or not the main bitmap is in it. | 983 // or not the main bitmap is in it. |
1043 SkShader::TileMode tileModes[2]; | 984 SkShader::TileMode tileModes[2]; |
1044 tileModes[0] = state.fImageTileModes[0]; | 985 tileModes[0] = state.fImageTileModes[0]; |
1045 tileModes[1] = state.fImageTileModes[1]; | 986 tileModes[1] = state.fImageTileModes[1]; |
1046 if (tileModes[0] != SkShader::kClamp_TileMode || | 987 if (tileModes[0] != SkShader::kClamp_TileMode || |
1047 tileModes[1] != SkShader::kClamp_TileMode) { | 988 tileModes[1] != SkShader::kClamp_TileMode) { |
1048 deviceBounds.join(bitmapBounds); | 989 deviceBounds.join(bitmapBounds); |
1049 } | 990 } |
1050 | 991 |
1051 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), | 992 SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), |
1052 SkScalarRoundToInt(deviceBounds.height())); | 993 SkScalarRoundToInt(deviceBounds.height())); |
1053 sk_sp<SkPDFDevice> patternDevice( | 994 sk_sp<SkPDFDevice> patternDevice( |
1054 SkPDFDevice::CreateUnflipped(size, dpi, doc)); | 995 SkPDFDevice::CreateUnflipped(size, dpi, doc)); |
1055 SkCanvas canvas(patternDevice.get()); | 996 SkCanvas canvas(patternDevice.get()); |
1056 | 997 |
1057 SkRect patternBBox; | 998 SkRect patternBBox; |
1058 image->getBounds(&patternBBox); | 999 image.getBounds(&patternBBox); |
1059 | 1000 |
1060 // Translate the canvas so that the bitmap origin is at (0, 0). | 1001 // Translate the canvas so that the bitmap origin is at (0, 0). |
1061 canvas.translate(-deviceBounds.left(), -deviceBounds.top()); | 1002 canvas.translate(-deviceBounds.left(), -deviceBounds.top()); |
1062 patternBBox.offset(-deviceBounds.left(), -deviceBounds.top()); | 1003 patternBBox.offset(-deviceBounds.left(), -deviceBounds.top()); |
1063 // Undo the translation in the final matrix | 1004 // Undo the translation in the final matrix |
1064 finalMatrix.preTranslate(deviceBounds.left(), deviceBounds.top()); | 1005 finalMatrix.preTranslate(deviceBounds.left(), deviceBounds.top()); |
1065 | 1006 |
1066 // If the bitmap is out of bounds (i.e. clamp mode where we only see the | 1007 // If the bitmap is out of bounds (i.e. clamp mode where we only see the |
1067 // stretched sides), canvas will clip this out and the extraneous data | 1008 // stretched sides), canvas will clip this out and the extraneous data |
1068 // won't be saved to the PDF. | 1009 // won't be saved to the PDF. |
1069 canvas.drawBitmap(*image, 0, 0); | 1010 canvas.drawBitmap(image, 0, 0); |
1070 | 1011 |
1071 SkScalar width = SkIntToScalar(image->width()); | 1012 SkScalar width = SkIntToScalar(image.width()); |
1072 SkScalar height = SkIntToScalar(image->height()); | 1013 SkScalar height = SkIntToScalar(image.height()); |
1073 | 1014 |
1074 // Tiling is implied. First we handle mirroring. | 1015 // Tiling is implied. First we handle mirroring. |
1075 if (tileModes[0] == SkShader::kMirror_TileMode) { | 1016 if (tileModes[0] == SkShader::kMirror_TileMode) { |
1076 SkMatrix xMirror; | 1017 SkMatrix xMirror; |
1077 xMirror.setScale(-1, 1); | 1018 xMirror.setScale(-1, 1); |
1078 xMirror.postTranslate(2 * width, 0); | 1019 xMirror.postTranslate(2 * width, 0); |
1079 drawBitmapMatrix(&canvas, *image, xMirror); | 1020 drawBitmapMatrix(&canvas, image, xMirror); |
1080 patternBBox.fRight += width; | 1021 patternBBox.fRight += width; |
1081 } | 1022 } |
1082 if (tileModes[1] == SkShader::kMirror_TileMode) { | 1023 if (tileModes[1] == SkShader::kMirror_TileMode) { |
1083 SkMatrix yMirror; | 1024 SkMatrix yMirror; |
1084 yMirror.setScale(SK_Scalar1, -SK_Scalar1); | 1025 yMirror.setScale(SK_Scalar1, -SK_Scalar1); |
1085 yMirror.postTranslate(0, 2 * height); | 1026 yMirror.postTranslate(0, 2 * height); |
1086 drawBitmapMatrix(&canvas, *image, yMirror); | 1027 drawBitmapMatrix(&canvas, image, yMirror); |
1087 patternBBox.fBottom += height; | 1028 patternBBox.fBottom += height; |
1088 } | 1029 } |
1089 if (tileModes[0] == SkShader::kMirror_TileMode && | 1030 if (tileModes[0] == SkShader::kMirror_TileMode && |
1090 tileModes[1] == SkShader::kMirror_TileMode) { | 1031 tileModes[1] == SkShader::kMirror_TileMode) { |
1091 SkMatrix mirror; | 1032 SkMatrix mirror; |
1092 mirror.setScale(-1, -1); | 1033 mirror.setScale(-1, -1); |
1093 mirror.postTranslate(2 * width, 2 * height); | 1034 mirror.postTranslate(2 * width, 2 * height); |
1094 drawBitmapMatrix(&canvas, *image, mirror); | 1035 drawBitmapMatrix(&canvas, image, mirror); |
1095 } | 1036 } |
1096 | 1037 |
1097 // Then handle Clamping, which requires expanding the pattern canvas to | 1038 // Then handle Clamping, which requires expanding the pattern canvas to |
1098 // cover the entire surfaceBBox. | 1039 // cover the entire surfaceBBox. |
1099 | 1040 |
1100 // If both x and y are in clamp mode, we start by filling in the corners. | 1041 // If both x and y are in clamp mode, we start by filling in the corners. |
1101 // (Which are just a rectangles of the corner colors.) | 1042 // (Which are just a rectangles of the corner colors.) |
1102 if (tileModes[0] == SkShader::kClamp_TileMode && | 1043 if (tileModes[0] == SkShader::kClamp_TileMode && |
1103 tileModes[1] == SkShader::kClamp_TileMode) { | 1044 tileModes[1] == SkShader::kClamp_TileMode) { |
1104 SkPaint paint; | 1045 SkPaint paint; |
1105 SkRect rect; | 1046 SkRect rect; |
1106 rect = SkRect::MakeLTRB(deviceBounds.left(), deviceBounds.top(), 0, 0); | 1047 rect = SkRect::MakeLTRB(deviceBounds.left(), deviceBounds.top(), 0, 0); |
1107 if (!rect.isEmpty()) { | 1048 if (!rect.isEmpty()) { |
1108 paint.setColor(image->getColor(0, 0)); | 1049 paint.setColor(image.getColor(0, 0)); |
1109 canvas.drawRect(rect, paint); | 1050 canvas.drawRect(rect, paint); |
1110 } | 1051 } |
1111 | 1052 |
1112 rect = SkRect::MakeLTRB(width, deviceBounds.top(), | 1053 rect = SkRect::MakeLTRB(width, deviceBounds.top(), |
1113 deviceBounds.right(), 0); | 1054 deviceBounds.right(), 0); |
1114 if (!rect.isEmpty()) { | 1055 if (!rect.isEmpty()) { |
1115 paint.setColor(image->getColor(image->width() - 1, 0)); | 1056 paint.setColor(image.getColor(image.width() - 1, 0)); |
1116 canvas.drawRect(rect, paint); | 1057 canvas.drawRect(rect, paint); |
1117 } | 1058 } |
1118 | 1059 |
1119 rect = SkRect::MakeLTRB(width, height, | 1060 rect = SkRect::MakeLTRB(width, height, |
1120 deviceBounds.right(), deviceBounds.bottom()); | 1061 deviceBounds.right(), deviceBounds.bottom()); |
1121 if (!rect.isEmpty()) { | 1062 if (!rect.isEmpty()) { |
1122 paint.setColor(image->getColor(image->width() - 1, | 1063 paint.setColor(image.getColor(image.width() - 1, |
1123 image->height() - 1)); | 1064 image.height() - 1)); |
1124 canvas.drawRect(rect, paint); | 1065 canvas.drawRect(rect, paint); |
1125 } | 1066 } |
1126 | 1067 |
1127 rect = SkRect::MakeLTRB(deviceBounds.left(), height, | 1068 rect = SkRect::MakeLTRB(deviceBounds.left(), height, |
1128 0, deviceBounds.bottom()); | 1069 0, deviceBounds.bottom()); |
1129 if (!rect.isEmpty()) { | 1070 if (!rect.isEmpty()) { |
1130 paint.setColor(image->getColor(0, image->height() - 1)); | 1071 paint.setColor(image.getColor(0, image.height() - 1)); |
1131 canvas.drawRect(rect, paint); | 1072 canvas.drawRect(rect, paint); |
1132 } | 1073 } |
1133 } | 1074 } |
1134 | 1075 |
1135 // Then expand the left, right, top, then bottom. | 1076 // Then expand the left, right, top, then bottom. |
1136 if (tileModes[0] == SkShader::kClamp_TileMode) { | 1077 if (tileModes[0] == SkShader::kClamp_TileMode) { |
1137 SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, image->height()); | 1078 SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, image.height()); |
1138 if (deviceBounds.left() < 0) { | 1079 if (deviceBounds.left() < 0) { |
1139 SkBitmap left; | 1080 SkBitmap left; |
1140 SkAssertResult(image->extractSubset(&left, subset)); | 1081 SkAssertResult(image.extractSubset(&left, subset)); |
1141 | 1082 |
1142 SkMatrix leftMatrix; | 1083 SkMatrix leftMatrix; |
1143 leftMatrix.setScale(-deviceBounds.left(), 1); | 1084 leftMatrix.setScale(-deviceBounds.left(), 1); |
1144 leftMatrix.postTranslate(deviceBounds.left(), 0); | 1085 leftMatrix.postTranslate(deviceBounds.left(), 0); |
1145 drawBitmapMatrix(&canvas, left, leftMatrix); | 1086 drawBitmapMatrix(&canvas, left, leftMatrix); |
1146 | 1087 |
1147 if (tileModes[1] == SkShader::kMirror_TileMode) { | 1088 if (tileModes[1] == SkShader::kMirror_TileMode) { |
1148 leftMatrix.postScale(SK_Scalar1, -SK_Scalar1); | 1089 leftMatrix.postScale(SK_Scalar1, -SK_Scalar1); |
1149 leftMatrix.postTranslate(0, 2 * height); | 1090 leftMatrix.postTranslate(0, 2 * height); |
1150 drawBitmapMatrix(&canvas, left, leftMatrix); | 1091 drawBitmapMatrix(&canvas, left, leftMatrix); |
1151 } | 1092 } |
1152 patternBBox.fLeft = 0; | 1093 patternBBox.fLeft = 0; |
1153 } | 1094 } |
1154 | 1095 |
1155 if (deviceBounds.right() > width) { | 1096 if (deviceBounds.right() > width) { |
1156 SkBitmap right; | 1097 SkBitmap right; |
1157 subset.offset(image->width() - 1, 0); | 1098 subset.offset(image.width() - 1, 0); |
1158 SkAssertResult(image->extractSubset(&right, subset)); | 1099 SkAssertResult(image.extractSubset(&right, subset)); |
1159 | 1100 |
1160 SkMatrix rightMatrix; | 1101 SkMatrix rightMatrix; |
1161 rightMatrix.setScale(deviceBounds.right() - width, 1); | 1102 rightMatrix.setScale(deviceBounds.right() - width, 1); |
1162 rightMatrix.postTranslate(width, 0); | 1103 rightMatrix.postTranslate(width, 0); |
1163 drawBitmapMatrix(&canvas, right, rightMatrix); | 1104 drawBitmapMatrix(&canvas, right, rightMatrix); |
1164 | 1105 |
1165 if (tileModes[1] == SkShader::kMirror_TileMode) { | 1106 if (tileModes[1] == SkShader::kMirror_TileMode) { |
1166 rightMatrix.postScale(SK_Scalar1, -SK_Scalar1); | 1107 rightMatrix.postScale(SK_Scalar1, -SK_Scalar1); |
1167 rightMatrix.postTranslate(0, 2 * height); | 1108 rightMatrix.postTranslate(0, 2 * height); |
1168 drawBitmapMatrix(&canvas, right, rightMatrix); | 1109 drawBitmapMatrix(&canvas, right, rightMatrix); |
1169 } | 1110 } |
1170 patternBBox.fRight = deviceBounds.width(); | 1111 patternBBox.fRight = deviceBounds.width(); |
1171 } | 1112 } |
1172 } | 1113 } |
1173 | 1114 |
1174 if (tileModes[1] == SkShader::kClamp_TileMode) { | 1115 if (tileModes[1] == SkShader::kClamp_TileMode) { |
1175 SkIRect subset = SkIRect::MakeXYWH(0, 0, image->width(), 1); | 1116 SkIRect subset = SkIRect::MakeXYWH(0, 0, image.width(), 1); |
1176 if (deviceBounds.top() < 0) { | 1117 if (deviceBounds.top() < 0) { |
1177 SkBitmap top; | 1118 SkBitmap top; |
1178 SkAssertResult(image->extractSubset(&top, subset)); | 1119 SkAssertResult(image.extractSubset(&top, subset)); |
1179 | 1120 |
1180 SkMatrix topMatrix; | 1121 SkMatrix topMatrix; |
1181 topMatrix.setScale(SK_Scalar1, -deviceBounds.top()); | 1122 topMatrix.setScale(SK_Scalar1, -deviceBounds.top()); |
1182 topMatrix.postTranslate(0, deviceBounds.top()); | 1123 topMatrix.postTranslate(0, deviceBounds.top()); |
1183 drawBitmapMatrix(&canvas, top, topMatrix); | 1124 drawBitmapMatrix(&canvas, top, topMatrix); |
1184 | 1125 |
1185 if (tileModes[0] == SkShader::kMirror_TileMode) { | 1126 if (tileModes[0] == SkShader::kMirror_TileMode) { |
1186 topMatrix.postScale(-1, 1); | 1127 topMatrix.postScale(-1, 1); |
1187 topMatrix.postTranslate(2 * width, 0); | 1128 topMatrix.postTranslate(2 * width, 0); |
1188 drawBitmapMatrix(&canvas, top, topMatrix); | 1129 drawBitmapMatrix(&canvas, top, topMatrix); |
1189 } | 1130 } |
1190 patternBBox.fTop = 0; | 1131 patternBBox.fTop = 0; |
1191 } | 1132 } |
1192 | 1133 |
1193 if (deviceBounds.bottom() > height) { | 1134 if (deviceBounds.bottom() > height) { |
1194 SkBitmap bottom; | 1135 SkBitmap bottom; |
1195 subset.offset(0, image->height() - 1); | 1136 subset.offset(0, image.height() - 1); |
1196 SkAssertResult(image->extractSubset(&bottom, subset)); | 1137 SkAssertResult(image.extractSubset(&bottom, subset)); |
1197 | 1138 |
1198 SkMatrix bottomMatrix; | 1139 SkMatrix bottomMatrix; |
1199 bottomMatrix.setScale(SK_Scalar1, deviceBounds.bottom() - height); | 1140 bottomMatrix.setScale(SK_Scalar1, deviceBounds.bottom() - height); |
1200 bottomMatrix.postTranslate(0, height); | 1141 bottomMatrix.postTranslate(0, height); |
1201 drawBitmapMatrix(&canvas, bottom, bottomMatrix); | 1142 drawBitmapMatrix(&canvas, bottom, bottomMatrix); |
1202 | 1143 |
1203 if (tileModes[0] == SkShader::kMirror_TileMode) { | 1144 if (tileModes[0] == SkShader::kMirror_TileMode) { |
1204 bottomMatrix.postScale(-1, 1); | 1145 bottomMatrix.postScale(-1, 1); |
1205 bottomMatrix.postTranslate(2 * width, 0); | 1146 bottomMatrix.postTranslate(2 * width, 0); |
1206 drawBitmapMatrix(&canvas, bottom, bottomMatrix); | 1147 drawBitmapMatrix(&canvas, bottom, bottomMatrix); |
1207 } | 1148 } |
1208 patternBBox.fBottom = deviceBounds.height(); | 1149 patternBBox.fBottom = deviceBounds.height(); |
1209 } | 1150 } |
1210 } | 1151 } |
1211 | 1152 |
1212 // Put the canvas into the pattern stream (fContent). | 1153 auto imageShader = sk_make_sp<SkPDFStream>(patternDevice->content()); |
1213 SkPDFImageShader* imageShader = new SkPDFImageShader(autoState->release()); | |
1214 imageShader->setData(patternDevice->content()); | |
1215 | |
1216 auto resourceDict = patternDevice->makeResourceDict(); | |
1217 populate_tiling_pattern_dict(imageShader->dict(), patternBBox, | 1154 populate_tiling_pattern_dict(imageShader->dict(), patternBBox, |
1218 resourceDict.get(), finalMatrix); | 1155 patternDevice->makeResourceDict(), finalMatrix)
; |
1219 | |
1220 imageShader->fShaderState->fImage.unlockPixels(); | |
1221 | |
1222 doc->canon()->addImageShader(imageShader); | |
1223 return imageShader; | 1156 return imageShader; |
1224 } | 1157 } |
1225 | 1158 |
1226 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { | 1159 bool SkPDFShader::State::operator==(const SkPDFShader::State& b) const { |
1227 if (fType != b.fType || | 1160 if (fType != b.fType || |
1228 fCanvasTransform != b.fCanvasTransform || | 1161 fCanvasTransform != b.fCanvasTransform || |
1229 fShaderTransform != b.fShaderTransform || | 1162 fShaderTransform != b.fShaderTransform || |
1230 fBBox != b.fBBox) { | 1163 fBBox != b.fBBox) { |
1231 return false; | 1164 return false; |
1232 } | 1165 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 case SkShader::kSweep_GradientType: | 1203 case SkShader::kSweep_GradientType: |
1271 case SkShader::kNone_GradientType: | 1204 case SkShader::kNone_GradientType: |
1272 case SkShader::kColor_GradientType: | 1205 case SkShader::kColor_GradientType: |
1273 break; | 1206 break; |
1274 } | 1207 } |
1275 } | 1208 } |
1276 return true; | 1209 return true; |
1277 } | 1210 } |
1278 | 1211 |
1279 SkPDFShader::State::State(SkShader* shader, const SkMatrix& canvasTransform, | 1212 SkPDFShader::State::State(SkShader* shader, const SkMatrix& canvasTransform, |
1280 const SkIRect& bbox, SkScalar rasterScale) | 1213 const SkIRect& bbox, SkScalar rasterScale, |
| 1214 SkBitmap* imageDst) |
1281 : fCanvasTransform(canvasTransform), | 1215 : fCanvasTransform(canvasTransform), |
1282 fBBox(bbox) { | 1216 fBBox(bbox) { |
| 1217 SkASSERT(imageDst); |
1283 fInfo.fColorCount = 0; | 1218 fInfo.fColorCount = 0; |
1284 fInfo.fColors = nullptr; | 1219 fInfo.fColors = nullptr; |
1285 fInfo.fColorOffsets = nullptr; | 1220 fInfo.fColorOffsets = nullptr; |
1286 fShaderTransform = shader->getLocalMatrix(); | 1221 fShaderTransform = shader->getLocalMatrix(); |
1287 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; | 1222 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; |
1288 | 1223 |
1289 fType = shader->asAGradient(&fInfo); | 1224 fType = shader->asAGradient(&fInfo); |
1290 | 1225 |
1291 if (fType == SkShader::kNone_GradientType) { | 1226 if (fType == SkShader::kNone_GradientType) { |
1292 if (!shader->isABitmap(&fImage, nullptr, fImageTileModes)) { | 1227 if (!shader->isABitmap(imageDst, nullptr, fImageTileModes)) { |
1293 // Generic fallback for unsupported shaders: | 1228 // Generic fallback for unsupported shaders: |
1294 // * allocate a bbox-sized bitmap | 1229 // * allocate a bbox-sized bitmap |
1295 // * shade the whole area | 1230 // * shade the whole area |
1296 // * use the result as a bitmap shader | 1231 // * use the result as a bitmap shader |
1297 | 1232 |
1298 // bbox is in device space. While that's exactly what we want for si
zing our bitmap, | 1233 // bbox is in device space. While that's exactly what we |
1299 // we need to map it into shader space for adjustments (to match | 1234 // want for sizing our bitmap, we need to map it into |
1300 // SkPDFImageShader::Create's behavior). | 1235 // shader space for adjustments (to match |
| 1236 // MakeImageShader's behavior). |
1301 SkRect shaderRect = SkRect::Make(bbox); | 1237 SkRect shaderRect = SkRect::Make(bbox); |
1302 if (!inverse_transform_bbox(canvasTransform, &shaderRect)) { | 1238 if (!inverse_transform_bbox(canvasTransform, &shaderRect)) { |
1303 fImage.reset(); | 1239 imageDst->reset(); |
1304 return; | 1240 return; |
1305 } | 1241 } |
1306 | 1242 |
1307 // Clamp the bitmap size to about 1M pixels | 1243 // Clamp the bitmap size to about 1M pixels |
1308 static const SkScalar kMaxBitmapArea = 1024 * 1024; | 1244 static const SkScalar kMaxBitmapArea = 1024 * 1024; |
1309 SkScalar bitmapArea = rasterScale * bbox.width() * rasterScale * bbo
x.height(); | 1245 SkScalar bitmapArea = rasterScale * bbox.width() * rasterScale * bbo
x.height(); |
1310 if (bitmapArea > kMaxBitmapArea) { | 1246 if (bitmapArea > kMaxBitmapArea) { |
1311 rasterScale *= SkScalarSqrt(kMaxBitmapArea / bitmapArea); | 1247 rasterScale *= SkScalarSqrt(kMaxBitmapArea / bitmapArea); |
1312 } | 1248 } |
1313 | 1249 |
1314 SkISize size = SkISize::Make(SkScalarRoundToInt(rasterScale * bbox.w
idth()), | 1250 SkISize size = SkISize::Make(SkScalarRoundToInt(rasterScale * bbox.w
idth()), |
1315 SkScalarRoundToInt(rasterScale * bbox.h
eight())); | 1251 SkScalarRoundToInt(rasterScale * bbox.h
eight())); |
1316 SkSize scale = SkSize::Make(SkIntToScalar(size.width()) / shaderRect
.width(), | 1252 SkSize scale = SkSize::Make(SkIntToScalar(size.width()) / shaderRect
.width(), |
1317 SkIntToScalar(size.height()) / shaderRec
t.height()); | 1253 SkIntToScalar(size.height()) / shaderRec
t.height()); |
1318 | 1254 |
1319 fImage.allocN32Pixels(size.width(), size.height()); | 1255 imageDst->allocN32Pixels(size.width(), size.height()); |
1320 fImage.eraseColor(SK_ColorTRANSPARENT); | 1256 imageDst->eraseColor(SK_ColorTRANSPARENT); |
1321 | 1257 |
1322 SkPaint p; | 1258 SkPaint p; |
1323 p.setShader(sk_ref_sp(shader)); | 1259 p.setShader(sk_ref_sp(shader)); |
1324 | 1260 |
1325 SkCanvas canvas(fImage); | 1261 SkCanvas canvas(*imageDst); |
1326 canvas.scale(scale.width(), scale.height()); | 1262 canvas.scale(scale.width(), scale.height()); |
1327 canvas.translate(-shaderRect.x(), -shaderRect.y()); | 1263 canvas.translate(-shaderRect.x(), -shaderRect.y()); |
1328 canvas.drawPaint(p); | 1264 canvas.drawPaint(p); |
1329 | 1265 |
1330 fShaderTransform.setTranslate(shaderRect.x(), shaderRect.y()); | 1266 fShaderTransform.setTranslate(shaderRect.x(), shaderRect.y()); |
1331 fShaderTransform.preScale(1 / scale.width(), 1 / scale.height()); | 1267 fShaderTransform.preScale(1 / scale.width(), 1 / scale.height()); |
1332 } | 1268 } |
1333 fBitmapKey = SkBitmapKey(fImage); | 1269 fBitmapKey = SkBitmapKey(*imageDst); |
1334 } else { | 1270 } else { |
1335 AllocateGradientInfoStorage(); | 1271 this->allocateGradientInfoStorage(); |
1336 shader->asAGradient(&fInfo); | 1272 shader->asAGradient(&fInfo); |
1337 } | 1273 } |
1338 } | 1274 } |
1339 | 1275 |
1340 SkPDFShader::State::State(const SkPDFShader::State& other) | 1276 SkPDFShader::State::State(const SkPDFShader::State& other) |
1341 : fType(other.fType), | 1277 : fType(other.fType), |
1342 fCanvasTransform(other.fCanvasTransform), | 1278 fCanvasTransform(other.fCanvasTransform), |
1343 fShaderTransform(other.fShaderTransform), | 1279 fShaderTransform(other.fShaderTransform), |
1344 fBBox(other.fBBox) | 1280 fBBox(other.fBBox) |
1345 { | 1281 { |
1346 // Only gradients supported for now, since that is all that is used. | 1282 // Only gradients supported for now, since that is all that is used. |
1347 // If needed, image state copy constructor can be added here later. | 1283 // If needed, image state copy constructor can be added here later. |
1348 SkASSERT(fType != SkShader::kNone_GradientType); | 1284 SkASSERT(fType != SkShader::kNone_GradientType); |
1349 | 1285 |
1350 if (fType != SkShader::kNone_GradientType) { | 1286 if (fType != SkShader::kNone_GradientType) { |
1351 fInfo = other.fInfo; | 1287 fInfo = other.fInfo; |
1352 | 1288 |
1353 AllocateGradientInfoStorage(); | 1289 this->allocateGradientInfoStorage(); |
1354 for (int i = 0; i < fInfo.fColorCount; i++) { | 1290 for (int i = 0; i < fInfo.fColorCount; i++) { |
1355 fInfo.fColors[i] = other.fInfo.fColors[i]; | 1291 fInfo.fColors[i] = other.fInfo.fColors[i]; |
1356 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; | 1292 fInfo.fColorOffsets[i] = other.fInfo.fColorOffsets[i]; |
1357 } | 1293 } |
1358 } | 1294 } |
1359 } | 1295 } |
1360 | 1296 |
1361 /** | 1297 /** |
1362 * Create a copy of this gradient state with alpha assigned to RGB luminousity. | 1298 * Create a copy of this gradient state with alpha assigned to RGB luminousity. |
1363 * Only valid for gradient states. | 1299 * Only valid for gradient states. |
1364 */ | 1300 */ |
1365 SkPDFShader::State* SkPDFShader::State::CreateAlphaToLuminosityState() const { | 1301 SkPDFShader::State SkPDFShader::State::MakeAlphaToLuminosityState() const { |
| 1302 SkASSERT(fBitmapKey == SkBitmapKey()); |
1366 SkASSERT(fType != SkShader::kNone_GradientType); | 1303 SkASSERT(fType != SkShader::kNone_GradientType); |
1367 | 1304 |
1368 SkPDFShader::State* newState = new SkPDFShader::State(*this); | 1305 SkPDFShader::State newState(*this); |
1369 | 1306 |
1370 for (int i = 0; i < fInfo.fColorCount; i++) { | 1307 for (int i = 0; i < fInfo.fColorCount; i++) { |
1371 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | 1308 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
1372 newState->fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); | 1309 newState.fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha); |
1373 } | 1310 } |
1374 | 1311 |
1375 return newState; | 1312 return newState; |
1376 } | 1313 } |
1377 | 1314 |
1378 /** | 1315 /** |
1379 * Create a copy of this gradient state with alpha set to fully opaque | 1316 * Create a copy of this gradient state with alpha set to fully opaque |
1380 * Only valid for gradient states. | 1317 * Only valid for gradient states. |
1381 */ | 1318 */ |
1382 SkPDFShader::State* SkPDFShader::State::CreateOpaqueState() const { | 1319 SkPDFShader::State SkPDFShader::State::MakeOpaqueState() const { |
| 1320 SkASSERT(fBitmapKey == SkBitmapKey()); |
1383 SkASSERT(fType != SkShader::kNone_GradientType); | 1321 SkASSERT(fType != SkShader::kNone_GradientType); |
1384 | 1322 |
1385 SkPDFShader::State* newState = new SkPDFShader::State(*this); | 1323 SkPDFShader::State newState(*this); |
1386 for (int i = 0; i < fInfo.fColorCount; i++) { | 1324 for (int i = 0; i < fInfo.fColorCount; i++) { |
1387 newState->fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], | 1325 newState.fInfo.fColors[i] = SkColorSetA(fInfo.fColors[i], |
1388 SK_AlphaOPAQUE); | 1326 SK_AlphaOPAQUE); |
1389 } | 1327 } |
1390 | 1328 |
1391 return newState; | 1329 return newState; |
1392 } | 1330 } |
1393 | 1331 |
1394 /** | 1332 /** |
1395 * Returns true if state is a gradient and the gradient has alpha. | 1333 * Returns true if state is a gradient and the gradient has alpha. |
1396 */ | 1334 */ |
1397 bool SkPDFShader::State::GradientHasAlpha() const { | 1335 bool SkPDFShader::State::GradientHasAlpha() const { |
1398 if (fType == SkShader::kNone_GradientType) { | 1336 if (fType == SkShader::kNone_GradientType) { |
1399 return false; | 1337 return false; |
1400 } | 1338 } |
1401 | 1339 |
1402 for (int i = 0; i < fInfo.fColorCount; i++) { | 1340 for (int i = 0; i < fInfo.fColorCount; i++) { |
1403 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); | 1341 SkAlpha alpha = SkColorGetA(fInfo.fColors[i]); |
1404 if (alpha != SK_AlphaOPAQUE) { | 1342 if (alpha != SK_AlphaOPAQUE) { |
1405 return true; | 1343 return true; |
1406 } | 1344 } |
1407 } | 1345 } |
1408 return false; | 1346 return false; |
1409 } | 1347 } |
1410 | 1348 |
1411 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1349 void SkPDFShader::State::allocateGradientInfoStorage() { |
1412 fColorData.set(sk_malloc_throw( | 1350 fColors.reset(new SkColor[fInfo.fColorCount]); |
1413 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1351 fStops.reset(new SkScalar[fInfo.fColorCount]); |
1414 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1352 fInfo.fColors = fColors.get(); |
1415 fInfo.fColorOffsets = | 1353 fInfo.fColorOffsets = fStops.get(); |
1416 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | |
1417 } | 1354 } |
OLD | NEW |