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 #include "SkDevice.h" | 8 #include "SkDevice.h" |
9 #include "SkDeviceProperties.h" | 9 #include "SkDeviceProperties.h" |
10 #include "SkDraw.h" | 10 #include "SkDraw.h" |
11 #include "SkMetaData.h" | 11 #include "SkMetaData.h" |
12 #include "SkPatchUtils.h" | 12 #include "SkPatchUtils.h" |
13 #include "SkPathMeasure.h" | |
14 #include "SkRasterClip.h" | |
13 #include "SkShader.h" | 15 #include "SkShader.h" |
14 #include "SkTextBlob.h" | 16 #include "SkTextBlob.h" |
17 #include "SkTextToPathIter.h" | |
15 | 18 |
16 SkBaseDevice::SkBaseDevice() | 19 SkBaseDevice::SkBaseDevice() |
17 : fLeakyProperties(SkNEW_ARGS(SkDeviceProperties, (SkDeviceProperties::kLega cyLCD_InitType))) | 20 : fLeakyProperties(SkNEW_ARGS(SkDeviceProperties, (SkDeviceProperties::kLega cyLCD_InitType))) |
18 #ifdef SK_DEBUG | 21 #ifdef SK_DEBUG |
19 , fAttachedToCanvas(false) | 22 , fAttachedToCanvas(false) |
20 #endif | 23 #endif |
21 { | 24 { |
22 fOrigin.setZero(); | 25 fOrigin.setZero(); |
23 fMetaData = NULL; | 26 fMetaData = NULL; |
24 } | 27 } |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 return NULL; | 207 return NULL; |
205 } | 208 } |
206 | 209 |
207 bool SkBaseDevice::EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const S kMatrix*, | 210 bool SkBaseDevice::EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const S kMatrix*, |
208 const SkPaint*) { | 211 const SkPaint*) { |
209 // The base class doesn't perform any accelerated picture rendering | 212 // The base class doesn't perform any accelerated picture rendering |
210 return false; | 213 return false; |
211 } | 214 } |
212 | 215 |
213 //////////////////////////////////////////////////////////////////////////////// ////////// | 216 //////////////////////////////////////////////////////////////////////////////// ////////// |
214 | 217 |
robertphillips
2015/02/17 18:50:47
morph_points ?
| |
218 static void morphpoints(SkPoint dst[], const SkPoint src[], int count, | |
219 SkPathMeasure& meas, const SkMatrix& matrix) { | |
220 SkMatrix::MapXYProc proc = matrix.getMapXYProc(); | |
221 | |
222 for (int i = 0; i < count; i++) { | |
223 SkPoint pos; | |
224 SkVector tangent; | |
225 | |
226 proc(matrix, src[i].fX, src[i].fY, &pos); | |
227 SkScalar sx = pos.fX; | |
228 SkScalar sy = pos.fY; | |
229 | |
230 if (!meas.getPosTan(sx, &pos, &tangent)) { | |
231 // set to 0 if the measure failed, so that we just set dst == pos | |
232 tangent.set(0, 0); | |
233 } | |
234 | |
235 /* This is the old way (that explains our approach but is way too slow | |
236 SkMatrix matrix; | |
237 SkPoint pt; | |
238 | |
239 pt.set(sx, sy); | |
240 matrix.setSinCos(tangent.fY, tangent.fX); | |
241 matrix.preTranslate(-sx, 0); | |
242 matrix.postTranslate(pos.fX, pos.fY); | |
243 matrix.mapPoints(&dst[i], &pt, 1); | |
244 */ | |
245 dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy), | |
246 pos.fY + SkScalarMul(tangent.fX, sy)); | |
247 } | |
248 } | |
249 | |
250 /* TODO | |
251 | |
252 Need differentially more subdivisions when the follow-path is curvy. Not sure h ow to | |
253 determine that, but we need it. I guess a cheap answer is let the caller tell u s, | |
254 but that seems like a cop-out. Another answer is to get Rob Johnson to figure i t out. | |
255 */ | |
robertphillips
2015/02/17 18:50:47
morph_path ?
| |
256 static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas, | |
257 const SkMatrix& matrix) { | |
258 SkPath::Iter iter(src, false); | |
259 SkPoint srcP[4], dstP[3]; | |
260 SkPath::Verb verb; | |
261 | |
262 while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) { | |
263 switch (verb) { | |
264 case SkPath::kMove_Verb: | |
265 morphpoints(dstP, srcP, 1, meas, matrix); | |
266 dst->moveTo(dstP[0]); | |
267 break; | |
268 case SkPath::kLine_Verb: | |
269 // turn lines into quads to look bendy | |
270 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX); | |
271 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY); | |
272 morphpoints(dstP, srcP, 2, meas, matrix); | |
273 dst->quadTo(dstP[0], dstP[1]); | |
274 break; | |
275 case SkPath::kQuad_Verb: | |
276 morphpoints(dstP, &srcP[1], 2, meas, matrix); | |
277 dst->quadTo(dstP[0], dstP[1]); | |
278 break; | |
robertphillips
2015/02/17 18:50:47
kConic_Verb ?
| |
279 case SkPath::kCubic_Verb: | |
280 morphpoints(dstP, &srcP[1], 3, meas, matrix); | |
281 dst->cubicTo(dstP[0], dstP[1], dstP[2]); | |
282 break; | |
283 case SkPath::kClose_Verb: | |
284 dst->close(); | |
285 break; | |
286 default: | |
287 SkDEBUGFAIL("unknown verb"); | |
288 break; | |
289 } | |
290 } | |
291 } | |
292 | |
293 void SkBaseDevice::drawTextOnPath(const SkDraw& draw, const void* text, size_t b yteLength, | |
294 const SkPath& follow, const SkMatrix* matrix, | |
295 const SkPaint& paint) { | |
296 SkASSERT(byteLength == 0 || text != NULL); | |
297 | |
298 // nothing to draw | |
299 if (text == NULL || byteLength == 0 || draw.fRC->isEmpty()) { | |
300 return; | |
301 } | |
302 | |
303 SkTextToPathIter iter((const char*)text, byteLength, paint, true); | |
304 SkPathMeasure meas(follow, false); | |
305 SkScalar hOffset = 0; | |
306 | |
307 // need to measure first | |
308 if (paint.getTextAlign() != SkPaint::kLeft_Align) { | |
309 SkScalar pathLen = meas.getLength(); | |
310 if (paint.getTextAlign() == SkPaint::kCenter_Align) { | |
311 pathLen = SkScalarHalf(pathLen); | |
312 } | |
313 hOffset += pathLen; | |
314 } | |
315 | |
316 const SkPath* iterPath; | |
317 SkScalar xpos; | |
318 SkMatrix scaledMatrix; | |
319 SkScalar scale = iter.getPathScale(); | |
320 | |
321 scaledMatrix.setScale(scale, scale); | |
322 | |
323 while (iter.next(&iterPath, &xpos)) { | |
324 if (iterPath) { | |
325 SkPath tmp; | |
326 SkMatrix m(scaledMatrix); | |
327 | |
328 tmp.setIsVolatile(true); | |
329 m.postTranslate(xpos + hOffset, 0); | |
330 if (matrix) { | |
331 m.postConcat(*matrix); | |
332 } | |
333 morphpath(&tmp, *iterPath, meas, m); | |
334 this->drawPath(draw, tmp, iter.getPaint(), NULL, true); | |
335 } | |
336 } | |
337 } | |
338 | |
339 //////////////////////////////////////////////////////////////////////////////// ////////// | |
340 | |
215 uint32_t SkBaseDevice::filterTextFlags(const SkPaint& paint) const { | 341 uint32_t SkBaseDevice::filterTextFlags(const SkPaint& paint) const { |
216 uint32_t flags = paint.getFlags(); | 342 uint32_t flags = paint.getFlags(); |
217 | 343 |
218 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { | 344 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { |
219 return flags; | 345 return flags; |
220 } | 346 } |
221 | 347 |
222 if (kUnknown_SkPixelGeometry == fLeakyProperties->pixelGeometry() | 348 if (kUnknown_SkPixelGeometry == fLeakyProperties->pixelGeometry() |
223 || this->onShouldDisableLCD(paint)) { | 349 || this->onShouldDisableLCD(paint)) { |
224 | 350 |
225 flags &= ~SkPaint::kLCDRenderText_Flag; | 351 flags &= ~SkPaint::kLCDRenderText_Flag; |
226 flags |= SkPaint::kGenA8FromLCD_Flag; | 352 flags |= SkPaint::kGenA8FromLCD_Flag; |
227 } | 353 } |
228 | 354 |
229 return flags; | 355 return flags; |
230 } | 356 } |
231 | 357 |
OLD | NEW |