OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
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 "SkGlyphCache.h" | 8 #include "SkGlyphCache.h" |
9 #include "SkGlyphCache_Globals.h" | 9 #include "SkGlyphCache_Globals.h" |
10 #include "SkGraphics.h" | 10 #include "SkGraphics.h" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 if (glyph.fPath == nullptr) { | 217 if (glyph.fPath == nullptr) { |
218 const_cast<SkGlyph&>(glyph).fPath = new SkPath; | 218 const_cast<SkGlyph&>(glyph).fPath = new SkPath; |
219 fScalerContext->getPath(glyph, glyph.fPath); | 219 fScalerContext->getPath(glyph, glyph.fPath); |
220 fMemoryUsed += sizeof(SkPath) + | 220 fMemoryUsed += sizeof(SkPath) + |
221 glyph.fPath->countPoints() * sizeof(SkPoint); | 221 glyph.fPath->countPoints() * sizeof(SkPoint); |
222 } | 222 } |
223 } | 223 } |
224 return glyph.fPath; | 224 return glyph.fPath; |
225 } | 225 } |
226 | 226 |
| 227 #include "../pathops/SkPathOpsCubic.h" |
| 228 #include "../pathops/SkPathOpsQuad.h" |
| 229 |
| 230 static bool quad_in_bounds(const SkScalar* pts, const SkScalar bounds[2]) { |
| 231 SkScalar min = SkTMin(SkTMin(pts[0], pts[2]), pts[4]); |
| 232 if (bounds[1] < min) { |
| 233 return false; |
| 234 } |
| 235 SkScalar max = SkTMax(SkTMax(pts[0], pts[2]), pts[4]); |
| 236 return bounds[0] < max; |
| 237 } |
| 238 |
| 239 static bool cubic_in_bounds(const SkScalar* pts, const SkScalar bounds[2]) { |
| 240 SkScalar min = SkTMin(SkTMin(SkTMin(pts[0], pts[2]), pts[4]), pts[6]); |
| 241 if (bounds[1] < min) { |
| 242 return false; |
| 243 } |
| 244 SkScalar max = SkTMax(SkTMax(SkTMax(pts[0], pts[2]), pts[4]), pts[6]); |
| 245 return bounds[0] < max; |
| 246 } |
| 247 |
| 248 void SkGlyphCache::OffsetResults(const SkGlyph::Intercept* intercept, SkScalar s
cale, |
| 249 SkScalar xPos, SkScalar* array, int* count) { |
| 250 if (array) { |
| 251 array += *count; |
| 252 for (int index = 0; index < 2; index++) { |
| 253 *array++ = intercept->fInterval[index] * scale + xPos; |
| 254 } |
| 255 } |
| 256 *count += 2; |
| 257 } |
| 258 |
| 259 void SkGlyphCache::AddInterval(SkScalar val, SkGlyph::Intercept* intercept) { |
| 260 intercept->fInterval[0] = SkTMin(intercept->fInterval[0], val); |
| 261 intercept->fInterval[1] = SkTMax(intercept->fInterval[1], val); |
| 262 } |
| 263 |
| 264 void SkGlyphCache::AddPoints(const SkPoint* pts, int ptCount, const SkScalar bou
nds[2], |
| 265 bool yAxis, SkGlyph::Intercept* intercept) { |
| 266 for (int i = 0; i < ptCount; ++i) { |
| 267 SkScalar val = *(&pts[i].fY - yAxis); |
| 268 if (bounds[0] < val && val < bounds[1]) { |
| 269 AddInterval(*(&pts[i].fX + yAxis), intercept); |
| 270 } |
| 271 } |
| 272 } |
| 273 |
| 274 void SkGlyphCache::AddLine(const SkPoint pts[2], SkScalar axis, bool yAxis, |
| 275 SkGlyph::Intercept* intercept) { |
| 276 SkScalar t = yAxis ? (axis - pts[0].fX) / (pts[1].fX - pts[0].fX) |
| 277 : (axis - pts[0].fY) / (pts[1].fY - pts[0].fY); |
| 278 if (0 <= t && t < 1) { // this handles divide by zero above |
| 279 AddInterval(yAxis ? pts[0].fY + t * (pts[1].fY - pts[0].fY) |
| 280 : pts[0].fX + t * (pts[1].fX - pts[0].fX), intercept); |
| 281 } |
| 282 } |
| 283 |
| 284 void SkGlyphCache::AddQuad(const SkPoint pts[2], SkScalar axis, bool yAxis, |
| 285 SkGlyph::Intercept* intercept) { |
| 286 SkDQuad quad; |
| 287 quad.set(pts); |
| 288 double roots[2]; |
| 289 int count = yAxis ? quad.verticalIntersect(axis, roots) |
| 290 : quad.horizontalIntersect(axis, roots); |
| 291 while (--count >= 0) { |
| 292 SkPoint pt = quad.ptAtT(roots[count]).asSkPoint(); |
| 293 AddInterval(*(&pt.fX + yAxis), intercept); |
| 294 } |
| 295 } |
| 296 |
| 297 void SkGlyphCache::AddCubic(const SkPoint pts[3], SkScalar axis, bool yAxis, |
| 298 SkGlyph::Intercept* intercept) { |
| 299 SkDCubic cubic; |
| 300 cubic.set(pts); |
| 301 double roots[3]; |
| 302 int count = yAxis ? cubic.verticalIntersect(axis, roots) |
| 303 : cubic.horizontalIntersect(axis, roots); |
| 304 while (--count >= 0) { |
| 305 SkPoint pt = cubic.ptAtT(roots[count]).asSkPoint(); |
| 306 AddInterval(*(&pt.fX + yAxis), intercept); |
| 307 } |
| 308 } |
| 309 |
| 310 const SkGlyph::Intercept* SkGlyphCache::MatchBounds(const SkGlyph* glyph, |
| 311 const SkScalar bounds[2]) { |
| 312 const SkGlyph::Intercept* intercept = glyph->fIntercept; |
| 313 while (intercept) { |
| 314 if (bounds[0] == intercept->fBounds[0] && bounds[1] == intercept->fBound
s[1]) { |
| 315 return intercept; |
| 316 } |
| 317 intercept = intercept->fNext; |
| 318 } |
| 319 return nullptr; |
| 320 } |
| 321 |
| 322 void SkGlyphCache::findIntercepts(const SkScalar bounds[2], SkScalar scale, SkSc
alar xPos, |
| 323 bool yAxis, SkGlyph* glyph, SkScalar* array, int* count) { |
| 324 const SkGlyph::Intercept* match = MatchBounds(glyph, bounds); |
| 325 |
| 326 if (match) { |
| 327 if (match->fInterval[0] < match->fInterval[1]) { |
| 328 OffsetResults(match, scale, xPos, array, count); |
| 329 } |
| 330 return; |
| 331 } |
| 332 |
| 333 SkGlyph::Intercept* intercept = |
| 334 (SkGlyph::Intercept* ) fGlyphAlloc.allocThrow(sizeof(SkGlyph::Interc
ept)); |
| 335 intercept->fNext = glyph->fIntercept; |
| 336 intercept->fBounds[0] = bounds[0]; |
| 337 intercept->fBounds[1] = bounds[1]; |
| 338 intercept->fInterval[0] = SK_ScalarMax; |
| 339 intercept->fInterval[1] = SK_ScalarMin; |
| 340 glyph->fIntercept = intercept; |
| 341 const SkPath* path = glyph->fPath; |
| 342 const SkRect& pathBounds = path->getBounds(); |
| 343 if (*(&pathBounds.fBottom - yAxis) < bounds[0] || bounds[1] < *(&pathBounds.
fTop - yAxis)) { |
| 344 return; |
| 345 } |
| 346 SkPath::Iter iter(*path, false); |
| 347 SkPoint pts[4]; |
| 348 SkPath::Verb verb; |
| 349 while (SkPath::kDone_Verb != (verb = iter.next(pts))) { |
| 350 switch (verb) { |
| 351 case SkPath::kMove_Verb: |
| 352 break; |
| 353 case SkPath::kLine_Verb: |
| 354 AddLine(pts, bounds[0], yAxis, intercept); |
| 355 AddLine(pts, bounds[1], yAxis, intercept); |
| 356 AddPoints(pts, 2, bounds, yAxis, intercept); |
| 357 break; |
| 358 case SkPath::kQuad_Verb: |
| 359 if (!quad_in_bounds(&pts[0].fY - yAxis, bounds)) { |
| 360 break; |
| 361 } |
| 362 AddQuad(pts, bounds[0], yAxis, intercept); |
| 363 AddQuad(pts, bounds[1], yAxis, intercept); |
| 364 AddPoints(pts, 3, bounds, yAxis, intercept); |
| 365 break; |
| 366 case SkPath::kConic_Verb: |
| 367 SkASSERT(0); // no support for text composed of conics |
| 368 break; |
| 369 case SkPath::kCubic_Verb: |
| 370 if (!cubic_in_bounds(&pts[0].fY - yAxis, bounds)) { |
| 371 break; |
| 372 } |
| 373 AddCubic(pts, bounds[0], yAxis, intercept); |
| 374 AddCubic(pts, bounds[1], yAxis, intercept); |
| 375 AddPoints(pts, 4, bounds, yAxis, intercept); |
| 376 break; |
| 377 case SkPath::kClose_Verb: |
| 378 break; |
| 379 default: |
| 380 SkASSERT(0); |
| 381 break; |
| 382 } |
| 383 } |
| 384 if (intercept->fInterval[0] >= intercept->fInterval[1]) { |
| 385 intercept->fInterval[0] = SK_ScalarMax; |
| 386 intercept->fInterval[1] = SK_ScalarMin; |
| 387 return; |
| 388 } |
| 389 OffsetResults(intercept, scale, xPos, array, count); |
| 390 } |
| 391 |
227 void SkGlyphCache::dump() const { | 392 void SkGlyphCache::dump() const { |
228 const SkTypeface* face = fScalerContext->getTypeface(); | 393 const SkTypeface* face = fScalerContext->getTypeface(); |
229 const SkScalerContextRec& rec = fScalerContext->getRec(); | 394 const SkScalerContextRec& rec = fScalerContext->getRec(); |
230 SkMatrix matrix; | 395 SkMatrix matrix; |
231 rec.getSingleMatrix(&matrix); | 396 rec.getSingleMatrix(&matrix); |
232 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); | 397 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); |
233 SkString name; | 398 SkString name; |
234 face->getFamilyName(&name); | 399 face->getFamilyName(&name); |
235 | 400 |
236 SkString msg; | 401 SkString msg; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 } | 804 } |
640 | 805 |
641 void SkGraphics::PurgeFontCache() { | 806 void SkGraphics::PurgeFontCache() { |
642 get_globals().purgeAll(); | 807 get_globals().purgeAll(); |
643 SkTypefaceCache::PurgeAll(); | 808 SkTypefaceCache::PurgeAll(); |
644 } | 809 } |
645 | 810 |
646 // TODO(herb): clean up TLS apis. | 811 // TODO(herb): clean up TLS apis. |
647 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } | 812 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } |
648 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } | 813 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } |
OLD | NEW |