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 static void offset_results(const SkGlyph::Intercept* intercept, SkScalar scale,
SkScalar xPos, |
| 249 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 static void add_interval(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 static void add_points(const SkPoint* pts, int ptCount, const SkScalar bounds[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 add_interval(*(&pts[i].fX + yAxis), intercept); |
| 270 } |
| 271 } |
| 272 } |
| 273 |
| 274 static void add_line(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 add_interval(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 static void add_quad(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 add_interval(*(&pt.fX + yAxis), intercept); |
| 294 } |
| 295 } |
| 296 |
| 297 static void add_cubic(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 add_interval(*(&pt.fX + yAxis), intercept); |
| 307 } |
| 308 } |
| 309 |
| 310 static const SkGlyph::Intercept* match_bounds(const SkGlyph* glyph, const SkScal
ar bounds[2]) { |
| 311 const SkGlyph::Intercept* intercept = glyph->fIntercept; |
| 312 while (intercept) { |
| 313 if (bounds[0] == intercept->fBounds[0] && bounds[1] == intercept->fBound
s[1]) { |
| 314 return intercept; |
| 315 } |
| 316 intercept = intercept->fNext; |
| 317 } |
| 318 return nullptr; |
| 319 } |
| 320 |
| 321 void SkGlyphCache::findIntercepts(const SkScalar bounds[2], SkScalar scale, SkSc
alar xPos, |
| 322 bool yAxis, SkGlyph* glyph, SkScalar* array, int* count) { |
| 323 const SkGlyph::Intercept* match = match_bounds(glyph, bounds); |
| 324 |
| 325 if (match) { |
| 326 if (match->fInterval[0] < match->fInterval[1]) { |
| 327 offset_results(match, scale, xPos, array, count); |
| 328 } |
| 329 return; |
| 330 } |
| 331 |
| 332 SkGlyph::Intercept* intercept = |
| 333 (SkGlyph::Intercept* ) fGlyphAlloc.allocThrow(sizeof(SkGlyph::Interc
ept)); |
| 334 intercept->fNext = glyph->fIntercept; |
| 335 intercept->fBounds[0] = bounds[0]; |
| 336 intercept->fBounds[1] = bounds[1]; |
| 337 intercept->fInterval[0] = SK_ScalarMax; |
| 338 intercept->fInterval[1] = SK_ScalarMin; |
| 339 glyph->fIntercept = intercept; |
| 340 const SkPath* path = glyph->fPath; |
| 341 const SkRect& pathBounds = path->getBounds(); |
| 342 if (*(&pathBounds.fBottom - yAxis) < bounds[0] || bounds[1] < *(&pathBounds.
fTop - yAxis)) { |
| 343 return; |
| 344 } |
| 345 SkPath::Iter iter(*path, false); |
| 346 SkPoint pts[4]; |
| 347 SkPath::Verb verb; |
| 348 while (SkPath::kDone_Verb != (verb = iter.next(pts))) { |
| 349 switch (verb) { |
| 350 case SkPath::kMove_Verb: |
| 351 break; |
| 352 case SkPath::kLine_Verb: |
| 353 add_line(pts, bounds[0], yAxis, intercept); |
| 354 add_line(pts, bounds[1], yAxis, intercept); |
| 355 add_points(pts, 2, bounds, yAxis, intercept); |
| 356 break; |
| 357 case SkPath::kQuad_Verb: |
| 358 if (!quad_in_bounds(&pts[0].fY - yAxis, bounds)) { |
| 359 break; |
| 360 } |
| 361 add_quad(pts, bounds[0], yAxis, intercept); |
| 362 add_quad(pts, bounds[1], yAxis, intercept); |
| 363 add_points(pts, 3, bounds, yAxis, intercept); |
| 364 break; |
| 365 case SkPath::kConic_Verb: |
| 366 SkASSERT(0); // no support for text composed of conics |
| 367 break; |
| 368 case SkPath::kCubic_Verb: |
| 369 if (!cubic_in_bounds(&pts[0].fY - yAxis, bounds)) { |
| 370 break; |
| 371 } |
| 372 add_cubic(pts, bounds[0], yAxis, intercept); |
| 373 add_cubic(pts, bounds[1], yAxis, intercept); |
| 374 add_points(pts, 4, bounds, yAxis, intercept); |
| 375 break; |
| 376 case SkPath::kClose_Verb: |
| 377 break; |
| 378 default: |
| 379 SkASSERT(0); |
| 380 break; |
| 381 } |
| 382 } |
| 383 if (intercept->fInterval[0] >= intercept->fInterval[1]) { |
| 384 intercept->fInterval[0] = SK_ScalarMax; |
| 385 intercept->fInterval[1] = SK_ScalarMin; |
| 386 return; |
| 387 } |
| 388 offset_results(intercept, scale, xPos, array, count); |
| 389 } |
| 390 |
227 void SkGlyphCache::dump() const { | 391 void SkGlyphCache::dump() const { |
228 const SkTypeface* face = fScalerContext->getTypeface(); | 392 const SkTypeface* face = fScalerContext->getTypeface(); |
229 const SkScalerContextRec& rec = fScalerContext->getRec(); | 393 const SkScalerContextRec& rec = fScalerContext->getRec(); |
230 SkMatrix matrix; | 394 SkMatrix matrix; |
231 rec.getSingleMatrix(&matrix); | 395 rec.getSingleMatrix(&matrix); |
232 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); | 396 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); |
233 SkString name; | 397 SkString name; |
234 face->getFamilyName(&name); | 398 face->getFamilyName(&name); |
235 | 399 |
236 SkString msg; | 400 SkString msg; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 } | 803 } |
640 | 804 |
641 void SkGraphics::PurgeFontCache() { | 805 void SkGraphics::PurgeFontCache() { |
642 get_globals().purgeAll(); | 806 get_globals().purgeAll(); |
643 SkTypefaceCache::PurgeAll(); | 807 SkTypefaceCache::PurgeAll(); |
644 } | 808 } |
645 | 809 |
646 // TODO(herb): clean up TLS apis. | 810 // TODO(herb): clean up TLS apis. |
647 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } | 811 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } |
648 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } | 812 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } |
OLD | NEW |