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

Side by Side Diff: src/core/SkFindAndPlaceGlyph.h

Issue 1458193003: Move glyph choosing to the find and place glyph code. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Comments and fixes. Created 5 years, 1 month 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/SkDraw.cpp ('k') | src/gpu/GrAtlasTextContext.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 2015 Google Inc. 2 * Copyright 2015 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 #ifndef SkFindAndPositionGlyph_DEFINED 8 #ifndef SkFindAndPositionGlyph_DEFINED
9 #define SkFindAndPositionGlyph_DEFINED 9 #define SkFindAndPositionGlyph_DEFINED
10 10
11 #include "SkAutoKern.h" 11 #include "SkAutoKern.h"
12 #include "SkGlyph.h" 12 #include "SkGlyph.h"
13 #include "SkGlyphCache.h" 13 #include "SkGlyphCache.h"
14 #include "SkPaint.h" 14 #include "SkPaint.h"
15 #include "SkTemplates.h" 15 #include "SkTemplates.h"
16 #include "SkUtils.h"
16 17
17 // Calculate a type with the same size as the max of all the Ts. 18 // Calculate a type with the same size as the max of all the Ts.
18 // This must be top level because the is no specialization of inner classes. 19 // This must be top level because the is no specialization of inner classes.
19 template<typename... Ts> struct SkMaxSizeOf; 20 template<typename... Ts> struct SkMaxSizeOf;
20 21
21 template<> 22 template<>
22 struct SkMaxSizeOf<> { 23 struct SkMaxSizeOf<> {
23 static const size_t value = 0; 24 static const size_t value = 0;
24 }; 25 };
25 26
26 template<typename H, typename... Ts> 27 template<typename H, typename... Ts>
27 struct SkMaxSizeOf<H, Ts...> { 28 struct SkMaxSizeOf<H, Ts...> {
28 static const size_t value = 29 static const size_t value =
29 sizeof(H) >= SkMaxSizeOf<Ts...>::value ? sizeof(H) : SkMaxSizeOf<Ts...>: :value; 30 sizeof(H) >= SkMaxSizeOf<Ts...>::value ? sizeof(H) : SkMaxSizeOf<Ts...>: :value;
30 }; 31 };
31 32
32 class SkFindAndPlaceGlyph { 33 class SkFindAndPlaceGlyph {
33 public: 34 public:
34 template<typename ProcessOneGlyph> 35 template<typename ProcessOneGlyph>
35 static void ProcessText(const char text[], size_t byteLength, SkPoint offset , const 36 static void ProcessText(
36 SkMatrix& matrix, SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheP roc, 37 SkPaint::TextEncoding, const char text[], size_t byteLength,
37 SkGlyphCache* cache, ProcessOneGlyph&& processOneGly ph); 38 SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment,
39 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph);
38 // ProcessPosText handles all cases for finding and positioning glyphs. It h as a very large 40 // ProcessPosText handles all cases for finding and positioning glyphs. It h as a very large
39 // multiplicity. It figures out the glyph, position and rounding and pass th ose parameters to 41 // multiplicity. It figures out the glyph, position and rounding and pass th ose parameters to
40 // processOneGlyph. 42 // processOneGlyph.
41 // 43 //
42 // The routine processOneGlyph passed in by the client has the following sig nature: 44 // The routine processOneGlyph passed in by the client has the following sig nature:
43 // void f(const SkGlyph& glyph, SkPoint position, SkPoint rounding); 45 // void f(const SkGlyph& glyph, SkPoint position, SkPoint rounding);
44 // 46 //
45 // * Sub-pixel positioning (2) - use sub-pixel positioning. 47 // * Sub-pixel positioning (2) - use sub-pixel positioning.
46 // * Text alignment (3) - text alignment with respect to the glyph's width. 48 // * Text alignment (3) - text alignment with respect to the glyph's width.
47 // * Matrix type (3) - special cases for translation and X-coordinate scalin g. 49 // * Matrix type (3) - special cases for translation and X-coordinate scalin g.
48 // * Components per position (2) - the positions vector can have a common Y with different 50 // * Components per position (2) - the positions vector can have a common Y with different
49 // Xs, or XY-pairs. 51 // Xs, or XY-pairs.
50 // * Axis Alignment (for sub-pixel positioning) (3) - when using sub-pixel p ositioning, round 52 // * Axis Alignment (for sub-pixel positioning) (3) - when using sub-pixel p ositioning, round
51 // to a whole coordinate instead of using sub-pixel positioning. 53 // to a whole coordinate instead of using sub-pixel positioning.
52 // The number of variations is 108 for sub-pixel and 36 for full-pixel. 54 // The number of variations is 108 for sub-pixel and 36 for full-pixel.
53 // This routine handles all of them using inline polymorphic variable (no he ap allocation). 55 // This routine handles all of them using inline polymorphic variable (no he ap allocation).
54 template<typename ProcessOneGlyph> 56 template<typename ProcessOneGlyph>
55 static void ProcessPosText(const char text[], size_t byteLength, 57 static void ProcessPosText(
56 SkPoint offset, const SkMatrix& matrix, 58 SkPaint::TextEncoding, const char text[], size_t byteLength,
57 const SkScalar pos[], int scalarsPerPosition, 59 SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalar sPerPosition,
58 SkPaint::Align textAlignment, SkDrawCacheProc& gl yphCacheProc, 60 SkPaint::Align textAlignment,
59 SkGlyphCache* cache, ProcessOneGlyph&& processOne Glyph); 61 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph);
60 62
61 private: 63 private:
62 // UntaggedVariant is a pile of memory that can hold one of the Ts. It provi des a way 64 // UntaggedVariant is a pile of memory that can hold one of the Ts. It provi des a way
63 // to initialize that memory in a typesafe way. 65 // to initialize that memory in a typesafe way.
64 template<typename... Ts> 66 template<typename... Ts>
65 class UntaggedVariant { 67 class UntaggedVariant {
66 public: 68 public:
67 UntaggedVariant() { } 69 UntaggedVariant() { }
68 70
69 ~UntaggedVariant() { } 71 ~UntaggedVariant() { }
(...skipping 29 matching lines...) Expand all
99 } 101 }
100 ~PolymorphicVariant() { get()->~Base(); } 102 ~PolymorphicVariant() { get()->~Base(); }
101 Base* get() const { return reinterpret_cast<Base*>(&fVariants); } 103 Base* get() const { return reinterpret_cast<Base*>(&fVariants); }
102 Base* operator->() const { return get(); } 104 Base* operator->() const { return get(); }
103 Base& operator*() const { return *get(); } 105 Base& operator*() const { return *get(); }
104 106
105 private: 107 private:
106 mutable Variants fVariants; 108 mutable Variants fVariants;
107 }; 109 };
108 110
111 // GlyphFinderInterface is the polymorphic base for classes that parse a str eam of chars into
112 // the right UniChar (or GlyphID) and lookup up the glyph on the cache. The concrete
113 // implementations are: Utf8GlyphFinder, Utf16GlyphFinder, Utf32GlyphFinder,
114 // and GlyphIdGlyphFinder.
115 class GlyphFinderInterface {
116 public:
117 virtual ~GlyphFinderInterface() {}
118 virtual const SkGlyph& lookupGlyph(const char** text) = 0;
119 virtual const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFix ed y) = 0;
120 };
121
122 class UtfNGlyphFinder : public GlyphFinderInterface {
123 public:
124 UtfNGlyphFinder(SkGlyphCache* cache) : fCache(cache) { SkASSERT(cache != nullptr); }
125
126 const SkGlyph& lookupGlyph(const char** text) override {
127 SkASSERT(text != nullptr);
128 return fCache->getUnicharMetrics(nextUnichar(text));
129 }
130 const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) ov erride {
131 SkASSERT(text != nullptr);
132 return fCache->getUnicharMetrics(nextUnichar(text), x, y);
133 }
134
135 private:
136 virtual SkUnichar nextUnichar(const char** text) = 0;
137 SkGlyphCache* fCache;
138 };
139
140 class Utf8GlyphFinder final : public UtfNGlyphFinder {
141 public:
142 Utf8GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }
143
144 private:
145 SkUnichar nextUnichar(const char** text) override { return SkUTF8_NextUn ichar(text); }
146 };
147
148 class Utf16GlyphFinder final : public UtfNGlyphFinder {
149 public:
150 Utf16GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }
151
152 private:
153 SkUnichar nextUnichar(const char** text) override {
154 return SkUTF16_NextUnichar((const uint16_t**)text);
155 }
156 };
157
158 class Utf32GlyphFinder final : public UtfNGlyphFinder {
159 public:
160 Utf32GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }
161
162 private:
163 SkUnichar nextUnichar(const char** text) override {
164 const int32_t* ptr = *(const int32_t**)text;
165 SkUnichar uni = *ptr++;
166 *text = (const char*)ptr;
167 return uni;
168 }
169 };
170
171 class GlyphIdGlyphFinder final : public GlyphFinderInterface {
172 public:
173 GlyphIdGlyphFinder(SkGlyphCache* cache) : fCache(cache) { SkASSERT(cache != nullptr); }
174
175 const SkGlyph& lookupGlyph(const char** text) override {
176 return fCache->getGlyphIDMetrics(nextGlyphId(text));
177 }
178 const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) ov erride {
179 return fCache->getGlyphIDMetrics(nextGlyphId(text), x, y);
180 }
181
182 private:
183 uint16_t nextGlyphId(const char** text) {
184 SkASSERT(text != nullptr);
185
186 const uint16_t* ptr = *(const uint16_t**)text;
187 uint16_t glyphID = *ptr;
188 ptr += 1;
189 *text = (const char*)ptr;
190 return glyphID;
191 }
192 SkGlyphCache* fCache;
193 };
194
195 typedef PolymorphicVariant<
196 GlyphFinderInterface,
197 Utf8GlyphFinder,
198 Utf16GlyphFinder,
199 Utf32GlyphFinder,
200 GlyphIdGlyphFinder> LookupGlyphVariant;
201
202 class LookupGlyph : public LookupGlyphVariant {
203 public:
204 LookupGlyph(SkPaint::TextEncoding encoding, SkGlyphCache* cache)
205 : LookupGlyphVariant(
206 [&](LookupGlyphVariant::Variants* to_init) {
207 switch(encoding) {
208 case SkPaint::kUTF8_TextEncoding:
209 to_init->initialize<Utf8GlyphFinder>(cache);
210 break;
211 case SkPaint::kUTF16_TextEncoding:
212 to_init->initialize<Utf16GlyphFinder>(cache);
213 break;
214 case SkPaint::kUTF32_TextEncoding:
215 to_init->initialize<Utf32GlyphFinder>(cache);
216 break;
217 case SkPaint::kGlyphID_TextEncoding:
218 to_init->initialize<GlyphIdGlyphFinder>(cache);
219 break;
220 }
221 }
222 ) { }
223 };
224
109 // PositionReaderInterface reads a point from the pos vector. 225 // PositionReaderInterface reads a point from the pos vector.
110 // * HorizontalPositions - assumes a common Y for many X values. 226 // * HorizontalPositions - assumes a common Y for many X values.
111 // * ArbitraryPositions - a list of (X,Y) pairs. 227 // * ArbitraryPositions - a list of (X,Y) pairs.
112 class PositionReaderInterface { 228 class PositionReaderInterface {
113 public: 229 public:
114 virtual ~PositionReaderInterface() { } 230 virtual ~PositionReaderInterface() { }
115 virtual SkPoint nextPoint() = 0; 231 virtual SkPoint nextPoint() = 0;
116 }; 232 };
117 233
118 class HorizontalPositions final : public PositionReaderInterface { 234 class HorizontalPositions final : public PositionReaderInterface {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 }; 402 };
287 }; 403 };
288 404
289 // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pix el positioning is 405 // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pix el positioning is
290 // requested. After it has found and placed the glyph it calls the templated function 406 // requested. After it has found and placed the glyph it calls the templated function
291 // ProcessOneGlyph in order to actually perform an action. 407 // ProcessOneGlyph in order to actually perform an action.
292 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, 408 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment,
293 SkAxisAlignment kAxisAlignment> 409 SkAxisAlignment kAxisAlignment>
294 class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<Pr ocessOneGlyph> { 410 class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<Pr ocessOneGlyph> {
295 public: 411 public:
296 GlyphFindAndPlaceSubpixel(SkGlyphCache* cache, SkDrawCacheProc glyphCach eProc) 412 GlyphFindAndPlaceSubpixel(LookupGlyph& glyphFinder)
297 : fCache(cache) 413 : fGlyphFinder(glyphFinder) { }
298 , fGlyphCacheProc(glyphCacheProc) { }
299 414
300 SkPoint findAndPositionGlyph( 415 SkPoint findAndPositionGlyph(
301 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly ph) override { 416 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly ph) override {
302 SkPoint finalPosition = position; 417 SkPoint finalPosition = position;
303 if (kTextAlignment != SkPaint::kLeft_Align) { 418 if (kTextAlignment != SkPaint::kLeft_Align) {
304 // Get the width of an un-sub-pixel positioned glyph for calcula ting the 419 // Get the width of an un-sub-pixel positioned glyph for calcula ting the
305 // alignment. This is not needed for kLeftAlign because its adju stment is 420 // alignment. This is not needed for kLeftAlign because its adju stment is
306 // always {0, 0}. 421 // always {0, 0}.
307 const char* tempText = *text; 422 const char* tempText = *text;
308 const SkGlyph &metricGlyph = fGlyphCacheProc(fCache, &tempText, 0, 0); 423 const SkGlyph &metricGlyph = fGlyphFinder->lookupGlyph(&tempText );
309 424
310 if (metricGlyph.fWidth <= 0) { 425 if (metricGlyph.fWidth <= 0) {
311 // Exiting early, be sure to update text pointer. 426 // Exiting early, be sure to update text pointer.
312 *text = tempText; 427 *text = tempText;
313 return finalPosition + SkPoint{SkFixedToScalar(metricGlyph.f AdvanceX), 428 return finalPosition + SkPoint{SkFixedToScalar(metricGlyph.f AdvanceX),
314 SkFixedToScalar(metricGlyph.f AdvanceY)}; 429 SkFixedToScalar(metricGlyph.f AdvanceY)};
315 } 430 }
316 431
317 // Adjust the final position by the alignment adjustment. 432 // Adjust the final position by the alignment adjustment.
318 finalPosition -= TextAlignmentAdjustment(kTextAlignment, metricG lyph); 433 finalPosition -= TextAlignmentAdjustment(kTextAlignment, metricG lyph);
319 } 434 }
320 435
321 // Find the glyph. 436 // Find the glyph.
322 SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, finalPos ition); 437 SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, finalPos ition);
323 const SkGlyph& renderGlyph = 438 const SkGlyph& renderGlyph =
324 fGlyphCacheProc(fCache, text, lookupPosition.fX, lookupPosition. fY); 439 fGlyphFinder->lookupGlyphXY(text, lookupPosition.fX, lookupPosit ion.fY);
325 440
326 // If the glyph has no width (no pixels) then don't bother processin g it. 441 // If the glyph has no width (no pixels) then don't bother processin g it.
327 if (renderGlyph.fWidth > 0) { 442 if (renderGlyph.fWidth > 0) {
328 processOneGlyph(renderGlyph, finalPosition, 443 processOneGlyph(renderGlyph, finalPosition,
329 SubpixelPositionRounding(kAxisAlignment)); 444 SubpixelPositionRounding(kAxisAlignment));
330 } 445 }
331 return finalPosition + SkPoint{SkFixedToScalar(renderGlyph.fAdvanceX ), 446 return finalPosition + SkPoint{SkFixedToScalar(renderGlyph.fAdvanceX ),
332 SkFixedToScalar(renderGlyph.fAdvanceY )}; 447 SkFixedToScalar(renderGlyph.fAdvanceY )};
333 } 448 }
334 449
335 private: 450 private:
336 SkGlyphCache* const fCache; 451 LookupGlyph& fGlyphFinder;
337 SkDrawCacheProc fGlyphCacheProc;
338 }; 452 };
339 453
340 enum SelectKerning { 454 enum SelectKerning {
341 kNoKerning = false, 455 kNoKerning = false,
342 kUseKerning = true 456 kUseKerning = true
343 }; 457 };
344 458
345 // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub -pixel 459 // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub -pixel
346 // positioning is requested. The kUseKerning argument should be true for dra wText, and false 460 // positioning is requested. The kUseKerning argument should be true for dra wText, and false
347 // for drawPosText. 461 // for drawPosText.
348 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKern ing kUseKerning> 462 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKern ing kUseKerning>
349 class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<P rocessOneGlyph> { 463 class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<P rocessOneGlyph> {
350 public: 464 public:
351 GlyphFindAndPlaceFullPixel(SkGlyphCache* cache, SkDrawCacheProc glyphCac heProc) 465 GlyphFindAndPlaceFullPixel(LookupGlyph& glyphFinder)
352 : fCache(cache), fGlyphCacheProc(glyphCacheProc) { 466 : fGlyphFinder(glyphFinder) {
353 // Kerning can only be used with SkPaint::kLeft_Align 467 // Kerning can only be used with SkPaint::kLeft_Align
354 static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment , 468 static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment ,
355 "Kerning can only be used with left aligned text."); 469 "Kerning can only be used with left aligned text.");
356 } 470 }
357 471
358 SkPoint findAndPositionGlyph( 472 SkPoint findAndPositionGlyph(
359 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly ph) override { 473 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly ph) override {
360 SkPoint finalPosition = position; 474 SkPoint finalPosition = position;
361 const SkGlyph& glyph = fGlyphCacheProc(fCache, text, 0, 0); 475 const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text);
362 if (kUseKerning) { 476 if (kUseKerning) {
363 finalPosition += {SkFixedToScalar(fAutoKern.adjust(glyph)), 0.0f }; 477 finalPosition += {SkFixedToScalar(fAutoKern.adjust(glyph)), 0.0f };
364 } 478 }
365 if (glyph.fWidth > 0) { 479 if (glyph.fWidth > 0) {
366 finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph); 480 finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph);
367 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarH alf}); 481 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarH alf});
368 } 482 }
369 return finalPosition + SkPoint{SkFixedToScalar(glyph.fAdvanceX), 483 return finalPosition + SkPoint{SkFixedToScalar(glyph.fAdvanceX),
370 SkFixedToScalar(glyph.fAdvanceY)}; 484 SkFixedToScalar(glyph.fAdvanceY)};
371 } 485 }
372 486
373 private: 487 private:
374 SkGlyphCache* const fCache; 488 LookupGlyph& fGlyphFinder;
375 SkDrawCacheProc fGlyphCacheProc; 489
376 SkAutoKern fAutoKern; 490 SkAutoKern fAutoKern;
377 }; 491 };
378 492
379 // GlyphFindAndPlace is a large variant that encapsulates the multiple types of finding and 493 // GlyphFindAndPlace is a large variant that encapsulates the multiple types of finding and
380 // placing a glyph. There are three factors that go into the different facto rs. 494 // placing a glyph. There are three factors that go into the different facto rs.
381 // * Is sub-pixel positioned - a boolean that says whether to use sub-pixel positioning. 495 // * Is sub-pixel positioned - a boolean that says whether to use sub-pixel positioning.
382 // * Text alignment - indicates if the glyph should be placed to the right, centered or left 496 // * Text alignment - indicates if the glyph should be placed to the right, centered or left
383 // of a given position. 497 // of a given position.
384 // * Axis alignment - indicates if the glyphs final sub-pixel position shoul d be rounded to a 498 // * Axis alignment - indicates if the glyphs final sub-pixel position shoul d be rounded to a
385 // whole pixel if the glyph is aligned with an axis. This is only used for sub-pixel 499 // whole pixel if the glyph is aligned with an axis. This is only used for sub-pixel
(...skipping 16 matching lines...) Expand all
402 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNoK erning>, 516 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNoK erning>,
403 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kRight_Align, kNoK erning> 517 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kRight_Align, kNoK erning>
404 >; 518 >;
405 519
406 // InitSubpixel is a helper function for initializing all the variants of 520 // InitSubpixel is a helper function for initializing all the variants of
407 // GlyphFindAndPlaceSubpixel. 521 // GlyphFindAndPlaceSubpixel.
408 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment> 522 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
409 static void InitSubpixel( 523 static void InitSubpixel(
410 typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init, 524 typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init,
411 SkAxisAlignment axisAlignment, 525 SkAxisAlignment axisAlignment,
412 SkGlyphCache* cache, 526 LookupGlyph& glyphFinder) {
413 SkDrawCacheProc glyphCacheProc) {
414 switch (axisAlignment) { 527 switch (axisAlignment) {
415 case kX_SkAxisAlignment: 528 case kX_SkAxisAlignment:
416 to_init->template initialize<GlyphFindAndPlaceSubpixel< 529 to_init->template initialize<GlyphFindAndPlaceSubpixel<
417 ProcessOneGlyph, kTextAlignment, kX_SkAxisAlignment>>( 530 ProcessOneGlyph, kTextAlignment, kX_SkAxisAlignment>>(glyphF inder);
418 cache, glyphCacheProc);
419 break; 531 break;
420 case kNone_SkAxisAlignment: 532 case kNone_SkAxisAlignment:
421 to_init->template initialize<GlyphFindAndPlaceSubpixel< 533 to_init->template initialize<GlyphFindAndPlaceSubpixel<
422 ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>( 534 ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>(gly phFinder);
423 cache, glyphCacheProc);
424 break; 535 break;
425 case kY_SkAxisAlignment: 536 case kY_SkAxisAlignment:
426 to_init->template initialize<GlyphFindAndPlaceSubpixel< 537 to_init->template initialize<GlyphFindAndPlaceSubpixel<
427 ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>( 538 ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>(glyphF inder);
428 cache, glyphCacheProc);
429 break; 539 break;
430 } 540 }
431 } 541 }
432 542
433 static SkPoint MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCachePr oc, 543 static SkPoint MeasureText(LookupGlyph& glyphFinder, const char text[], size _t byteLength) {
434 const char text[], size_t byteLength) {
435 SkFixed x = 0, y = 0; 544 SkFixed x = 0, y = 0;
436 const char* stop = text + byteLength; 545 const char* stop = text + byteLength;
437 546
438 SkAutoKern autokern; 547 SkAutoKern autokern;
439 548
440 while (text < stop) { 549 while (text < stop) {
441 // don't need x, y here, since all subpixel variants will have the 550 // don't need x, y here, since all subpixel variants will have the
442 // same advance 551 // same advance
443 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 552 const SkGlyph& glyph = glyphFinder->lookupGlyph(&text);
444 553
445 x += autokern.adjust(glyph) + glyph.fAdvanceX; 554 x += autokern.adjust(glyph) + glyph.fAdvanceX;
446 y += glyph.fAdvanceY; 555 y += glyph.fAdvanceY;
447 } 556 }
448 SkASSERT(text == stop); 557 SkASSERT(text == stop);
449 return {SkFixedToScalar(x), SkFixedToScalar(y)}; 558 return {SkFixedToScalar(x), SkFixedToScalar(y)};
450 } 559 }
451 }; 560 };
452 561
453 template<typename ProcessOneGlyph> 562 template<typename ProcessOneGlyph>
454 inline void SkFindAndPlaceGlyph::ProcessPosText( 563 inline void SkFindAndPlaceGlyph::ProcessPosText(
455 const char text[], size_t byteLength, SkPoint offset, const SkMatrix& matrix , 564 SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength,
456 const SkScalar pos[], int scalarsPerPosition, SkPaint::Align textAlignment, 565 SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalarsPer Position,
457 SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, ProcessOneGlyph&& proc essOneGlyph) { 566 SkPaint::Align textAlignment,
567 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) {
458 568
459 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix); 569 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix);
460 uint32_t mtype = matrix.getType(); 570 uint32_t mtype = matrix.getType();
461 571
572 LookupGlyph glyphFinder(textEncoding, cache);
573
462 // Specialized code for handling the most common case for blink. The while l oop is totally 574 // Specialized code for handling the most common case for blink. The while l oop is totally
463 // de-virtualized. 575 // de-virtualized.
464 if (scalarsPerPosition == 1 576 if (scalarsPerPosition == 1
465 && textAlignment == SkPaint::kLeft_Align 577 && textAlignment == SkPaint::kLeft_Align
466 && axisAlignment == kX_SkAxisAlignment 578 && axisAlignment == kX_SkAxisAlignment
467 && cache->isSubpixel() 579 && cache->isSubpixel()
468 && mtype <= SkMatrix::kTranslate_Mask) { 580 && mtype <= SkMatrix::kTranslate_Mask) {
469 typedef GlyphFindAndPlaceSubpixel< 581 typedef GlyphFindAndPlaceSubpixel<
470 ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment> Positione r; 582 ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment> Positione r;
471 HorizontalPositions positions{pos}; 583 HorizontalPositions positions{pos};
472 TranslationMapper mapper{matrix, offset}; 584 TranslationMapper mapper{matrix, offset};
473 Positioner positioner(cache, glyphCacheProc); 585 Positioner positioner(glyphFinder);
474 const char* cursor = text; 586 const char* cursor = text;
475 const char* stop = text + byteLength; 587 const char* stop = text + byteLength;
476 while (cursor < stop) { 588 while (cursor < stop) {
477 SkPoint mappedPoint = mapper.TranslationMapper::map( 589 SkPoint mappedPoint = mapper.TranslationMapper::map(
478 positions.HorizontalPositions::nextPoint()); 590 positions.HorizontalPositions::nextPoint());
479 positioner.Positioner::findAndPositionGlyph( 591 positioner.Positioner::findAndPositionGlyph(
480 &cursor, mappedPoint, skstd::forward<ProcessOneGlyph>(processOne Glyph)); 592 &cursor, mappedPoint, skstd::forward<ProcessOneGlyph>(processOne Glyph));
481 } 593 }
482 return; 594 return;
483 } 595 }
(...skipping 20 matching lines...) Expand all
504 } 616 }
505 } 617 }
506 }; 618 };
507 619
508 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{ 620 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{
509 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) { 621 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) {
510 if (cache->isSubpixel()) { 622 if (cache->isSubpixel()) {
511 switch (textAlignment) { 623 switch (textAlignment) {
512 case SkPaint::kLeft_Align: 624 case SkPaint::kLeft_Align:
513 InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>( 625 InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
514 to_init, axisAlignment, cache, glyphCacheProc); 626 to_init, axisAlignment, glyphFinder);
515 break; 627 break;
516 case SkPaint::kCenter_Align: 628 case SkPaint::kCenter_Align:
517 InitSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align>( 629 InitSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align>(
518 to_init, axisAlignment, cache, glyphCacheProc); 630 to_init, axisAlignment, glyphFinder);
519 break; 631 break;
520 case SkPaint::kRight_Align: 632 case SkPaint::kRight_Align:
521 InitSubpixel<ProcessOneGlyph, SkPaint::kRight_Align>( 633 InitSubpixel<ProcessOneGlyph, SkPaint::kRight_Align>(
522 to_init, axisAlignment, cache, glyphCacheProc); 634 to_init, axisAlignment, glyphFinder);
523 break; 635 break;
524 } 636 }
525 } else { 637 } else {
526 switch (textAlignment) { 638 switch (textAlignment) {
527 case SkPaint::kLeft_Align: 639 case SkPaint::kLeft_Align:
528 to_init->template initialize< 640 to_init->template initialize<
529 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 641 GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
530 SkPaint::kLeft_Align, kNoKerning>>(cache, glyphCache Proc); 642 SkPaint::kLeft_Align, kNoKerning>>(glyphFinder);
531 break; 643 break;
532 case SkPaint::kCenter_Align: 644 case SkPaint::kCenter_Align:
533 to_init->template initialize< 645 to_init->template initialize<
534 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 646 GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
535 SkPaint::kCenter_Align, kNoKerning>>(cache, glyphCac heProc); 647 SkPaint::kCenter_Align, kNoKerning>>(glyphFinder);
536 break; 648 break;
537 case SkPaint::kRight_Align: 649 case SkPaint::kRight_Align:
538 to_init->template initialize< 650 to_init->template initialize<
539 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 651 GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
540 SkPaint::kRight_Align, kNoKerning>>(cache, glyphCach eProc); 652 SkPaint::kRight_Align, kNoKerning>>(glyphFinder);
541 break; 653 break;
542 } 654 }
543 } 655 }
544 } 656 }
545 }; 657 };
546 658
547 const char* stop = text + byteLength; 659 const char* stop = text + byteLength;
548 while (text < stop) { 660 while (text < stop) {
549 SkPoint mappedPoint = mapper->map(positionReader->nextPoint()); 661 SkPoint mappedPoint = mapper->map(positionReader->nextPoint());
550 findAndPosition->findAndPositionGlyph( 662 findAndPosition->findAndPositionGlyph(
551 &text, mappedPoint, skstd::forward<ProcessOneGlyph>(processOneGlyph) ); 663 &text, mappedPoint, skstd::forward<ProcessOneGlyph>(processOneGlyph) );
552 } 664 }
553 } 665 }
554 666
555 template<typename ProcessOneGlyph> 667 template<typename ProcessOneGlyph>
556 inline void SkFindAndPlaceGlyph::ProcessText( 668 inline void SkFindAndPlaceGlyph::ProcessText(
557 const char text[], size_t byteLength, SkPoint offset, const SkMatrix& matrix , 669 SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength,
558 SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, 670 SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment,
559 ProcessOneGlyph&& processOneGlyph) { 671 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) {
560 672
561 // transform the starting point 673 // transform the starting point
562 matrix.mapPoints(&offset, 1); 674 matrix.mapPoints(&offset, 1);
563 675
676 LookupGlyph glyphFinder(textEncoding, cache);
677
564 // need to measure first 678 // need to measure first
565 if (textAlignment != SkPaint::kLeft_Align) { 679 if (textAlignment != SkPaint::kLeft_Align) {
566 SkVector stop = MeasureText(cache, glyphCacheProc, text, byteLength); 680 SkVector stop = MeasureText(glyphFinder, text, byteLength);
567 681
568 if (textAlignment == SkPaint::kCenter_Align) { 682 if (textAlignment == SkPaint::kCenter_Align) {
569 stop *= SK_ScalarHalf; 683 stop *= SK_ScalarHalf;
570 } 684 }
571 offset -= stop; 685 offset -= stop;
572 } 686 }
573 687
574 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{ 688 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{
575 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) { 689 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) {
576 if (cache->isSubpixel()) { 690 if (cache->isSubpixel()) {
577 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(m atrix); 691 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(m atrix);
578 InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>( 692 InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
579 to_init, axisAlignment, cache, glyphCacheProc); 693 to_init, axisAlignment, glyphFinder);
580 } else { 694 } else {
581 to_init->template initialize< 695 to_init->template initialize<
582 GlyphFindAndPlaceFullPixel< 696 GlyphFindAndPlaceFullPixel<
583 ProcessOneGlyph, SkPaint::kLeft_Align, kUseKerning>>( 697 ProcessOneGlyph, SkPaint::kLeft_Align, kUseKerning>>(gly phFinder);
584 cache, glyphCacheProc);
585 } 698 }
586 } 699 }
587 }; 700 };
588 701
589 const char* stop = text + byteLength; 702 const char* stop = text + byteLength;
590 SkPoint current = offset; 703 SkPoint current = offset;
591 while (text < stop) { 704 while (text < stop) {
592 current = 705 current =
593 findAndPosition->findAndPositionGlyph( 706 findAndPosition->findAndPositionGlyph(
594 &text, current, skstd::forward<ProcessOneGlyph>(processOneGlyph) ); 707 &text, current, skstd::forward<ProcessOneGlyph>(processOneGlyph) );
595 708
596 } 709 }
597 } 710 }
598 711
599 #endif // SkFindAndPositionGlyph_DEFINED 712 #endif // SkFindAndPositionGlyph_DEFINED
OLDNEW
« no previous file with comments | « src/core/SkDraw.cpp ('k') | src/gpu/GrAtlasTextContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698