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 "SkData.h" | 9 #include "SkData.h" |
10 #include "SkGeometry.h" | 10 #include "SkGeometry.h" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 SkPDFUtils::AppendScalar(bottom, content); | 111 SkPDFUtils::AppendScalar(bottom, content); |
112 content->writeText(" "); | 112 content->writeText(" "); |
113 SkPDFUtils::AppendScalar(rect.width(), content); | 113 SkPDFUtils::AppendScalar(rect.width(), content); |
114 content->writeText(" "); | 114 content->writeText(" "); |
115 SkPDFUtils::AppendScalar(rect.height(), content); | 115 SkPDFUtils::AppendScalar(rect.height(), content); |
116 content->writeText(" re\n"); | 116 content->writeText(" re\n"); |
117 } | 117 } |
118 | 118 |
119 // static | 119 // static |
120 void SkPDFUtils::EmitPath(const SkPath& path, SkPaint::Style paintStyle, | 120 void SkPDFUtils::EmitPath(const SkPath& path, SkPaint::Style paintStyle, |
121 SkWStream* content) { | 121 bool doConsumeDegerates, SkWStream* content) { |
122 // Filling a path with no area results in a drawing in PDF renderers but | 122 // Filling a path with no area results in a drawing in PDF renderers but |
123 // Chrome expects to be able to draw some such entities with no visible | 123 // Chrome expects to be able to draw some such entities with no visible |
124 // result, so we detect those cases and discard the drawing for them. | 124 // result, so we detect those cases and discard the drawing for them. |
125 // Specifically: moveTo(X), lineTo(Y) and moveTo(X), lineTo(X), lineTo(Y). | 125 // Specifically: moveTo(X), lineTo(Y) and moveTo(X), lineTo(X), lineTo(Y). |
126 enum SkipFillState { | 126 enum SkipFillState { |
127 kEmpty_SkipFillState = 0, | 127 kEmpty_SkipFillState, |
128 kSingleLine_SkipFillState = 1, | 128 kSingleLine_SkipFillState, |
129 kNonSingleLine_SkipFillState = 2, | 129 kNonSingleLine_SkipFillState, |
130 }; | 130 }; |
131 SkipFillState fillState = kEmpty_SkipFillState; | 131 SkipFillState fillState = kEmpty_SkipFillState; |
132 if (paintStyle != SkPaint::kFill_Style) { | 132 //if (paintStyle != SkPaint::kFill_Style) { |
133 fillState = kNonSingleLine_SkipFillState; | 133 // fillState = kNonSingleLine_SkipFillState; |
134 } | 134 //} |
135 SkPoint lastMovePt = SkPoint::Make(0,0); | 135 SkPoint lastMovePt = SkPoint::Make(0,0); |
136 SkDynamicMemoryWStream currentSegment; | 136 SkDynamicMemoryWStream currentSegment; |
137 SkPoint args[4]; | 137 SkPoint args[4]; |
138 SkPath::Iter iter(path, false); | 138 SkPath::Iter iter(path, false); |
139 for (SkPath::Verb verb = iter.next(args); verb != SkPath::kDone_Verb; verb =
iter.next(args)) { | 139 for (SkPath::Verb verb = iter.next(args, doConsumeDegerates); |
| 140 verb != SkPath::kDone_Verb; |
| 141 verb = iter.next(args, doConsumeDegerates)) { |
140 // args gets all the points, even the implicit first point. | 142 // args gets all the points, even the implicit first point. |
141 switch (verb) { | 143 switch (verb) { |
142 case SkPath::kMove_Verb: | 144 case SkPath::kMove_Verb: |
143 MoveTo(args[0].fX, args[0].fY, ¤tSegment); | 145 MoveTo(args[0].fX, args[0].fY, ¤tSegment); |
144 lastMovePt = args[0]; | 146 lastMovePt = args[0]; |
145 fillState = kEmpty_SkipFillState; | 147 fillState = kEmpty_SkipFillState; |
146 break; | 148 break; |
147 case SkPath::kLine_Verb: | 149 case SkPath::kLine_Verb: |
148 AppendLine(args[1].fX, args[1].fY, ¤tSegment); | 150 AppendLine(args[1].fX, args[1].fY, ¤tSegment); |
149 if (fillState == kEmpty_SkipFillState) { | 151 if ((fillState == kEmpty_SkipFillState) && (args[0] != lastMoveP
t)) { |
150 if (args[0] != lastMovePt) { | 152 fillState = kSingleLine_SkipFillState; |
151 fillState = kSingleLine_SkipFillState; | 153 break; |
152 } | |
153 } else if (fillState == kSingleLine_SkipFillState) { | |
154 fillState = kNonSingleLine_SkipFillState; | |
155 } | 154 } |
| 155 fillState = kNonSingleLine_SkipFillState; |
156 break; | 156 break; |
157 case SkPath::kQuad_Verb: | 157 case SkPath::kQuad_Verb: |
158 append_quad(args, ¤tSegment); | 158 append_quad(args, ¤tSegment); |
159 fillState = kNonSingleLine_SkipFillState; | 159 fillState = kNonSingleLine_SkipFillState; |
160 break; | 160 break; |
161 case SkPath::kConic_Verb: { | 161 case SkPath::kConic_Verb: { |
162 const SkScalar tol = SK_Scalar1 / 4; | 162 const SkScalar tol = SK_Scalar1 / 4; |
163 SkAutoConicToQuads converter; | 163 SkAutoConicToQuads converter; |
164 const SkPoint* quads = converter.computeQuads(args, iter.conicWe
ight(), tol); | 164 const SkPoint* quads = converter.computeQuads(args, iter.conicWe
ight(), tol); |
165 for (int i = 0; i < converter.countQuads(); ++i) { | 165 for (int i = 0; i < converter.countQuads(); ++i) { |
166 append_quad(&quads[i * 2], ¤tSegment); | 166 append_quad(&quads[i * 2], ¤tSegment); |
167 } | 167 } |
| 168 fillState = kNonSingleLine_SkipFillState; |
168 } break; | 169 } break; |
169 case SkPath::kCubic_Verb: | 170 case SkPath::kCubic_Verb: |
170 AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY, | 171 AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY, |
171 args[3].fX, args[3].fY, ¤tSegment); | 172 args[3].fX, args[3].fY, ¤tSegment); |
172 fillState = kNonSingleLine_SkipFillState; | 173 fillState = kNonSingleLine_SkipFillState; |
173 break; | 174 break; |
174 case SkPath::kClose_Verb: | 175 case SkPath::kClose_Verb: |
175 if (fillState != kSingleLine_SkipFillState) { | 176 |
176 ClosePath(¤tSegment); | 177 ClosePath(¤tSegment); |
177 currentSegment.writeToStream(content); | 178 |
178 } | 179 currentSegment.writeToStream(content); |
179 currentSegment.reset(); | 180 currentSegment.reset(); |
180 break; | 181 break; |
181 default: | 182 default: |
182 SkASSERT(false); | 183 SkASSERT(false); |
183 break; | 184 break; |
184 } | 185 } |
185 } | 186 } |
186 if (currentSegment.bytesWritten() > 0) { | 187 if (currentSegment.bytesWritten() > 0) { |
187 currentSegment.writeToStream(content); | 188 currentSegment.writeToStream(content); |
188 } | 189 } |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 for (size_t i = 0; i < len; i++) { | 337 for (size_t i = 0; i < len; i++) { |
337 uint8_t c = static_cast<uint8_t>(cin[i]); | 338 uint8_t c = static_cast<uint8_t>(cin[i]); |
338 static const char gHex[] = "0123456789ABCDEF"; | 339 static const char gHex[] = "0123456789ABCDEF"; |
339 *str++ = gHex[(c >> 4) & 0xF]; | 340 *str++ = gHex[(c >> 4) & 0xF]; |
340 *str++ = gHex[(c ) & 0xF]; | 341 *str++ = gHex[(c ) & 0xF]; |
341 } | 342 } |
342 *str++ = '>'; | 343 *str++ = '>'; |
343 } | 344 } |
344 return result; | 345 return result; |
345 } | 346 } |
OLD | NEW |