OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkPDFShader.h" | 10 #include "SkPDFShader.h" |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 static SkPDFObject* get_pdf_shader_by_state( | 488 static SkPDFObject* get_pdf_shader_by_state( |
489 SkPDFCanon* canon, | 489 SkPDFCanon* canon, |
490 SkScalar dpi, | 490 SkScalar dpi, |
491 SkAutoTDelete<SkPDFShader::State>* autoState) { | 491 SkAutoTDelete<SkPDFShader::State>* autoState) { |
492 const SkPDFShader::State& state = **autoState; | 492 const SkPDFShader::State& state = **autoState; |
493 if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) { | 493 if (state.fType == SkShader::kNone_GradientType && state.fImage.isNull()) { |
494 // TODO(vandebo) This drops SKComposeShader on the floor. We could | 494 // TODO(vandebo) This drops SKComposeShader on the floor. We could |
495 // handle compose shader by pulling things up to a layer, drawing with | 495 // handle compose shader by pulling things up to a layer, drawing with |
496 // the first shader, applying the xfer mode and drawing again with the | 496 // the first shader, applying the xfer mode and drawing again with the |
497 // second shader, then applying the layer to the original drawing. | 497 // second shader, then applying the layer to the original drawing. |
498 return NULL; | 498 return nullptr; |
499 } else if (state.fType == SkShader::kNone_GradientType) { | 499 } else if (state.fType == SkShader::kNone_GradientType) { |
500 SkPDFObject* shader = canon->findImageShader(state); | 500 SkPDFObject* shader = canon->findImageShader(state); |
501 return shader ? SkRef(shader) | 501 return shader ? SkRef(shader) |
502 : SkPDFImageShader::Create(canon, dpi, autoState); | 502 : SkPDFImageShader::Create(canon, dpi, autoState); |
503 } else if (state.GradientHasAlpha()) { | 503 } else if (state.GradientHasAlpha()) { |
504 SkPDFObject* shader = canon->findAlphaShader(state); | 504 SkPDFObject* shader = canon->findAlphaShader(state); |
505 return shader ? SkRef(shader) | 505 return shader ? SkRef(shader) |
506 : SkPDFAlphaFunctionShader::Create(canon, dpi, autoState); | 506 : SkPDFAlphaFunctionShader::Create(canon, dpi, autoState); |
507 } else { | 507 } else { |
508 SkPDFObject* shader = canon->findFunctionShader(state); | 508 SkPDFObject* shader = canon->findFunctionShader(state); |
(...skipping 17 matching lines...) Expand all Loading... |
526 SkPDFObject* functionShader, | 526 SkPDFObject* functionShader, |
527 SkPDFObject* gState) { | 527 SkPDFObject* gState) { |
528 SkTDArray<SkPDFObject*> patterns; | 528 SkTDArray<SkPDFObject*> patterns; |
529 if (functionShader) { | 529 if (functionShader) { |
530 patterns.push(functionShader); | 530 patterns.push(functionShader); |
531 } | 531 } |
532 SkTDArray<SkPDFObject*> graphicStates; | 532 SkTDArray<SkPDFObject*> graphicStates; |
533 if (gState) { | 533 if (gState) { |
534 graphicStates.push(gState); | 534 graphicStates.push(gState); |
535 } | 535 } |
536 return SkPDFResourceDict::Create(&graphicStates, &patterns, NULL, NULL); | 536 return SkPDFResourceDict::Create(&graphicStates, &patterns, nullptr, nullptr
); |
537 } | 537 } |
538 | 538 |
539 static void populate_tiling_pattern_dict(SkPDFDict* pattern, | 539 static void populate_tiling_pattern_dict(SkPDFDict* pattern, |
540 SkRect& bbox, | 540 SkRect& bbox, |
541 SkPDFDict* resources, | 541 SkPDFDict* resources, |
542 const SkMatrix& matrix) { | 542 const SkMatrix& matrix) { |
543 const int kTiling_PatternType = 1; | 543 const int kTiling_PatternType = 1; |
544 const int kColoredTilingPattern_PaintType = 1; | 544 const int kColoredTilingPattern_PaintType = 1; |
545 const int kConstantSpacing_TilingType = 1; | 545 const int kConstantSpacing_TilingType = 1; |
546 | 546 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 bbox.set(state.fBBox); | 585 bbox.set(state.fBBox); |
586 | 586 |
587 SkAutoTDelete<SkPDFShader::State> alphaToLuminosityState( | 587 SkAutoTDelete<SkPDFShader::State> alphaToLuminosityState( |
588 state.CreateAlphaToLuminosityState()); | 588 state.CreateAlphaToLuminosityState()); |
589 SkAutoTUnref<SkPDFObject> luminosityShader( | 589 SkAutoTUnref<SkPDFObject> luminosityShader( |
590 get_pdf_shader_by_state(canon, dpi, &alphaToLuminosityState)); | 590 get_pdf_shader_by_state(canon, dpi, &alphaToLuminosityState)); |
591 | 591 |
592 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); | 592 SkAutoTDelete<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); |
593 | 593 |
594 SkAutoTUnref<SkPDFDict> | 594 SkAutoTUnref<SkPDFDict> |
595 resources(get_gradient_resource_dict(luminosityShader, NULL)); | 595 resources(get_gradient_resource_dict(luminosityShader, nullptr)); |
596 | 596 |
597 SkAutoTUnref<SkPDFFormXObject> alphaMask( | 597 SkAutoTUnref<SkPDFFormXObject> alphaMask( |
598 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); | 598 new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); |
599 | 599 |
600 return SkPDFGraphicState::GetSMaskGraphicState( | 600 return SkPDFGraphicState::GetSMaskGraphicState( |
601 alphaMask.get(), false, | 601 alphaMask.get(), false, |
602 SkPDFGraphicState::kLuminosity_SMaskMode); | 602 SkPDFGraphicState::kLuminosity_SMaskMode); |
603 } | 603 } |
604 | 604 |
605 SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( | 605 SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( |
606 SkPDFCanon* canon, | 606 SkPDFCanon* canon, |
607 SkScalar dpi, | 607 SkScalar dpi, |
608 SkAutoTDelete<SkPDFShader::State>* autoState) { | 608 SkAutoTDelete<SkPDFShader::State>* autoState) { |
609 const SkPDFShader::State& state = **autoState; | 609 const SkPDFShader::State& state = **autoState; |
610 SkRect bbox; | 610 SkRect bbox; |
611 bbox.set(state.fBBox); | 611 bbox.set(state.fBBox); |
612 | 612 |
613 SkAutoTDelete<SkPDFShader::State> opaqueState(state.CreateOpaqueState()); | 613 SkAutoTDelete<SkPDFShader::State> opaqueState(state.CreateOpaqueState()); |
614 | 614 |
615 SkAutoTUnref<SkPDFObject> colorShader( | 615 SkAutoTUnref<SkPDFObject> colorShader( |
616 get_pdf_shader_by_state(canon, dpi, &opaqueState)); | 616 get_pdf_shader_by_state(canon, dpi, &opaqueState)); |
617 if (!colorShader) { | 617 if (!colorShader) { |
618 return NULL; | 618 return nullptr; |
619 } | 619 } |
620 | 620 |
621 // Create resource dict with alpha graphics state as G0 and | 621 // Create resource dict with alpha graphics state as G0 and |
622 // pattern shader as P0, then write content stream. | 622 // pattern shader as P0, then write content stream. |
623 SkAutoTUnref<SkPDFObject> alphaGs( | 623 SkAutoTUnref<SkPDFObject> alphaGs( |
624 create_smask_graphic_state(canon, dpi, state)); | 624 create_smask_graphic_state(canon, dpi, state)); |
625 | 625 |
626 SkPDFAlphaFunctionShader* alphaFunctionShader = | 626 SkPDFAlphaFunctionShader* alphaFunctionShader = |
627 new SkPDFAlphaFunctionShader(autoState->detach()); | 627 new SkPDFAlphaFunctionShader(autoState->detach()); |
628 | 628 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 result->insertObject("Domain", SkRef(domain)); | 705 result->insertObject("Domain", SkRef(domain)); |
706 result->insertObject("Range", SkRef(rangeObject.get())); | 706 result->insertObject("Range", SkRef(rangeObject.get())); |
707 return result; | 707 return result; |
708 } | 708 } |
709 | 709 |
710 SkPDFFunctionShader* SkPDFFunctionShader::Create( | 710 SkPDFFunctionShader* SkPDFFunctionShader::Create( |
711 SkPDFCanon* canon, SkAutoTDelete<SkPDFShader::State>* autoState) { | 711 SkPDFCanon* canon, SkAutoTDelete<SkPDFShader::State>* autoState) { |
712 const SkPDFShader::State& state = **autoState; | 712 const SkPDFShader::State& state = **autoState; |
713 | 713 |
714 SkString (*codeFunction)(const SkShader::GradientInfo& info, | 714 SkString (*codeFunction)(const SkShader::GradientInfo& info, |
715 const SkMatrix& perspectiveRemover) = NULL; | 715 const SkMatrix& perspectiveRemover) = nullptr; |
716 SkPoint transformPoints[2]; | 716 SkPoint transformPoints[2]; |
717 | 717 |
718 // Depending on the type of the gradient, we want to transform the | 718 // Depending on the type of the gradient, we want to transform the |
719 // coordinate space in different ways. | 719 // coordinate space in different ways. |
720 const SkShader::GradientInfo* info = &state.fInfo; | 720 const SkShader::GradientInfo* info = &state.fInfo; |
721 transformPoints[0] = info->fPoint[0]; | 721 transformPoints[0] = info->fPoint[0]; |
722 transformPoints[1] = info->fPoint[1]; | 722 transformPoints[1] = info->fPoint[1]; |
723 switch (state.fType) { | 723 switch (state.fType) { |
724 case SkShader::kLinear_GradientType: | 724 case SkShader::kLinear_GradientType: |
725 codeFunction = &linearCode; | 725 codeFunction = &linearCode; |
(...skipping 10 matching lines...) Expand all Loading... |
736 break; | 736 break; |
737 } | 737 } |
738 case SkShader::kSweep_GradientType: | 738 case SkShader::kSweep_GradientType: |
739 transformPoints[1] = transformPoints[0]; | 739 transformPoints[1] = transformPoints[0]; |
740 transformPoints[1].fX += SK_Scalar1; | 740 transformPoints[1].fX += SK_Scalar1; |
741 codeFunction = &sweepCode; | 741 codeFunction = &sweepCode; |
742 break; | 742 break; |
743 case SkShader::kColor_GradientType: | 743 case SkShader::kColor_GradientType: |
744 case SkShader::kNone_GradientType: | 744 case SkShader::kNone_GradientType: |
745 default: | 745 default: |
746 return NULL; | 746 return nullptr; |
747 } | 747 } |
748 | 748 |
749 // Move any scaling (assuming a unit gradient) or translation | 749 // Move any scaling (assuming a unit gradient) or translation |
750 // (and rotation for linear gradient), of the final gradient from | 750 // (and rotation for linear gradient), of the final gradient from |
751 // info->fPoints to the matrix (updating bbox appropriately). Now | 751 // info->fPoints to the matrix (updating bbox appropriately). Now |
752 // the gradient can be drawn on on the unit segment. | 752 // the gradient can be drawn on on the unit segment. |
753 SkMatrix mapperMatrix; | 753 SkMatrix mapperMatrix; |
754 unitToPointsMatrix(transformPoints, &mapperMatrix); | 754 unitToPointsMatrix(transformPoints, &mapperMatrix); |
755 | 755 |
756 SkMatrix finalMatrix = state.fCanvasTransform; | 756 SkMatrix finalMatrix = state.fCanvasTransform; |
757 finalMatrix.preConcat(state.fShaderTransform); | 757 finalMatrix.preConcat(state.fShaderTransform); |
758 finalMatrix.preConcat(mapperMatrix); | 758 finalMatrix.preConcat(mapperMatrix); |
759 | 759 |
760 // Preserves as much as posible in the final matrix, and only removes | 760 // Preserves as much as posible in the final matrix, and only removes |
761 // the perspective. The inverse of the perspective is stored in | 761 // the perspective. The inverse of the perspective is stored in |
762 // perspectiveInverseOnly matrix and has 3 useful numbers | 762 // perspectiveInverseOnly matrix and has 3 useful numbers |
763 // (p0, p1, p2), while everything else is either 0 or 1. | 763 // (p0, p1, p2), while everything else is either 0 or 1. |
764 // In this way the shader will handle it eficiently, with minimal code. | 764 // In this way the shader will handle it eficiently, with minimal code. |
765 SkMatrix perspectiveInverseOnly = SkMatrix::I(); | 765 SkMatrix perspectiveInverseOnly = SkMatrix::I(); |
766 if (finalMatrix.hasPerspective()) { | 766 if (finalMatrix.hasPerspective()) { |
767 if (!split_perspective(finalMatrix, | 767 if (!split_perspective(finalMatrix, |
768 &finalMatrix, &perspectiveInverseOnly)) { | 768 &finalMatrix, &perspectiveInverseOnly)) { |
769 return NULL; | 769 return nullptr; |
770 } | 770 } |
771 } | 771 } |
772 | 772 |
773 SkRect bbox; | 773 SkRect bbox; |
774 bbox.set(state.fBBox); | 774 bbox.set(state.fBBox); |
775 if (!inverse_transform_bbox(finalMatrix, &bbox)) { | 775 if (!inverse_transform_bbox(finalMatrix, &bbox)) { |
776 return NULL; | 776 return nullptr; |
777 } | 777 } |
778 | 778 |
779 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); | 779 SkAutoTUnref<SkPDFArray> domain(new SkPDFArray); |
780 domain->reserve(4); | 780 domain->reserve(4); |
781 domain->appendScalar(bbox.fLeft); | 781 domain->appendScalar(bbox.fLeft); |
782 domain->appendScalar(bbox.fRight); | 782 domain->appendScalar(bbox.fRight); |
783 domain->appendScalar(bbox.fTop); | 783 domain->appendScalar(bbox.fTop); |
784 domain->appendScalar(bbox.fBottom); | 784 domain->appendScalar(bbox.fBottom); |
785 | 785 |
786 SkString functionCode; | 786 SkString functionCode; |
787 // The two point radial gradient further references | 787 // The two point radial gradient further references |
788 // state.fInfo | 788 // state.fInfo |
789 // in translating from x, y coordinates to the t parameter. So, we have | 789 // in translating from x, y coordinates to the t parameter. So, we have |
790 // to transform the points and radii according to the calculated matrix. | 790 // to transform the points and radii according to the calculated matrix. |
791 if (state.fType == SkShader::kConical_GradientType) { | 791 if (state.fType == SkShader::kConical_GradientType) { |
792 SkShader::GradientInfo twoPointRadialInfo = *info; | 792 SkShader::GradientInfo twoPointRadialInfo = *info; |
793 SkMatrix inverseMapperMatrix; | 793 SkMatrix inverseMapperMatrix; |
794 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | 794 if (!mapperMatrix.invert(&inverseMapperMatrix)) { |
795 return NULL; | 795 return nullptr; |
796 } | 796 } |
797 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | 797 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); |
798 twoPointRadialInfo.fRadius[0] = | 798 twoPointRadialInfo.fRadius[0] = |
799 inverseMapperMatrix.mapRadius(info->fRadius[0]); | 799 inverseMapperMatrix.mapRadius(info->fRadius[0]); |
800 twoPointRadialInfo.fRadius[1] = | 800 twoPointRadialInfo.fRadius[1] = |
801 inverseMapperMatrix.mapRadius(info->fRadius[1]); | 801 inverseMapperMatrix.mapRadius(info->fRadius[1]); |
802 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); | 802 functionCode = codeFunction(twoPointRadialInfo, perspectiveInverseOnly); |
803 } else { | 803 } else { |
804 functionCode = codeFunction(*info, perspectiveInverseOnly); | 804 functionCode = codeFunction(*info, perspectiveInverseOnly); |
805 } | 805 } |
(...skipping 30 matching lines...) Expand all Loading... |
836 // in pattern cell space (no scaling on the bitmap, though there may be | 836 // in pattern cell space (no scaling on the bitmap, though there may be |
837 // translations so that all content is in the device, coordinates > 0). | 837 // translations so that all content is in the device, coordinates > 0). |
838 | 838 |
839 // Map clip bounds to shader space to ensure the device is large enough | 839 // Map clip bounds to shader space to ensure the device is large enough |
840 // to handle fake clamping. | 840 // to handle fake clamping. |
841 SkMatrix finalMatrix = state.fCanvasTransform; | 841 SkMatrix finalMatrix = state.fCanvasTransform; |
842 finalMatrix.preConcat(state.fShaderTransform); | 842 finalMatrix.preConcat(state.fShaderTransform); |
843 SkRect deviceBounds; | 843 SkRect deviceBounds; |
844 deviceBounds.set(state.fBBox); | 844 deviceBounds.set(state.fBBox); |
845 if (!inverse_transform_bbox(finalMatrix, &deviceBounds)) { | 845 if (!inverse_transform_bbox(finalMatrix, &deviceBounds)) { |
846 return NULL; | 846 return nullptr; |
847 } | 847 } |
848 | 848 |
849 const SkBitmap* image = &state.fImage; | 849 const SkBitmap* image = &state.fImage; |
850 SkRect bitmapBounds; | 850 SkRect bitmapBounds; |
851 image->getBounds(&bitmapBounds); | 851 image->getBounds(&bitmapBounds); |
852 | 852 |
853 // For tiling modes, the bounds should be extended to include the bitmap, | 853 // For tiling modes, the bounds should be extended to include the bitmap, |
854 // otherwise the bitmap gets clipped out and the shader is empty and awful. | 854 // otherwise the bitmap gets clipped out and the shader is empty and awful. |
855 // For clamp modes, we're only interested in the clip region, whether | 855 // For clamp modes, we're only interested in the clip region, whether |
856 // or not the main bitmap is in it. | 856 // or not the main bitmap is in it. |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 } | 1092 } |
1093 return true; | 1093 return true; |
1094 } | 1094 } |
1095 | 1095 |
1096 SkPDFShader::State::State(const SkShader& shader, const SkMatrix& canvasTransfor
m, | 1096 SkPDFShader::State::State(const SkShader& shader, const SkMatrix& canvasTransfor
m, |
1097 const SkIRect& bbox, SkScalar rasterScale) | 1097 const SkIRect& bbox, SkScalar rasterScale) |
1098 : fCanvasTransform(canvasTransform), | 1098 : fCanvasTransform(canvasTransform), |
1099 fBBox(bbox), | 1099 fBBox(bbox), |
1100 fPixelGeneration(0) { | 1100 fPixelGeneration(0) { |
1101 fInfo.fColorCount = 0; | 1101 fInfo.fColorCount = 0; |
1102 fInfo.fColors = NULL; | 1102 fInfo.fColors = nullptr; |
1103 fInfo.fColorOffsets = NULL; | 1103 fInfo.fColorOffsets = nullptr; |
1104 fShaderTransform = shader.getLocalMatrix(); | 1104 fShaderTransform = shader.getLocalMatrix(); |
1105 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; | 1105 fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; |
1106 | 1106 |
1107 fType = shader.asAGradient(&fInfo); | 1107 fType = shader.asAGradient(&fInfo); |
1108 | 1108 |
1109 if (fType == SkShader::kNone_GradientType) { | 1109 if (fType == SkShader::kNone_GradientType) { |
1110 SkMatrix matrix; | 1110 SkMatrix matrix; |
1111 if (shader.isABitmap(&fImage, &matrix, fImageTileModes)) { | 1111 if (shader.isABitmap(&fImage, &matrix, fImageTileModes)) { |
1112 SkASSERT(matrix.isIdentity()); | 1112 SkASSERT(matrix.isIdentity()); |
1113 } else { | 1113 } else { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 return false; | 1229 return false; |
1230 } | 1230 } |
1231 | 1231 |
1232 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1232 void SkPDFShader::State::AllocateGradientInfoStorage() { |
1233 fColorData.set(sk_malloc_throw( | 1233 fColorData.set(sk_malloc_throw( |
1234 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1234 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
1235 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1235 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
1236 fInfo.fColorOffsets = | 1236 fInfo.fColorOffsets = |
1237 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | 1237 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
1238 } | 1238 } |
OLD | NEW |