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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 fPrev = fNext = nullptr; | 46 fPrev = fNext = nullptr; |
47 | 47 |
48 fScalerContext->getFontMetrics(&fFontMetrics); | 48 fScalerContext->getFontMetrics(&fFontMetrics); |
49 | 49 |
50 fMemoryUsed = sizeof(*this); | 50 fMemoryUsed = sizeof(*this); |
51 | 51 |
52 fAuxProcList = nullptr; | 52 fAuxProcList = nullptr; |
53 } | 53 } |
54 | 54 |
55 SkGlyphCache::~SkGlyphCache() { | 55 SkGlyphCache::~SkGlyphCache() { |
56 fGlyphMap.foreach ([](SkGlyph* g) { delete g->fPath; }); | 56 fGlyphMap.foreach ([](SkGlyph* g) { |
| 57 if (g->fPathData) { |
| 58 delete g->fPathData->fPath; |
| 59 } } ); |
57 SkDescriptor::Free(fDesc); | 60 SkDescriptor::Free(fDesc); |
58 delete fScalerContext; | 61 delete fScalerContext; |
59 this->invokeAndRemoveAuxProcs(); | 62 this->invokeAndRemoveAuxProcs(); |
60 } | 63 } |
61 | 64 |
62 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(PackedUnicharID packed
UnicharID) { | 65 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(PackedUnicharID packed
UnicharID) { |
63 if (nullptr == fPackedUnicharIDToPackedGlyphID.get()) { | 66 if (nullptr == fPackedUnicharIDToPackedGlyphID.get()) { |
64 // Allocate the array. | 67 // Allocate the array. |
65 fPackedUnicharIDToPackedGlyphID.reset(kHashCount); | 68 fPackedUnicharIDToPackedGlyphID.reset(kHashCount); |
66 // Initialize array to map character and position with the impossible gl
yph ID. This | 69 // Initialize array to map character and position with the impossible gl
yph ID. This |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 // is smaller, and if so, strink the alloc size in fImageAlloc. | 210 // is smaller, and if so, strink the alloc size in fImageAlloc. |
208 fMemoryUsed += size; | 211 fMemoryUsed += size; |
209 } | 212 } |
210 } | 213 } |
211 } | 214 } |
212 return glyph.fImage; | 215 return glyph.fImage; |
213 } | 216 } |
214 | 217 |
215 const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) { | 218 const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) { |
216 if (glyph.fWidth) { | 219 if (glyph.fWidth) { |
217 if (glyph.fPath == nullptr) { | 220 if (glyph.fPathData == nullptr) { |
218 const_cast<SkGlyph&>(glyph).fPath = new SkPath; | 221 SkGlyph::PathData* pathData = |
219 fScalerContext->getPath(glyph, glyph.fPath); | 222 (SkGlyph::PathData* ) fGlyphAlloc.allocThrow(sizeof(SkGlyph:
:PathData)); |
220 fMemoryUsed += sizeof(SkPath) + | 223 const_cast<SkGlyph&>(glyph).fPathData = pathData; |
221 glyph.fPath->countPoints() * sizeof(SkPoint); | 224 pathData->fIntercept = nullptr; |
| 225 SkPath* path = pathData->fPath = new SkPath; |
| 226 fScalerContext->getPath(glyph, path); |
| 227 fMemoryUsed += sizeof(SkPath) + path->countPoints() * sizeof(SkPoint
); |
222 } | 228 } |
223 } | 229 } |
224 return glyph.fPath; | 230 return glyph.fPathData ? glyph.fPathData->fPath : nullptr; |
| 231 } |
| 232 |
| 233 #include "../pathops/SkPathOpsCubic.h" |
| 234 #include "../pathops/SkPathOpsQuad.h" |
| 235 |
| 236 static bool quad_in_bounds(const SkScalar* pts, const SkScalar bounds[2]) { |
| 237 SkScalar min = SkTMin(SkTMin(pts[0], pts[2]), pts[4]); |
| 238 if (bounds[1] < min) { |
| 239 return false; |
| 240 } |
| 241 SkScalar max = SkTMax(SkTMax(pts[0], pts[2]), pts[4]); |
| 242 return bounds[0] < max; |
| 243 } |
| 244 |
| 245 static bool cubic_in_bounds(const SkScalar* pts, const SkScalar bounds[2]) { |
| 246 SkScalar min = SkTMin(SkTMin(SkTMin(pts[0], pts[2]), pts[4]), pts[6]); |
| 247 if (bounds[1] < min) { |
| 248 return false; |
| 249 } |
| 250 SkScalar max = SkTMax(SkTMax(SkTMax(pts[0], pts[2]), pts[4]), pts[6]); |
| 251 return bounds[0] < max; |
| 252 } |
| 253 |
| 254 void SkGlyphCache::OffsetResults(const SkGlyph::Intercept* intercept, SkScalar s
cale, |
| 255 SkScalar xPos, SkScalar* array, int* count) { |
| 256 if (array) { |
| 257 array += *count; |
| 258 for (int index = 0; index < 2; index++) { |
| 259 *array++ = intercept->fInterval[index] * scale + xPos; |
| 260 } |
| 261 } |
| 262 *count += 2; |
| 263 } |
| 264 |
| 265 void SkGlyphCache::AddInterval(SkScalar val, SkGlyph::Intercept* intercept) { |
| 266 intercept->fInterval[0] = SkTMin(intercept->fInterval[0], val); |
| 267 intercept->fInterval[1] = SkTMax(intercept->fInterval[1], val); |
| 268 } |
| 269 |
| 270 void SkGlyphCache::AddPoints(const SkPoint* pts, int ptCount, const SkScalar bou
nds[2], |
| 271 bool yAxis, SkGlyph::Intercept* intercept) { |
| 272 for (int i = 0; i < ptCount; ++i) { |
| 273 SkScalar val = *(&pts[i].fY - yAxis); |
| 274 if (bounds[0] < val && val < bounds[1]) { |
| 275 AddInterval(*(&pts[i].fX + yAxis), intercept); |
| 276 } |
| 277 } |
| 278 } |
| 279 |
| 280 void SkGlyphCache::AddLine(const SkPoint pts[2], SkScalar axis, bool yAxis, |
| 281 SkGlyph::Intercept* intercept) { |
| 282 SkScalar t = yAxis ? (axis - pts[0].fX) / (pts[1].fX - pts[0].fX) |
| 283 : (axis - pts[0].fY) / (pts[1].fY - pts[0].fY); |
| 284 if (0 <= t && t < 1) { // this handles divide by zero above |
| 285 AddInterval(yAxis ? pts[0].fY + t * (pts[1].fY - pts[0].fY) |
| 286 : pts[0].fX + t * (pts[1].fX - pts[0].fX), intercept); |
| 287 } |
| 288 } |
| 289 |
| 290 void SkGlyphCache::AddQuad(const SkPoint pts[2], SkScalar axis, bool yAxis, |
| 291 SkGlyph::Intercept* intercept) { |
| 292 SkDQuad quad; |
| 293 quad.set(pts); |
| 294 double roots[2]; |
| 295 int count = yAxis ? quad.verticalIntersect(axis, roots) |
| 296 : quad.horizontalIntersect(axis, roots); |
| 297 while (--count >= 0) { |
| 298 SkPoint pt = quad.ptAtT(roots[count]).asSkPoint(); |
| 299 AddInterval(*(&pt.fX + yAxis), intercept); |
| 300 } |
| 301 } |
| 302 |
| 303 void SkGlyphCache::AddCubic(const SkPoint pts[3], SkScalar axis, bool yAxis, |
| 304 SkGlyph::Intercept* intercept) { |
| 305 SkDCubic cubic; |
| 306 cubic.set(pts); |
| 307 double roots[3]; |
| 308 int count = yAxis ? cubic.verticalIntersect(axis, roots) |
| 309 : cubic.horizontalIntersect(axis, roots); |
| 310 while (--count >= 0) { |
| 311 SkPoint pt = cubic.ptAtT(roots[count]).asSkPoint(); |
| 312 AddInterval(*(&pt.fX + yAxis), intercept); |
| 313 } |
| 314 } |
| 315 |
| 316 const SkGlyph::Intercept* SkGlyphCache::MatchBounds(const SkGlyph* glyph, |
| 317 const SkScalar bounds[2]) { |
| 318 if (!glyph->fPathData) { |
| 319 return nullptr; |
| 320 } |
| 321 const SkGlyph::Intercept* intercept = glyph->fPathData->fIntercept; |
| 322 while (intercept) { |
| 323 if (bounds[0] == intercept->fBounds[0] && bounds[1] == intercept->fBound
s[1]) { |
| 324 return intercept; |
| 325 } |
| 326 intercept = intercept->fNext; |
| 327 } |
| 328 return nullptr; |
| 329 } |
| 330 |
| 331 void SkGlyphCache::findIntercepts(const SkScalar bounds[2], SkScalar scale, SkSc
alar xPos, |
| 332 bool yAxis, SkGlyph* glyph, SkScalar* array, int* count) { |
| 333 const SkGlyph::Intercept* match = MatchBounds(glyph, bounds); |
| 334 |
| 335 if (match) { |
| 336 if (match->fInterval[0] < match->fInterval[1]) { |
| 337 OffsetResults(match, scale, xPos, array, count); |
| 338 } |
| 339 return; |
| 340 } |
| 341 |
| 342 SkGlyph::Intercept* intercept = |
| 343 (SkGlyph::Intercept* ) fGlyphAlloc.allocThrow(sizeof(SkGlyph::Interc
ept)); |
| 344 intercept->fNext = glyph->fPathData->fIntercept; |
| 345 intercept->fBounds[0] = bounds[0]; |
| 346 intercept->fBounds[1] = bounds[1]; |
| 347 intercept->fInterval[0] = SK_ScalarMax; |
| 348 intercept->fInterval[1] = SK_ScalarMin; |
| 349 glyph->fPathData->fIntercept = intercept; |
| 350 const SkPath* path = glyph->fPathData->fPath; |
| 351 const SkRect& pathBounds = path->getBounds(); |
| 352 if (*(&pathBounds.fBottom - yAxis) < bounds[0] || bounds[1] < *(&pathBounds.
fTop - yAxis)) { |
| 353 return; |
| 354 } |
| 355 SkPath::Iter iter(*path, false); |
| 356 SkPoint pts[4]; |
| 357 SkPath::Verb verb; |
| 358 while (SkPath::kDone_Verb != (verb = iter.next(pts))) { |
| 359 switch (verb) { |
| 360 case SkPath::kMove_Verb: |
| 361 break; |
| 362 case SkPath::kLine_Verb: |
| 363 AddLine(pts, bounds[0], yAxis, intercept); |
| 364 AddLine(pts, bounds[1], yAxis, intercept); |
| 365 AddPoints(pts, 2, bounds, yAxis, intercept); |
| 366 break; |
| 367 case SkPath::kQuad_Verb: |
| 368 if (!quad_in_bounds(&pts[0].fY - yAxis, bounds)) { |
| 369 break; |
| 370 } |
| 371 AddQuad(pts, bounds[0], yAxis, intercept); |
| 372 AddQuad(pts, bounds[1], yAxis, intercept); |
| 373 AddPoints(pts, 3, bounds, yAxis, intercept); |
| 374 break; |
| 375 case SkPath::kConic_Verb: |
| 376 SkASSERT(0); // no support for text composed of conics |
| 377 break; |
| 378 case SkPath::kCubic_Verb: |
| 379 if (!cubic_in_bounds(&pts[0].fY - yAxis, bounds)) { |
| 380 break; |
| 381 } |
| 382 AddCubic(pts, bounds[0], yAxis, intercept); |
| 383 AddCubic(pts, bounds[1], yAxis, intercept); |
| 384 AddPoints(pts, 4, bounds, yAxis, intercept); |
| 385 break; |
| 386 case SkPath::kClose_Verb: |
| 387 break; |
| 388 default: |
| 389 SkASSERT(0); |
| 390 break; |
| 391 } |
| 392 } |
| 393 if (intercept->fInterval[0] >= intercept->fInterval[1]) { |
| 394 intercept->fInterval[0] = SK_ScalarMax; |
| 395 intercept->fInterval[1] = SK_ScalarMin; |
| 396 return; |
| 397 } |
| 398 OffsetResults(intercept, scale, xPos, array, count); |
225 } | 399 } |
226 | 400 |
227 void SkGlyphCache::dump() const { | 401 void SkGlyphCache::dump() const { |
228 const SkTypeface* face = fScalerContext->getTypeface(); | 402 const SkTypeface* face = fScalerContext->getTypeface(); |
229 const SkScalerContextRec& rec = fScalerContext->getRec(); | 403 const SkScalerContextRec& rec = fScalerContext->getRec(); |
230 SkMatrix matrix; | 404 SkMatrix matrix; |
231 rec.getSingleMatrix(&matrix); | 405 rec.getSingleMatrix(&matrix); |
232 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); | 406 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); |
233 SkString name; | 407 SkString name; |
234 face->getFamilyName(&name); | 408 face->getFamilyName(&name); |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 } | 813 } |
640 | 814 |
641 void SkGraphics::PurgeFontCache() { | 815 void SkGraphics::PurgeFontCache() { |
642 get_globals().purgeAll(); | 816 get_globals().purgeAll(); |
643 SkTypefaceCache::PurgeAll(); | 817 SkTypefaceCache::PurgeAll(); |
644 } | 818 } |
645 | 819 |
646 // TODO(herb): clean up TLS apis. | 820 // TODO(herb): clean up TLS apis. |
647 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } | 821 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } |
648 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } | 822 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } |
OLD | NEW |