Chromium Code Reviews| 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 |