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

Side by Side Diff: src/pdf/SkPDFShader.cpp

Issue 2193973002: SkPDF: PDFShader code modernized. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2016-08-02 (Tuesday) 17:24:52 EDT Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pdf/SkPDFShader.h ('k') | src/pdf/SkPDFTypes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * 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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFShader.h ('k') | src/pdf/SkPDFTypes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698