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

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

Issue 1925233003: SkPDF: Use type 2/3 shading for gradient shaders (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: redesigned gradient stop logic Created 4 years, 6 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 | « no previous file | no next file » | 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698