Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(563)

Side by Side Diff: src/core/SkGlyphCache.cpp

Issue 1654883003: add helper to create fancy underlines (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: correct comment to multiply by two Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkGlyphCache.h ('k') | src/core/SkPaint.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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) { }
OLDNEW
« no previous file with comments | « src/core/SkGlyphCache.h ('k') | src/core/SkPaint.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698