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

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

Issue 1448453002: Convert drawText to using the find and place code. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Remove adjusted test. 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 "SkGlyph.h" 12 #include "SkGlyph.h"
12 #include "SkGlyphCache.h" 13 #include "SkGlyphCache.h"
13 #include "SkPaint.h" 14 #include "SkPaint.h"
14 #include "SkTemplates.h" 15 #include "SkTemplates.h"
15 16
16 // Calculate a type with the same size as the max of all the Ts. 17 // Calculate a type with the same size as the max of all the Ts.
17 // This must be top level because the is no specialization of inner classes. 18 // This must be top level because the is no specialization of inner classes.
18 template<typename... Ts> struct SkMaxSizeOf; 19 template<typename... Ts> struct SkMaxSizeOf;
19 20
20 template<> 21 template<>
21 struct SkMaxSizeOf<> { 22 struct SkMaxSizeOf<> {
22 static const size_t value = 0; 23 static const size_t value = 0;
23 }; 24 };
24 25
25 template<typename H, typename... Ts> 26 template<typename H, typename... Ts>
26 struct SkMaxSizeOf<H, Ts...> { 27 struct SkMaxSizeOf<H, Ts...> {
27 static const size_t value = 28 static const size_t value =
28 sizeof(H) >= SkMaxSizeOf<Ts...>::value ? sizeof(H) : SkMaxSizeOf<Ts...>: :value; 29 sizeof(H) >= SkMaxSizeOf<Ts...>::value ? sizeof(H) : SkMaxSizeOf<Ts...>: :value;
29 }; 30 };
30 31
31 class SkFindAndPlaceGlyph { 32 class SkFindAndPlaceGlyph {
32 public: 33 public:
34 template<typename ProcessOneGlyph>
35 static void ProcessText(const char text[], size_t byteLength, SkPoint offset , const
36 SkMatrix& matrix, SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheP roc,
37 SkGlyphCache* cache, ProcessOneGlyph&& processOneGly ph);
33 // ProcessPosText handles all cases for finding and positioning glyphs. It h as a very large 38 // ProcessPosText handles all cases for finding and positioning glyphs. It h as a very large
34 // multiplicity. It figures out the glyph, position and rounding and pass th ose parameters to 39 // multiplicity. It figures out the glyph, position and rounding and pass th ose parameters to
35 // processOneGlyph. 40 // processOneGlyph.
36 // 41 //
37 // The routine processOneGlyph passed in by the client has the following sig nature: 42 // The routine processOneGlyph passed in by the client has the following sig nature:
38 // void f(const SkGlyph& glyph, SkPoint position, SkPoint rounding); 43 // void f(const SkGlyph& glyph, SkPoint position, SkPoint rounding);
39 // 44 //
40 // * Sub-pixel positioning (2) - use sub-pixel positioning. 45 // * Sub-pixel positioning (2) - use sub-pixel positioning.
41 // * Text alignment (3) - text alignment with respect to the glyph's width. 46 // * Text alignment (3) - text alignment with respect to the glyph's width.
42 // * Matrix type (3) - special cases for translation and X-coordinate scalin g. 47 // * Matrix type (3) - special cases for translation and X-coordinate scalin g.
43 // * Components per position (2) - the positions vector can have a common Y with different 48 // * Components per position (2) - the positions vector can have a common Y with different
44 // Xs, or XY-pairs. 49 // Xs, or XY-pairs.
45 // * Axis Alignment (for sub-pixel positioning) (3) - when using sub-pixel p ositioning, round 50 // * Axis Alignment (for sub-pixel positioning) (3) - when using sub-pixel p ositioning, round
46 // to a whole coordinate instead of using sub-pixel positioning. 51 // to a whole coordinate instead of using sub-pixel positioning.
47 // The number of variations is 108 for sub-pixel and 36 for full-pixel. 52 // The number of variations is 108 for sub-pixel and 36 for full-pixel.
48 // This routine handles all of them using inline polymorphic variable (no he ap allocation). 53 // This routine handles all of them using inline polymorphic variable (no he ap allocation).
49 template<typename ProcessOneGlyph> 54 template<typename ProcessOneGlyph>
50 static void ProcessPosText(const char text[], size_t byteLength, 55 static void ProcessPosText(const char text[], size_t byteLength,
51 const SkPoint& offset, const SkMatrix& matrix, 56 SkPoint offset, const SkMatrix& matrix,
52 const SkScalar pos[], int scalarsPerPosition, 57 const SkScalar pos[], int scalarsPerPosition,
53 SkPaint::Align textAlignment, SkDrawCacheProc& gl yphCacheProc, 58 SkPaint::Align textAlignment, SkDrawCacheProc& gl yphCacheProc,
54 SkGlyphCache* cache, ProcessOneGlyph&& processOne Glyph); 59 SkGlyphCache* cache, ProcessOneGlyph&& processOne Glyph);
55 60
56 private: 61 private:
57 // UntaggedVariant is a pile of memory that can hold one of the Ts. It provi des a way 62 // UntaggedVariant is a pile of memory that can hold one of the Ts. It provi des a way
58 // to initialize that memory in a typesafe way. 63 // to initialize that memory in a typesafe way.
59 template<typename... Ts> 64 template<typename... Ts>
60 class UntaggedVariant { 65 class UntaggedVariant {
61 public: 66 public:
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 return to_return; 140 return to_return;
136 } 141 }
137 142
138 private: 143 private:
139 const SkScalar* fPositions; 144 const SkScalar* fPositions;
140 }; 145 };
141 146
142 typedef PolymorphicVariant<PositionReaderInterface, HorizontalPositions, Arb itraryPositions> 147 typedef PolymorphicVariant<PositionReaderInterface, HorizontalPositions, Arb itraryPositions>
143 PositionReader; 148 PositionReader;
144 149
145 // MapperInterface given a point map it through the matrix. There are severa l shortcut variants. 150 // MapperInterface given a point map it through the matrix. There are severa l shortcut
151 // variants.
146 // * TranslationMapper - assumes a translation only matrix. 152 // * TranslationMapper - assumes a translation only matrix.
147 // * XScaleMapper - assumes an X scaling and a translation. 153 // * XScaleMapper - assumes an X scaling and a translation.
148 // * GeneralMapper - Does all other matricies. 154 // * GeneralMapper - Does all other matricies.
149 class MapperInterface { 155 class MapperInterface {
150 public: 156 public:
151 virtual ~MapperInterface() { } 157 virtual ~MapperInterface() { }
152 158
153 virtual SkPoint map(SkPoint position) const = 0; 159 virtual SkPoint map(SkPoint position) const = 0;
154 }; 160 };
155 161
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 200
195 private: 201 private:
196 const SkPoint fOrigin; 202 const SkPoint fOrigin;
197 const SkMatrix& fMatrix; 203 const SkMatrix& fMatrix;
198 const SkMatrix::MapXYProc fMapProc; 204 const SkMatrix::MapXYProc fMapProc;
199 }; 205 };
200 206
201 typedef PolymorphicVariant< 207 typedef PolymorphicVariant<
202 MapperInterface, TranslationMapper, XScaleMapper, GeneralMapper> Mapper; 208 MapperInterface, TranslationMapper, XScaleMapper, GeneralMapper> Mapper;
203 209
204 // Text alignment handles shifting the glyph based on its width. 210 // TextAlignmentAdjustment handles shifting the glyph based on its width.
205 static SkPoint TextAlignmentAdjustment(SkPaint::Align textAlignment, const S kGlyph& glyph) { 211 static SkPoint TextAlignmentAdjustment(SkPaint::Align textAlignment, const S kGlyph& glyph) {
206 switch (textAlignment) { 212 switch (textAlignment) {
207 case SkPaint::kLeft_Align: 213 case SkPaint::kLeft_Align:
208 return {0.0f, 0.0f}; 214 return {0.0f, 0.0f};
209 case SkPaint::kCenter_Align: 215 case SkPaint::kCenter_Align:
210 return {SkFixedToScalar(glyph.fAdvanceX >> 1), 216 return {SkFixedToScalar(glyph.fAdvanceX >> 1),
211 SkFixedToScalar(glyph.fAdvanceY >> 1)}; 217 SkFixedToScalar(glyph.fAdvanceY >> 1)};
212 case SkPaint::kRight_Align: 218 case SkPaint::kRight_Align:
213 return {SkFixedToScalar(glyph.fAdvanceX), 219 return {SkFixedToScalar(glyph.fAdvanceX),
214 SkFixedToScalar(glyph.fAdvanceY)}; 220 SkFixedToScalar(glyph.fAdvanceY)};
215 } 221 }
216 // Even though the entire enum is covered above, MVSC doesn't think so. Make it happy. 222 // Even though the entire enum is covered above, MVSC doesn't think so. Make it happy.
217 SkFAIL("Should never get here."); 223 SkFAIL("Should never get here.");
218 return {0.0f, 0.0f}; 224 return {0.0f, 0.0f};
219 } 225 }
220 226
221 // The "call" to SkFixedToScalar is actually a macro. It's macros all the wa y down. 227 // The "call" to SkFixedToScalar is actually a macro. It's macros all the wa y down.
222 // Needs to be a macro because you can't have a const float unless you make it constexpr. 228 // Needs to be a macro because you can't have a const float unless you make it constexpr.
223 #define kSubpixelRounding (SkFixedToScalar(SkGlyph::kSubpixelRound)) 229 #define kSubpixelRounding (SkFixedToScalar(SkGlyph::kSubpixelRound))
224 230
225 // Functions for handling sub-pixel aligned positions. 231 // The SubpixelPositionRounding function returns a point suitable for roundi ng a sub-pixel
226 // The subpixel_position_rounding function returns a point suitable for roun ding a sub-pixel
227 // positioned glyph. 232 // positioned glyph.
228 static SkPoint SubpixelPositionRounding(SkAxisAlignment axisAlignment) { 233 static SkPoint SubpixelPositionRounding(SkAxisAlignment axisAlignment) {
229 switch (axisAlignment) { 234 switch (axisAlignment) {
230 case kX_SkAxisAlignment: 235 case kX_SkAxisAlignment:
231 return {SkFixedToScalar(SkGlyph::kSubpixelRound), SK_ScalarHalf} ; 236 return {SkFixedToScalar(SkGlyph::kSubpixelRound), SK_ScalarHalf} ;
232 case kY_SkAxisAlignment: 237 case kY_SkAxisAlignment:
233 return {SK_ScalarHalf, kSubpixelRounding}; 238 return {SK_ScalarHalf, kSubpixelRounding};
234 case kNone_SkAxisAlignment: 239 case kNone_SkAxisAlignment:
235 return {kSubpixelRounding, kSubpixelRounding}; 240 return {kSubpixelRounding, kSubpixelRounding};
236 } 241 }
237 SkFAIL("Should not get here."); 242 SkFAIL("Should not get here.");
238 return {0.0f, 0.0f}; 243 return {0.0f, 0.0f};
239 } 244 }
240 245
241 // The subpixel_position_alignment function produces a suitable position for the glyph cache to 246 // The SubpixelAlignment function produces a suitable position for the glyph cache to
242 // produce the correct sub-pixel alignment. If a position is aligned with an axis a shortcut 247 // produce the correct sub-pixel alignment. If a position is aligned with an axis a shortcut
243 // of 0 is used for the sub-pixel position. 248 // of 0 is used for the sub-pixel position.
244 static SkIPoint SubpixelAlignment(SkAxisAlignment axisAlignment, SkPoint pos ition) { 249 static SkIPoint SubpixelAlignment(SkAxisAlignment axisAlignment, SkPoint pos ition) {
245 switch (axisAlignment) { 250 switch (axisAlignment) {
246 case kX_SkAxisAlignment: 251 case kX_SkAxisAlignment:
247 return {SkScalarToFixed(position.fX + kSubpixelRounding), 0}; 252 return {SkScalarToFixed(position.fX + kSubpixelRounding), 0};
248 case kY_SkAxisAlignment: 253 case kY_SkAxisAlignment:
249 return {0, SkScalarToFixed(position.fY + kSubpixelRounding)}; 254 return {0, SkScalarToFixed(position.fY + kSubpixelRounding)};
250 case kNone_SkAxisAlignment: 255 case kNone_SkAxisAlignment:
251 return {SkScalarToFixed(position.fX + kSubpixelRounding), 256 return {SkScalarToFixed(position.fX + kSubpixelRounding),
252 SkScalarToFixed(position.fY + kSubpixelRounding)}; 257 SkScalarToFixed(position.fY + kSubpixelRounding)};
253 } 258 }
254 SkFAIL("Should not get here."); 259 SkFAIL("Should not get here.");
255 return {0, 0}; 260 return {0, 0};
256 } 261 }
257 262
258 #undef kSubpixelRounding 263 #undef kSubpixelRounding
259 264
260 // GlyphFindAndPlaceInterface given the text and position finds the correct glyph and does 265 // GlyphFindAndPlaceInterface given the text and position finds the correct glyph and does
261 // glyph specific position adjustment. The findAndPositionGlyph method takes text and 266 // glyph specific position adjustment. The findAndPositionGlyph method takes text and
262 // position and calls processOneGlyph with the correct glyph, final position and rounding 267 // position and calls processOneGlyph with the correct glyph, final position and rounding
263 // terms. The final position is not rounded yet and is the responsibility of processOneGlyph. 268 // terms. The final position is not rounded yet and is the responsibility of processOneGlyph.
264 template<typename ProcessOneGlyph> 269 template<typename ProcessOneGlyph>
265 class GlyphFindAndPlaceInterface : SkNoncopyable { 270 class GlyphFindAndPlaceInterface : SkNoncopyable {
266 public: 271 public:
267 virtual ~GlyphFindAndPlaceInterface() { }; 272 virtual ~GlyphFindAndPlaceInterface() { };
268 273
274 // findAndPositionGlyph calculates the position of the glyph, finds the glyph, and
275 // returns the position of where the next glyph will be using the glyph' s advance and
276 // possibly kerning. The returned position is used by drawText, but igno red by drawPosText.
277 // The compiler should prune all this calculation if the return value is not used.
278 //
269 // This should be a pure virtual, but some versions of GCC <= 4.8 have a bug that causes a 279 // This should be a pure virtual, but some versions of GCC <= 4.8 have a bug that causes a
270 // compile error. 280 // compile error.
271 // See GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60277 281 // See GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60277
272 virtual void findAndPositionGlyph(const char** text, SkPoint position, 282 virtual SkPoint findAndPositionGlyph(
273 ProcessOneGlyph&& processOneGlyph) { } ; 283 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly ph) {
284 SkFAIL("Should never get here.");
285 return {0.0f, 0.0f};
286 };
274 }; 287 };
275 288
276 // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pix el positioning is 289 // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pix el positioning is
277 // requested. After it has found and placed the glyph it calls the templated function 290 // requested. After it has found and placed the glyph it calls the templated function
278 // ProcessOneGlyph in order to actually perform an action. 291 // ProcessOneGlyph in order to actually perform an action.
279 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SkAxisAlig nment kAxisAlignment> 292 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment,
293 SkAxisAlignment kAxisAlignment>
280 class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<Pr ocessOneGlyph> { 294 class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<Pr ocessOneGlyph> {
281 public: 295 public:
282 GlyphFindAndPlaceSubpixel(SkGlyphCache* cache, SkDrawCacheProc glyphCach eProc) 296 GlyphFindAndPlaceSubpixel(SkGlyphCache* cache, SkDrawCacheProc glyphCach eProc)
283 : fCache(cache), fGlyphCacheProc(glyphCacheProc) { 297 : fCache(cache)
284 } 298 , fGlyphCacheProc(glyphCacheProc) { }
285 299
286 void findAndPositionGlyph(const char** text, SkPoint position, 300 SkPoint findAndPositionGlyph(
287 ProcessOneGlyph&& processOneGlyph) override { 301 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly ph) override {
288 SkPoint finalPosition = position; 302 SkPoint finalPosition = position;
289 if (kTextAlignment != SkPaint::kLeft_Align) { 303 if (kTextAlignment != SkPaint::kLeft_Align) {
290 // Get the width of an un-sub-pixel positioned glyph for calcula ting the alignment. 304 // Get the width of an un-sub-pixel positioned glyph for calcula ting the
291 // This is not needed for kLeftAlign because its adjustment is a lways {0, 0}. 305 // alignment. This is not needed for kLeftAlign because its adju stment is
306 // always {0, 0}.
292 const char* tempText = *text; 307 const char* tempText = *text;
293 const SkGlyph &metricGlyph = fGlyphCacheProc(fCache, &tempText, 0, 0); 308 const SkGlyph &metricGlyph = fGlyphCacheProc(fCache, &tempText, 0, 0);
294 309
295 if (metricGlyph.fWidth <= 0) { 310 if (metricGlyph.fWidth <= 0) {
296 // Exiting early, be sure to update text pointer. 311 // Exiting early, be sure to update text pointer.
297 *text = tempText; 312 *text = tempText;
298 return; 313 return finalPosition + SkPoint{SkFixedToScalar(metricGlyph.f AdvanceX),
314 SkFixedToScalar(metricGlyph.f AdvanceY)};
299 } 315 }
300 316
301 // Adjust the final position by the alignment adjustment. 317 // Adjust the final position by the alignment adjustment.
302 finalPosition -= TextAlignmentAdjustment(kTextAlignment, metricG lyph); 318 finalPosition -= TextAlignmentAdjustment(kTextAlignment, metricG lyph);
303 } 319 }
304 320
305 // Find the glyph. 321 // Find the glyph.
306 SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, finalPos ition); 322 SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, finalPos ition);
307 const SkGlyph& renderGlyph = fGlyphCacheProc( 323 const SkGlyph& renderGlyph =
308 fCache, text, lookupPosition.fX, lookupPosition.fY); 324 fGlyphCacheProc(fCache, text, lookupPosition.fX, lookupPosition. fY);
309 325
310 // If the glyph has no width (no pixels) then don't bother processin g it. 326 // If the glyph has no width (no pixels) then don't bother processin g it.
311 if (renderGlyph.fWidth > 0) { 327 if (renderGlyph.fWidth > 0) {
312 processOneGlyph(renderGlyph, finalPosition, 328 processOneGlyph(renderGlyph, finalPosition,
313 SubpixelPositionRounding(kAxisAlignment)); 329 SubpixelPositionRounding(kAxisAlignment));
314 } 330 }
331 return finalPosition + SkPoint{SkFixedToScalar(renderGlyph.fAdvanceX ),
332 SkFixedToScalar(renderGlyph.fAdvanceY )};
315 } 333 }
316 334
317 private: 335 private:
318 SkGlyphCache* const fCache; 336 SkGlyphCache* const fCache;
319 SkDrawCacheProc fGlyphCacheProc; 337 SkDrawCacheProc fGlyphCacheProc;
320 }; 338 };
321 339
340 enum SelectKerning {
341 kNoKerning = false,
342 kUseKerning = true
343 };
344
322 // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub -pixel 345 // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub -pixel
323 // positioning is requested. 346 // positioning is requested. The kUseKerning argument should be true for dra wText, and false
324 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment> 347 // for drawPosText.
348 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKern ing kUseKerning>
325 class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<P rocessOneGlyph> { 349 class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<P rocessOneGlyph> {
326 public: 350 public:
327 GlyphFindAndPlaceFullPixel(SkGlyphCache* cache, SkDrawCacheProc glyphCac heProc) 351 GlyphFindAndPlaceFullPixel(SkGlyphCache* cache, SkDrawCacheProc glyphCac heProc)
328 : fCache(cache), fGlyphCacheProc(glyphCacheProc) { } 352 : fCache(cache), fGlyphCacheProc(glyphCacheProc) {
353 // Kerning can only be used with SkPaint::kLeft_Align
354 static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment ,
355 "Kerning can only be used with left aligned text.");
356 }
329 357
330 void findAndPositionGlyph(const char** text, SkPoint position, 358 SkPoint findAndPositionGlyph(
331 ProcessOneGlyph&& processOneGlyph) override { 359 const char** text, SkPoint position, ProcessOneGlyph&& processOneGly ph) override {
332 SkPoint finalPosition = position; 360 SkPoint finalPosition = position;
333 const SkGlyph& glyph = fGlyphCacheProc(fCache, text, 0, 0); 361 const SkGlyph& glyph = fGlyphCacheProc(fCache, text, 0, 0);
334 if (glyph.fWidth <= 0) { 362 if (kUseKerning) {
335 return; 363 finalPosition += {SkFixedToScalar(fAutoKern.adjust(glyph)), 0.0f };
336 } 364 }
337 finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph); 365 if (glyph.fWidth > 0) {
338 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf} ); 366 finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph);
367 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarH alf});
368 }
369 return finalPosition + SkPoint{SkFixedToScalar(glyph.fAdvanceX),
370 SkFixedToScalar(glyph.fAdvanceY)};
339 } 371 }
340 372
341 private: 373 private:
342 SkGlyphCache* const fCache; 374 SkGlyphCache* const fCache;
343 SkDrawCacheProc fGlyphCacheProc; 375 SkDrawCacheProc fGlyphCacheProc;
376 SkAutoKern fAutoKern;
344 }; 377 };
345 378
346 // GlyphFindAndPlace is a large variant that encapsulates the multiple types of finding and 379 // GlyphFindAndPlace is a large variant that encapsulates the multiple types of finding and
347 // placing a glyph. There are three factors that go into the different facto rs. 380 // placing a glyph. There are three factors that go into the different facto rs.
348 // * Is sub-pixel positioned - a boolean that says whether to use sub-pixel positioning. 381 // * Is sub-pixel positioned - a boolean that says whether to use sub-pixel positioning.
349 // * Text alignment - indicates if the glyph should be placed to the right, centered or left 382 // * Text alignment - indicates if the glyph should be placed to the right, centered or left
350 // of a given position. 383 // of a given position.
351 // * Axis alignment - indicates if the glyphs final sub-pixel position shoul d be rounded to a 384 // * Axis alignment - indicates if the glyphs final sub-pixel position shoul d be rounded to a
352 // whole pixel if the glyph is aligned with an axis. This is only used for sub-pixel 385 // whole pixel if the glyph is aligned with an axis. This is only used for sub-pixel
353 // positioning and allows the baseline to look crisp. 386 // positioning and allows the baseline to look crisp.
354 template<typename ProcessOneGlyph> 387 template<typename ProcessOneGlyph>
355 using GlyphFindAndPlace = PolymorphicVariant< 388 using GlyphFindAndPlace = PolymorphicVariant<
356 GlyphFindAndPlaceInterface<ProcessOneGlyph>, 389 GlyphFindAndPlaceInterface<ProcessOneGlyph>,
357 // Subpixel 390 // Subpixel
358 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kNon e_SkAxisAlignment>, 391 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kNon e_SkAxisAlignment>,
359 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kX_S kAxisAlignment >, 392 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kX_S kAxisAlignment >,
360 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kY_S kAxisAlignment >, 393 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kY_S kAxisAlignment >,
361 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNon e_SkAxisAlignment>, 394 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNon e_SkAxisAlignment>,
362 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kX_S kAxisAlignment >, 395 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kX_S kAxisAlignment >,
363 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kY_S kAxisAlignment >, 396 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kY_S kAxisAlignment >,
364 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kNon e_SkAxisAlignment>, 397 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kNon e_SkAxisAlignment>,
365 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kX_S kAxisAlignment >, 398 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kX_S kAxisAlignment >,
366 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kY_S kAxisAlignment >, 399 GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kY_S kAxisAlignment >,
367 // Full pixel 400 // Full pixel
368 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align >, 401 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align, kNoK erning>,
369 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align>, 402 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNoK erning>,
370 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kRight_Align > 403 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kRight_Align, kNoK erning>
371 >; 404 >;
372 405
373 // InitSubpixel is a helper function for initializing all the variants of 406 // InitSubpixel is a helper function for initializing all the variants of
374 // GlyphFindAndPlaceSubpixel. 407 // GlyphFindAndPlaceSubpixel.
375 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment> 408 template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
376 static void InitSubpixel( 409 static void InitSubpixel(
377 typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init, 410 typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init,
378 SkAxisAlignment axisAlignment, 411 SkAxisAlignment axisAlignment,
379 SkGlyphCache* cache, 412 SkGlyphCache* cache,
380 SkDrawCacheProc glyphCacheProc) { 413 SkDrawCacheProc glyphCacheProc) {
381 switch (axisAlignment) { 414 switch (axisAlignment) {
382 case kX_SkAxisAlignment: 415 case kX_SkAxisAlignment:
383 to_init->template initialize<GlyphFindAndPlaceSubpixel< 416 to_init->template initialize<GlyphFindAndPlaceSubpixel<
384 ProcessOneGlyph, kTextAlignment, kX_SkAxisAlignment>>( 417 ProcessOneGlyph, kTextAlignment, kX_SkAxisAlignment>>(
385 cache, glyphCacheProc); 418 cache, glyphCacheProc);
386 break; 419 break;
387 case kNone_SkAxisAlignment: 420 case kNone_SkAxisAlignment:
388 to_init->template initialize<GlyphFindAndPlaceSubpixel< 421 to_init->template initialize<GlyphFindAndPlaceSubpixel<
389 ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>( 422 ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>(
390 cache, glyphCacheProc); 423 cache, glyphCacheProc);
391 break; 424 break;
392 case kY_SkAxisAlignment: 425 case kY_SkAxisAlignment:
393 to_init->template initialize<GlyphFindAndPlaceSubpixel< 426 to_init->template initialize<GlyphFindAndPlaceSubpixel<
394 ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>( 427 ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>(
395 cache, glyphCacheProc); 428 cache, glyphCacheProc);
396 break; 429 break;
397 } 430 }
398 } 431 }
432
433 static SkPoint MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCachePr oc,
434 const char text[], size_t byteLength) {
435 SkFixed x = 0, y = 0;
436 const char* stop = text + byteLength;
437
438 SkAutoKern autokern;
439
440 while (text < stop) {
441 // don't need x, y here, since all subpixel variants will have the
442 // same advance
443 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
444
445 x += autokern.adjust(glyph) + glyph.fAdvanceX;
446 y += glyph.fAdvanceY;
447 }
448 SkASSERT(text == stop);
449 return {SkFixedToScalar(x), SkFixedToScalar(y)};
450 }
399 }; 451 };
400 452
401 template<typename ProcessOneGlyph> 453 template<typename ProcessOneGlyph>
402 inline void SkFindAndPlaceGlyph::ProcessPosText( 454 inline void SkFindAndPlaceGlyph::ProcessPosText(
403 const char text[], size_t byteLength, const SkPoint& offset, const SkMatrix& matrix, 455 const char text[], size_t byteLength, SkPoint offset, const SkMatrix& matrix ,
404 const SkScalar pos[], int scalarsPerPosition, SkPaint::Align textAlignment, 456 const SkScalar pos[], int scalarsPerPosition, SkPaint::Align textAlignment,
405 SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, ProcessOneGlyph&& proc essOneGlyph) { 457 SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, ProcessOneGlyph&& proc essOneGlyph) {
406 458
407 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix); 459 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix);
408 uint32_t mtype = matrix.getType(); 460 uint32_t mtype = matrix.getType();
409 461
410 // Specialized code for handling the most common case for blink. The while l oop is totally 462 // Specialized code for handling the most common case for blink. The while l oop is totally
411 // de-virtualized. 463 // de-virtualized.
412 if (scalarsPerPosition == 1 464 if (scalarsPerPosition == 1
413 && textAlignment == SkPaint::kLeft_Align 465 && textAlignment == SkPaint::kLeft_Align
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 case SkPaint::kRight_Align: 520 case SkPaint::kRight_Align:
469 InitSubpixel<ProcessOneGlyph, SkPaint::kRight_Align>( 521 InitSubpixel<ProcessOneGlyph, SkPaint::kRight_Align>(
470 to_init, axisAlignment, cache, glyphCacheProc); 522 to_init, axisAlignment, cache, glyphCacheProc);
471 break; 523 break;
472 } 524 }
473 } else { 525 } else {
474 switch (textAlignment) { 526 switch (textAlignment) {
475 case SkPaint::kLeft_Align: 527 case SkPaint::kLeft_Align:
476 to_init->template initialize< 528 to_init->template initialize<
477 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 529 GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
478 SkPaint::kLeft_Align>>(cache, glyphCacheProc); 530 SkPaint::kLeft_Align, kNoKerning>>(cache, glyphCache Proc);
479 break; 531 break;
480 case SkPaint::kCenter_Align: 532 case SkPaint::kCenter_Align:
481 to_init->template initialize< 533 to_init->template initialize<
482 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 534 GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
483 SkPaint::kCenter_Align>>(cache, glyphCacheProc); 535 SkPaint::kCenter_Align, kNoKerning>>(cache, glyphCac heProc);
484 break; 536 break;
485 case SkPaint::kRight_Align: 537 case SkPaint::kRight_Align:
486 to_init->template initialize< 538 to_init->template initialize<
487 GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 539 GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
488 SkPaint::kRight_Align>>(cache, glyphCacheProc); 540 SkPaint::kRight_Align, kNoKerning>>(cache, glyphCach eProc);
489 break; 541 break;
490 } 542 }
491 } 543 }
492 } 544 }
493 }; 545 };
494 546
495 const char* stop = text + byteLength; 547 const char* stop = text + byteLength;
496 while (text < stop) { 548 while (text < stop) {
497 SkPoint mappedPoint = mapper->map(positionReader->nextPoint()); 549 SkPoint mappedPoint = mapper->map(positionReader->nextPoint());
498 findAndPosition->findAndPositionGlyph( 550 findAndPosition->findAndPositionGlyph(
499 &text, mappedPoint, skstd::forward<ProcessOneGlyph>(processOneGlyph) ); 551 &text, mappedPoint, skstd::forward<ProcessOneGlyph>(processOneGlyph) );
500 } 552 }
501 } 553 }
502 554
555 template<typename ProcessOneGlyph>
556 inline void SkFindAndPlaceGlyph::ProcessText(
557 const char text[], size_t byteLength, SkPoint offset, const SkMatrix& matrix ,
558 SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache,
559 ProcessOneGlyph&& processOneGlyph) {
560
561 // transform the starting point
562 matrix.mapPoints(&offset, 1);
563
564 // need to measure first
565 if (textAlignment != SkPaint::kLeft_Align) {
566 SkVector stop = MeasureText(cache, glyphCacheProc, text, byteLength);
567
568 if (textAlignment == SkPaint::kCenter_Align) {
569 stop *= SK_ScalarHalf;
570 }
571 offset -= stop;
572 }
573
574 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{
575 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) {
576 if (cache->isSubpixel()) {
577 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(m atrix);
578 InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
579 to_init, axisAlignment, cache, glyphCacheProc);
580 } else {
581 to_init->template initialize<
582 GlyphFindAndPlaceFullPixel<
583 ProcessOneGlyph, SkPaint::kLeft_Align, kUseKerning>>(
584 cache, glyphCacheProc);
585 }
586 }
587 };
588
589 const char* stop = text + byteLength;
590 SkPoint current = offset;
591 while (text < stop) {
592 current =
593 findAndPosition->findAndPositionGlyph(
594 &text, current, skstd::forward<ProcessOneGlyph>(processOneGlyph) );
595
596 }
597 }
598
503 #endif // SkFindAndPositionGlyph_DEFINED 599 #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