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 | |
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 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); | |
218 ColorTuple *colorData = colorDataAlloc.get(); | |
219 const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); | |
220 for (int i = 0; i < info.fColorCount; i++) { | |
221 colorData[i][0] = SkScalarMul(SkColorGetR(info.fColors[i]), scale); | |
222 colorData[i][1] = SkScalarMul(SkColorGetG(info.fColors[i]), scale); | |
223 colorData[i][2] = SkScalarMul(SkColorGetB(info.fColors[i]), scale); | |
224 } | |
225 | |
226 // no need for a stitch function if there are only 2 stops. | |
227 if (info.fColorCount == 2) | |
228 return createInterpolationFunction(colorData[0], colorData[1]); | |
229 | |
230 auto encode = sk_make_sp<SkPDFArray>(); | |
231 auto bounds = sk_make_sp<SkPDFArray>(); | |
232 auto functions = sk_make_sp<SkPDFArray>(); | |
233 | |
234 auto domain = sk_make_sp<SkPDFArray>(); | |
235 domain->appendScalar(0); | |
236 domain->appendScalar(1.0f); | |
237 retval->insertObject("Domain", std::move(domain)); | |
238 retval->insertInt("FunctionType", 3); | |
239 | |
240 for (int i = 1; i < info.fColorCount; i++) { | |
241 SkScalar offset = 0; | |
242 if (functions->size() > 0) { | |
243 offset = info.fColorOffsets[i-1]; | |
244 if (offset >= 0.99998f) { | |
245 bounds->appendScalar(1.0f); | |
246 } else if (offset == 0) {// if a colorstop has offset 0, remove prev ious stops. | |
hal.canary
2016/05/04 17:42:59
does this ever happen?
offsets [0,0,1,1] with a c
| |
247 encode = sk_make_sp<SkPDFArray>(); | |
248 bounds = sk_make_sp<SkPDFArray>(); | |
249 functions = sk_make_sp<SkPDFArray>(); | |
250 } else { | |
251 bounds->appendScalar(offset); | |
252 } | |
253 } | |
254 | |
255 encode->appendScalar(0); | |
256 encode->appendScalar(1.0f); | |
257 | |
258 functions->appendObject(createInterpolationFunction(colorData[i-1], colo rData[i])); | |
259 | |
260 if (offset >= 0.99998f) { // stop at colorstop that has 100% offset. ign ore later ones. | |
261 break; | |
262 } | |
263 } | |
264 | |
265 retval->insertObject("Encode", std::move(encode)); | |
266 retval->insertObject("Bounds", std::move(bounds)); | |
267 retval->insertObject("Functions", std::move(functions)); | |
268 | |
269 return retval; | |
270 } | |
271 | |
272 | |
186 /* Map a value of t on the stack into [0, 1) for Repeat or Mirror tile mode. */ | 273 /* Map a value of t on the stack into [0, 1) for Repeat or Mirror tile mode. */ |
187 static void tileModeCode(SkShader::TileMode mode, | 274 static void tileModeCode(SkShader::TileMode mode, |
188 SkDynamicMemoryWStream* result) { | 275 SkDynamicMemoryWStream* result) { |
189 if (mode == SkShader::kRepeat_TileMode) { | 276 if (mode == SkShader::kRepeat_TileMode) { |
190 result->writeText("dup truncate sub\n"); // Get the fractional part. | 277 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) | 278 result->writeText("dup 0 le {1 add} if\n"); // Map (-1,0) => (0,1) |
192 return; | 279 return; |
193 } | 280 } |
194 | 281 |
195 if (mode == SkShader::kMirror_TileMode) { | 282 if (mode == SkShader::kMirror_TileMode) { |
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
706 } | 793 } |
707 | 794 |
708 SkPDFFunctionShader* SkPDFFunctionShader::Create( | 795 SkPDFFunctionShader* SkPDFFunctionShader::Create( |
709 SkPDFCanon* canon, std::unique_ptr<SkPDFShader::State>* autoState) { | 796 SkPDFCanon* canon, std::unique_ptr<SkPDFShader::State>* autoState) { |
710 const SkPDFShader::State& state = **autoState; | 797 const SkPDFShader::State& state = **autoState; |
711 | 798 |
712 void (*codeFunction)(const SkShader::GradientInfo& info, | 799 void (*codeFunction)(const SkShader::GradientInfo& info, |
713 const SkMatrix& perspectiveRemover, | 800 const SkMatrix& perspectiveRemover, |
714 SkDynamicMemoryWStream* function) = nullptr; | 801 SkDynamicMemoryWStream* function) = nullptr; |
715 SkPoint transformPoints[2]; | 802 SkPoint transformPoints[2]; |
803 const SkShader::GradientInfo* info = &state.fInfo; | |
716 | 804 |
717 // Depending on the type of the gradient, we want to transform the | 805 bool doStitchFunctions = (state.fType == SkShader::kLinear_GradientType || |
718 // coordinate space in different ways. | 806 state.fType == SkShader::kRadial_GradientType || |
719 const SkShader::GradientInfo* info = &state.fInfo; | 807 state.fType == SkShader::kConical_GradientType) && |
720 transformPoints[0] = info->fPoint[0]; | 808 info->fTileMode == SkShader::kClamp_TileMode; |
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 | 809 |
755 SkMatrix finalMatrix = state.fCanvasTransform; | 810 SkMatrix finalMatrix = state.fCanvasTransform; |
756 finalMatrix.preConcat(state.fShaderTransform); | 811 finalMatrix.preConcat(state.fShaderTransform); |
757 finalMatrix.preConcat(mapperMatrix); | |
758 | |
759 // Preserves as much as posible in the final matrix, and only removes | |
760 // the perspective. The inverse of the perspective is stored in | |
761 // perspectiveInverseOnly matrix and has 3 useful numbers | |
762 // (p0, p1, p2), while everything else is either 0 or 1. | |
763 // In this way the shader will handle it eficiently, with minimal code. | |
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 | 812 |
778 auto domain = sk_make_sp<SkPDFArray>(); | 813 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 | 814 |
785 SkDynamicMemoryWStream functionCode; | 815 int32_t shadingType = 1; |
816 auto pdfShader = sk_make_sp<SkPDFDict>(); | |
786 // The two point radial gradient further references | 817 // The two point radial gradient further references |
787 // state.fInfo | 818 // state.fInfo |
788 // in translating from x, y coordinates to the t parameter. So, we have | 819 // 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. | 820 // to transform the points and radii according to the calculated matrix. |
790 if (state.fType == SkShader::kConical_GradientType) { | 821 if (doStitchFunctions) { |
791 SkShader::GradientInfo twoPointRadialInfo = *info; | 822 pdfShader->insertObject("Function", std::move(gradientStitchCode(*info)) ); |
hal.canary
2016/05/04 12:57:17
don't need the std::move here, it is already a r-v
| |
792 SkMatrix inverseMapperMatrix; | 823 shadingType = (state.fType == SkShader::kLinear_GradientType) ? 2 : 3; |
793 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | 824 |
825 auto extend = sk_make_sp<SkPDFArray>(); | |
826 extend->reserve(2); | |
827 extend->appendBool(true); | |
828 extend->appendBool(true); | |
829 pdfShader->insertObject("Extend", std::move(extend)); | |
830 | |
831 auto coords = sk_make_sp<SkPDFArray>(); | |
832 if (state.fType == SkShader::kConical_GradientType) { | |
833 coords->reserve(6); | |
834 coords->appendScalar(info->fPoint[0].fX); | |
835 coords->appendScalar(info->fPoint[0].fY); | |
836 coords->appendScalar(info->fRadius[0]); | |
837 | |
838 coords->appendScalar(info->fPoint[1].fX); | |
839 coords->appendScalar(info->fPoint[1].fY); | |
840 coords->appendScalar(info->fRadius[1]); | |
841 } else if (state.fType == SkShader::kRadial_GradientType) { | |
842 coords->reserve(6); | |
843 coords->appendScalar(info->fPoint[0].fX); | |
844 coords->appendScalar(info->fPoint[0].fY); | |
845 coords->appendScalar(0); | |
846 | |
847 coords->appendScalar(info->fPoint[0].fX); | |
848 coords->appendScalar(info->fPoint[0].fY); | |
849 coords->appendScalar(info->fRadius[0]); | |
850 } else { | |
851 coords->reserve(4); | |
852 coords->appendScalar(info->fPoint[0].fX); | |
853 coords->appendScalar(info->fPoint[0].fY); | |
854 | |
855 coords->appendScalar(info->fPoint[1].fX); | |
856 coords->appendScalar(info->fPoint[1].fY); | |
857 } | |
858 | |
859 pdfShader->insertObject("Coords", std::move(coords)); | |
860 } else { | |
861 // Depending on the type of the gradient, we want to transform the | |
862 // coordinate space in different ways. | |
863 transformPoints[0] = info->fPoint[0]; | |
864 transformPoints[1] = info->fPoint[1]; | |
865 switch (state.fType) { | |
866 case SkShader::kLinear_GradientType: | |
867 codeFunction = &linearCode; | |
868 break; | |
869 case SkShader::kRadial_GradientType: | |
870 transformPoints[1] = transformPoints[0]; | |
871 transformPoints[1].fX += info->fRadius[0]; | |
872 codeFunction = &radialCode; | |
873 break; | |
874 case SkShader::kConical_GradientType: { | |
875 transformPoints[1] = transformPoints[0]; | |
876 transformPoints[1].fX += SK_Scalar1; | |
877 codeFunction = &twoPointConicalCode; | |
878 break; | |
879 } | |
880 case SkShader::kSweep_GradientType: | |
881 transformPoints[1] = transformPoints[0]; | |
882 transformPoints[1].fX += SK_Scalar1; | |
883 codeFunction = &sweepCode; | |
884 break; | |
885 case SkShader::kColor_GradientType: | |
886 case SkShader::kNone_GradientType: | |
887 default: | |
888 return nullptr; | |
889 } | |
890 | |
891 // Move any scaling (assuming a unit gradient) or translation | |
892 // (and rotation for linear gradient), of the final gradient from | |
893 // info->fPoints to the matrix (updating bbox appropriately). Now | |
894 // the gradient can be drawn on on the unit segment. | |
895 SkMatrix mapperMatrix; | |
896 unitToPointsMatrix(transformPoints, &mapperMatrix); | |
897 | |
898 finalMatrix.preConcat(mapperMatrix); | |
899 | |
900 // Preserves as much as posible in the final matrix, and only removes | |
901 // the perspective. The inverse of the perspective is stored in | |
902 // perspectiveInverseOnly matrix and has 3 useful numbers | |
903 // (p0, p1, p2), while everything else is either 0 or 1. | |
904 // In this way the shader will handle it eficiently, with minimal code. | |
905 SkMatrix perspectiveInverseOnly = SkMatrix::I(); | |
906 if (finalMatrix.hasPerspective()) { | |
907 if (!split_perspective(finalMatrix, | |
908 &finalMatrix, &perspectiveInverseOnly)) { | |
909 return nullptr; | |
910 } | |
911 } | |
912 | |
913 SkRect bbox; | |
914 bbox.set(state.fBBox); | |
915 if (!inverse_transform_bbox(finalMatrix, &bbox)) { | |
794 return nullptr; | 916 return nullptr; |
795 } | 917 } |
796 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | 918 domain->reserve(4); |
797 twoPointRadialInfo.fRadius[0] = | 919 domain->appendScalar(bbox.fLeft); |
798 inverseMapperMatrix.mapRadius(info->fRadius[0]); | 920 domain->appendScalar(bbox.fRight); |
799 twoPointRadialInfo.fRadius[1] = | 921 domain->appendScalar(bbox.fTop); |
800 inverseMapperMatrix.mapRadius(info->fRadius[1]); | 922 domain->appendScalar(bbox.fBottom); |
801 codeFunction(twoPointRadialInfo, perspectiveInverseOnly, &functionCode); | 923 |
802 } else { | 924 SkDynamicMemoryWStream functionCode; |
803 codeFunction(*info, perspectiveInverseOnly, &functionCode); | 925 |
926 if (state.fType == SkShader::kConical_GradientType) { | |
927 SkShader::GradientInfo twoPointRadialInfo = *info; | |
928 SkMatrix inverseMapperMatrix; | |
929 if (!mapperMatrix.invert(&inverseMapperMatrix)) { | |
930 return nullptr; | |
931 } | |
932 inverseMapperMatrix.mapPoints(twoPointRadialInfo.fPoint, 2); | |
933 twoPointRadialInfo.fRadius[0] = | |
934 inverseMapperMatrix.mapRadius(info->fRadius[0]); | |
935 twoPointRadialInfo.fRadius[1] = | |
936 inverseMapperMatrix.mapRadius(info->fRadius[1]); | |
937 codeFunction(twoPointRadialInfo, perspectiveInverseOnly, &functionCo de); | |
938 } else { | |
939 codeFunction(*info, perspectiveInverseOnly, &functionCode); | |
940 } | |
941 | |
942 pdfShader->insertObject("Domain", sk_ref_sp(domain.get())); | |
943 | |
944 // Call canon->makeRangeObject() instead of | |
945 // SkPDFShader::MakeRangeObject() so that the canon can | |
946 // deduplicate. | |
947 std::unique_ptr<SkStreamAsset> functionStream( | |
948 functionCode.detachAsStream()); | |
949 auto function = make_ps_function(std::move(functionStream), domain.get() , | |
950 canon->makeRangeObject()); | |
951 pdfShader->insertObjRef("Function", std::move(function)); | |
804 } | 952 } |
805 | 953 |
806 auto pdfShader = sk_make_sp<SkPDFDict>(); | 954 pdfShader->insertInt("ShadingType", shadingType); |
807 pdfShader->insertInt("ShadingType", 1); | |
808 pdfShader->insertName("ColorSpace", "DeviceRGB"); | 955 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 | 956 |
820 sk_sp<SkPDFFunctionShader> pdfFunctionShader( | 957 sk_sp<SkPDFFunctionShader> pdfFunctionShader( |
821 new SkPDFFunctionShader(autoState->release())); | 958 new SkPDFFunctionShader(autoState->release())); |
822 pdfFunctionShader->insertInt("PatternType", 2); | 959 pdfFunctionShader->insertInt("PatternType", 2); |
823 pdfFunctionShader->insertObject("Matrix", | 960 pdfFunctionShader->insertObject("Matrix", |
824 SkPDFUtils::MatrixToArray(finalMatrix)); | 961 SkPDFUtils::MatrixToArray(finalMatrix)); |
825 pdfFunctionShader->insertObject("Shading", std::move(pdfShader)); | 962 pdfFunctionShader->insertObject("Shading", std::move(pdfShader)); |
826 | 963 |
827 canon->addFunctionShader(pdfFunctionShader.get()); | 964 canon->addFunctionShader(pdfFunctionShader.get()); |
828 return pdfFunctionShader.release(); | 965 return pdfFunctionShader.release(); |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1231 return false; | 1368 return false; |
1232 } | 1369 } |
1233 | 1370 |
1234 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1371 void SkPDFShader::State::AllocateGradientInfoStorage() { |
1235 fColorData.set(sk_malloc_throw( | 1372 fColorData.set(sk_malloc_throw( |
1236 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1373 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
1237 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1374 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
1238 fInfo.fColorOffsets = | 1375 fInfo.fColorOffsets = |
1239 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | 1376 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
1240 } | 1377 } |
OLD | NEW |