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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 colorData[2][r,g,b]); | 115 colorData[2][r,g,b]); |
116 } else { | 116 } else { |
117 | 117 |
118 ... } else { | 118 ... } else { |
119 return colorData[info.fColorCount - 1][r,g,b]; | 119 return colorData[info.fColorCount - 1][r,g,b]; |
120 } | 120 } |
121 ... | 121 ... |
122 } | 122 } |
123 } | 123 } |
124 */ | 124 */ |
125 static const int kColorComponents = 3; | |
126 typedef SkScalar ColorTuple[kColorComponents]; | |
125 static void gradientFunctionCode(const SkShader::GradientInfo& info, | 127 static void gradientFunctionCode(const SkShader::GradientInfo& info, |
126 SkDynamicMemoryWStream* result) { | 128 SkDynamicMemoryWStream* result) { |
127 /* We want to linearly interpolate from the previous color to the next. | 129 /* We want to linearly interpolate from the previous color to the next. |
128 Scale the colors from 0..255 to 0..1 and determine the multipliers | 130 Scale the colors from 0..255 to 0..1 and determine the multipliers |
129 for interpolation. | 131 for interpolation. |
130 C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. | 132 C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. |
131 */ | 133 */ |
132 static const int kColorComponents = 3; | 134 |
133 typedef SkScalar ColorTuple[kColorComponents]; | |
134 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); | 135 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); |
135 ColorTuple *colorData = colorDataAlloc.get(); | 136 ColorTuple *colorData = colorDataAlloc.get(); |
136 const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); | 137 const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); |
137 for (int i = 0; i < info.fColorCount; i++) { | 138 for (int i = 0; i < info.fColorCount; i++) { |
138 colorData[i][0] = SkScalarMul(SkColorGetR(info.fColors[i]), scale); | 139 colorData[i][0] = SkScalarMul(SkColorGetR(info.fColors[i]), scale); |
139 colorData[i][1] = SkScalarMul(SkColorGetG(info.fColors[i]), scale); | 140 colorData[i][1] = SkScalarMul(SkColorGetG(info.fColors[i]), scale); |
140 colorData[i][2] = SkScalarMul(SkColorGetB(info.fColors[i]), scale); | 141 colorData[i][2] = SkScalarMul(SkColorGetB(info.fColors[i]), scale); |
141 } | 142 } |
142 | 143 |
143 // Clamp the initial color. | 144 // Clamp the initial color. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 result->writeText(" "); | 177 result->writeText(" "); |
177 SkPDFUtils::AppendScalar(colorData[info.fColorCount - 1][1], result); | 178 SkPDFUtils::AppendScalar(colorData[info.fColorCount - 1][1], result); |
178 result->writeText(" "); | 179 result->writeText(" "); |
179 SkPDFUtils::AppendScalar(colorData[info.fColorCount - 1][2], result); | 180 SkPDFUtils::AppendScalar(colorData[info.fColorCount - 1][2], result); |
180 | 181 |
181 for (int i = 0 ; i < gradients + 1; i++) { | 182 for (int i = 0 ; i < gradients + 1; i++) { |
182 result->writeText("} ifelse\n"); | 183 result->writeText("} ifelse\n"); |
183 } | 184 } |
184 } | 185 } |
185 | 186 |
187 static sk_sp<SkPDFDict> createInterpolationFunction(const ColorTuple& color1, | |
188 const ColorTuple& color2 ) { | |
189 auto retval = sk_make_sp<SkPDFDict>(); | |
190 | |
hal.canary
2016/06/17 17:08:55
nit: please remove trailing whitespace.
| |
191 auto c0 = sk_make_sp<SkPDFArray>(); | |
192 c0->appendScalar(color1[0]); | |
193 c0->appendScalar(color1[1]); | |
194 c0->appendScalar(color1[2]); | |
195 retval->insertObject("C0", std::move(c0)); | |
196 | |
197 auto c1 = sk_make_sp<SkPDFArray>(); | |
198 c1->appendScalar(color2[0]); | |
199 c1->appendScalar(color2[1]); | |
200 c1->appendScalar(color2[2]); | |
201 retval->insertObject("C1", std::move(c1)); | |
202 | |
203 auto domain = sk_make_sp<SkPDFArray>(); | |
204 domain->appendScalar(0); | |
205 domain->appendScalar(1.0f); | |
206 retval->insertObject("Domain", std::move(domain)); | |
207 | |
208 retval->insertInt("FunctionType", 2); | |
209 retval->insertScalar("N", 1.0f); | |
210 | |
211 return retval; | |
212 } | |
213 | |
214 static sk_sp<SkPDFDict> gradientStitchCode(const SkShader::GradientInfo& info) { | |
215 auto retval = sk_make_sp<SkPDFDict>(); | |
216 | |
217 // normalize color stops | |
218 int colorCount = info.fColorCount; | |
219 SkTDArray<SkColor> colors(info.fColors, colorCount); | |
220 SkTDArray<SkScalar> colorOffsets(info.fColorOffsets, colorCount); | |
221 | |
222 int i = 1; | |
223 while (i < colorCount - 1) { | |
224 // ensure stops are in order | |
225 if (colorOffsets[i - 1] > colorOffsets[i]) { | |
226 colorOffsets[i] = colorOffsets[i - 1]; | |
227 } | |
228 | |
229 // remove points that are between 2 coincident points | |
230 if ((colorOffsets[i - 1] == colorOffsets[i]) && (colorOffsets[i] == colo rOffsets[i + 1])) { | |
231 colorCount -= 1; | |
232 colors.remove(i); | |
233 colorOffsets.remove(i); | |
234 } else { | |
235 i++; | |
236 } | |
237 } | |
238 // find coincident points and slightly move them over | |
239 for (i = 1; i < colorCount - 1; i++) { | |
240 if (colorOffsets[i - 1] == colorOffsets[i]) { | |
241 colorOffsets[i] += 0.00001f; | |
242 } | |
243 } | |
244 // check if last 2 stops coincide | |
245 if (colorOffsets[i - 1] == colorOffsets[i]) { | |
246 colorOffsets[i - 1] -= 0.00001f; | |
247 } | |
248 | |
249 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(colorCount); | |
250 ColorTuple *colorData = colorDataAlloc.get(); | |
251 const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); | |
252 for (int i = 0; i < colorCount; i++) { | |
253 colorData[i][0] = SkScalarMul(SkColorGetR(colors[i]), scale); | |
254 colorData[i][1] = SkScalarMul(SkColorGetG(colors[i]), scale); | |
255 colorData[i][2] = SkScalarMul(SkColorGetB(colors[i]), scale); | |
256 } | |
257 | |
258 // no need for a stitch function if there are only 2 stops. | |
259 if (colorCount == 2) | |
260 return createInterpolationFunction(colorData[0], colorData[1]); | |
261 | |
262 auto encode = sk_make_sp<SkPDFArray>(); | |
263 auto bounds = sk_make_sp<SkPDFArray>(); | |
264 auto functions = sk_make_sp<SkPDFArray>(); | |
265 | |
266 auto domain = sk_make_sp<SkPDFArray>(); | |
267 domain->appendScalar(0); | |
268 domain->appendScalar(1.0f); | |
269 retval->insertObject("Domain", std::move(domain)); | |
270 retval->insertInt("FunctionType", 3); | |
271 | |
272 for (int i = 1; i < colorCount; i++) { | |
273 if (i > 1) { | |
274 bounds->appendScalar(colorOffsets[i-1]); | |
275 } | |
276 | |
277 encode->appendScalar(0); | |
278 encode->appendScalar(1.0f); | |
279 | |
280 functions->appendObject(createInterpolationFunction(colorData[i-1], colo rData[i])); | |
281 } | |
282 | |
283 retval->insertObject("Encode", std::move(encode)); | |
284 retval->insertObject("Bounds", std::move(bounds)); | |
285 retval->insertObject("Functions", std::move(functions)); | |
286 | |
287 return retval; | |
288 } | |
289 | |
290 | |
186 /* Map a value of t on the stack into [0, 1) for Repeat or Mirror tile mode. */ | 291 /* Map a value of t on the stack into [0, 1) for Repeat or Mirror tile mode. */ |
187 static void tileModeCode(SkShader::TileMode mode, | 292 static void tileModeCode(SkShader::TileMode mode, |
188 SkDynamicMemoryWStream* result) { | 293 SkDynamicMemoryWStream* result) { |
189 if (mode == SkShader::kRepeat_TileMode) { | 294 if (mode == SkShader::kRepeat_TileMode) { |
190 result->writeText("dup truncate sub\n"); // Get the fractional part. | 295 result->writeText("dup truncate sub\n"); // Get the fractional part. |
191 result->writeText("dup 0 le {1 add} if\n"); // Map (-1,0) => (0,1) | 296 result->writeText("dup 0 le {1 add} if\n"); // Map (-1,0) => (0,1) |
192 return; | 297 return; |
193 } | 298 } |
194 | 299 |
195 if (mode == SkShader::kMirror_TileMode) { | 300 if (mode == SkShader::kMirror_TileMode) { |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
698 std::unique_ptr<SkStreamAsset> psCode, | 803 std::unique_ptr<SkStreamAsset> psCode, |
699 SkPDFArray* domain, | 804 SkPDFArray* domain, |
700 sk_sp<SkPDFObject> range) { | 805 sk_sp<SkPDFObject> range) { |
701 auto result = sk_make_sp<SkPDFStream>(psCode.get()); | 806 auto result = sk_make_sp<SkPDFStream>(psCode.get()); |
702 result->insertInt("FunctionType", 4); | 807 result->insertInt("FunctionType", 4); |
703 result->insertObject("Domain", sk_ref_sp(domain)); | 808 result->insertObject("Domain", sk_ref_sp(domain)); |
704 result->insertObject("Range", std::move(range)); | 809 result->insertObject("Range", std::move(range)); |
705 return result; | 810 return result; |
706 } | 811 } |
707 | 812 |
813 // catch cases where the inner just touches the outer circle | |
814 // and make the inner circle just inside the outer one to match raster | |
815 static void FixUpRadius(const SkPoint& p1, SkScalar& r1, const SkPoint& p2, SkSc alar& r2) { | |
816 // detect touching circles | |
817 SkScalar distance = SkPoint::Distance(p1, p2); | |
818 SkScalar subtractRadii = fabs(r1 - r2); | |
819 if (fabs(distance - subtractRadii) < 0.002f) { | |
820 if (r1 > r2) { | |
821 r1 += 0.002f; | |
822 } else { | |
823 r2 += 0.002f; | |
824 } | |
825 } | |
826 } | |
827 | |
708 SkPDFFunctionShader* SkPDFFunctionShader::Create( | 828 SkPDFFunctionShader* SkPDFFunctionShader::Create( |
709 SkPDFCanon* canon, std::unique_ptr<SkPDFShader::State>* autoState) { | 829 SkPDFCanon* canon, std::unique_ptr<SkPDFShader::State>* autoState) { |
710 const SkPDFShader::State& state = **autoState; | 830 const SkPDFShader::State& state = **autoState; |
711 | 831 |
712 void (*codeFunction)(const SkShader::GradientInfo& info, | 832 void (*codeFunction)(const SkShader::GradientInfo& info, |
713 const SkMatrix& perspectiveRemover, | 833 const SkMatrix& perspectiveRemover, |
714 SkDynamicMemoryWStream* function) = nullptr; | 834 SkDynamicMemoryWStream* function) = nullptr; |
715 SkPoint transformPoints[2]; | 835 SkPoint transformPoints[2]; |
716 | |
717 // Depending on the type of the gradient, we want to transform the | |
718 // coordinate space in different ways. | |
719 const SkShader::GradientInfo* info = &state.fInfo; | 836 const SkShader::GradientInfo* info = &state.fInfo; |
720 transformPoints[0] = info->fPoint[0]; | |
721 transformPoints[1] = info->fPoint[1]; | |
722 switch (state.fType) { | |
723 case SkShader::kLinear_GradientType: | |
724 codeFunction = &linearCode; | |
725 break; | |
726 case SkShader::kRadial_GradientType: | |
727 transformPoints[1] = transformPoints[0]; | |
728 transformPoints[1].fX += info->fRadius[0]; | |
729 codeFunction = &radialCode; | |
730 break; | |
731 case SkShader::kConical_GradientType: { | |
732 transformPoints[1] = transformPoints[0]; | |
733 transformPoints[1].fX += SK_Scalar1; | |
734 codeFunction = &twoPointConicalCode; | |
735 break; | |
736 } | |
737 case SkShader::kSweep_GradientType: | |
738 transformPoints[1] = transformPoints[0]; | |
739 transformPoints[1].fX += SK_Scalar1; | |
740 codeFunction = &sweepCode; | |
741 break; | |
742 case SkShader::kColor_GradientType: | |
743 case SkShader::kNone_GradientType: | |
744 default: | |
745 return nullptr; | |
746 } | |
747 | |
748 // Move any scaling (assuming a unit gradient) or translation | |
749 // (and rotation for linear gradient), of the final gradient from | |
750 // info->fPoints to the matrix (updating bbox appropriately). Now | |
751 // the gradient can be drawn on on the unit segment. | |
752 SkMatrix mapperMatrix; | |
753 unitToPointsMatrix(transformPoints, &mapperMatrix); | |
754 | |
755 SkMatrix finalMatrix = state.fCanvasTransform; | 837 SkMatrix finalMatrix = state.fCanvasTransform; |
756 finalMatrix.preConcat(state.fShaderTransform); | 838 finalMatrix.preConcat(state.fShaderTransform); |
757 finalMatrix.preConcat(mapperMatrix); | |
758 | 839 |
759 // Preserves as much as posible in the final matrix, and only removes | 840 bool doStitchFunctions = (state.fType == SkShader::kLinear_GradientType || |
760 // the perspective. The inverse of the perspective is stored in | 841 state.fType == SkShader::kRadial_GradientType || |
761 // perspectiveInverseOnly matrix and has 3 useful numbers | 842 state.fType == SkShader::kConical_GradientType) && |
762 // (p0, p1, p2), while everything else is either 0 or 1. | 843 info->fTileMode == SkShader::kClamp_TileMode && |
763 // In this way the shader will handle it eficiently, with minimal code. | 844 !finalMatrix.hasPerspective(); |
764 SkMatrix perspectiveInverseOnly = SkMatrix::I(); | |
765 if (finalMatrix.hasPerspective()) { | |
766 if (!split_perspective(finalMatrix, | |
767 &finalMatrix, &perspectiveInverseOnly)) { | |
768 return nullptr; | |
769 } | |
770 } | |
771 | |
772 SkRect bbox; | |
773 bbox.set(state.fBBox); | |
774 if (!inverse_transform_bbox(finalMatrix, &bbox)) { | |
775 return nullptr; | |
776 } | |
777 | 845 |
778 auto domain = sk_make_sp<SkPDFArray>(); | 846 auto domain = sk_make_sp<SkPDFArray>(); |
779 domain->reserve(4); | |
780 domain->appendScalar(bbox.fLeft); | |
781 domain->appendScalar(bbox.fRight); | |
782 domain->appendScalar(bbox.fTop); | |
783 domain->appendScalar(bbox.fBottom); | |
784 | 847 |
785 SkDynamicMemoryWStream functionCode; | 848 int32_t shadingType = 1; |
849 auto pdfShader = sk_make_sp<SkPDFDict>(); | |
786 // The two point radial gradient further references | 850 // The two point radial gradient further references |
787 // state.fInfo | 851 // state.fInfo |
788 // in translating from x, y coordinates to the t parameter. So, we have | 852 // in translating from x, y coordinates to the t parameter. So, we have |
789 // to transform the points and radii according to the calculated matrix. | 853 // to transform the points and radii according to the calculated matrix. |
790 if (state.fType == SkShader::kConical_GradientType) { | 854 if (doStitchFunctions) { |
791 SkShader::GradientInfo twoPointRadialInfo = *info; | 855 pdfShader->insertObject("Function", gradientStitchCode(*info)); |
792 SkMatrix inverseMapperMatrix; | 856 shadingType = (state.fType == SkShader::kLinear_GradientType) ? 2 : 3; |
793 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | 857 |
858 auto extend = sk_make_sp<SkPDFArray>(); | |
859 extend->reserve(2); | |
860 extend->appendBool(true); | |
861 extend->appendBool(true); | |
862 pdfShader->insertObject("Extend", std::move(extend)); | |
863 | |
864 auto coords = sk_make_sp<SkPDFArray>(); | |
865 if (state.fType == SkShader::kConical_GradientType) { | |
866 coords->reserve(6); | |
867 SkScalar r1 = info->fRadius[0]; | |
868 SkScalar r2 = info->fRadius[1]; | |
869 SkPoint pt1 = info->fPoint[0]; | |
870 SkPoint pt2 = info->fPoint[1]; | |
871 FixUpRadius(pt1, r1, pt2, r2); | |
872 | |
873 coords->appendScalar(pt1.fX); | |
874 coords->appendScalar(pt1.fY); | |
875 coords->appendScalar(r1); | |
876 | |
877 coords->appendScalar(pt2.fX); | |
878 coords->appendScalar(pt2.fY); | |
879 coords->appendScalar(r2); | |
880 } else if (state.fType == SkShader::kRadial_GradientType) { | |
881 coords->reserve(6); | |
882 const SkPoint& pt1 = info->fPoint[0]; | |
883 | |
884 coords->appendScalar(pt1.fX); | |
885 coords->appendScalar(pt1.fY); | |
886 coords->appendScalar(0); | |
887 | |
888 coords->appendScalar(pt1.fX); | |
889 coords->appendScalar(pt1.fY); | |
890 coords->appendScalar(info->fRadius[0]); | |
891 } else { | |
892 coords->reserve(4); | |
893 const SkPoint& pt1 = info->fPoint[0]; | |
894 const SkPoint& pt2 = info->fPoint[1]; | |
895 | |
896 coords->appendScalar(pt1.fX); | |
897 coords->appendScalar(pt1.fY); | |
898 | |
899 coords->appendScalar(pt2.fX); | |
900 coords->appendScalar(pt2.fY); | |
901 } | |
902 | |
903 pdfShader->insertObject("Coords", std::move(coords)); | |
904 } else { | |
905 // Depending on the type of the gradient, we want to transform the | |
906 // coordinate space in different ways. | |
907 transformPoints[0] = info->fPoint[0]; | |
908 transformPoints[1] = info->fPoint[1]; | |
909 switch (state.fType) { | |
910 case SkShader::kLinear_GradientType: | |
911 codeFunction = &linearCode; | |
912 break; | |
913 case SkShader::kRadial_GradientType: | |
914 transformPoints[1] = transformPoints[0]; | |
915 transformPoints[1].fX += info->fRadius[0]; | |
916 codeFunction = &radialCode; | |
917 break; | |
918 case SkShader::kConical_GradientType: { | |
919 transformPoints[1] = transformPoints[0]; | |
920 transformPoints[1].fX += SK_Scalar1; | |
921 codeFunction = &twoPointConicalCode; | |
922 break; | |
923 } | |
924 case SkShader::kSweep_GradientType: | |
925 transformPoints[1] = transformPoints[0]; | |
926 transformPoints[1].fX += SK_Scalar1; | |
927 codeFunction = &sweepCode; | |
928 break; | |
929 case SkShader::kColor_GradientType: | |
930 case SkShader::kNone_GradientType: | |
931 default: | |
932 return nullptr; | |
933 } | |
934 | |
935 // Move any scaling (assuming a unit gradient) or translation | |
936 // (and rotation for linear gradient), of the final gradient from | |
937 // info->fPoints to the matrix (updating bbox appropriately). Now | |
938 // the gradient can be drawn on on the unit segment. | |
939 SkMatrix mapperMatrix; | |
940 unitToPointsMatrix(transformPoints, &mapperMatrix); | |
941 | |
942 finalMatrix.preConcat(mapperMatrix); | |
943 | |
944 // Preserves as much as posible in the final matrix, and only removes | |
945 // the perspective. The inverse of the perspective is stored in | |
946 // perspectiveInverseOnly matrix and has 3 useful numbers | |
947 // (p0, p1, p2), while everything else is either 0 or 1. | |
948 // In this way the shader will handle it eficiently, with minimal code. | |
949 SkMatrix perspectiveInverseOnly = SkMatrix::I(); | |
950 if (finalMatrix.hasPerspective()) { | |
951 if (!split_perspective(finalMatrix, | |
952 &finalMatrix, &perspectiveInverseOnly)) { | |
953 return nullptr; | |
954 } | |
955 } | |
956 | |
957 SkRect bbox; | |
958 bbox.set(state.fBBox); | |
959 if (!inverse_transform_bbox(finalMatrix, &bbox)) { | |
794 return nullptr; | 960 return nullptr; |
795 } | 961 } |
796 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | 962 domain->reserve(4); |
797 twoPointRadialInfo.fRadius[0] = | 963 domain->appendScalar(bbox.fLeft); |
798 inverseMapperMatrix.mapRadius(info->fRadius[0]); | 964 domain->appendScalar(bbox.fRight); |
799 twoPointRadialInfo.fRadius[1] = | 965 domain->appendScalar(bbox.fTop); |
800 inverseMapperMatrix.mapRadius(info->fRadius[1]); | 966 domain->appendScalar(bbox.fBottom); |
801 codeFunction(twoPointRadialInfo, perspectiveInverseOnly, &functionCode); | 967 |
802 } else { | 968 SkDynamicMemoryWStream functionCode; |
803 codeFunction(*info, perspectiveInverseOnly, &functionCode); | 969 |
970 if (state.fType == SkShader::kConical_GradientType) { | |
971 SkShader::GradientInfo twoPointRadialInfo = *info; | |
972 SkMatrix inverseMapperMatrix; | |
973 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | |
974 return nullptr; | |
975 } | |
976 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | |
977 twoPointRadialInfo.fRadius[0] = | |
978 inverseMapperMatrix.mapRadius(info->fRadius[0]); | |
979 twoPointRadialInfo.fRadius[1] = | |
980 inverseMapperMatrix.mapRadius(info->fRadius[1]); | |
981 codeFunction(twoPointRadialInfo, perspectiveInverseOnly, &functionCo de); | |
982 } else { | |
983 codeFunction(*info, perspectiveInverseOnly, &functionCode); | |
984 } | |
985 | |
986 pdfShader->insertObject("Domain", sk_ref_sp(domain.get())); | |
987 | |
988 // Call canon->makeRangeObject() instead of | |
989 // SkPDFShader::MakeRangeObject() so that the canon can | |
990 // deduplicate. | |
991 std::unique_ptr<SkStreamAsset> functionStream( | |
992 functionCode.detachAsStream()); | |
993 auto function = make_ps_function(std::move(functionStream), domain.get() , | |
994 canon->makeRangeObject()); | |
995 pdfShader->insertObjRef("Function", std::move(function)); | |
804 } | 996 } |
805 | 997 |
806 auto pdfShader = sk_make_sp<SkPDFDict>(); | 998 pdfShader->insertInt("ShadingType", shadingType); |
807 pdfShader->insertInt("ShadingType", 1); | |
808 pdfShader->insertName("ColorSpace", "DeviceRGB"); | 999 pdfShader->insertName("ColorSpace", "DeviceRGB"); |
809 pdfShader->insertObject("Domain", sk_ref_sp(domain.get())); | |
810 | |
811 // Call canon->makeRangeObject() instead of | |
812 // SkPDFShader::MakeRangeObject() so that the canon can | |
813 // deduplicate. | |
814 std::unique_ptr<SkStreamAsset> functionStream( | |
815 functionCode.detachAsStream()); | |
816 auto function = make_ps_function(std::move(functionStream), domain.get(), | |
817 canon->makeRangeObject()); | |
818 pdfShader->insertObjRef("Function", std::move(function)); | |
819 | 1000 |
820 sk_sp<SkPDFFunctionShader> pdfFunctionShader( | 1001 sk_sp<SkPDFFunctionShader> pdfFunctionShader( |
821 new SkPDFFunctionShader(autoState->release())); | 1002 new SkPDFFunctionShader(autoState->release())); |
822 pdfFunctionShader->insertInt("PatternType", 2); | 1003 pdfFunctionShader->insertInt("PatternType", 2); |
823 pdfFunctionShader->insertObject("Matrix", | 1004 pdfFunctionShader->insertObject("Matrix", |
824 SkPDFUtils::MatrixToArray(finalMatrix)); | 1005 SkPDFUtils::MatrixToArray(finalMatrix)); |
825 pdfFunctionShader->insertObject("Shading", std::move(pdfShader)); | 1006 pdfFunctionShader->insertObject("Shading", std::move(pdfShader)); |
826 | 1007 |
827 canon->addFunctionShader(pdfFunctionShader.get()); | 1008 canon->addFunctionShader(pdfFunctionShader.get()); |
828 return pdfFunctionShader.release(); | 1009 return pdfFunctionShader.release(); |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1231 return false; | 1412 return false; |
1232 } | 1413 } |
1233 | 1414 |
1234 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1415 void SkPDFShader::State::AllocateGradientInfoStorage() { |
1235 fColorData.set(sk_malloc_throw( | 1416 fColorData.set(sk_malloc_throw( |
1236 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1417 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
1237 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1418 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
1238 fInfo.fColorOffsets = | 1419 fInfo.fColorOffsets = |
1239 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | 1420 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
1240 } | 1421 } |
OLD | NEW |